~damg/ubuntu/quantal/asterisk/LP1097687

« back to all changes in this revision

Viewing changes to .pc/dahdi_fxs_false_ringing/channels/chan_dahdi.c

  • Committer: Bazaar Package Importer
  • Author(s): Lorenzo De Liso
  • Date: 2010-10-15 22:24:34 UTC
  • mfrom: (1.2.8 upstream) (8.3.8 sid)
  • Revision ID: james.westby@ubuntu.com-20101015222434-iy328q8in3lajzlv
Tags: 1:1.6.2.9-2ubuntu1
* Merge from debian unstable, remaining changes:
  - debian/control:
    + Build-depend on hardening-wrapper
    + Change Maintainer
    + Removed Uploaders field.
    + Removed Debian Vcs-Svn entry and replaced with ubuntu-voip Vcs-Bzr,
      to reflect divergence in packages.
  - debian/rules: Make use of hardening-wrapper
  - debian/asterisk.init: chown /dev/dahdi
  - debian/backports/hardy: add file
  - debian/backports/asterisk.init.hardy: add file
 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Asterisk -- An open source telephony toolkit.
3
 
 *
4
 
 * Copyright (C) 1999 - 2006, Digium, Inc.
5
 
 *
6
 
 * Mark Spencer <markster@digium.com>
7
 
 *
8
 
 * See http://www.asterisk.org for more information about
9
 
 * the Asterisk project. Please do not directly contact
10
 
 * any of the maintainers of this project for assistance;
11
 
 * the project provides a web site, mailing lists and IRC
12
 
 * channels for your use.
13
 
 *
14
 
 * This program is free software, distributed under the terms of
15
 
 * the GNU General Public License Version 2. See the LICENSE file
16
 
 * at the top of the source tree.
17
 
 */
18
 
 
19
 
/*! \file
20
 
 *
21
 
 * \brief DAHDI for Pseudo TDM
22
 
 *
23
 
 * \author Mark Spencer <markster@digium.com>
24
 
 *
25
 
 * Connects to the DAHDI telephony library as well as
26
 
 * libpri. Libpri is optional and needed only if you are
27
 
 * going to use ISDN connections.
28
 
 *
29
 
 * You need to install libraries before you attempt to compile
30
 
 * and install the DAHDI channel.
31
 
 *
32
 
 * \par See also
33
 
 * \arg \ref Config_dahdi
34
 
 *
35
 
 * \ingroup channel_drivers
36
 
 *
37
 
 * \todo Deprecate the "musiconhold" configuration option post 1.4
38
 
 */
39
 
 
40
 
/*** MODULEINFO
41
 
        <depend>res_smdi</depend>
42
 
        <depend>dahdi</depend>
43
 
        <depend>tonezone</depend>
44
 
        <use>pri</use>
45
 
        <use>ss7</use>
46
 
        <use>openr2</use>
47
 
 ***/
48
 
 
49
 
#include "asterisk.h"
50
 
 
51
 
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 253595 $")
52
 
 
53
 
#if defined(__NetBSD__) || defined(__FreeBSD__)
54
 
#include <pthread.h>
55
 
#include <signal.h>
56
 
#else
57
 
#include <sys/signal.h>
58
 
#endif
59
 
#include <sys/ioctl.h>
60
 
#include <math.h>
61
 
#include <ctype.h>
62
 
 
63
 
#include <dahdi/user.h>
64
 
#include <dahdi/tonezone.h>
65
 
 
66
 
#ifdef HAVE_PRI
67
 
#include <libpri.h>
68
 
#endif
69
 
 
70
 
#ifdef HAVE_SS7
71
 
#include <libss7.h>
72
 
#endif
73
 
 
74
 
#ifdef HAVE_OPENR2
75
 
#include <openr2.h>
76
 
#endif
77
 
 
78
 
#include "asterisk/lock.h"
79
 
#include "asterisk/channel.h"
80
 
#include "asterisk/config.h"
81
 
#include "asterisk/module.h"
82
 
#include "asterisk/pbx.h"
83
 
#include "asterisk/file.h"
84
 
#include "asterisk/ulaw.h"
85
 
#include "asterisk/alaw.h"
86
 
#include "asterisk/callerid.h"
87
 
#include "asterisk/adsi.h"
88
 
#include "asterisk/cli.h"
89
 
#include "asterisk/cdr.h"
90
 
#include "asterisk/features.h"
91
 
#include "asterisk/musiconhold.h"
92
 
#include "asterisk/say.h"
93
 
#include "asterisk/tdd.h"
94
 
#include "asterisk/app.h"
95
 
#include "asterisk/dsp.h"
96
 
#include "asterisk/astdb.h"
97
 
#include "asterisk/manager.h"
98
 
#include "asterisk/causes.h"
99
 
#include "asterisk/term.h"
100
 
#include "asterisk/utils.h"
101
 
#include "asterisk/transcap.h"
102
 
#include "asterisk/stringfields.h"
103
 
#include "asterisk/abstract_jb.h"
104
 
#include "asterisk/smdi.h"
105
 
#include "asterisk/astobj.h"
106
 
#include "asterisk/event.h"
107
 
#include "asterisk/devicestate.h"
108
 
#include "asterisk/paths.h"
109
 
 
110
 
/*** DOCUMENTATION
111
 
        <application name="DAHDISendKeypadFacility" language="en_US">
112
 
                <synopsis>
113
 
                        Send digits out of band over a PRI.
114
 
                </synopsis>
115
 
                <syntax>
116
 
                        <parameter name="digits" required="true" />
117
 
                </syntax>
118
 
                <description>
119
 
                        <para>This application will send the given string of digits in a Keypad
120
 
                        Facility IE over the current channel.</para>
121
 
                </description>
122
 
        </application>
123
 
        <application name="DAHDISendCallreroutingFacility" language="en_US">
124
 
                <synopsis>
125
 
                        Send QSIG call rerouting facility over a PRI.
126
 
                </synopsis>
127
 
                <syntax argsep=",">
128
 
                        <parameter name="destination" required="true">
129
 
                                <para>Destination number.</para>
130
 
                        </parameter>
131
 
                        <parameter name="original">
132
 
                                <para>Original called number.</para>
133
 
                        </parameter>
134
 
                        <parameter name="reason">
135
 
                                <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
136
 
                        </parameter>
137
 
                </syntax>
138
 
                <description>
139
 
                        <para>This application will send a Callrerouting Facility IE over the
140
 
                        current channel.</para>
141
 
                </description>
142
 
        </application>
143
 
        <application name="DAHDIAcceptR2Call" language="en_US">
144
 
                <synopsis>
145
 
                        Accept an R2 call if its not already accepted (you still need to answer it)
146
 
                </synopsis>
147
 
                <syntax>
148
 
                        <parameter name="charge" required="true">
149
 
                                <para>Yes or No.</para>
150
 
                                <para>Whether you want to accept the call with charge or without charge.</para>
151
 
                        </parameter>
152
 
                </syntax>
153
 
                <description>
154
 
                        <para>This application will Accept the R2 call either with charge or no charge.</para>
155
 
                </description>
156
 
        </application>
157
 
 ***/
158
 
 
159
 
#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
160
 
 
161
 
static const char *lbostr[] = {
162
 
"0 db (CSU)/0-133 feet (DSX-1)",
163
 
"133-266 feet (DSX-1)",
164
 
"266-399 feet (DSX-1)",
165
 
"399-533 feet (DSX-1)",
166
 
"533-655 feet (DSX-1)",
167
 
"-7.5db (CSU)",
168
 
"-15db (CSU)",
169
 
"-22.5db (CSU)"
170
 
};
171
 
 
172
 
/*! Global jitterbuffer configuration - by default, jb is disabled */
173
 
static struct ast_jb_conf default_jbconf =
174
 
{
175
 
        .flags = 0,
176
 
        .max_size = -1,
177
 
        .resync_threshold = -1,
178
 
        .impl = "",
179
 
        .target_extra = -1,
180
 
};
181
 
static struct ast_jb_conf global_jbconf;
182
 
 
183
 
/* define this to send PRI user-user information elements */
184
 
#undef SUPPORT_USERUSER
185
 
 
186
 
/*!
187
 
 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
188
 
 * the user hangs up to reset the state machine so ring works properly.
189
 
 * This is used to be able to support kewlstart by putting the zhone in
190
 
 * groundstart mode since their forward disconnect supervision is entirely
191
 
 * broken even though their documentation says it isn't and their support
192
 
 * is entirely unwilling to provide any assistance with their channel banks
193
 
 * even though their web site says they support their products for life.
194
 
 */
195
 
/* #define ZHONE_HACK */
196
 
 
197
 
/*! \note
198
 
 * Define if you want to check the hook state for an FXO (FXS signalled) interface
199
 
 * before dialing on it.  Certain FXO interfaces always think they're out of
200
 
 * service with this method however.
201
 
 */
202
 
/* #define DAHDI_CHECK_HOOKSTATE */
203
 
 
204
 
/*! \brief Typically, how many rings before we should send Caller*ID */
205
 
#define DEFAULT_CIDRINGS 1
206
 
 
207
 
#define CHANNEL_PSEUDO -12
208
 
 
209
 
#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
210
 
 
211
 
 
212
 
/*! \brief Signaling types that need to use MF detection should be placed in this macro */
213
 
#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))
214
 
 
215
 
static const char tdesc[] = "DAHDI Telephony Driver"
216
 
#if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
217
 
        " w/"
218
 
#endif
219
 
#ifdef HAVE_PRI
220
 
        "PRI"
221
 
#endif
222
 
#ifdef HAVE_SS7
223
 
        #ifdef HAVE_PRI
224
 
        " & SS7"
225
 
        #else
226
 
        "SS7"
227
 
        #endif
228
 
#endif
229
 
#ifdef HAVE_OPENR2
230
 
        #if defined(HAVE_PRI) || defined(HAVE_SS7)
231
 
        " & MFC/R2"
232
 
        #else
233
 
        "MFC/R2"
234
 
        #endif
235
 
#endif
236
 
;
237
 
 
238
 
static const char config[] = "chan_dahdi.conf";
239
 
 
240
 
#define SIG_EM          DAHDI_SIG_EM
241
 
#define SIG_EMWINK      (0x0100000 | DAHDI_SIG_EM)
242
 
#define SIG_FEATD       (0x0200000 | DAHDI_SIG_EM)
243
 
#define SIG_FEATDMF     (0x0400000 | DAHDI_SIG_EM)
244
 
#define SIG_FEATB       (0x0800000 | DAHDI_SIG_EM)
245
 
#define SIG_E911        (0x1000000 | DAHDI_SIG_EM)
246
 
#define SIG_FEATDMF_TA  (0x2000000 | DAHDI_SIG_EM)
247
 
#define SIG_FGC_CAMA    (0x4000000 | DAHDI_SIG_EM)
248
 
#define SIG_FGC_CAMAMF  (0x8000000 | DAHDI_SIG_EM)
249
 
#define SIG_FXSLS       DAHDI_SIG_FXSLS
250
 
#define SIG_FXSGS       DAHDI_SIG_FXSGS
251
 
#define SIG_FXSKS       DAHDI_SIG_FXSKS
252
 
#define SIG_FXOLS       DAHDI_SIG_FXOLS
253
 
#define SIG_FXOGS       DAHDI_SIG_FXOGS
254
 
#define SIG_FXOKS       DAHDI_SIG_FXOKS
255
 
#define SIG_PRI         DAHDI_SIG_CLEAR
256
 
#define SIG_BRI         (0x2000000 | DAHDI_SIG_CLEAR)
257
 
#define SIG_BRI_PTMP    (0X4000000 | DAHDI_SIG_CLEAR)
258
 
#define SIG_SS7         (0x1000000 | DAHDI_SIG_CLEAR)
259
 
#define SIG_MFCR2       DAHDI_SIG_CAS
260
 
#define SIG_SF          DAHDI_SIG_SF
261
 
#define SIG_SFWINK      (0x0100000 | DAHDI_SIG_SF)
262
 
#define SIG_SF_FEATD    (0x0200000 | DAHDI_SIG_SF)
263
 
#define SIG_SF_FEATDMF  (0x0400000 | DAHDI_SIG_SF)
264
 
#define SIG_SF_FEATB    (0x0800000 | DAHDI_SIG_SF)
265
 
#define SIG_EM_E1       DAHDI_SIG_EM_E1
266
 
#define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
267
 
#define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
268
 
 
269
 
#ifdef LOTS_OF_SPANS
270
 
#define NUM_SPANS       DAHDI_MAX_SPANS
271
 
#else
272
 
#define NUM_SPANS               32
273
 
#endif
274
 
#define NUM_DCHANS              4       /*!< No more than 4 d-channels */
275
 
#define MAX_CHANNELS    672             /*!< No more than a DS3 per trunk group */
276
 
 
277
 
#define CHAN_PSEUDO     -2
278
 
 
279
 
#define DCHAN_PROVISIONED (1 << 0)
280
 
#define DCHAN_NOTINALARM  (1 << 1)
281
 
#define DCHAN_UP          (1 << 2)
282
 
 
283
 
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
284
 
 
285
 
/* Overlap dialing option types */
286
 
#define DAHDI_OVERLAPDIAL_NONE 0
287
 
#define DAHDI_OVERLAPDIAL_OUTGOING 1
288
 
#define DAHDI_OVERLAPDIAL_INCOMING 2
289
 
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
290
 
 
291
 
#define CALLPROGRESS_PROGRESS           1
292
 
#define CALLPROGRESS_FAX_OUTGOING       2
293
 
#define CALLPROGRESS_FAX_INCOMING       4
294
 
#define CALLPROGRESS_FAX                (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
295
 
 
296
 
static char defaultcic[64] = "";
297
 
static char defaultozz[64] = "";
298
 
 
299
 
static char parkinglot[AST_MAX_EXTENSION] = "";         /*!< Default parking lot for this channel */
300
 
 
301
 
/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
302
 
static char mwimonitornotify[PATH_MAX] = "";
303
 
#ifndef HAVE_DAHDI_LINEREVERSE_VMWI
304
 
static int  mwisend_rpas = 0;
305
 
#endif
306
 
 
307
 
static char progzone[10] = "";
308
 
 
309
 
static int usedistinctiveringdetection = 0;
310
 
static int distinctiveringaftercid = 0;
311
 
 
312
 
static int numbufs = 4;
313
 
 
314
 
static int mwilevel = 512;
315
 
 
316
 
#ifdef HAVE_PRI
317
 
static struct ast_channel inuse;
318
 
#ifdef PRI_GETSET_TIMERS
319
 
static int pritimers[PRI_MAX_TIMERS];
320
 
#endif
321
 
static int pridebugfd = -1;
322
 
static char pridebugfilename[1024] = "";
323
 
#endif
324
 
 
325
 
/*! \brief Wait up to 16 seconds for first digit (FXO logic) */
326
 
static int firstdigittimeout = 16000;
327
 
 
328
 
/*! \brief How long to wait for following digits (FXO logic) */
329
 
static int gendigittimeout = 8000;
330
 
 
331
 
/*! \brief How long to wait for an extra digit, if there is an ambiguous match */
332
 
static int matchdigittimeout = 3000;
333
 
 
334
 
/*! \brief Protect the interface list (of dahdi_pvt's) */
335
 
AST_MUTEX_DEFINE_STATIC(iflock);
336
 
 
337
 
/* QSIG channel mapping option types */
338
 
#define DAHDI_CHAN_MAPPING_PHYSICAL     0
339
 
#define DAHDI_CHAN_MAPPING_LOGICAL      1
340
 
 
341
 
 
342
 
static int ifcount = 0;
343
 
 
344
 
#ifdef HAVE_PRI
345
 
AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
346
 
#endif
347
 
 
348
 
/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
349
 
   when it's doing something critical. */
350
 
AST_MUTEX_DEFINE_STATIC(monlock);
351
 
 
352
 
/*! \brief This is the thread for the monitor which checks for input on the channels
353
 
   which are not currently in use. */
354
 
static pthread_t monitor_thread = AST_PTHREADT_NULL;
355
 
static ast_cond_t ss_thread_complete;
356
 
AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
357
 
AST_MUTEX_DEFINE_STATIC(restart_lock);
358
 
static int ss_thread_count = 0;
359
 
static int num_restart_pending = 0;
360
 
 
361
 
static int restart_monitor(void);
362
 
 
363
 
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);
364
 
 
365
 
static int dahdi_sendtext(struct ast_channel *c, const char *text);
366
 
 
367
 
static void mwi_event_cb(const struct ast_event *event, void *userdata)
368
 
{
369
 
        /* This module does not handle MWI in an event-based manner.  However, it
370
 
         * subscribes to MWI for each mailbox that is configured so that the core
371
 
         * knows that we care about it.  Then, chan_dahdi will get the MWI from the
372
 
         * event cache instead of checking the mailbox directly. */
373
 
}
374
 
 
375
 
/*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
376
 
static inline int dahdi_get_event(int fd)
377
 
{
378
 
        int j;
379
 
        if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
380
 
                return -1;
381
 
        return j;
382
 
}
383
 
 
384
 
/*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
385
 
static inline int dahdi_wait_event(int fd)
386
 
{
387
 
        int i, j = 0;
388
 
        i = DAHDI_IOMUX_SIGEVENT;
389
 
        if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
390
 
                return -1;
391
 
        if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
392
 
                return -1;
393
 
        return j;
394
 
}
395
 
 
396
 
/*! Chunk size to read -- we use 20ms chunks to make things happy. */
397
 
#define READ_SIZE 160
398
 
 
399
 
#define MASK_AVAIL              (1 << 0)        /*!< Channel available for PRI use */
400
 
#define MASK_INUSE              (1 << 1)        /*!< Channel currently in use */
401
 
 
402
 
#define CALLWAITING_SILENT_SAMPLES      ( (300 * 8) / READ_SIZE) /*!< 300 ms */
403
 
#define CALLWAITING_REPEAT_SAMPLES      ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
404
 
#define CIDCW_EXPIRE_SAMPLES            ( (500 * 8) / READ_SIZE) /*!< 500 ms */
405
 
#define MIN_MS_SINCE_FLASH                      ( (2000) )      /*!< 2000 ms */
406
 
#define DEFAULT_RINGT                           ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
407
 
 
408
 
struct dahdi_pvt;
409
 
 
410
 
/*!
411
 
 * \brief Configured ring timeout base.
412
 
 * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
413
 
 */
414
 
static int ringt_base = DEFAULT_RINGT;
415
 
 
416
 
#ifdef HAVE_SS7
417
 
 
418
 
#define LINKSTATE_INALARM       (1 << 0)
419
 
#define LINKSTATE_STARTING      (1 << 1)
420
 
#define LINKSTATE_UP            (1 << 2)
421
 
#define LINKSTATE_DOWN          (1 << 3)
422
 
 
423
 
#define SS7_NAI_DYNAMIC         -1
424
 
 
425
 
#define LINKSET_FLAG_EXPLICITACM (1 << 0)
426
 
 
427
 
struct dahdi_ss7 {
428
 
        pthread_t master;                                               /*!< Thread of master */
429
 
        ast_mutex_t lock;
430
 
        int fds[NUM_DCHANS];
431
 
        int numsigchans;
432
 
        int linkstate[NUM_DCHANS];
433
 
        int numchans;
434
 
        int type;
435
 
        enum {
436
 
                LINKSET_STATE_DOWN = 0,
437
 
                LINKSET_STATE_UP
438
 
        } state;
439
 
        char called_nai;                                                /*!< Called Nature of Address Indicator */
440
 
        char calling_nai;                                               /*!< Calling Nature of Address Indicator */
441
 
        char internationalprefix[10];                                   /*!< country access code ('00' for european dialplans) */
442
 
        char nationalprefix[10];                                        /*!< area access code ('0' for european dialplans) */
443
 
        char subscriberprefix[20];                                      /*!< area access code + area code ('0'+area code for european dialplans) */
444
 
        char unknownprefix[20];                                         /*!< for unknown dialplans */
445
 
        struct ss7 *ss7;
446
 
        struct dahdi_pvt *pvts[MAX_CHANNELS];                           /*!< Member channel pvt structs */
447
 
        int flags;                                                      /*!< Linkset flags */
448
 
};
449
 
 
450
 
static struct dahdi_ss7 linksets[NUM_SPANS];
451
 
 
452
 
static int cur_ss7type = -1;
453
 
static int cur_linkset = -1;
454
 
static int cur_pointcode = -1;
455
 
static int cur_cicbeginswith = -1;
456
 
static int cur_adjpointcode = -1;
457
 
static int cur_networkindicator = -1;
458
 
static int cur_defaultdpc = -1;
459
 
#endif /* HAVE_SS7 */
460
 
 
461
 
#ifdef HAVE_OPENR2
462
 
struct dahdi_mfcr2 {
463
 
        pthread_t r2master;                    /*!< Thread of master */
464
 
        openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
465
 
        struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
466
 
        int numchans;                          /*!< Number of channels in this R2 block */
467
 
        int monitored_count;                   /*!< Number of channels being monitored */
468
 
};
469
 
 
470
 
struct dahdi_mfcr2_conf {
471
 
        openr2_variant_t variant;
472
 
        int mfback_timeout;
473
 
        int metering_pulse_timeout;
474
 
        int max_ani;
475
 
        int max_dnis;
476
 
        signed int get_ani_first:2;
477
 
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
478
 
        signed int skip_category_request:2;
479
 
#endif
480
 
        unsigned int call_files:1;
481
 
        unsigned int allow_collect_calls:1;
482
 
        unsigned int charge_calls:1;
483
 
        unsigned int accept_on_offer:1;
484
 
        unsigned int forced_release:1;
485
 
        unsigned int double_answer:1;
486
 
        signed int immediate_accept:2;
487
 
        char logdir[OR2_MAX_PATH];
488
 
        char r2proto_file[OR2_MAX_PATH];
489
 
        openr2_log_level_t loglevel;
490
 
        openr2_calling_party_category_t category;
491
 
};
492
 
 
493
 
/* malloc'd array of malloc'd r2links */
494
 
static struct dahdi_mfcr2 **r2links;
495
 
/* how many r2links have been malloc'd */
496
 
static int r2links_count = 0;
497
 
 
498
 
#endif /* HAVE_OPENR2 */
499
 
 
500
 
#ifdef HAVE_PRI
501
 
 
502
 
#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
503
 
#define PRI_CHANNEL(p) ((p) & 0xff)
504
 
#define PRI_SPAN(p) (((p) >> 8) & 0xff)
505
 
#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
506
 
 
507
 
struct dahdi_pri {
508
 
        pthread_t master;                                               /*!< Thread of master */
509
 
        ast_mutex_t lock;                                               /*!< Mutex */
510
 
        char idleext[AST_MAX_EXTENSION];                                /*!< Where to idle extra calls */
511
 
        char idlecontext[AST_MAX_CONTEXT];                              /*!< What context to use for idle */
512
 
        char idledial[AST_MAX_EXTENSION];                               /*!< What to dial before dumping */
513
 
        int minunused;                                                  /*!< Min # of channels to keep empty */
514
 
        int minidle;                                                    /*!< Min # of "idling" calls to keep active */
515
 
        int nodetype;                                                   /*!< Node type */
516
 
        int switchtype;                                                 /*!< Type of switch to emulate */
517
 
        int nsf;                                                        /*!< Network-Specific Facilities */
518
 
        int dialplan;                                                   /*!< Dialing plan */
519
 
        int localdialplan;                                              /*!< Local dialing plan */
520
 
        char internationalprefix[10];                                   /*!< country access code ('00' for european dialplans) */
521
 
        char nationalprefix[10];                                        /*!< area access code ('0' for european dialplans) */
522
 
        char localprefix[20];                                           /*!< area access code + area code ('0'+area code for european dialplans) */
523
 
        char privateprefix[20];                                         /*!< for private dialplans */
524
 
        char unknownprefix[20];                                         /*!< for unknown dialplans */
525
 
        int dchannels[NUM_DCHANS];                                      /*!< What channel are the dchannels on */
526
 
        int trunkgroup;                                                 /*!< What our trunkgroup is */
527
 
        int mastertrunkgroup;                                           /*!< What trunk group is our master */
528
 
        int prilogicalspan;                                             /*!< Logical span number within trunk group */
529
 
        int numchans;                                                   /*!< Num of channels we represent */
530
 
        int overlapdial;                                                /*!< In overlap dialing mode */
531
 
        int qsigchannelmapping;                                         /*!< QSIG channel mapping type */
532
 
        int discardremoteholdretrieval;                                 /*!< shall remote hold or remote retrieval notifications be discarded? */
533
 
        int facilityenable;                                             /*!< Enable facility IEs */
534
 
        struct pri *dchans[NUM_DCHANS];                                 /*!< Actual d-channels */
535
 
        int dchanavail[NUM_DCHANS];                                     /*!< Whether each channel is available */
536
 
        struct pri *pri;                                                /*!< Currently active D-channel */
537
 
        /*! \brief TRUE if to dump PRI event info (Tested but never set) */
538
 
        int debug;
539
 
        int fds[NUM_DCHANS];                                            /*!< FD's for d-channels */
540
 
        /*! \brief Value set but not used */
541
 
        int offset;
542
 
        /*! \brief Span number put into user output messages */
543
 
        int span;
544
 
        /*! \brief TRUE if span is being reset/restarted */
545
 
        int resetting;
546
 
        /*! \brief Current position during a reset (-1 if not started) */
547
 
        int resetpos;
548
 
#ifdef HAVE_PRI_INBANDDISCONNECT
549
 
        unsigned int inbanddisconnect:1;                                /*!< Should we support inband audio after receiving DISCONNECT? */
550
 
#endif
551
 
        time_t lastreset;                                               /*!< time when unused channels were last reset */
552
 
        long resetinterval;                                             /*!< Interval (in seconds) for resetting unused channels */
553
 
        /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
554
 
        int sig;
555
 
        struct dahdi_pvt *pvts[MAX_CHANNELS];                           /*!< Member channel pvt structs */
556
 
        struct dahdi_pvt *crvs;                                         /*!< Member CRV structs */
557
 
        struct dahdi_pvt *crvend;                                               /*!< Pointer to end of CRV structs */
558
 
};
559
 
 
560
 
 
561
 
static struct dahdi_pri pris[NUM_SPANS];
562
 
 
563
 
#if 0
564
 
#define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
565
 
#else
566
 
#define DEFAULT_PRI_DEBUG 0
567
 
#endif
568
 
 
569
 
static inline void pri_rel(struct dahdi_pri *pri)
570
 
{
571
 
        ast_mutex_unlock(&pri->lock);
572
 
}
573
 
 
574
 
#else
575
 
/*! Shut up the compiler */
576
 
struct dahdi_pri;
577
 
#endif
578
 
 
579
 
#define SUB_REAL        0                       /*!< Active call */
580
 
#define SUB_CALLWAIT    1                       /*!< Call-Waiting call on hold */
581
 
#define SUB_THREEWAY    2                       /*!< Three-way call */
582
 
 
583
 
/* Polarity states */
584
 
#define POLARITY_IDLE   0
585
 
#define POLARITY_REV    1
586
 
 
587
 
 
588
 
struct distRingData {
589
 
        int ring[3];
590
 
        int range;
591
 
};
592
 
struct ringContextData {
593
 
        char contextData[AST_MAX_CONTEXT];
594
 
};
595
 
struct dahdi_distRings {
596
 
        struct distRingData ringnum[3];
597
 
        struct ringContextData ringContext[3];
598
 
};
599
 
 
600
 
static char *subnames[] = {
601
 
        "Real",
602
 
        "Callwait",
603
 
        "Threeway"
604
 
};
605
 
 
606
 
struct dahdi_subchannel {
607
 
        int dfd;
608
 
        struct ast_channel *owner;
609
 
        int chan;
610
 
        short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
611
 
        struct ast_frame f;             /*!< One frame for each channel.  How did this ever work before? */
612
 
        unsigned int needringing:1;
613
 
        unsigned int needbusy:1;
614
 
        unsigned int needcongestion:1;
615
 
        unsigned int needcallerid:1;
616
 
        unsigned int needanswer:1;
617
 
        unsigned int needflash:1;
618
 
        unsigned int needhold:1;
619
 
        unsigned int needunhold:1;
620
 
        unsigned int linear:1;
621
 
        unsigned int inthreeway:1;
622
 
        struct dahdi_confinfo curconf;
623
 
};
624
 
 
625
 
#define CONF_USER_REAL          (1 << 0)
626
 
#define CONF_USER_THIRDCALL     (1 << 1)
627
 
 
628
 
#define MAX_SLAVES      4
629
 
 
630
 
/* States for sending MWI message
631
 
 * First three states are required for send Ring Pulse Alert Signal
632
 
 */
633
 
typedef enum {
634
 
        MWI_SEND_NULL = 0,
635
 
        MWI_SEND_SA,
636
 
        MWI_SEND_SA_WAIT,
637
 
        MWI_SEND_PAUSE,
638
 
        MWI_SEND_SPILL,
639
 
        MWI_SEND_CLEANUP,
640
 
        MWI_SEND_DONE,
641
 
} mwisend_states;
642
 
 
643
 
struct mwisend_info {
644
 
        struct  timeval pause;
645
 
        mwisend_states  mwisend_current;
646
 
};
647
 
 
648
 
static struct dahdi_pvt {
649
 
        ast_mutex_t lock;                                       /*!< Channel private lock. */
650
 
        struct ast_channel *owner;                      /*!< Our current active owner (if applicable) */
651
 
                                                        /*!< Up to three channels can be associated with this call */
652
 
 
653
 
        struct dahdi_subchannel sub_unused;             /*!< Just a safety precaution */
654
 
        struct dahdi_subchannel subs[3];                        /*!< Sub-channels */
655
 
        struct dahdi_confinfo saveconf;                 /*!< Saved conference info */
656
 
 
657
 
        struct dahdi_pvt *slaves[MAX_SLAVES];           /*!< Slave to us (follows our conferencing) */
658
 
        struct dahdi_pvt *master;                               /*!< Master to us (we follow their conferencing) */
659
 
        int inconference;                               /*!< If our real should be in the conference */
660
 
 
661
 
        int bufsize;                /*!< Size of the buffers */
662
 
        int buf_no;                                     /*!< Number of buffers */
663
 
        int buf_policy;                         /*!< Buffer policy */
664
 
        int faxbuf_no;              /*!< Number of Fax buffers */
665
 
        int faxbuf_policy;          /*!< Fax buffer policy */
666
 
        int sig;                                        /*!< Signalling style */
667
 
        /*!
668
 
         * \brief Nonzero if the signaling type is sent over a radio.
669
 
         * \note Set to a couple of nonzero values but it is only tested like a boolean.
670
 
         */
671
 
        int radio;
672
 
        int outsigmod;                                  /*!< Outbound Signalling style (modifier) */
673
 
        int oprmode;                                    /*!< "Operator Services" mode */
674
 
        struct dahdi_pvt *oprpeer;                              /*!< "Operator Services" peer tech_pvt ptr */
675
 
        /*! \brief Amount of gain to increase during caller id */
676
 
        float cid_rxgain;
677
 
        /*! \brief Rx gain set by chan_dahdi.conf */
678
 
        float rxgain;
679
 
        /*! \brief Tx gain set by chan_dahdi.conf */
680
 
        float txgain;
681
 
        int tonezone;                                   /*!< tone zone for this chan, or -1 for default */
682
 
        struct dahdi_pvt *next;                         /*!< Next channel in list */
683
 
        struct dahdi_pvt *prev;                         /*!< Prev channel in list */
684
 
 
685
 
        /* flags */
686
 
 
687
 
        /*!
688
 
         * \brief TRUE if ADSI (Analog Display Services Interface) available
689
 
         * \note Set from the "adsi" value read in from chan_dahdi.conf
690
 
         */
691
 
        unsigned int adsi:1;
692
 
        /*!
693
 
         * \brief TRUE if we can use a polarity reversal to mark when an outgoing
694
 
         * call is answered by the remote party.
695
 
         * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
696
 
         */
697
 
        unsigned int answeronpolarityswitch:1;
698
 
        /*!
699
 
         * \brief TRUE if busy detection is enabled.
700
 
         * (Listens for the beep-beep busy pattern.)
701
 
         * \note Set from the "busydetect" value read in from chan_dahdi.conf
702
 
         */
703
 
        unsigned int busydetect:1;
704
 
        /*!
705
 
         * \brief TRUE if call return is enabled.
706
 
         * (*69, if your dialplan doesn't catch this first)
707
 
         * \note Set from the "callreturn" value read in from chan_dahdi.conf
708
 
         */
709
 
        unsigned int callreturn:1;
710
 
        /*!
711
 
         * \brief TRUE if busy extensions will hear the call-waiting tone
712
 
         * and can use hook-flash to switch between callers.
713
 
         * \note Can be disabled by dialing *70.
714
 
         * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
715
 
         */
716
 
        unsigned int callwaiting:1;
717
 
        /*!
718
 
         * \brief TRUE if send caller ID for Call Waiting
719
 
         * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
720
 
         */
721
 
        unsigned int callwaitingcallerid:1;
722
 
        /*!
723
 
         * \brief TRUE if support for call forwarding enabled.
724
 
         * Dial *72 to enable call forwarding.
725
 
         * Dial *73 to disable call forwarding.
726
 
         * \note Set from the "cancallforward" value read in from chan_dahdi.conf
727
 
         */
728
 
        unsigned int cancallforward:1;
729
 
        /*!
730
 
         * \brief TRUE if support for call parking is enabled.
731
 
         * \note Set from the "canpark" value read in from chan_dahdi.conf
732
 
         */
733
 
        unsigned int canpark:1;
734
 
        /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
735
 
        unsigned int confirmanswer:1;
736
 
        /*!
737
 
         * \brief TRUE if the channel is to be destroyed on hangup.
738
 
         * (Used by pseudo channels.)
739
 
         */
740
 
        unsigned int destroy:1;
741
 
        unsigned int didtdd:1;                          /*!< flag to say its done it once */
742
 
        /*! \brief TRUE if analog type line dialed no digits in Dial() */
743
 
        unsigned int dialednone:1;
744
 
        /*! \brief TRUE if in the process of dialing digits or sending something. */
745
 
        unsigned int dialing:1;
746
 
        /*! \brief TRUE if the transfer capability of the call is digital. */
747
 
        unsigned int digital:1;
748
 
        /*! \brief TRUE if Do-Not-Disturb is enabled. */
749
 
        unsigned int dnd:1;
750
 
        /*! \brief XXX BOOLEAN Purpose??? */
751
 
        unsigned int echobreak:1;
752
 
        /*!
753
 
         * \brief TRUE if echo cancellation enabled when bridged.
754
 
         * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
755
 
         * \note Disabled if the echo canceller is not setup.
756
 
         */
757
 
        unsigned int echocanbridged:1;
758
 
        /*! \brief TRUE if echo cancellation is turned on. */
759
 
        unsigned int echocanon:1;
760
 
        /*! \brief TRUE if a fax tone has already been handled. */
761
 
        unsigned int faxhandled:1;
762
 
        /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
763
 
        unsigned int usefaxbuffers:1;
764
 
        /*! \brief TRUE while dynamic faxbuffers are in use */
765
 
        unsigned int faxbuffersinuse:1;
766
 
        /*! \brief TRUE if over a radio and dahdi_read() has been called. */
767
 
        unsigned int firstradio:1;
768
 
        /*!
769
 
         * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
770
 
         * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
771
 
         */
772
 
        unsigned int hanguponpolarityswitch:1;
773
 
        /*! \brief TRUE if DTMF detection needs to be done by hardware. */
774
 
        unsigned int hardwaredtmf:1;
775
 
        /*!
776
 
         * \brief TRUE if the outgoing caller ID is blocked/hidden.
777
 
         * \note Caller ID can be disabled by dialing *67.
778
 
         * \note Caller ID can be enabled by dialing *82.
779
 
         * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
780
 
         */
781
 
        unsigned int hidecallerid:1;
782
 
        /*!
783
 
         * \brief TRUE if hide just the name not the number for legacy PBX use.
784
 
         * \note Only applies to PRI channels.
785
 
         * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
786
 
         */
787
 
        unsigned int hidecalleridname:1;
788
 
        /*! \brief TRUE if DTMF detection is disabled. */
789
 
        unsigned int ignoredtmf:1;
790
 
        /*!
791
 
         * \brief TRUE if the channel should be answered immediately
792
 
         * without attempting to gather any digits.
793
 
         * \note Set from the "immediate" value read in from chan_dahdi.conf
794
 
         */
795
 
        unsigned int immediate:1;
796
 
        /*! \brief TRUE if in an alarm condition. */
797
 
        unsigned int inalarm:1;
798
 
        /*! \brief TRUE if TDD in MATE mode */
799
 
        unsigned int mate:1;
800
 
        /*! \brief TRUE if we originated the call leg. */
801
 
        unsigned int outgoing:1;
802
 
        /* unsigned int overlapdial:1;                  unused and potentially confusing */
803
 
        /*!
804
 
         * \brief TRUE if busy extensions will hear the call-waiting tone
805
 
         * and can use hook-flash to switch between callers.
806
 
         * \note Set from the "callwaiting" value read in from chan_dahdi.conf
807
 
         */
808
 
        unsigned int permcallwaiting:1;
809
 
        /*!
810
 
         * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
811
 
         * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
812
 
         */
813
 
        unsigned int permhidecallerid:1;
814
 
        /*!
815
 
         * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
816
 
         * \note Set from the "priindication" value read in from chan_dahdi.conf
817
 
         */
818
 
        unsigned int priindication_oob:1;
819
 
        /*!
820
 
         * \brief TRUE if PRI B channels are always exclusively selected.
821
 
         * \note Set from the "priexclusive" value read in from chan_dahdi.conf
822
 
         */
823
 
        unsigned int priexclusive:1;
824
 
        /*!
825
 
         * \brief TRUE if we will pulse dial.
826
 
         * \note Set from the "pulsedial" value read in from chan_dahdi.conf
827
 
         */
828
 
        unsigned int pulse:1;
829
 
        /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
830
 
        unsigned int pulsedial:1;
831
 
        unsigned int restartpending:1;          /*!< flag to ensure counted only once for restart */
832
 
        /*!
833
 
         * \brief TRUE if caller ID is restricted.
834
 
         * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
835
 
         * \note Set from the "restrictcid" value read in from chan_dahdi.conf
836
 
         */
837
 
        unsigned int restrictcid:1;
838
 
        /*!
839
 
         * \brief TRUE if three way calling is enabled
840
 
         * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
841
 
         */
842
 
        unsigned int threewaycalling:1;
843
 
        /*!
844
 
         * \brief TRUE if call transfer is enabled
845
 
         * \note For FXS ports (either direct analog or over T1/E1):
846
 
         *   Support flash-hook call transfer
847
 
         * \note For digital ports using ISDN PRI protocols:
848
 
         *   Support switch-side transfer (called 2BCT, RLT or other names)
849
 
         * \note Set from the "transfer" value read in from chan_dahdi.conf
850
 
         */
851
 
        unsigned int transfer:1;
852
 
        /*!
853
 
         * \brief TRUE if caller ID is used on this channel.
854
 
         * \note PRI and SS7 spans will save caller ID from the networking peer.
855
 
         * \note FXS ports will generate the caller ID spill.
856
 
         * \note FXO ports will listen for the caller ID spill.
857
 
         * \note Set from the "usecallerid" value read in from chan_dahdi.conf
858
 
         */
859
 
        unsigned int use_callerid:1;
860
 
        /*!
861
 
         * \brief TRUE if we will use the calling presentation setting
862
 
         * from the Asterisk channel for outgoing calls.
863
 
         * \note Only applies to PRI and SS7 channels.
864
 
         * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
865
 
         */
866
 
        unsigned int use_callingpres:1;
867
 
        /*!
868
 
         * \brief TRUE if distinctive rings are to be detected.
869
 
         * \note For FXO lines
870
 
         * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
871
 
         */
872
 
        unsigned int usedistinctiveringdetection:1;
873
 
        /*!
874
 
         * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
875
 
         * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
876
 
         */
877
 
        unsigned int dahditrcallerid:1;
878
 
        /*!
879
 
         * \brief TRUE if allowed to flash-transfer to busy channels.
880
 
         * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
881
 
         */
882
 
        unsigned int transfertobusy:1;
883
 
        /*!
884
 
         * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
885
 
         * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
886
 
         */
887
 
        unsigned int mwimonitor_neon:1;
888
 
        /*!
889
 
         * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
890
 
         * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
891
 
         */
892
 
        unsigned int mwimonitor_fsk:1;
893
 
        /*!
894
 
         * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
895
 
         * \note RPAS - Ring Pulse Alert Signal
896
 
         * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
897
 
         */
898
 
        unsigned int mwimonitor_rpas:1;
899
 
        /*! \brief TRUE if an MWI monitor thread is currently active */
900
 
        unsigned int mwimonitoractive:1;
901
 
        /*! \brief TRUE if a MWI message sending thread is active */
902
 
        unsigned int mwisendactive:1;
903
 
        /*!
904
 
         * \brief TRUE if channel is out of reset and ready
905
 
         * \note Set but not used.
906
 
         */
907
 
        unsigned int inservice:1;
908
 
        /*!
909
 
         * \brief TRUE if the channel is locally blocked.
910
 
         * \note Applies to SS7 channels.
911
 
         */
912
 
        unsigned int locallyblocked:1;
913
 
        /*!
914
 
         * \brief TRUE if the channel is remotely blocked.
915
 
         * \note Applies to SS7 channels.
916
 
         */
917
 
        unsigned int remotelyblocked:1;
918
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
919
 
        /*!
920
 
         * \brief XXX BOOLEAN Purpose???
921
 
         * \note Applies to SS7 channels.
922
 
         */
923
 
        unsigned int rlt:1;
924
 
        /*! \brief TRUE if channel is alerting/ringing */
925
 
        unsigned int alerting:1;
926
 
        /*! \brief TRUE if the call has already gone/hungup */
927
 
        unsigned int alreadyhungup:1;
928
 
        /*!
929
 
         * \brief TRUE if this is an idle call
930
 
         * \note Applies to PRI channels.
931
 
         */
932
 
        unsigned int isidlecall:1;
933
 
        /*!
934
 
         * \brief TRUE if call is in a proceeding state.
935
 
         * The call has started working its way through the network.
936
 
         */
937
 
        unsigned int proceeding:1;
938
 
        /*! \brief TRUE if the call has seen progress through the network. */
939
 
        unsigned int progress:1;
940
 
        /*!
941
 
         * \brief TRUE if this channel is being reset/restarted
942
 
         * \note Applies to PRI channels.
943
 
         */
944
 
        unsigned int resetting:1;
945
 
        /*!
946
 
         * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
947
 
         * \note Applies to PRI channels.
948
 
         */
949
 
        unsigned int setup_ack:1;
950
 
#endif
951
 
        /*!
952
 
         * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
953
 
         * \note Set from the "usesmdi" value read in from chan_dahdi.conf
954
 
         */
955
 
        unsigned int use_smdi:1;
956
 
        struct mwisend_info mwisend_data;
957
 
        /*! \brief The serial port to listen for SMDI data on */
958
 
        struct ast_smdi_interface *smdi_iface;
959
 
 
960
 
        /*! \brief Distinctive Ring data */
961
 
        struct dahdi_distRings drings;
962
 
 
963
 
        /*!
964
 
         * \brief The configured context for incoming calls.
965
 
         * \note The "context" string read in from chan_dahdi.conf
966
 
         */
967
 
        char context[AST_MAX_CONTEXT];
968
 
        /*!
969
 
         * \brief Saved context string.
970
 
         */
971
 
        char defcontext[AST_MAX_CONTEXT];
972
 
        /*! \brief Extension to use in the dialplan. */
973
 
        char exten[AST_MAX_EXTENSION];
974
 
        /*!
975
 
         * \brief Language configured for calls.
976
 
         * \note The "language" string read in from chan_dahdi.conf
977
 
         */
978
 
        char language[MAX_LANGUAGE];
979
 
        /*!
980
 
         * \brief The configured music-on-hold class to use for calls.
981
 
         * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
982
 
         */
983
 
        char mohinterpret[MAX_MUSICCLASS];
984
 
        /*!
985
 
         * \brief Suggested music-on-hold class for peer channel to use for calls.
986
 
         * \note The "mohsuggest" string read in from chan_dahdi.conf
987
 
         */
988
 
        char mohsuggest[MAX_MUSICCLASS];
989
 
        char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
990
 
#if defined(PRI_ANI) || defined(HAVE_SS7)
991
 
        /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
992
 
        char cid_ani[AST_MAX_EXTENSION];
993
 
#endif
994
 
        /*! \brief Automatic Number Identification code from PRI */
995
 
        int cid_ani2;
996
 
        /*! \brief Caller ID number from an incoming call. */
997
 
        char cid_num[AST_MAX_EXTENSION];
998
 
        /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
999
 
        int cid_ton;
1000
 
        /*! \brief Caller ID name from an incoming call. */
1001
 
        char cid_name[AST_MAX_EXTENSION];
1002
 
        /*! \brief Last Caller ID number from an incoming call. */
1003
 
        char lastcid_num[AST_MAX_EXTENSION];
1004
 
        /*! \brief Last Caller ID name from an incoming call. */
1005
 
        char lastcid_name[AST_MAX_EXTENSION];
1006
 
        char *origcid_num;                              /*!< malloced original callerid */
1007
 
        char *origcid_name;                             /*!< malloced original callerid */
1008
 
        /*! \brief Call waiting number. */
1009
 
        char callwait_num[AST_MAX_EXTENSION];
1010
 
        /*! \brief Call waiting name. */
1011
 
        char callwait_name[AST_MAX_EXTENSION];
1012
 
        /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
1013
 
        char rdnis[AST_MAX_EXTENSION];
1014
 
        /*! \brief Dialed Number Identifier */
1015
 
        char dnid[AST_MAX_EXTENSION];
1016
 
        /*!
1017
 
         * \brief Bitmapped groups this belongs to.
1018
 
         * \note The "group" bitmapped group string read in from chan_dahdi.conf
1019
 
         */
1020
 
        ast_group_t group;
1021
 
        /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
1022
 
        int law;
1023
 
        int confno;                                     /*!< Our conference */
1024
 
        int confusers;                                  /*!< Who is using our conference */
1025
 
        int propconfno;                                 /*!< Propagated conference number */
1026
 
        /*!
1027
 
         * \brief Bitmapped call groups this belongs to.
1028
 
         * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
1029
 
         */
1030
 
        ast_group_t callgroup;
1031
 
        /*!
1032
 
         * \brief Bitmapped pickup groups this belongs to.
1033
 
         * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
1034
 
         */
1035
 
        ast_group_t pickupgroup;
1036
 
        /*!
1037
 
         * \brief Channel variable list with associated values to set when a channel is created.
1038
 
         * \note The "setvar" strings read in from chan_dahdi.conf
1039
 
         */
1040
 
        struct ast_variable *vars;
1041
 
        int channel;                                    /*!< Channel Number or CRV */
1042
 
        int span;                                       /*!< Span number */
1043
 
        time_t guardtime;                               /*!< Must wait this much time before using for new call */
1044
 
        int cid_signalling;                             /*!< CID signalling type bell202 or v23 */
1045
 
        int cid_start;                                  /*!< CID start indicator, polarity or ring */
1046
 
        int callingpres;                                /*!< The value of calling presentation that we're going to use when placing a PRI call */
1047
 
        int callwaitingrepeat;                          /*!< How many samples to wait before repeating call waiting */
1048
 
        int cidcwexpire;                                /*!< When to expire our muting for CID/CW */
1049
 
        /*! \brief Analog caller ID waveform sample buffer */
1050
 
        unsigned char *cidspill;
1051
 
        /*! \brief Position in the cidspill buffer to send out next. */
1052
 
        int cidpos;
1053
 
        /*! \brief Length of the cidspill buffer containing samples. */
1054
 
        int cidlen;
1055
 
        /*! \brief Ring timeout timer?? */
1056
 
        int ringt;
1057
 
        /*!
1058
 
         * \brief Ring timeout base.
1059
 
         * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
1060
 
         */
1061
 
        int ringt_base;
1062
 
        /*!
1063
 
         * \brief Number of most significant digits/characters to strip from the dialed number.
1064
 
         * \note Feature is deprecated.  Use dialplan logic.
1065
 
         * \note The characters are stripped before the PRI TON/NPI prefix
1066
 
         * characters are processed.
1067
 
         */
1068
 
        int stripmsd;
1069
 
        /*! \brief BOOLEAN. XXX Meaning what?? */
1070
 
        int callwaitcas;
1071
 
        /*! \brief Number of call waiting rings. */
1072
 
        int callwaitrings;
1073
 
        /*! \brief Echo cancel parameters. */
1074
 
        struct {
1075
 
                struct dahdi_echocanparams head;
1076
 
                struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
1077
 
        } echocancel;
1078
 
        /*!
1079
 
         * \brief Echo training time. 0 = disabled
1080
 
         * \note Set from the "echotraining" value read in from chan_dahdi.conf
1081
 
         */
1082
 
        int echotraining;
1083
 
        /*! \brief Filled with 'w'.  XXX Purpose?? */
1084
 
        char echorest[20];
1085
 
        /*!
1086
 
         * \brief Number of times to see "busy" tone before hanging up.
1087
 
         * \note Set from the "busycount" value read in from chan_dahdi.conf
1088
 
         */
1089
 
        int busycount;
1090
 
        /*!
1091
 
         * \brief Length of "busy" tone on time.
1092
 
         * \note Set from the "busypattern" value read in from chan_dahdi.conf
1093
 
         */
1094
 
        int busy_tonelength;
1095
 
        /*!
1096
 
         * \brief Length of "busy" tone off time.
1097
 
         * \note Set from the "busypattern" value read in from chan_dahdi.conf
1098
 
         */
1099
 
        int busy_quietlength;
1100
 
        /*!
1101
 
         * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
1102
 
         * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
1103
 
         */
1104
 
        int callprogress;
1105
 
        /*!
1106
 
         * \brief Number of milliseconds to wait for dialtone.
1107
 
         * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
1108
 
         */
1109
 
        int waitfordialtone;
1110
 
        struct timeval waitingfordt;                    /*!< Time we started waiting for dialtone */
1111
 
        struct timeval flashtime;                       /*!< Last flash-hook time */
1112
 
        /*! \brief Opaque DSP configuration structure. */
1113
 
        struct ast_dsp *dsp;
1114
 
        //int cref;                                     /*!< Call reference number (Not used) */
1115
 
        /*! \brief DAHDI dial operation command struct for ioctl() call. */
1116
 
        struct dahdi_dialoperation dop;
1117
 
        int whichwink;                                  /*!< SIG_FEATDMF_TA Which wink are we on? */
1118
 
        /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
1119
 
        char finaldial[64];
1120
 
        char accountcode[AST_MAX_ACCOUNT_CODE];         /*!< Account code */
1121
 
        int amaflags;                                   /*!< AMA Flags */
1122
 
        struct tdd_state *tdd;                          /*!< TDD flag */
1123
 
        /*! \brief Accumulated call forwarding number. */
1124
 
        char call_forward[AST_MAX_EXTENSION];
1125
 
        /*!
1126
 
         * \brief Voice mailbox location.
1127
 
         * \note Set from the "mailbox" string read in from chan_dahdi.conf
1128
 
         */
1129
 
        char mailbox[AST_MAX_EXTENSION];
1130
 
        /*! \brief Opaque event subscription parameters for message waiting indication support. */
1131
 
        struct ast_event_sub *mwi_event_sub;
1132
 
        /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
1133
 
        char dialdest[256];
1134
 
        /*! \brief Time the interface went on-hook. */
1135
 
        int onhooktime;
1136
 
        /*! \brief TRUE if the FXS port is off-hook */
1137
 
        int fxsoffhookstate;
1138
 
        /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
1139
 
        int msgstate;
1140
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1141
 
        struct dahdi_vmwi_info mwisend_setting;                         /*!< Which VMWI methods to use */
1142
 
        unsigned int mwisend_fsk: 1;            /*! Variable for enabling FSK MWI handling in chan_dahdi */
1143
 
        unsigned int mwisend_rpas:1;            /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
1144
 
#endif
1145
 
        int distinctivering;                            /*!< Which distinctivering to use */
1146
 
        int cidrings;                                   /*!< Which ring to deliver CID on */
1147
 
        int dtmfrelax;                                  /*!< whether to run in relaxed DTMF mode */
1148
 
        /*! \brief Holding place for event injected from outside normal operation. */
1149
 
        int fake_event;
1150
 
        /*!
1151
 
         * \brief Minimal time period (ms) between the answer polarity
1152
 
         * switch and hangup polarity switch.
1153
 
         */
1154
 
        int polarityonanswerdelay;
1155
 
        /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
1156
 
        struct timeval polaritydelaytv;
1157
 
        /*!
1158
 
         * \brief Send caller ID after this many rings.
1159
 
         * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
1160
 
         */
1161
 
        int sendcalleridafter;
1162
 
#ifdef HAVE_PRI
1163
 
        /*! \brief DAHDI PRI control parameters */
1164
 
        struct dahdi_pri *pri;
1165
 
        /*! \brief XXX Purpose??? */
1166
 
        struct dahdi_pvt *bearer;
1167
 
        /*! \brief XXX Purpose??? */
1168
 
        struct dahdi_pvt *realcall;
1169
 
        /*! \brief Opaque libpri call control structure */
1170
 
        q931_call *call;
1171
 
        /*! \brief Channel number in span. */
1172
 
        int prioffset;
1173
 
        /*! \brief Logical span number within trunk group */
1174
 
        int logicalspan;
1175
 
#endif
1176
 
        /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
1177
 
        int polarity;
1178
 
        /*! \brief DSP feature flags: DSP_FEATURE_xxx */
1179
 
        int dsp_features;
1180
 
#ifdef HAVE_SS7
1181
 
        /*! \brief SS7 control parameters */
1182
 
        struct dahdi_ss7 *ss7;
1183
 
        /*! \brief Opaque libss7 call control structure */
1184
 
        struct isup_call *ss7call;
1185
 
        char charge_number[50];
1186
 
        char gen_add_number[50];
1187
 
        char gen_dig_number[50];
1188
 
        char orig_called_num[50];
1189
 
        char redirecting_num[50];
1190
 
        char generic_name[50];
1191
 
        unsigned char gen_add_num_plan;
1192
 
        unsigned char gen_add_nai;
1193
 
        unsigned char gen_add_pres_ind;
1194
 
        unsigned char gen_add_type;
1195
 
        unsigned char gen_dig_type;
1196
 
        unsigned char gen_dig_scheme;
1197
 
        char jip_number[50];
1198
 
        unsigned char lspi_type;
1199
 
        unsigned char lspi_scheme;
1200
 
        unsigned char lspi_context;
1201
 
        char lspi_ident[50];
1202
 
        unsigned int call_ref_ident;
1203
 
        unsigned int call_ref_pc;
1204
 
        unsigned char calling_party_cat;
1205
 
        int transcap;
1206
 
        int cic;                                                        /*!< CIC associated with channel */
1207
 
        unsigned int dpc;                                               /*!< CIC's DPC */
1208
 
        unsigned int loopedback:1;
1209
 
#endif
1210
 
#ifdef HAVE_OPENR2
1211
 
        struct dahdi_mfcr2 *mfcr2;
1212
 
        openr2_chan_t *r2chan;
1213
 
        openr2_calling_party_category_t mfcr2_recvd_category;
1214
 
        openr2_calling_party_category_t mfcr2_category;
1215
 
        int mfcr2_dnis_index;
1216
 
        int mfcr2_ani_index;
1217
 
        int mfcr2call:1;
1218
 
        int mfcr2_answer_pending:1;
1219
 
        int mfcr2_charge_calls:1;
1220
 
        int mfcr2_allow_collect_calls:1;
1221
 
        int mfcr2_forced_release:1;
1222
 
        int mfcr2_dnis_matched:1;
1223
 
        int mfcr2_call_accepted:1;
1224
 
        int mfcr2_accept_on_offer:1;
1225
 
#endif
1226
 
        /*! \brief DTMF digit in progress.  0 when no digit in progress. */
1227
 
        char begindigit;
1228
 
        /*! \brief TRUE if confrence is muted. */
1229
 
        int muting;
1230
 
} *iflist = NULL, *ifend = NULL;
1231
 
 
1232
 
/*! \brief Channel configuration from chan_dahdi.conf .
1233
 
 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
1234
 
 * Generally there is a field here for every possible configuration item.
1235
 
 *
1236
 
 * The state of fields is saved along the parsing and whenever a 'channel'
1237
 
 * statement is reached, the current dahdi_chan_conf is used to configure the
1238
 
 * channel (struct dahdi_pvt)
1239
 
 *
1240
 
 * \see dahdi_chan_init for the default values.
1241
 
 */
1242
 
struct dahdi_chan_conf {
1243
 
        struct dahdi_pvt chan;
1244
 
#ifdef HAVE_PRI
1245
 
        struct dahdi_pri pri;
1246
 
#endif
1247
 
 
1248
 
#ifdef HAVE_SS7
1249
 
        struct dahdi_ss7 ss7;
1250
 
#endif
1251
 
 
1252
 
#ifdef HAVE_OPENR2
1253
 
        struct dahdi_mfcr2_conf mfcr2;
1254
 
#endif
1255
 
        struct dahdi_params timing;
1256
 
        int is_sig_auto; /*!< Use channel signalling from DAHDI? */
1257
 
 
1258
 
        /*!
1259
 
         * \brief The serial port to listen for SMDI data on
1260
 
         * \note Set from the "smdiport" string read in from chan_dahdi.conf
1261
 
         */
1262
 
        char smdi_port[SMDI_MAX_FILENAME_LEN];
1263
 
};
1264
 
 
1265
 
/*! returns a new dahdi_chan_conf with default values (by-value) */
1266
 
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
1267
 
{
1268
 
        /* recall that if a field is not included here it is initialized
1269
 
         * to 0 or equivalent
1270
 
         */
1271
 
        struct dahdi_chan_conf conf = {
1272
 
#ifdef HAVE_PRI
1273
 
                .pri = {
1274
 
                        .nsf = PRI_NSF_NONE,
1275
 
                        .switchtype = PRI_SWITCH_NI2,
1276
 
                        .dialplan = PRI_UNKNOWN + 1,
1277
 
                        .localdialplan = PRI_NATIONAL_ISDN + 1,
1278
 
                        .nodetype = PRI_CPE,
1279
 
                        .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1280
 
 
1281
 
                        .minunused = 2,
1282
 
                        .idleext = "",
1283
 
                        .idledial = "",
1284
 
                        .internationalprefix = "",
1285
 
                        .nationalprefix = "",
1286
 
                        .localprefix = "",
1287
 
                        .privateprefix = "",
1288
 
                        .unknownprefix = "",
1289
 
                        .resetinterval = -1,
1290
 
                },
1291
 
#endif
1292
 
#ifdef HAVE_SS7
1293
 
                .ss7 = {
1294
 
                        .called_nai = SS7_NAI_NATIONAL,
1295
 
                        .calling_nai = SS7_NAI_NATIONAL,
1296
 
                        .internationalprefix = "",
1297
 
                        .nationalprefix = "",
1298
 
                        .subscriberprefix = "",
1299
 
                        .unknownprefix = ""
1300
 
                },
1301
 
#endif
1302
 
#ifdef HAVE_OPENR2
1303
 
                .mfcr2 = {
1304
 
                        .variant = OR2_VAR_ITU,
1305
 
                        .mfback_timeout = -1,
1306
 
                        .metering_pulse_timeout = -1,
1307
 
                        .max_ani = 10,
1308
 
                        .max_dnis = 4,
1309
 
                        .get_ani_first = -1,
1310
 
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1311
 
                        .skip_category_request = -1,
1312
 
#endif
1313
 
                        .call_files = 0,
1314
 
                        .allow_collect_calls = 0,
1315
 
                        .charge_calls = 1,
1316
 
                        .accept_on_offer = 1,
1317
 
                        .forced_release = 0,
1318
 
                        .double_answer = 0,
1319
 
                        .immediate_accept = -1,
1320
 
                        .logdir = "",
1321
 
                        .r2proto_file = "",
1322
 
                        .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1323
 
                        .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1324
 
                },
1325
 
#endif
1326
 
                .chan = {
1327
 
                        .context = "default",
1328
 
                        .cid_num = "",
1329
 
                        .cid_name = "",
1330
 
                        .mohinterpret = "default",
1331
 
                        .mohsuggest = "",
1332
 
                        .parkinglot = "",
1333
 
                        .transfertobusy = 1,
1334
 
 
1335
 
                        .cid_signalling = CID_SIG_BELL,
1336
 
                        .cid_start = CID_START_RING,
1337
 
                        .dahditrcallerid = 0,
1338
 
                        .use_callerid = 1,
1339
 
                        .sig = -1,
1340
 
                        .outsigmod = -1,
1341
 
 
1342
 
                        .cid_rxgain = +5.0,
1343
 
 
1344
 
                        .tonezone = -1,
1345
 
 
1346
 
                        .echocancel.head.tap_length = 1,
1347
 
 
1348
 
                        .busycount = 3,
1349
 
 
1350
 
                        .accountcode = "",
1351
 
 
1352
 
                        .mailbox = "",
1353
 
 
1354
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1355
 
                        .mwisend_fsk = 1,
1356
 
#endif
1357
 
                        .polarityonanswerdelay = 600,
1358
 
 
1359
 
                        .sendcalleridafter = DEFAULT_CIDRINGS,
1360
 
 
1361
 
                        .buf_policy = DAHDI_POLICY_IMMEDIATE,
1362
 
                        .buf_no = numbufs,
1363
 
                        .usefaxbuffers = 0,
1364
 
                        .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
1365
 
                        .faxbuf_no = numbufs,
1366
 
                },
1367
 
                .timing = {
1368
 
                        .prewinktime = -1,
1369
 
                        .preflashtime = -1,
1370
 
                        .winktime = -1,
1371
 
                        .flashtime = -1,
1372
 
                        .starttime = -1,
1373
 
                        .rxwinktime = -1,
1374
 
                        .rxflashtime = -1,
1375
 
                        .debouncetime = -1
1376
 
                },
1377
 
                .is_sig_auto = 1,
1378
 
                .smdi_port = "/dev/ttyS0",
1379
 
        };
1380
 
 
1381
 
        return conf;
1382
 
}
1383
 
 
1384
 
 
1385
 
static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
1386
 
static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1387
 
static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1388
 
static int dahdi_sendtext(struct ast_channel *c, const char *text);
1389
 
static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
1390
 
static int dahdi_hangup(struct ast_channel *ast);
1391
 
static int dahdi_answer(struct ast_channel *ast);
1392
 
static struct ast_frame *dahdi_read(struct ast_channel *ast);
1393
 
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1394
 
static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1395
 
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1396
 
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1397
 
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1398
 
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1399
 
static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
1400
 
 
1401
 
static const struct ast_channel_tech dahdi_tech = {
1402
 
        .type = "DAHDI",
1403
 
        .description = tdesc,
1404
 
        .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
1405
 
        .requester = dahdi_request,
1406
 
        .send_digit_begin = dahdi_digit_begin,
1407
 
        .send_digit_end = dahdi_digit_end,
1408
 
        .send_text = dahdi_sendtext,
1409
 
        .call = dahdi_call,
1410
 
        .hangup = dahdi_hangup,
1411
 
        .answer = dahdi_answer,
1412
 
        .read = dahdi_read,
1413
 
        .write = dahdi_write,
1414
 
        .bridge = dahdi_bridge,
1415
 
        .exception = dahdi_exception,
1416
 
        .indicate = dahdi_indicate,
1417
 
        .fixup = dahdi_fixup,
1418
 
        .setoption = dahdi_setoption,
1419
 
        .func_channel_read = dahdi_func_read,
1420
 
};
1421
 
 
1422
 
#ifdef HAVE_PRI
1423
 
#define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
1424
 
#else
1425
 
#define GET_CHANNEL(p) ((p)->channel)
1426
 
#endif
1427
 
 
1428
 
struct dahdi_pvt *round_robin[32];
1429
 
 
1430
 
#if defined(HAVE_PRI)
1431
 
static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
1432
 
{
1433
 
        int res;
1434
 
        /* Grab the lock first */
1435
 
        do {
1436
 
                res = ast_mutex_trylock(&pri->lock);
1437
 
                if (res) {
1438
 
                        DEADLOCK_AVOIDANCE(&pvt->lock);
1439
 
                }
1440
 
        } while (res);
1441
 
        /* Then break the poll */
1442
 
        if (pri->master != AST_PTHREADT_NULL)
1443
 
                pthread_kill(pri->master, SIGURG);
1444
 
        return 0;
1445
 
}
1446
 
#endif  /* defined(HAVE_PRI) */
1447
 
 
1448
 
#if defined(HAVE_SS7)
1449
 
static inline void ss7_rel(struct dahdi_ss7 *ss7)
1450
 
{
1451
 
        ast_mutex_unlock(&ss7->lock);
1452
 
}
1453
 
#endif  /* defined(HAVE_SS7) */
1454
 
 
1455
 
#if defined(HAVE_SS7)
1456
 
static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
1457
 
{
1458
 
        int res;
1459
 
        /* Grab the lock first */
1460
 
        do {
1461
 
                res = ast_mutex_trylock(&pri->lock);
1462
 
                if (res) {
1463
 
                        DEADLOCK_AVOIDANCE(&pvt->lock);
1464
 
                }
1465
 
        } while (res);
1466
 
        /* Then break the poll */
1467
 
        if (pri->master != AST_PTHREADT_NULL)
1468
 
                pthread_kill(pri->master, SIGURG);
1469
 
        return 0;
1470
 
}
1471
 
#endif  /* defined(HAVE_SS7) */
1472
 
#define NUM_CADENCE_MAX 25
1473
 
static int num_cadence = 4;
1474
 
static int user_has_defined_cadences = 0;
1475
 
 
1476
 
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
1477
 
        { { 125, 125, 2000, 4000 } },                   /*!< Quick chirp followed by normal ring */
1478
 
        { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
1479
 
        { { 125, 125, 125, 125, 125, 4000 } },  /*!< Three short bursts */
1480
 
        { { 1000, 500, 2500, 5000 } },  /*!< Long ring */
1481
 
};
1482
 
 
1483
 
/*! \brief cidrings says in which pause to transmit the cid information, where the first pause
1484
 
 * is 1, the second pause is 2 and so on.
1485
 
 */
1486
 
 
1487
 
static int cidrings[NUM_CADENCE_MAX] = {
1488
 
        2,                                                                              /*!< Right after first long ring */
1489
 
        4,                                                                              /*!< Right after long part */
1490
 
        3,                                                                              /*!< After third chirp */
1491
 
        2,                                                                              /*!< Second spell */
1492
 
};
1493
 
 
1494
 
/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
1495
 
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
1496
 
 
1497
 
#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
1498
 
                        (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
1499
 
 
1500
 
#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
1501
 
#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
1502
 
 
1503
 
static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
1504
 
{
1505
 
        int res;
1506
 
        if (p->subs[SUB_REAL].owner == ast)
1507
 
                res = 0;
1508
 
        else if (p->subs[SUB_CALLWAIT].owner == ast)
1509
 
                res = 1;
1510
 
        else if (p->subs[SUB_THREEWAY].owner == ast)
1511
 
                res = 2;
1512
 
        else {
1513
 
                res = -1;
1514
 
                if (!nullok)
1515
 
                        ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
1516
 
        }
1517
 
        return res;
1518
 
}
1519
 
 
1520
 
static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
1521
 
{
1522
 
#ifdef HAVE_PRI
1523
 
        if (pri)
1524
 
                ast_mutex_unlock(&pri->lock);
1525
 
#endif
1526
 
        for (;;) {
1527
 
                if (p->subs[a].owner) {
1528
 
                        if (ast_channel_trylock(p->subs[a].owner)) {
1529
 
                                DEADLOCK_AVOIDANCE(&p->lock);
1530
 
                        } else {
1531
 
                                ast_queue_frame(p->subs[a].owner, &ast_null_frame);
1532
 
                                ast_channel_unlock(p->subs[a].owner);
1533
 
                                break;
1534
 
                        }
1535
 
                } else
1536
 
                        break;
1537
 
        }
1538
 
#ifdef HAVE_PRI
1539
 
        if (pri)
1540
 
                ast_mutex_lock(&pri->lock);
1541
 
#endif
1542
 
}
1543
 
 
1544
 
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
1545
 
{
1546
 
#ifdef HAVE_PRI
1547
 
        struct dahdi_pri *pri = (struct dahdi_pri*) data;
1548
 
#endif
1549
 
#ifdef HAVE_SS7
1550
 
        struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
1551
 
#endif
1552
 
        /* We must unlock the PRI to avoid the possibility of a deadlock */
1553
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
1554
 
        if (data) {
1555
 
                switch (p->sig) {
1556
 
#ifdef HAVE_PRI
1557
 
                case SIG_BRI:
1558
 
                case SIG_BRI_PTMP:
1559
 
                case SIG_PRI:
1560
 
                        ast_mutex_unlock(&pri->lock);
1561
 
                        break;
1562
 
#endif
1563
 
#ifdef HAVE_SS7
1564
 
                case SIG_SS7:
1565
 
                        ast_mutex_unlock(&ss7->lock);
1566
 
                        break;
1567
 
#endif
1568
 
                default:
1569
 
                        break;
1570
 
                }
1571
 
        }
1572
 
#endif
1573
 
        for (;;) {
1574
 
                if (p->owner) {
1575
 
                        if (ast_channel_trylock(p->owner)) {
1576
 
                                DEADLOCK_AVOIDANCE(&p->lock);
1577
 
                        } else {
1578
 
                                ast_queue_frame(p->owner, f);
1579
 
                                ast_channel_unlock(p->owner);
1580
 
                                break;
1581
 
                        }
1582
 
                } else
1583
 
                        break;
1584
 
        }
1585
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
1586
 
        if (data) {
1587
 
                switch (p->sig) {
1588
 
#ifdef HAVE_PRI
1589
 
                case SIG_BRI:
1590
 
                case SIG_BRI_PTMP:
1591
 
                case SIG_PRI:
1592
 
                        ast_mutex_lock(&pri->lock);
1593
 
                        break;
1594
 
#endif
1595
 
#ifdef HAVE_SS7
1596
 
                case SIG_SS7:
1597
 
                        ast_mutex_lock(&ss7->lock);
1598
 
                        break;
1599
 
#endif
1600
 
                default:
1601
 
                        break;
1602
 
                }
1603
 
        }
1604
 
#endif
1605
 
}
1606
 
 
1607
 
static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
1608
 
#ifdef HAVE_OPENR2
1609
 
 
1610
 
static int dahdi_r2_answer(struct dahdi_pvt *p)
1611
 
{
1612
 
        int res = 0;
1613
 
        /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
1614
 
        * and does not has support for openr2_chan_answer_call_with_mode
1615
 
        *  */
1616
 
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1617
 
        const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
1618
 
        int wants_double_answer = ast_true(double_answer) ? 1 : 0;
1619
 
        if (!double_answer) {
1620
 
                /* this still can result in double answer if the channel context
1621
 
                * was configured that way */
1622
 
                res = openr2_chan_answer_call(p->r2chan);
1623
 
        } else if (wants_double_answer) {
1624
 
                res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
1625
 
        } else {
1626
 
                res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
1627
 
        }
1628
 
#else
1629
 
        res = openr2_chan_answer_call(p->r2chan);
1630
 
#endif
1631
 
        return res;
1632
 
}
1633
 
 
1634
 
 
1635
 
 
1636
 
/* should be called with the ast_channel locked */
1637
 
static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
1638
 
{
1639
 
        openr2_calling_party_category_t cat;
1640
 
        const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
1641
 
        struct dahdi_pvt *p = c->tech_pvt;
1642
 
        if (ast_strlen_zero(catstr)) {
1643
 
                ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
1644
 
                                c->name, openr2_proto_get_category_string(p->mfcr2_category));
1645
 
                return p->mfcr2_category;
1646
 
        }
1647
 
        if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
1648
 
                ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
1649
 
                                catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
1650
 
                return p->mfcr2_category;
1651
 
        }
1652
 
        ast_debug(1, "Using category %s\n", catstr);
1653
 
        return cat;
1654
 
}
1655
 
 
1656
 
static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
1657
 
{
1658
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1659
 
        ast_mutex_lock(&p->lock);
1660
 
        if (p->mfcr2call) {
1661
 
                ast_mutex_unlock(&p->lock);
1662
 
                /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
1663
 
                   interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
1664
 
                   can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
1665
 
                   the other end will see our seize as a forced release and drop the call, we will see an invalid
1666
 
                   pattern that will be seen and treated as protocol error. */
1667
 
                ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
1668
 
                return;
1669
 
        }
1670
 
        p->mfcr2call = 1;
1671
 
        /* better safe than sorry ... */
1672
 
        p->cid_name[0] = '\0';
1673
 
        p->cid_num[0] = '\0';
1674
 
        p->rdnis[0] = '\0';
1675
 
        p->exten[0] = '\0';
1676
 
        p->mfcr2_ani_index = '\0';
1677
 
        p->mfcr2_dnis_index = '\0';
1678
 
        p->mfcr2_dnis_matched = 0;
1679
 
        p->mfcr2_answer_pending = 0;
1680
 
        p->mfcr2_call_accepted = 0;
1681
 
        ast_mutex_unlock(&p->lock);
1682
 
        ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
1683
 
}
1684
 
 
1685
 
static int get_alarms(struct dahdi_pvt *p);
1686
 
static void handle_alarms(struct dahdi_pvt *p, int alms);
1687
 
static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
1688
 
{
1689
 
        int res;
1690
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1691
 
        ast_mutex_lock(&p->lock);
1692
 
        p->inalarm = alarm ? 1 : 0;
1693
 
        if (p->inalarm) {
1694
 
                res = get_alarms(p);
1695
 
                handle_alarms(p, res);
1696
 
        } else {
1697
 
                ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
1698
 
                manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
1699
 
        }
1700
 
        ast_mutex_unlock(&p->lock);
1701
 
}
1702
 
 
1703
 
static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
1704
 
{
1705
 
        ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
1706
 
}
1707
 
 
1708
 
static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
1709
 
{
1710
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1711
 
        ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
1712
 
        if (p->owner) {
1713
 
                p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
1714
 
                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
1715
 
        }
1716
 
        ast_mutex_lock(&p->lock);
1717
 
        p->mfcr2call = 0;
1718
 
        ast_mutex_unlock(&p->lock);
1719
 
}
1720
 
 
1721
 
static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
1722
 
{
1723
 
        if (openr2_chan_disconnect_call(p->r2chan, cause)) {
1724
 
                ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
1725
 
                   p->channel, openr2_proto_get_disconnect_string(cause));
1726
 
                /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
1727
 
                openr2_chan_set_idle(p->r2chan);
1728
 
                ast_mutex_lock(&p->lock);
1729
 
                p->mfcr2call = 0;
1730
 
                ast_mutex_unlock(&p->lock);
1731
 
        }
1732
 
}
1733
 
 
1734
 
static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
1735
 
{
1736
 
        struct dahdi_pvt *p;
1737
 
        struct ast_channel *c;
1738
 
        ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
1739
 
                        openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
1740
 
                        openr2_proto_get_category_string(category));
1741
 
        p = openr2_chan_get_client_data(r2chan);
1742
 
        /* if collect calls are not allowed and this is a collect call, reject it! */
1743
 
        if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
1744
 
                ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
1745
 
                dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
1746
 
                return;
1747
 
        }
1748
 
        ast_mutex_lock(&p->lock);
1749
 
        p->mfcr2_recvd_category = category;
1750
 
        /* if we're not supposed to use CID, clear whatever we have */
1751
 
        if (!p->use_callerid) {
1752
 
                ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
1753
 
                p->cid_num[0] = 0;
1754
 
                p->cid_name[0] = 0;
1755
 
        }
1756
 
        /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
1757
 
        if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
1758
 
                ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
1759
 
                p->exten[0] = 's';
1760
 
                p->exten[1] = 0;
1761
 
        }
1762
 
        ast_mutex_unlock(&p->lock);
1763
 
        if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
1764
 
                ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
1765
 
                                p->channel, p->exten, p->context);
1766
 
                dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
1767
 
                return;
1768
 
        }
1769
 
        if (!p->mfcr2_accept_on_offer) {
1770
 
                /* The user wants us to start the PBX thread right away without accepting the call first */
1771
 
                c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
1772
 
                if (c) {
1773
 
                        /* Done here, don't disable reading now since we still need to generate MF tones to accept
1774
 
                           the call or reject it and detect the tone off condition of the other end, all of this
1775
 
                           will be done in the PBX thread now */
1776
 
                        return;
1777
 
                }
1778
 
                ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
1779
 
                dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
1780
 
        } else if (p->mfcr2_charge_calls) {
1781
 
                ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
1782
 
                openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
1783
 
        } else {
1784
 
                ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
1785
 
                openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
1786
 
        }
1787
 
}
1788
 
 
1789
 
static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
1790
 
{
1791
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1792
 
        ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
1793
 
        ast_mutex_lock(&p->lock);
1794
 
        p->mfcr2call = 0;
1795
 
        ast_mutex_unlock(&p->lock);
1796
 
}
1797
 
 
1798
 
static void dahdi_enable_ec(struct dahdi_pvt *p);
1799
 
static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
1800
 
{
1801
 
        struct dahdi_pvt *p = NULL;
1802
 
        struct ast_channel *c = NULL;
1803
 
        p = openr2_chan_get_client_data(r2chan);
1804
 
        dahdi_enable_ec(p);
1805
 
        p->mfcr2_call_accepted = 1;
1806
 
        /* if it's an incoming call ... */
1807
 
        if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
1808
 
                ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
1809
 
                /* If accept on offer is not set, it means at this point the PBX thread is already
1810
 
                   launched (was launched in the 'on call offered' handler) and therefore this callback
1811
 
                   is being executed already in the PBX thread rather than the monitor thread, don't launch
1812
 
                   any other thread, just disable the openr2 reading and answer the call if needed */
1813
 
                if (!p->mfcr2_accept_on_offer) {
1814
 
                        openr2_chan_disable_read(r2chan);
1815
 
                        if (p->mfcr2_answer_pending) {
1816
 
                                ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
1817
 
                                dahdi_r2_answer(p);
1818
 
                        }
1819
 
                        return;
1820
 
                }
1821
 
                c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
1822
 
                if (c) {
1823
 
                        /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
1824
 
                           library to forget about it */
1825
 
                        openr2_chan_disable_read(r2chan);
1826
 
                        return;
1827
 
                }
1828
 
                ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
1829
 
                /* failed to create the channel, bail out and report it as an out of order line */
1830
 
                dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
1831
 
                return;
1832
 
        }
1833
 
        /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
1834
 
        ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
1835
 
        p->subs[SUB_REAL].needringing = 1;
1836
 
        p->dialing = 0;
1837
 
        /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
1838
 
        openr2_chan_disable_read(r2chan);
1839
 
}
1840
 
 
1841
 
static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
1842
 
{
1843
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1844
 
        ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
1845
 
        p->subs[SUB_REAL].needanswer = 1;
1846
 
}
1847
 
 
1848
 
static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
1849
 
{
1850
 
        /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
1851
 
}
1852
 
 
1853
 
static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
1854
 
{
1855
 
        switch (cause) {
1856
 
        case OR2_CAUSE_BUSY_NUMBER:
1857
 
                return AST_CAUSE_BUSY;
1858
 
        case OR2_CAUSE_NETWORK_CONGESTION:
1859
 
                return AST_CAUSE_CONGESTION;
1860
 
        case OR2_CAUSE_OUT_OF_ORDER:
1861
 
                return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
1862
 
        case OR2_CAUSE_UNALLOCATED_NUMBER:
1863
 
                return AST_CAUSE_UNREGISTERED;
1864
 
        case OR2_CAUSE_NO_ANSWER:
1865
 
                return AST_CAUSE_NO_ANSWER;
1866
 
        case OR2_CAUSE_NORMAL_CLEARING:
1867
 
                return AST_CAUSE_NORMAL_CLEARING;
1868
 
        case OR2_CAUSE_UNSPECIFIED:
1869
 
        default:
1870
 
                return AST_CAUSE_NOTDEFINED;
1871
 
        }
1872
 
}
1873
 
 
1874
 
static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
1875
 
{
1876
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1877
 
        ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
1878
 
        ast_mutex_lock(&p->lock);
1879
 
        if (!p->owner) {
1880
 
                ast_mutex_unlock(&p->lock);
1881
 
                /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
1882
 
                dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
1883
 
                return;
1884
 
        }
1885
 
        /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
1886
 
           be done in dahdi_hangup */
1887
 
        if (p->owner->_state == AST_STATE_UP) {
1888
 
                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
1889
 
                ast_mutex_unlock(&p->lock);
1890
 
        } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
1891
 
                /* being the forward side we must report what happened to the call to whoever requested it */
1892
 
                switch (cause) {
1893
 
                case OR2_CAUSE_BUSY_NUMBER:
1894
 
                        p->subs[SUB_REAL].needbusy = 1;
1895
 
                        break;
1896
 
                case OR2_CAUSE_NETWORK_CONGESTION:
1897
 
                case OR2_CAUSE_OUT_OF_ORDER:
1898
 
                case OR2_CAUSE_UNALLOCATED_NUMBER:
1899
 
                case OR2_CAUSE_NO_ANSWER:
1900
 
                case OR2_CAUSE_UNSPECIFIED:
1901
 
                case OR2_CAUSE_NORMAL_CLEARING:
1902
 
                        p->subs[SUB_REAL].needcongestion = 1;
1903
 
                        break;
1904
 
                default:
1905
 
                        p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
1906
 
                }
1907
 
                ast_mutex_unlock(&p->lock);
1908
 
        } else {
1909
 
                ast_mutex_unlock(&p->lock);
1910
 
                /* being the backward side and not UP yet, we only need to request hangup */
1911
 
                /* TODO: what about doing this same thing when were AST_STATE_UP? */
1912
 
                ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
1913
 
        }
1914
 
}
1915
 
 
1916
 
static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
1917
 
{
1918
 
        switch (level) {
1919
 
        case OR2_LOG_NOTICE:
1920
 
                ast_verbose("%s", logmessage);
1921
 
                break;
1922
 
        case OR2_LOG_WARNING:
1923
 
                ast_log(LOG_WARNING, "%s", logmessage);
1924
 
                break;
1925
 
        case OR2_LOG_ERROR:
1926
 
                ast_log(LOG_ERROR, "%s", logmessage);
1927
 
                break;
1928
 
        case OR2_LOG_STACK_TRACE:
1929
 
        case OR2_LOG_MF_TRACE:
1930
 
        case OR2_LOG_CAS_TRACE:
1931
 
        case OR2_LOG_DEBUG:
1932
 
        case OR2_LOG_EX_DEBUG:
1933
 
                ast_log(LOG_DEBUG, "%s", logmessage);
1934
 
                break;
1935
 
        default:
1936
 
                ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
1937
 
                ast_log(LOG_DEBUG, "%s", logmessage);
1938
 
                break;
1939
 
        }
1940
 
}
1941
 
 
1942
 
static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
1943
 
{
1944
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1945
 
        ast_mutex_lock(&p->lock);
1946
 
        p->remotelyblocked = 1;
1947
 
        ast_mutex_unlock(&p->lock);
1948
 
        ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
1949
 
}
1950
 
 
1951
 
static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
1952
 
{
1953
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1954
 
        ast_mutex_lock(&p->lock);
1955
 
        p->remotelyblocked = 0;
1956
 
        ast_mutex_unlock(&p->lock);
1957
 
        ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
1958
 
}
1959
 
 
1960
 
static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
1961
 
        __attribute__((format (printf, 3, 0)));
1962
 
static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
1963
 
{
1964
 
#define CONTEXT_TAG "Context - "
1965
 
        char logmsg[256];
1966
 
        char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
1967
 
        vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
1968
 
        snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
1969
 
        dahdi_r2_write_log(level, completemsg);
1970
 
#undef CONTEXT_TAG
1971
 
}
1972
 
 
1973
 
static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
1974
 
        __attribute__((format (printf, 3, 0)));
1975
 
static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
1976
 
{
1977
 
#define CHAN_TAG "Chan "
1978
 
        char logmsg[256];
1979
 
        char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
1980
 
        vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
1981
 
        snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
1982
 
        dahdi_r2_write_log(level, completemsg);
1983
 
}
1984
 
 
1985
 
static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
1986
 
{
1987
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
1988
 
        /* if 'immediate' is set, let's stop requesting DNIS */
1989
 
        if (p->immediate) {
1990
 
                return 0;
1991
 
        }
1992
 
        p->exten[p->mfcr2_dnis_index] = digit;
1993
 
        p->rdnis[p->mfcr2_dnis_index] = digit;
1994
 
        p->mfcr2_dnis_index++;
1995
 
        p->exten[p->mfcr2_dnis_index] = 0;
1996
 
        p->rdnis[p->mfcr2_dnis_index] = 0;
1997
 
        /* if the DNIS is a match and cannot match more, stop requesting DNIS */
1998
 
        if ((p->mfcr2_dnis_matched ||
1999
 
            (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
2000
 
            !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
2001
 
                return 0;
2002
 
        }
2003
 
        /* otherwise keep going */
2004
 
        return 1;
2005
 
}
2006
 
 
2007
 
static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
2008
 
{
2009
 
        struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
2010
 
        p->cid_num[p->mfcr2_ani_index] = digit;
2011
 
        p->cid_name[p->mfcr2_ani_index] = digit;
2012
 
        p->mfcr2_ani_index++;
2013
 
        p->cid_num[p->mfcr2_ani_index] = 0;
2014
 
        p->cid_name[p->mfcr2_ani_index] = 0;
2015
 
}
2016
 
 
2017
 
static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
2018
 
{
2019
 
        ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
2020
 
}
2021
 
 
2022
 
static openr2_event_interface_t dahdi_r2_event_iface = {
2023
 
        .on_call_init = dahdi_r2_on_call_init,
2024
 
        .on_call_offered = dahdi_r2_on_call_offered,
2025
 
        .on_call_accepted = dahdi_r2_on_call_accepted,
2026
 
        .on_call_answered = dahdi_r2_on_call_answered,
2027
 
        .on_call_disconnect = dahdi_r2_on_call_disconnect,
2028
 
        .on_call_end = dahdi_r2_on_call_end,
2029
 
        .on_call_read = dahdi_r2_on_call_read,
2030
 
        .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
2031
 
        .on_os_error = dahdi_r2_on_os_error,
2032
 
        .on_protocol_error = dahdi_r2_on_protocol_error,
2033
 
        .on_line_blocked = dahdi_r2_on_line_blocked,
2034
 
        .on_line_idle = dahdi_r2_on_line_idle,
2035
 
        /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
2036
 
        .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
2037
 
        .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
2038
 
        .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
2039
 
        /* so far we do nothing with billing pulses */
2040
 
        .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
2041
 
};
2042
 
 
2043
 
static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
2044
 
{
2045
 
        return AST_ALAW(sample);
2046
 
}
2047
 
 
2048
 
static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
2049
 
{
2050
 
        return AST_LIN2A(sample);
2051
 
}
2052
 
 
2053
 
static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
2054
 
        dahdi_r2_alaw_to_linear,
2055
 
        dahdi_r2_linear_to_alaw
2056
 
};
2057
 
 
2058
 
#endif /* HAVE_OPENR2 */
2059
 
 
2060
 
static int restore_gains(struct dahdi_pvt *p);
2061
 
 
2062
 
static void swap_subs(struct dahdi_pvt *p, int a, int b)
2063
 
{
2064
 
        int tchan;
2065
 
        int tinthreeway;
2066
 
        struct ast_channel *towner;
2067
 
 
2068
 
        ast_debug(1, "Swapping %d and %d\n", a, b);
2069
 
 
2070
 
        tchan = p->subs[a].chan;
2071
 
        towner = p->subs[a].owner;
2072
 
        tinthreeway = p->subs[a].inthreeway;
2073
 
 
2074
 
        p->subs[a].chan = p->subs[b].chan;
2075
 
        p->subs[a].owner = p->subs[b].owner;
2076
 
        p->subs[a].inthreeway = p->subs[b].inthreeway;
2077
 
 
2078
 
        p->subs[b].chan = tchan;
2079
 
        p->subs[b].owner = towner;
2080
 
        p->subs[b].inthreeway = tinthreeway;
2081
 
 
2082
 
        if (p->subs[a].owner)
2083
 
                ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
2084
 
        if (p->subs[b].owner)
2085
 
                ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
2086
 
        wakeup_sub(p, a, NULL);
2087
 
        wakeup_sub(p, b, NULL);
2088
 
}
2089
 
 
2090
 
static int dahdi_open(char *fn)
2091
 
{
2092
 
        int fd;
2093
 
        int isnum;
2094
 
        int chan = 0;
2095
 
        int bs;
2096
 
        int x;
2097
 
        isnum = 1;
2098
 
        for (x = 0; x < strlen(fn); x++) {
2099
 
                if (!isdigit(fn[x])) {
2100
 
                        isnum = 0;
2101
 
                        break;
2102
 
                }
2103
 
        }
2104
 
        if (isnum) {
2105
 
                chan = atoi(fn);
2106
 
                if (chan < 1) {
2107
 
                        ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
2108
 
                        return -1;
2109
 
                }
2110
 
                fn = "/dev/dahdi/channel";
2111
 
        }
2112
 
        fd = open(fn, O_RDWR | O_NONBLOCK);
2113
 
        if (fd < 0) {
2114
 
                ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
2115
 
                return -1;
2116
 
        }
2117
 
        if (chan) {
2118
 
                if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
2119
 
                        x = errno;
2120
 
                        close(fd);
2121
 
                        errno = x;
2122
 
                        ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
2123
 
                        return -1;
2124
 
                }
2125
 
        }
2126
 
        bs = READ_SIZE;
2127
 
        if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
2128
 
                ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
2129
 
                x = errno;
2130
 
                close(fd);
2131
 
                errno = x;
2132
 
                return -1;
2133
 
        }
2134
 
        return fd;
2135
 
}
2136
 
 
2137
 
static void dahdi_close(int fd)
2138
 
{
2139
 
        if (fd > 0)
2140
 
                close(fd);
2141
 
}
2142
 
 
2143
 
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
2144
 
{
2145
 
        dahdi_close(chan_pvt->subs[sub_num].dfd);
2146
 
        chan_pvt->subs[sub_num].dfd = -1;
2147
 
}
2148
 
 
2149
 
#if defined(HAVE_PRI)
2150
 
static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
2151
 
{
2152
 
        dahdi_close(pri->fds[fd_num]);
2153
 
        pri->fds[fd_num] = -1;
2154
 
}
2155
 
#endif  /* defined(HAVE_PRI) */
2156
 
 
2157
 
#if defined(HAVE_SS7)
2158
 
static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
2159
 
{
2160
 
        dahdi_close(ss7->fds[fd_num]);
2161
 
        ss7->fds[fd_num] = -1;
2162
 
}
2163
 
#endif  /* defined(HAVE_SS7) */
2164
 
 
2165
 
static int dahdi_setlinear(int dfd, int linear)
2166
 
{
2167
 
        int res;
2168
 
        res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
2169
 
        if (res)
2170
 
                return res;
2171
 
        return 0;
2172
 
}
2173
 
 
2174
 
 
2175
 
static int alloc_sub(struct dahdi_pvt *p, int x)
2176
 
{
2177
 
        struct dahdi_bufferinfo bi;
2178
 
        int res;
2179
 
        if (p->subs[x].dfd >= 0) {
2180
 
                ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
2181
 
                return -1;
2182
 
        }
2183
 
 
2184
 
        p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
2185
 
        if (p->subs[x].dfd <= -1) {
2186
 
                ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
2187
 
                return -1;
2188
 
        }
2189
 
 
2190
 
        res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
2191
 
        if (!res) {
2192
 
                bi.txbufpolicy = p->buf_policy;
2193
 
                bi.rxbufpolicy = p->buf_policy;
2194
 
                bi.numbufs = p->buf_no;
2195
 
                res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
2196
 
                if (res < 0) {
2197
 
                        ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
2198
 
                }
2199
 
        } else
2200
 
                ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
2201
 
 
2202
 
        if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
2203
 
                ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
2204
 
                dahdi_close_sub(p, x);
2205
 
                p->subs[x].dfd = -1;
2206
 
                return -1;
2207
 
        }
2208
 
        ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
2209
 
        return 0;
2210
 
}
2211
 
 
2212
 
static int unalloc_sub(struct dahdi_pvt *p, int x)
2213
 
{
2214
 
        if (!x) {
2215
 
                ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
2216
 
                return -1;
2217
 
        }
2218
 
        ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
2219
 
        dahdi_close_sub(p, x);
2220
 
        p->subs[x].linear = 0;
2221
 
        p->subs[x].chan = 0;
2222
 
        p->subs[x].owner = NULL;
2223
 
        p->subs[x].inthreeway = 0;
2224
 
        p->polarity = POLARITY_IDLE;
2225
 
        memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
2226
 
        return 0;
2227
 
}
2228
 
 
2229
 
static int digit_to_dtmfindex(char digit)
2230
 
{
2231
 
        if (isdigit(digit))
2232
 
                return DAHDI_TONE_DTMF_BASE + (digit - '0');
2233
 
        else if (digit >= 'A' && digit <= 'D')
2234
 
                return DAHDI_TONE_DTMF_A + (digit - 'A');
2235
 
        else if (digit >= 'a' && digit <= 'd')
2236
 
                return DAHDI_TONE_DTMF_A + (digit - 'a');
2237
 
        else if (digit == '*')
2238
 
                return DAHDI_TONE_DTMF_s;
2239
 
        else if (digit == '#')
2240
 
                return DAHDI_TONE_DTMF_p;
2241
 
        else
2242
 
                return -1;
2243
 
}
2244
 
 
2245
 
static int dahdi_digit_begin(struct ast_channel *chan, char digit)
2246
 
{
2247
 
        struct dahdi_pvt *pvt;
2248
 
        int idx;
2249
 
        int dtmf = -1;
2250
 
 
2251
 
        pvt = chan->tech_pvt;
2252
 
 
2253
 
        ast_mutex_lock(&pvt->lock);
2254
 
 
2255
 
        idx = dahdi_get_index(chan, pvt, 0);
2256
 
 
2257
 
        if ((idx != SUB_REAL) || !pvt->owner)
2258
 
                goto out;
2259
 
 
2260
 
#ifdef HAVE_PRI
2261
 
        if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
2262
 
                        && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
2263
 
                if (pvt->setup_ack) {
2264
 
                        if (!pri_grab(pvt, pvt->pri)) {
2265
 
                                pri_information(pvt->pri->pri, pvt->call, digit);
2266
 
                                pri_rel(pvt->pri);
2267
 
                        } else
2268
 
                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
2269
 
                } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
2270
 
                        int res;
2271
 
                        ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
2272
 
                        res = strlen(pvt->dialdest);
2273
 
                        pvt->dialdest[res++] = digit;
2274
 
                        pvt->dialdest[res] = '\0';
2275
 
                }
2276
 
                goto out;
2277
 
        }
2278
 
#endif
2279
 
        if ((dtmf = digit_to_dtmfindex(digit)) == -1)
2280
 
                goto out;
2281
 
 
2282
 
        if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
2283
 
                int res;
2284
 
                struct dahdi_dialoperation zo = {
2285
 
                        .op = DAHDI_DIAL_OP_APPEND,
2286
 
                };
2287
 
 
2288
 
                zo.dialstr[0] = 'T';
2289
 
                zo.dialstr[1] = digit;
2290
 
                zo.dialstr[2] = '\0';
2291
 
                if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
2292
 
                        ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
2293
 
                else
2294
 
                        pvt->dialing = 1;
2295
 
        } else {
2296
 
                ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
2297
 
                pvt->dialing = 1;
2298
 
                pvt->begindigit = digit;
2299
 
        }
2300
 
 
2301
 
out:
2302
 
        ast_mutex_unlock(&pvt->lock);
2303
 
 
2304
 
        return 0;
2305
 
}
2306
 
 
2307
 
static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
2308
 
{
2309
 
        struct dahdi_pvt *pvt;
2310
 
        int res = 0;
2311
 
        int idx;
2312
 
        int x;
2313
 
 
2314
 
        pvt = chan->tech_pvt;
2315
 
 
2316
 
        ast_mutex_lock(&pvt->lock);
2317
 
 
2318
 
        idx = dahdi_get_index(chan, pvt, 0);
2319
 
 
2320
 
        if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
2321
 
                goto out;
2322
 
 
2323
 
#ifdef HAVE_PRI
2324
 
        /* This means that the digit was already sent via PRI signalling */
2325
 
        if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
2326
 
                        && !pvt->begindigit)
2327
 
                goto out;
2328
 
#endif
2329
 
 
2330
 
        if (pvt->begindigit) {
2331
 
                x = -1;
2332
 
                ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
2333
 
                res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
2334
 
                pvt->dialing = 0;
2335
 
                pvt->begindigit = 0;
2336
 
        }
2337
 
 
2338
 
out:
2339
 
        ast_mutex_unlock(&pvt->lock);
2340
 
 
2341
 
        return res;
2342
 
}
2343
 
 
2344
 
static char *events[] = {
2345
 
        "No event",
2346
 
        "On hook",
2347
 
        "Ring/Answered",
2348
 
        "Wink/Flash",
2349
 
        "Alarm",
2350
 
        "No more alarm",
2351
 
        "HDLC Abort",
2352
 
        "HDLC Overrun",
2353
 
        "HDLC Bad FCS",
2354
 
        "Dial Complete",
2355
 
        "Ringer On",
2356
 
        "Ringer Off",
2357
 
        "Hook Transition Complete",
2358
 
        "Bits Changed",
2359
 
        "Pulse Start",
2360
 
        "Timer Expired",
2361
 
        "Timer Ping",
2362
 
        "Polarity Reversal",
2363
 
        "Ring Begin",
2364
 
};
2365
 
 
2366
 
static struct {
2367
 
        int alarm;
2368
 
        char *name;
2369
 
} alarms[] = {
2370
 
        { DAHDI_ALARM_RED, "Red Alarm" },
2371
 
        { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
2372
 
        { DAHDI_ALARM_BLUE, "Blue Alarm" },
2373
 
        { DAHDI_ALARM_RECOVER, "Recovering" },
2374
 
        { DAHDI_ALARM_LOOPBACK, "Loopback" },
2375
 
        { DAHDI_ALARM_NOTOPEN, "Not Open" },
2376
 
        { DAHDI_ALARM_NONE, "None" },
2377
 
};
2378
 
 
2379
 
static char *alarm2str(int alm)
2380
 
{
2381
 
        int x;
2382
 
        for (x = 0; x < ARRAY_LEN(alarms); x++) {
2383
 
                if (alarms[x].alarm & alm)
2384
 
                        return alarms[x].name;
2385
 
        }
2386
 
        return alm ? "Unknown Alarm" : "No Alarm";
2387
 
}
2388
 
 
2389
 
static char *event2str(int event)
2390
 
{
2391
 
        static char buf[256];
2392
 
        if ((event < (ARRAY_LEN(events))) && (event > -1))
2393
 
                return events[event];
2394
 
        sprintf(buf, "Event %d", event); /* safe */
2395
 
        return buf;
2396
 
}
2397
 
 
2398
 
#ifdef HAVE_PRI
2399
 
static char *dialplan2str(int dialplan)
2400
 
{
2401
 
        if (dialplan == -1 || dialplan == -2) {
2402
 
                return("Dynamically set dialplan in ISDN");
2403
 
        }
2404
 
        return (pri_plan2str(dialplan));
2405
 
}
2406
 
#endif
2407
 
 
2408
 
static char *dahdi_sig2str(int sig)
2409
 
{
2410
 
        static char buf[256];
2411
 
        switch (sig) {
2412
 
        case SIG_EM:
2413
 
                return "E & M Immediate";
2414
 
        case SIG_EMWINK:
2415
 
                return "E & M Wink";
2416
 
        case SIG_EM_E1:
2417
 
                return "E & M E1";
2418
 
        case SIG_FEATD:
2419
 
                return "Feature Group D (DTMF)";
2420
 
        case SIG_FEATDMF:
2421
 
                return "Feature Group D (MF)";
2422
 
        case SIG_FEATDMF_TA:
2423
 
                return "Feature Groud D (MF) Tandem Access";
2424
 
        case SIG_FEATB:
2425
 
                return "Feature Group B (MF)";
2426
 
        case SIG_E911:
2427
 
                return "E911 (MF)";
2428
 
        case SIG_FGC_CAMA:
2429
 
                return "FGC/CAMA (Dialpulse)";
2430
 
        case SIG_FGC_CAMAMF:
2431
 
                return "FGC/CAMA (MF)";
2432
 
        case SIG_FXSLS:
2433
 
                return "FXS Loopstart";
2434
 
        case SIG_FXSGS:
2435
 
                return "FXS Groundstart";
2436
 
        case SIG_FXSKS:
2437
 
                return "FXS Kewlstart";
2438
 
        case SIG_FXOLS:
2439
 
                return "FXO Loopstart";
2440
 
        case SIG_FXOGS:
2441
 
                return "FXO Groundstart";
2442
 
        case SIG_FXOKS:
2443
 
                return "FXO Kewlstart";
2444
 
        case SIG_PRI:
2445
 
                return "ISDN PRI";
2446
 
        case SIG_BRI:
2447
 
                return "ISDN BRI Point to Point";
2448
 
        case SIG_BRI_PTMP:
2449
 
                return "ISDN BRI Point to MultiPoint";
2450
 
        case SIG_SS7:
2451
 
                return "SS7";
2452
 
        case SIG_MFCR2:
2453
 
                return "MFC/R2";
2454
 
        case SIG_SF:
2455
 
                return "SF (Tone) Immediate";
2456
 
        case SIG_SFWINK:
2457
 
                return "SF (Tone) Wink";
2458
 
        case SIG_SF_FEATD:
2459
 
                return "SF (Tone) with Feature Group D (DTMF)";
2460
 
        case SIG_SF_FEATDMF:
2461
 
                return "SF (Tone) with Feature Group D (MF)";
2462
 
        case SIG_SF_FEATB:
2463
 
                return "SF (Tone) with Feature Group B (MF)";
2464
 
        case SIG_GR303FXOKS:
2465
 
                return "GR-303 with FXOKS";
2466
 
        case SIG_GR303FXSKS:
2467
 
                return "GR-303 with FXSKS";
2468
 
        case 0:
2469
 
                return "Pseudo";
2470
 
        default:
2471
 
                snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
2472
 
                return buf;
2473
 
        }
2474
 
}
2475
 
 
2476
 
#define sig2str dahdi_sig2str
2477
 
 
2478
 
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
2479
 
{
2480
 
        /* If the conference already exists, and we're already in it
2481
 
           don't bother doing anything */
2482
 
        struct dahdi_confinfo zi;
2483
 
 
2484
 
        memset(&zi, 0, sizeof(zi));
2485
 
        zi.chan = 0;
2486
 
 
2487
 
        if (slavechannel > 0) {
2488
 
                /* If we have only one slave, do a digital mon */
2489
 
                zi.confmode = DAHDI_CONF_DIGITALMON;
2490
 
                zi.confno = slavechannel;
2491
 
        } else {
2492
 
                if (!idx) {
2493
 
                        /* Real-side and pseudo-side both participate in conference */
2494
 
                        zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
2495
 
                                DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
2496
 
                } else
2497
 
                        zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
2498
 
                zi.confno = p->confno;
2499
 
        }
2500
 
        if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
2501
 
                return 0;
2502
 
        if (c->dfd < 0)
2503
 
                return 0;
2504
 
        if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
2505
 
                ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
2506
 
                return -1;
2507
 
        }
2508
 
        if (slavechannel < 1) {
2509
 
                p->confno = zi.confno;
2510
 
        }
2511
 
        memcpy(&c->curconf, &zi, sizeof(c->curconf));
2512
 
        ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
2513
 
        return 0;
2514
 
}
2515
 
 
2516
 
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
2517
 
{
2518
 
        /* If they're listening to our channel, they're ours */
2519
 
        if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
2520
 
                return 1;
2521
 
        /* If they're a talker on our (allocated) conference, they're ours */
2522
 
        if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
2523
 
                return 1;
2524
 
        return 0;
2525
 
}
2526
 
 
2527
 
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
2528
 
{
2529
 
        struct dahdi_confinfo zi;
2530
 
        if (/* Can't delete if there's no dfd */
2531
 
                (c->dfd < 0) ||
2532
 
                /* Don't delete from the conference if it's not our conference */
2533
 
                !isourconf(p, c)
2534
 
                /* Don't delete if we don't think it's conferenced at all (implied) */
2535
 
                ) return 0;
2536
 
        memset(&zi, 0, sizeof(zi));
2537
 
        if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
2538
 
                ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
2539
 
                return -1;
2540
 
        }
2541
 
        ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
2542
 
        memcpy(&c->curconf, &zi, sizeof(c->curconf));
2543
 
        return 0;
2544
 
}
2545
 
 
2546
 
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
2547
 
{
2548
 
        int x;
2549
 
        int useslavenative;
2550
 
        struct dahdi_pvt *slave = NULL;
2551
 
        /* Start out optimistic */
2552
 
        useslavenative = 1;
2553
 
        /* Update conference state in a stateless fashion */
2554
 
        for (x = 0; x < 3; x++) {
2555
 
                /* Any three-way calling makes slave native mode *definitely* out
2556
 
                   of the question */
2557
 
                if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
2558
 
                        useslavenative = 0;
2559
 
        }
2560
 
        /* If we don't have any 3-way calls, check to see if we have
2561
 
           precisely one slave */
2562
 
        if (useslavenative) {
2563
 
                for (x = 0; x < MAX_SLAVES; x++) {
2564
 
                        if (p->slaves[x]) {
2565
 
                                if (slave) {
2566
 
                                        /* Whoops already have a slave!  No
2567
 
                                           slave native and stop right away */
2568
 
                                        slave = NULL;
2569
 
                                        useslavenative = 0;
2570
 
                                        break;
2571
 
                                } else {
2572
 
                                        /* We have one slave so far */
2573
 
                                        slave = p->slaves[x];
2574
 
                                }
2575
 
                        }
2576
 
                }
2577
 
        }
2578
 
        /* If no slave, slave native definitely out */
2579
 
        if (!slave)
2580
 
                useslavenative = 0;
2581
 
        else if (slave->law != p->law) {
2582
 
                useslavenative = 0;
2583
 
                slave = NULL;
2584
 
        }
2585
 
        if (out)
2586
 
                *out = slave;
2587
 
        return useslavenative;
2588
 
}
2589
 
 
2590
 
static int reset_conf(struct dahdi_pvt *p)
2591
 
{
2592
 
        p->confno = -1;
2593
 
        memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
2594
 
        if (p->subs[SUB_REAL].dfd > -1) {
2595
 
                struct dahdi_confinfo zi;
2596
 
 
2597
 
                memset(&zi, 0, sizeof(zi));
2598
 
                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
2599
 
                        ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
2600
 
        }
2601
 
        return 0;
2602
 
}
2603
 
 
2604
 
static int update_conf(struct dahdi_pvt *p)
2605
 
{
2606
 
        int needconf = 0;
2607
 
        int x;
2608
 
        int useslavenative;
2609
 
        struct dahdi_pvt *slave = NULL;
2610
 
 
2611
 
        useslavenative = isslavenative(p, &slave);
2612
 
        /* Start with the obvious, general stuff */
2613
 
        for (x = 0; x < 3; x++) {
2614
 
                /* Look for three way calls */
2615
 
                if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
2616
 
                        conf_add(p, &p->subs[x], x, 0);
2617
 
                        needconf++;
2618
 
                } else {
2619
 
                        conf_del(p, &p->subs[x], x);
2620
 
                }
2621
 
        }
2622
 
        /* If we have a slave, add him to our conference now. or DAX
2623
 
           if this is slave native */
2624
 
        for (x = 0; x < MAX_SLAVES; x++) {
2625
 
                if (p->slaves[x]) {
2626
 
                        if (useslavenative)
2627
 
                                conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2628
 
                        else {
2629
 
                                conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2630
 
                                needconf++;
2631
 
                        }
2632
 
                }
2633
 
        }
2634
 
        /* If we're supposed to be in there, do so now */
2635
 
        if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2636
 
                if (useslavenative)
2637
 
                        conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2638
 
                else {
2639
 
                        conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2640
 
                        needconf++;
2641
 
                }
2642
 
        }
2643
 
        /* If we have a master, add ourselves to his conference */
2644
 
        if (p->master) {
2645
 
                if (isslavenative(p->master, NULL)) {
2646
 
                        conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
2647
 
                } else {
2648
 
                        conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2649
 
                }
2650
 
        }
2651
 
        if (!needconf) {
2652
 
                /* Nobody is left (or should be left) in our conference.
2653
 
                   Kill it. */
2654
 
                p->confno = -1;
2655
 
        }
2656
 
        ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
2657
 
        return 0;
2658
 
}
2659
 
 
2660
 
static void dahdi_enable_ec(struct dahdi_pvt *p)
2661
 
{
2662
 
        int x;
2663
 
        int res;
2664
 
        if (!p)
2665
 
                return;
2666
 
        if (p->echocanon) {
2667
 
                ast_debug(1, "Echo cancellation already on\n");
2668
 
                return;
2669
 
        }
2670
 
        if (p->digital) {
2671
 
                ast_debug(1, "Echo cancellation isn't required on digital connection\n");
2672
 
                return;
2673
 
        }
2674
 
        if (p->echocancel.head.tap_length) {
2675
 
                if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
2676
 
                        x = 1;
2677
 
                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
2678
 
                        if (res)
2679
 
                                ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
2680
 
                }
2681
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
2682
 
                if (res) {
2683
 
                        ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
2684
 
                } else {
2685
 
                        p->echocanon = 1;
2686
 
                        ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
2687
 
                }
2688
 
        } else
2689
 
                ast_debug(1, "No echo cancellation requested\n");
2690
 
}
2691
 
 
2692
 
static void dahdi_train_ec(struct dahdi_pvt *p)
2693
 
{
2694
 
        int x;
2695
 
        int res;
2696
 
 
2697
 
        if (p && p->echocanon && p->echotraining) {
2698
 
                x = p->echotraining;
2699
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
2700
 
                if (res)
2701
 
                        ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
2702
 
                else
2703
 
                        ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
2704
 
        } else {
2705
 
                ast_debug(1, "No echo training requested\n");
2706
 
        }
2707
 
}
2708
 
 
2709
 
static void dahdi_disable_ec(struct dahdi_pvt *p)
2710
 
{
2711
 
        int res;
2712
 
 
2713
 
        if (p->echocanon) {
2714
 
                struct dahdi_echocanparams ecp = { .tap_length = 0 };
2715
 
 
2716
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
2717
 
 
2718
 
                if (res)
2719
 
                        ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
2720
 
                else
2721
 
                        ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
2722
 
        }
2723
 
 
2724
 
        p->echocanon = 0;
2725
 
}
2726
 
 
2727
 
static void fill_txgain(struct dahdi_gains *g, float gain, int law)
2728
 
{
2729
 
        int j;
2730
 
        int k;
2731
 
        float linear_gain = pow(10.0, gain / 20.0);
2732
 
 
2733
 
        switch (law) {
2734
 
        case DAHDI_LAW_ALAW:
2735
 
                for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
2736
 
                        if (gain) {
2737
 
                                k = (int) (((float) AST_ALAW(j)) * linear_gain);
2738
 
                                if (k > 32767) k = 32767;
2739
 
                                if (k < -32767) k = -32767;
2740
 
                                g->txgain[j] = AST_LIN2A(k);
2741
 
                        } else {
2742
 
                                g->txgain[j] = j;
2743
 
                        }
2744
 
                }
2745
 
                break;
2746
 
        case DAHDI_LAW_MULAW:
2747
 
                for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
2748
 
                        if (gain) {
2749
 
                                k = (int) (((float) AST_MULAW(j)) * linear_gain);
2750
 
                                if (k > 32767) k = 32767;
2751
 
                                if (k < -32767) k = -32767;
2752
 
                                g->txgain[j] = AST_LIN2MU(k);
2753
 
                        } else {
2754
 
                                g->txgain[j] = j;
2755
 
                        }
2756
 
                }
2757
 
                break;
2758
 
        }
2759
 
}
2760
 
 
2761
 
static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
2762
 
{
2763
 
        int j;
2764
 
        int k;
2765
 
        float linear_gain = pow(10.0, gain / 20.0);
2766
 
 
2767
 
        switch (law) {
2768
 
        case DAHDI_LAW_ALAW:
2769
 
                for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
2770
 
                        if (gain) {
2771
 
                                k = (int) (((float) AST_ALAW(j)) * linear_gain);
2772
 
                                if (k > 32767) k = 32767;
2773
 
                                if (k < -32767) k = -32767;
2774
 
                                g->rxgain[j] = AST_LIN2A(k);
2775
 
                        } else {
2776
 
                                g->rxgain[j] = j;
2777
 
                        }
2778
 
                }
2779
 
                break;
2780
 
        case DAHDI_LAW_MULAW:
2781
 
                for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
2782
 
                        if (gain) {
2783
 
                                k = (int) (((float) AST_MULAW(j)) * linear_gain);
2784
 
                                if (k > 32767) k = 32767;
2785
 
                                if (k < -32767) k = -32767;
2786
 
                                g->rxgain[j] = AST_LIN2MU(k);
2787
 
                        } else {
2788
 
                                g->rxgain[j] = j;
2789
 
                        }
2790
 
                }
2791
 
                break;
2792
 
        }
2793
 
}
2794
 
 
2795
 
static int set_actual_txgain(int fd, int chan, float gain, int law)
2796
 
{
2797
 
        struct dahdi_gains g;
2798
 
        int res;
2799
 
 
2800
 
        memset(&g, 0, sizeof(g));
2801
 
        g.chan = chan;
2802
 
        res = ioctl(fd, DAHDI_GETGAINS, &g);
2803
 
        if (res) {
2804
 
                ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
2805
 
                return res;
2806
 
        }
2807
 
 
2808
 
        fill_txgain(&g, gain, law);
2809
 
 
2810
 
        return ioctl(fd, DAHDI_SETGAINS, &g);
2811
 
}
2812
 
 
2813
 
static int set_actual_rxgain(int fd, int chan, float gain, int law)
2814
 
{
2815
 
        struct dahdi_gains g;
2816
 
        int res;
2817
 
 
2818
 
        memset(&g, 0, sizeof(g));
2819
 
        g.chan = chan;
2820
 
        res = ioctl(fd, DAHDI_GETGAINS, &g);
2821
 
        if (res) {
2822
 
                ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
2823
 
                return res;
2824
 
        }
2825
 
 
2826
 
        fill_rxgain(&g, gain, law);
2827
 
 
2828
 
        return ioctl(fd, DAHDI_SETGAINS, &g);
2829
 
}
2830
 
 
2831
 
static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
2832
 
{
2833
 
        return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
2834
 
}
2835
 
 
2836
 
static int bump_gains(struct dahdi_pvt *p)
2837
 
{
2838
 
        int res;
2839
 
 
2840
 
        /* Bump receive gain by value stored in cid_rxgain */
2841
 
        res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
2842
 
        if (res) {
2843
 
                ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
2844
 
                return -1;
2845
 
        }
2846
 
 
2847
 
        return 0;
2848
 
}
2849
 
 
2850
 
static int restore_gains(struct dahdi_pvt *p)
2851
 
{
2852
 
        int res;
2853
 
 
2854
 
        res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
2855
 
        if (res) {
2856
 
                ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
2857
 
                return -1;
2858
 
        }
2859
 
 
2860
 
        return 0;
2861
 
}
2862
 
 
2863
 
static inline int dahdi_set_hook(int fd, int hs)
2864
 
{
2865
 
        int x, res;
2866
 
 
2867
 
        x = hs;
2868
 
        res = ioctl(fd, DAHDI_HOOK, &x);
2869
 
 
2870
 
        if (res < 0) {
2871
 
                if (errno == EINPROGRESS)
2872
 
                        return 0;
2873
 
                ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
2874
 
                /* will expectedly fail if phone is off hook during operation, such as during a restart */
2875
 
        }
2876
 
 
2877
 
        return res;
2878
 
}
2879
 
 
2880
 
static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
2881
 
{
2882
 
        int x, y, res;
2883
 
        x = muted;
2884
 
        if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
2885
 
                y = 1;
2886
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
2887
 
                if (res)
2888
 
                        ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
2889
 
        }
2890
 
        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
2891
 
        if (res < 0)
2892
 
                ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
2893
 
        return res;
2894
 
}
2895
 
 
2896
 
static int save_conference(struct dahdi_pvt *p)
2897
 
{
2898
 
        struct dahdi_confinfo c;
2899
 
        int res;
2900
 
        if (p->saveconf.confmode) {
2901
 
                ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
2902
 
                return -1;
2903
 
        }
2904
 
        p->saveconf.chan = 0;
2905
 
        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
2906
 
        if (res) {
2907
 
                ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
2908
 
                p->saveconf.confmode = 0;
2909
 
                return -1;
2910
 
        }
2911
 
        memset(&c, 0, sizeof(c));
2912
 
        c.confmode = DAHDI_CONF_NORMAL;
2913
 
        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
2914
 
        if (res) {
2915
 
                ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
2916
 
                return -1;
2917
 
        }
2918
 
        ast_debug(1, "Disabled conferencing\n");
2919
 
        return 0;
2920
 
}
2921
 
 
2922
 
/*!
2923
 
 * \brief Send MWI state change
2924
 
 *
2925
 
 * \arg mailbox_full This is the mailbox associated with the FXO line that the
2926
 
 *      MWI state has changed on.
2927
 
 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
2928
 
 *      whether there are messages waiting or not.
2929
 
 *
2930
 
 *  \return nothing
2931
 
 *
2932
 
 * This function does two things:
2933
 
 *
2934
 
 * 1) It generates an internal Asterisk event notifying any other module that
2935
 
 *    cares about MWI that the state of a mailbox has changed.
2936
 
 *
2937
 
 * 2) It runs the script specified by the mwimonitornotify option to allow
2938
 
 *    some custom handling of the state change.
2939
 
 */
2940
 
static void notify_message(char *mailbox_full, int thereornot)
2941
 
{
2942
 
        char s[sizeof(mwimonitornotify) + 80];
2943
 
        struct ast_event *event;
2944
 
        char *mailbox, *context;
2945
 
 
2946
 
        /* Strip off @default */
2947
 
        context = mailbox = ast_strdupa(mailbox_full);
2948
 
        strsep(&context, "@");
2949
 
        if (ast_strlen_zero(context))
2950
 
                context = "default";
2951
 
 
2952
 
        if (!(event = ast_event_new(AST_EVENT_MWI,
2953
 
                        AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
2954
 
                        AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
2955
 
                        AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
2956
 
                        AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
2957
 
                        AST_EVENT_IE_END))) {
2958
 
                return;
2959
 
        }
2960
 
 
2961
 
        ast_event_queue_and_cache(event);
2962
 
 
2963
 
        if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
2964
 
                snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
2965
 
                ast_safe_system(s);
2966
 
        }
2967
 
}
2968
 
 
2969
 
static int restore_conference(struct dahdi_pvt *p)
2970
 
{
2971
 
        int res;
2972
 
        if (p->saveconf.confmode) {
2973
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
2974
 
                p->saveconf.confmode = 0;
2975
 
                if (res) {
2976
 
                        ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
2977
 
                        return -1;
2978
 
                }
2979
 
        }
2980
 
        ast_debug(1, "Restored conferencing\n");
2981
 
        return 0;
2982
 
}
2983
 
 
2984
 
static int send_callerid(struct dahdi_pvt *p);
2985
 
 
2986
 
static int send_cwcidspill(struct dahdi_pvt *p)
2987
 
{
2988
 
        p->callwaitcas = 0;
2989
 
        p->cidcwexpire = 0;
2990
 
        if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
2991
 
                return -1;
2992
 
        p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
2993
 
        /* Make sure we account for the end */
2994
 
        p->cidlen += READ_SIZE * 4;
2995
 
        p->cidpos = 0;
2996
 
        send_callerid(p);
2997
 
        ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
2998
 
        return 0;
2999
 
}
3000
 
 
3001
 
static int has_voicemail(struct dahdi_pvt *p)
3002
 
{
3003
 
        int new_msgs;
3004
 
        struct ast_event *event;
3005
 
        char *mailbox, *context;
3006
 
 
3007
 
        mailbox = context = ast_strdupa(p->mailbox);
3008
 
        strsep(&context, "@");
3009
 
        if (ast_strlen_zero(context))
3010
 
                context = "default";
3011
 
 
3012
 
        event = ast_event_get_cached(AST_EVENT_MWI,
3013
 
                AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
3014
 
                AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
3015
 
                AST_EVENT_IE_END);
3016
 
 
3017
 
        if (event) {
3018
 
                new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
3019
 
                ast_event_destroy(event);
3020
 
        } else
3021
 
                new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
3022
 
 
3023
 
        return new_msgs;
3024
 
}
3025
 
 
3026
 
static int send_callerid(struct dahdi_pvt *p)
3027
 
{
3028
 
        /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
3029
 
        int res;
3030
 
        /* Take out of linear mode if necessary */
3031
 
        if (p->subs[SUB_REAL].linear) {
3032
 
                p->subs[SUB_REAL].linear = 0;
3033
 
                dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
3034
 
        }
3035
 
        while (p->cidpos < p->cidlen) {
3036
 
                res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
3037
 
                if (res < 0) {
3038
 
                        if (errno == EAGAIN)
3039
 
                                return 0;
3040
 
                        else {
3041
 
                                ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
3042
 
                                return -1;
3043
 
                        }
3044
 
                }
3045
 
                if (!res)
3046
 
                        return 0;
3047
 
                p->cidpos += res;
3048
 
        }
3049
 
        ast_free(p->cidspill);
3050
 
        p->cidspill = NULL;
3051
 
        if (p->callwaitcas) {
3052
 
                /* Wait for CID/CW to expire */
3053
 
                p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
3054
 
        } else
3055
 
                restore_conference(p);
3056
 
        return 0;
3057
 
}
3058
 
 
3059
 
static int dahdi_callwait(struct ast_channel *ast)
3060
 
{
3061
 
        struct dahdi_pvt *p = ast->tech_pvt;
3062
 
        p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
3063
 
        if (p->cidspill) {
3064
 
                ast_log(LOG_WARNING, "Spill already exists?!?\n");
3065
 
                ast_free(p->cidspill);
3066
 
        }
3067
 
        if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
3068
 
                return -1;
3069
 
        save_conference(p);
3070
 
        /* Silence */
3071
 
        memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
3072
 
        if (!p->callwaitrings && p->callwaitingcallerid) {
3073
 
                ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
3074
 
                p->callwaitcas = 1;
3075
 
                p->cidlen = 2400 + 680 + READ_SIZE * 4;
3076
 
        } else {
3077
 
                ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
3078
 
                p->callwaitcas = 0;
3079
 
                p->cidlen = 2400 + READ_SIZE * 4;
3080
 
        }
3081
 
        p->cidpos = 0;
3082
 
        send_callerid(p);
3083
 
 
3084
 
        return 0;
3085
 
}
3086
 
 
3087
 
#if defined(HAVE_SS7)
3088
 
static unsigned char cid_pres2ss7pres(int cid_pres)
3089
 
{
3090
 
         return (cid_pres >> 5) & 0x03;
3091
 
}
3092
 
#endif  /* defined(HAVE_SS7) */
3093
 
 
3094
 
#if defined(HAVE_SS7)
3095
 
static unsigned char cid_pres2ss7screen(int cid_pres)
3096
 
{
3097
 
        return cid_pres & 0x03;
3098
 
}
3099
 
#endif  /* defined(HAVE_SS7) */
3100
 
 
3101
 
static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
3102
 
{
3103
 
        struct dahdi_pvt *p = ast->tech_pvt;
3104
 
        int x, res, idx,mysig;
3105
 
        char *c, *n, *l;
3106
 
#ifdef HAVE_PRI
3107
 
        char *s = NULL;
3108
 
#endif
3109
 
        char dest[256]; /* must be same length as p->dialdest */
3110
 
        ast_mutex_lock(&p->lock);
3111
 
        ast_copy_string(dest, rdest, sizeof(dest));
3112
 
        ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
3113
 
        if ((ast->_state == AST_STATE_BUSY)) {
3114
 
                p->subs[SUB_REAL].needbusy = 1;
3115
 
                ast_mutex_unlock(&p->lock);
3116
 
                return 0;
3117
 
        }
3118
 
        if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
3119
 
                ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
3120
 
                ast_mutex_unlock(&p->lock);
3121
 
                return -1;
3122
 
        }
3123
 
        p->waitingfordt.tv_sec = 0;
3124
 
        p->dialednone = 0;
3125
 
        if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
3126
 
        {
3127
 
                /* Special pseudo -- automatically up */
3128
 
                ast_setstate(ast, AST_STATE_UP);
3129
 
                ast_mutex_unlock(&p->lock);
3130
 
                return 0;
3131
 
        }
3132
 
        x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
3133
 
        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
3134
 
        if (res)
3135
 
                ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
3136
 
        p->outgoing = 1;
3137
 
 
3138
 
        if (IS_DIGITAL(ast->transfercapability)){
3139
 
                set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
3140
 
        } else {
3141
 
                set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
3142
 
        }       
3143
 
 
3144
 
        mysig = p->sig;
3145
 
        if (p->outsigmod > -1)
3146
 
                mysig = p->outsigmod;
3147
 
 
3148
 
        switch (mysig) {
3149
 
        case SIG_FXOLS:
3150
 
        case SIG_FXOGS:
3151
 
        case SIG_FXOKS:
3152
 
                if (p->owner == ast) {
3153
 
                        /* Normal ring, on hook */
3154
 
 
3155
 
                        /* Don't send audio while on hook, until the call is answered */
3156
 
                        p->dialing = 1;
3157
 
                        if (p->use_callerid) {
3158
 
                                /* Generate the Caller-ID spill if desired */
3159
 
                                if (p->cidspill) {
3160
 
                                        ast_log(LOG_WARNING, "cidspill already exists??\n");
3161
 
                                        ast_free(p->cidspill);
3162
 
                                }
3163
 
                                p->callwaitcas = 0;
3164
 
                                if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
3165
 
                                        p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
3166
 
                                        p->cidpos = 0;
3167
 
                                        send_callerid(p);
3168
 
                                }
3169
 
                        }
3170
 
                        /* Choose proper cadence */
3171
 
                        if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
3172
 
                                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
3173
 
                                        ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
3174
 
                                p->cidrings = cidrings[p->distinctivering - 1];
3175
 
                        } else {
3176
 
                                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
3177
 
                                        ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
3178
 
                                p->cidrings = p->sendcalleridafter;
3179
 
                        }
3180
 
 
3181
 
                        /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
3182
 
                        c = strchr(dest, '/');
3183
 
                        if (c)
3184
 
                                c++;
3185
 
                        if (c && (strlen(c) < p->stripmsd)) {
3186
 
                                ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
3187
 
                                c = NULL;
3188
 
                        }
3189
 
                        if (c) {
3190
 
                                p->dop.op = DAHDI_DIAL_OP_REPLACE;
3191
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
3192
 
                                ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
3193
 
                        } else {
3194
 
                                p->dop.dialstr[0] = '\0';
3195
 
                        }
3196
 
                        x = DAHDI_RING;
3197
 
                        if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
3198
 
                                ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
3199
 
                                ast_mutex_unlock(&p->lock);
3200
 
                                return -1;
3201
 
                        }
3202
 
                        p->dialing = 1;
3203
 
                } else {
3204
 
                        /* Call waiting call */
3205
 
                        p->callwaitrings = 0;
3206
 
                        if (ast->cid.cid_num)
3207
 
                                ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
3208
 
                        else
3209
 
                                p->callwait_num[0] = '\0';
3210
 
                        if (ast->cid.cid_name)
3211
 
                                ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
3212
 
                        else
3213
 
                                p->callwait_name[0] = '\0';
3214
 
                        /* Call waiting tone instead */
3215
 
                        if (dahdi_callwait(ast)) {
3216
 
                                ast_mutex_unlock(&p->lock);
3217
 
                                return -1;
3218
 
                        }
3219
 
                        /* Make ring-back */
3220
 
                        if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
3221
 
                                ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
3222
 
                }
3223
 
                n = ast->cid.cid_name;
3224
 
                l = ast->cid.cid_num;
3225
 
                if (l)
3226
 
                        ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
3227
 
                else
3228
 
                        p->lastcid_num[0] = '\0';
3229
 
                if (n)
3230
 
                        ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
3231
 
                else
3232
 
                        p->lastcid_name[0] = '\0';
3233
 
                ast_setstate(ast, AST_STATE_RINGING);
3234
 
                idx = dahdi_get_index(ast, p, 0);
3235
 
                if (idx > -1) {
3236
 
                        p->subs[idx].needringing = 1;
3237
 
                }
3238
 
                break;
3239
 
        case SIG_FXSLS:
3240
 
        case SIG_FXSGS:
3241
 
        case SIG_FXSKS:
3242
 
                if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
3243
 
                        ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
3244
 
                        p->polaritydelaytv = ast_tvnow();
3245
 
                }
3246
 
                /* fall through */
3247
 
        case SIG_EMWINK:
3248
 
        case SIG_EM:
3249
 
        case SIG_EM_E1:
3250
 
        case SIG_FEATD:
3251
 
        case SIG_FEATDMF:
3252
 
        case SIG_E911:
3253
 
        case SIG_FGC_CAMA:
3254
 
        case SIG_FGC_CAMAMF:
3255
 
        case SIG_FEATB:
3256
 
        case SIG_SFWINK:
3257
 
        case SIG_SF:
3258
 
        case SIG_SF_FEATD:
3259
 
        case SIG_SF_FEATDMF:
3260
 
        case SIG_FEATDMF_TA:
3261
 
        case SIG_SF_FEATB:
3262
 
                c = strchr(dest, '/');
3263
 
                if (c)
3264
 
                        c++;
3265
 
                else
3266
 
                        c = "";
3267
 
                if (strlen(c) < p->stripmsd) {
3268
 
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
3269
 
                        ast_mutex_unlock(&p->lock);
3270
 
                        return -1;
3271
 
                }
3272
 
#ifdef HAVE_PRI
3273
 
                /* Start the trunk, if not GR-303 */
3274
 
                if (!p->pri) {
3275
 
#endif
3276
 
                        x = DAHDI_START;
3277
 
                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3278
 
                        if (res < 0) {
3279
 
                                if (errno != EINPROGRESS) {
3280
 
                                        ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
3281
 
                                        ast_mutex_unlock(&p->lock);
3282
 
                                        return -1;
3283
 
                                }
3284
 
                        }
3285
 
#ifdef HAVE_PRI
3286
 
                }
3287
 
#endif
3288
 
                ast_debug(1, "Dialing '%s'\n", c);
3289
 
                p->dop.op = DAHDI_DIAL_OP_REPLACE;
3290
 
 
3291
 
                c += p->stripmsd;
3292
 
 
3293
 
                switch (mysig) {
3294
 
                case SIG_FEATD:
3295
 
                        l = ast->cid.cid_num;
3296
 
                        if (l)
3297
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
3298
 
                        else
3299
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
3300
 
                        break;
3301
 
                case SIG_FEATDMF:
3302
 
                        l = ast->cid.cid_num;
3303
 
                        if (l)
3304
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
3305
 
                        else
3306
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
3307
 
                        break;
3308
 
                case SIG_FEATDMF_TA:
3309
 
                {
3310
 
                        const char *cic, *ozz;
3311
 
 
3312
 
                        /* If you have to go through a Tandem Access point you need to use this */
3313
 
                        ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
3314
 
                        if (!ozz)
3315
 
                                ozz = defaultozz;
3316
 
                        cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
3317
 
                        if (!cic)
3318
 
                                cic = defaultcic;
3319
 
                        if (!ozz || !cic) {
3320
 
                                ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
3321
 
                                ast_mutex_unlock(&p->lock);
3322
 
                                return -1;
3323
 
                        }
3324
 
                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
3325
 
                        snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
3326
 
                        p->whichwink = 0;
3327
 
                }
3328
 
                        break;
3329
 
                case SIG_E911:
3330
 
                        ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
3331
 
                        break;
3332
 
                case SIG_FGC_CAMA:
3333
 
                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
3334
 
                        break;
3335
 
                case SIG_FGC_CAMAMF:
3336
 
                case SIG_FEATB:
3337
 
                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
3338
 
                        break;
3339
 
                default:
3340
 
                        if (p->pulse)
3341
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
3342
 
                        else
3343
 
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
3344
 
                        break;
3345
 
                }
3346
 
 
3347
 
                if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
3348
 
                        memset(p->echorest, 'w', sizeof(p->echorest) - 1);
3349
 
                        strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
3350
 
                        p->echorest[sizeof(p->echorest) - 1] = '\0';
3351
 
                        p->echobreak = 1;
3352
 
                        p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
3353
 
                } else
3354
 
                        p->echobreak = 0;
3355
 
 
3356
 
                /* waitfordialtone ? */
3357
 
#ifdef HAVE_PRI
3358
 
                if (!p->pri) {
3359
 
#endif
3360
 
                        if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
3361
 
                                ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
3362
 
                                gettimeofday(&p->waitingfordt,NULL);
3363
 
                                ast_setstate(ast, AST_STATE_OFFHOOK);
3364
 
                                break;
3365
 
                        }
3366
 
#ifdef HAVE_PRI
3367
 
                }
3368
 
#endif
3369
 
                if (!res) {
3370
 
                        if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
3371
 
                                int saveerr = errno;
3372
 
 
3373
 
                                x = DAHDI_ONHOOK;
3374
 
                                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3375
 
                                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
3376
 
                                ast_mutex_unlock(&p->lock);
3377
 
                                return -1;
3378
 
                        }
3379
 
                } else
3380
 
                        ast_debug(1, "Deferring dialing...\n");
3381
 
 
3382
 
                p->dialing = 1;
3383
 
                if (ast_strlen_zero(c))
3384
 
                        p->dialednone = 1;
3385
 
                ast_setstate(ast, AST_STATE_DIALING);
3386
 
                break;
3387
 
        case 0:
3388
 
                /* Special pseudo -- automatically up*/
3389
 
                ast_setstate(ast, AST_STATE_UP);
3390
 
                break;
3391
 
        case SIG_PRI:
3392
 
        case SIG_BRI:
3393
 
        case SIG_BRI_PTMP:
3394
 
        case SIG_SS7:
3395
 
        case SIG_MFCR2:
3396
 
                /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
3397
 
                p->dialdest[0] = '\0';
3398
 
                p->dialing = 1;
3399
 
                break;
3400
 
        default:
3401
 
                ast_debug(1, "not yet implemented\n");
3402
 
                ast_mutex_unlock(&p->lock);
3403
 
                return -1;
3404
 
        }
3405
 
#ifdef HAVE_SS7
3406
 
        if (p->ss7) {
3407
 
                char ss7_called_nai;
3408
 
                int called_nai_strip;
3409
 
                char ss7_calling_nai;
3410
 
                int calling_nai_strip;
3411
 
                const char *charge_str = NULL;
3412
 
                const char *gen_address = NULL;
3413
 
                const char *gen_digits = NULL;
3414
 
                const char *gen_dig_type = NULL;
3415
 
                const char *gen_dig_scheme = NULL;
3416
 
                const char *gen_name = NULL;
3417
 
                const char *jip_digits = NULL;
3418
 
                const char *lspi_ident = NULL;
3419
 
                const char *rlt_flag = NULL;
3420
 
                const char *call_ref_id = NULL;
3421
 
                const char *call_ref_pc = NULL;
3422
 
                const char *send_far = NULL;
3423
 
 
3424
 
                c = strchr(dest, '/');
3425
 
                if (c) {
3426
 
                        c++;
3427
 
                } else {
3428
 
                        c = "";
3429
 
                }
3430
 
                if (strlen(c) < p->stripmsd) {
3431
 
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
3432
 
                        ast_mutex_unlock(&p->lock);
3433
 
                        return -1;
3434
 
                }
3435
 
 
3436
 
                if (!p->hidecallerid) {
3437
 
                        l = ast->cid.cid_num;
3438
 
                } else {
3439
 
                        l = NULL;
3440
 
                }
3441
 
 
3442
 
                if (ss7_grab(p, p->ss7)) {
3443
 
                        ast_log(LOG_WARNING, "Failed to grab SS7!\n");
3444
 
                        ast_mutex_unlock(&p->lock);
3445
 
                        return -1;
3446
 
                }
3447
 
                p->digital = IS_DIGITAL(ast->transfercapability);
3448
 
                p->ss7call = isup_new_call(p->ss7->ss7);
3449
 
 
3450
 
                if (!p->ss7call) {
3451
 
                        ss7_rel(p->ss7);
3452
 
                        ast_mutex_unlock(&p->lock);
3453
 
                        ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
3454
 
                        return -1;
3455
 
                }
3456
 
 
3457
 
                called_nai_strip = 0;
3458
 
                ss7_called_nai = p->ss7->called_nai;
3459
 
                if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
3460
 
                        if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
3461
 
                                called_nai_strip = strlen(p->ss7->internationalprefix);
3462
 
                                ss7_called_nai = SS7_NAI_INTERNATIONAL;
3463
 
                        } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
3464
 
                                called_nai_strip = strlen(p->ss7->nationalprefix);
3465
 
                                ss7_called_nai = SS7_NAI_NATIONAL;
3466
 
                        } else {
3467
 
                                ss7_called_nai = SS7_NAI_SUBSCRIBER;
3468
 
                        }
3469
 
                }
3470
 
                isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
3471
 
 
3472
 
                calling_nai_strip = 0;
3473
 
                ss7_calling_nai = p->ss7->calling_nai;
3474
 
                if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
3475
 
                        if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
3476
 
                                calling_nai_strip = strlen(p->ss7->internationalprefix);
3477
 
                                ss7_calling_nai = SS7_NAI_INTERNATIONAL;
3478
 
                        } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
3479
 
                                calling_nai_strip = strlen(p->ss7->nationalprefix);
3480
 
                                ss7_calling_nai = SS7_NAI_NATIONAL;
3481
 
                        } else {
3482
 
                                ss7_calling_nai = SS7_NAI_SUBSCRIBER;
3483
 
                        }
3484
 
                }
3485
 
                isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
3486
 
                        p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
3487
 
                        p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
3488
 
 
3489
 
                isup_set_oli(p->ss7call, ast->cid.cid_ani2);
3490
 
                isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
3491
 
 
3492
 
                ast_channel_lock(ast);
3493
 
                /* Set the charge number if it is set */
3494
 
                charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
3495
 
                if (charge_str)
3496
 
                        isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
3497
 
 
3498
 
                gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
3499
 
                if (gen_address)
3500
 
                        isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
3501
 
 
3502
 
                gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
3503
 
                gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
3504
 
                gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
3505
 
                if (gen_digits)
3506
 
                        isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
3507
 
 
3508
 
                gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
3509
 
                if (gen_name)
3510
 
                        isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
3511
 
 
3512
 
                jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
3513
 
                if (jip_digits)
3514
 
                        isup_set_jip_digits(p->ss7call, jip_digits);
3515
 
 
3516
 
                lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
3517
 
                if (lspi_ident)
3518
 
                        isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
3519
 
 
3520
 
                rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
3521
 
                if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
3522
 
                        isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
3523
 
                }
3524
 
 
3525
 
                call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
3526
 
                call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
3527
 
                if (call_ref_id && call_ref_pc) {
3528
 
                        isup_set_callref(p->ss7call, atoi(call_ref_id),
3529
 
                                         call_ref_pc ? atoi(call_ref_pc) : 0);
3530
 
                }
3531
 
 
3532
 
                send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
3533
 
                if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
3534
 
                        (isup_far(p->ss7->ss7, p->ss7call));
3535
 
 
3536
 
                ast_channel_unlock(ast);
3537
 
 
3538
 
                isup_iam(p->ss7->ss7, p->ss7call);
3539
 
                ast_setstate(ast, AST_STATE_DIALING);
3540
 
                ss7_rel(p->ss7);
3541
 
        }
3542
 
#endif /* HAVE_SS7 */
3543
 
#ifdef HAVE_OPENR2
3544
 
        if (p->mfcr2) {
3545
 
                openr2_calling_party_category_t chancat;
3546
 
                int callres = 0;
3547
 
                char *c, *l;
3548
 
 
3549
 
                c = strchr(dest, '/');
3550
 
                if (c) {
3551
 
                        c++;
3552
 
                } else {
3553
 
                        c = "";
3554
 
                }
3555
 
                if (!p->hidecallerid) {
3556
 
                        l = ast->cid.cid_num;
3557
 
                } else {
3558
 
                        l = NULL;
3559
 
                }
3560
 
                if (strlen(c) < p->stripmsd) {
3561
 
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
3562
 
                        ast_mutex_unlock(&p->lock);
3563
 
                        return -1;
3564
 
                }
3565
 
                p->dialing = 1;
3566
 
                ast_channel_lock(ast);
3567
 
                chancat = dahdi_r2_get_channel_category(ast);
3568
 
                ast_channel_unlock(ast);
3569
 
                callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
3570
 
                if (-1 == callres) {
3571
 
                        ast_mutex_unlock(&p->lock);
3572
 
                        ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
3573
 
                        return -1;
3574
 
                }
3575
 
                ast_setstate(ast, AST_STATE_DIALING);
3576
 
        }
3577
 
#endif /* HAVE_OPENR2 */
3578
 
#ifdef HAVE_PRI
3579
 
        if (p->pri) {
3580
 
                struct pri_sr *sr;
3581
 
#ifdef SUPPORT_USERUSER
3582
 
                const char *useruser;
3583
 
#endif
3584
 
                int pridialplan;
3585
 
                int dp_strip;
3586
 
                int prilocaldialplan;
3587
 
                int ldp_strip;
3588
 
                int exclusive;
3589
 
                const char *rr_str;
3590
 
                int redirect_reason;
3591
 
 
3592
 
                c = strchr(dest, '/');
3593
 
                if (c) {
3594
 
                        c++;
3595
 
                } else {
3596
 
                        c = "";
3597
 
                }
3598
 
 
3599
 
                l = NULL;
3600
 
                n = NULL;
3601
 
                if (!p->hidecallerid) {
3602
 
                        l = ast->cid.cid_num;
3603
 
                        if (!p->hidecalleridname) {
3604
 
                                n = ast->cid.cid_name;
3605
 
                        }
3606
 
                }
3607
 
 
3608
 
                if (strlen(c) < p->stripmsd) {
3609
 
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
3610
 
                        ast_mutex_unlock(&p->lock);
3611
 
                        return -1;
3612
 
                }
3613
 
                if (mysig != SIG_FXSKS) {
3614
 
                        p->dop.op = DAHDI_DIAL_OP_REPLACE;
3615
 
                        s = strchr(c + p->stripmsd, 'w');
3616
 
                        if (s) {
3617
 
                                if (strlen(s) > 1)
3618
 
                                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
3619
 
                                else
3620
 
                                        p->dop.dialstr[0] = '\0';
3621
 
                                *s = '\0';
3622
 
                        } else {
3623
 
                                p->dop.dialstr[0] = '\0';
3624
 
                        }
3625
 
                }
3626
 
                if (pri_grab(p, p->pri)) {
3627
 
                        ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3628
 
                        ast_mutex_unlock(&p->lock);
3629
 
                        return -1;
3630
 
                }
3631
 
                if (!(p->call = pri_new_call(p->pri->pri))) {
3632
 
                        ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
3633
 
                        pri_rel(p->pri);
3634
 
                        ast_mutex_unlock(&p->lock);
3635
 
                        return -1;
3636
 
                }
3637
 
                if (!(sr = pri_sr_new())) {
3638
 
                        ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
3639
 
                        pri_rel(p->pri);
3640
 
                        ast_mutex_unlock(&p->lock);
3641
 
                }
3642
 
                if (p->bearer || (mysig == SIG_FXSKS)) {
3643
 
                        if (p->bearer) {
3644
 
                                ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
3645
 
                                p->bearer->call = p->call;
3646
 
                        } else
3647
 
                                ast_debug(1, "I'm being setup with no bearer right now...\n");
3648
 
 
3649
 
                        pri_set_crv(p->pri->pri, p->call, p->channel, 0);
3650
 
                }
3651
 
                p->digital = IS_DIGITAL(ast->transfercapability);
3652
 
 
3653
 
                /* Should the picked channel be used exclusively? */
3654
 
                if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
3655
 
                        exclusive = 1;
3656
 
                } else {
3657
 
                        exclusive = 0;
3658
 
                }
3659
 
 
3660
 
                pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
3661
 
                pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
3662
 
                        (p->digital ? -1 :
3663
 
                                ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
3664
 
                if (p->pri->facilityenable)
3665
 
                        pri_facility_enable(p->pri->pri);
3666
 
 
3667
 
                ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
3668
 
 
3669
 
                dp_strip = 0;
3670
 
                pridialplan = p->pri->dialplan - 1;
3671
 
                if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
3672
 
                        if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
3673
 
                                if (pridialplan == -2) {
3674
 
                                        dp_strip = strlen(p->pri->internationalprefix);
3675
 
                                }
3676
 
                                pridialplan = PRI_INTERNATIONAL_ISDN;
3677
 
                        } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
3678
 
                                if (pridialplan == -2) {
3679
 
                                        dp_strip = strlen(p->pri->nationalprefix);
3680
 
                                }
3681
 
                                pridialplan = PRI_NATIONAL_ISDN;
3682
 
                        } else {
3683
 
                                pridialplan = PRI_LOCAL_ISDN;
3684
 
                        }
3685
 
                }
3686
 
                while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
3687
 
                        switch (c[p->stripmsd]) {
3688
 
                        case 'U':
3689
 
                                pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
3690
 
                                break;
3691
 
                        case 'I':
3692
 
                                pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
3693
 
                                break;
3694
 
                        case 'N':
3695
 
                                pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
3696
 
                                break;
3697
 
                        case 'L':
3698
 
                                pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
3699
 
                                break;
3700
 
                        case 'S':
3701
 
                                pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
3702
 
                                break;
3703
 
                        case 'V':
3704
 
                                pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
3705
 
                                break;
3706
 
                        case 'R':
3707
 
                                pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
3708
 
                                break;
3709
 
                        case 'u':
3710
 
                                pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
3711
 
                                break;
3712
 
                        case 'e':
3713
 
                                pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
3714
 
                                break;
3715
 
                        case 'x':
3716
 
                                pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
3717
 
                                break;
3718
 
                        case 'f':
3719
 
                                pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
3720
 
                                break;
3721
 
                        case 'n':
3722
 
                                pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
3723
 
                                break;
3724
 
                        case 'p':
3725
 
                                pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
3726
 
                                break;
3727
 
                        case 'r':
3728
 
                                pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
3729
 
                                break;
3730
 
                        default:
3731
 
                                if (isalpha(c[p->stripmsd])) {
3732
 
                                        ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
3733
 
                                                c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
3734
 
                                }
3735
 
                                break;
3736
 
                        }
3737
 
                        c++;
3738
 
                }
3739
 
                pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
3740
 
 
3741
 
                ldp_strip = 0;
3742
 
                prilocaldialplan = p->pri->localdialplan - 1;
3743
 
                if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
3744
 
                        if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
3745
 
                                if (prilocaldialplan == -2) {
3746
 
                                        ldp_strip = strlen(p->pri->internationalprefix);
3747
 
                                }
3748
 
                                prilocaldialplan = PRI_INTERNATIONAL_ISDN;
3749
 
                        } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
3750
 
                                if (prilocaldialplan == -2) {
3751
 
                                        ldp_strip = strlen(p->pri->nationalprefix);
3752
 
                                }
3753
 
                                prilocaldialplan = PRI_NATIONAL_ISDN;
3754
 
                        } else {
3755
 
                                prilocaldialplan = PRI_LOCAL_ISDN;
3756
 
                        }
3757
 
                }
3758
 
                if (l != NULL) {
3759
 
                        while (*l > '9' && *l != '*' && *l != '#') {
3760
 
                                switch (*l) {
3761
 
                                case 'U':
3762
 
                                        prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
3763
 
                                        break;
3764
 
                                case 'I':
3765
 
                                        prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
3766
 
                                        break;
3767
 
                                case 'N':
3768
 
                                        prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
3769
 
                                        break;
3770
 
                                case 'L':
3771
 
                                        prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
3772
 
                                        break;
3773
 
                                case 'S':
3774
 
                                        prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
3775
 
                                        break;
3776
 
                                case 'V':
3777
 
                                        prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
3778
 
                                        break;
3779
 
                                case 'R':
3780
 
                                        prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
3781
 
                                        break;
3782
 
                                case 'u':
3783
 
                                        prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
3784
 
                                        break;
3785
 
                                case 'e':
3786
 
                                        prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
3787
 
                                        break;
3788
 
                                case 'x':
3789
 
                                        prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
3790
 
                                        break;
3791
 
                                case 'f':
3792
 
                                        prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
3793
 
                                        break;
3794
 
                                case 'n':
3795
 
                                        prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
3796
 
                                        break;
3797
 
                                case 'p':
3798
 
                                        prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
3799
 
                                        break;
3800
 
                                case 'r':
3801
 
                                        prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
3802
 
                                        break;
3803
 
                                default:
3804
 
                                        if (isalpha(*l)) {
3805
 
                                                ast_log(LOG_WARNING,
3806
 
                                                        "Unrecognized prilocaldialplan %s modifier: %c\n",
3807
 
                                                        *l > 'Z' ? "NPI" : "TON", *l);
3808
 
                                        }
3809
 
                                        break;
3810
 
                                }
3811
 
                                l++;
3812
 
                        }
3813
 
                }
3814
 
                pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
3815
 
                        p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
3816
 
                if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
3817
 
                        if (!strcasecmp(rr_str, "UNKNOWN"))
3818
 
                                redirect_reason = 0;
3819
 
                        else if (!strcasecmp(rr_str, "BUSY"))
3820
 
                                redirect_reason = 1;
3821
 
                        else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
3822
 
                        /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
3823
 
                                redirect_reason = 2;
3824
 
                        else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
3825
 
                                redirect_reason = 15;
3826
 
                        else
3827
 
                                redirect_reason = PRI_REDIR_UNCONDITIONAL;
3828
 
                } else
3829
 
                        redirect_reason = PRI_REDIR_UNCONDITIONAL;
3830
 
                pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
3831
 
 
3832
 
#ifdef SUPPORT_USERUSER
3833
 
                /* User-user info */
3834
 
                useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
3835
 
                if (useruser)
3836
 
                        pri_sr_set_useruser(sr, useruser);
3837
 
#endif
3838
 
 
3839
 
                if (pri_setup(p->pri->pri, p->call, sr)) {
3840
 
                        ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
3841
 
                                c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
3842
 
                        pri_rel(p->pri);
3843
 
                        ast_mutex_unlock(&p->lock);
3844
 
                        pri_sr_free(sr);
3845
 
                        return -1;
3846
 
                }
3847
 
                pri_sr_free(sr);
3848
 
                ast_setstate(ast, AST_STATE_DIALING);
3849
 
                pri_rel(p->pri);
3850
 
        }
3851
 
#endif
3852
 
        ast_mutex_unlock(&p->lock);
3853
 
        return 0;
3854
 
}
3855
 
 
3856
 
static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
3857
 
{
3858
 
        struct dahdi_pvt *p = *pvt;
3859
 
        /* Remove channel from the list */
3860
 
        if (p->prev)
3861
 
                p->prev->next = p->next;
3862
 
        if (p->next)
3863
 
                p->next->prev = p->prev;
3864
 
        if (p->use_smdi)
3865
 
                ast_smdi_interface_unref(p->smdi_iface);
3866
 
        if (p->mwi_event_sub)
3867
 
                ast_event_unsubscribe(p->mwi_event_sub);
3868
 
        if (p->vars) {
3869
 
                ast_variables_destroy(p->vars);
3870
 
        }
3871
 
        ast_mutex_destroy(&p->lock);
3872
 
        dahdi_close_sub(p, SUB_REAL);
3873
 
        if (p->owner)
3874
 
                p->owner->tech_pvt = NULL;
3875
 
        free(p);
3876
 
        *pvt = NULL;
3877
 
}
3878
 
 
3879
 
static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
3880
 
{
3881
 
        int owned = 0;
3882
 
        int i = 0;
3883
 
 
3884
 
        if (!now) {
3885
 
                if (cur->owner) {
3886
 
                        owned = 1;
3887
 
                }
3888
 
 
3889
 
                for (i = 0; i < 3; i++) {
3890
 
                        if (cur->subs[i].owner) {
3891
 
                                owned = 1;
3892
 
                        }
3893
 
                }
3894
 
                if (!owned) {
3895
 
                        if (prev) {
3896
 
                                prev->next = cur->next;
3897
 
                                if (prev->next)
3898
 
                                        prev->next->prev = prev;
3899
 
                                else
3900
 
                                        ifend = prev;
3901
 
                        } else {
3902
 
                                iflist = cur->next;
3903
 
                                if (iflist)
3904
 
                                        iflist->prev = NULL;
3905
 
                                else
3906
 
                                        ifend = NULL;
3907
 
                        }
3908
 
                        destroy_dahdi_pvt(&cur);
3909
 
                }
3910
 
        } else {
3911
 
                if (prev) {
3912
 
                        prev->next = cur->next;
3913
 
                        if (prev->next)
3914
 
                                prev->next->prev = prev;
3915
 
                        else
3916
 
                                ifend = prev;
3917
 
                } else {
3918
 
                        iflist = cur->next;
3919
 
                        if (iflist)
3920
 
                                iflist->prev = NULL;
3921
 
                        else
3922
 
                                ifend = NULL;
3923
 
                }
3924
 
                destroy_dahdi_pvt(&cur);
3925
 
        }
3926
 
        return 0;
3927
 
}
3928
 
 
3929
 
static void destroy_all_channels(void)
3930
 
{
3931
 
        int x;
3932
 
        struct dahdi_pvt *p, *pl;
3933
 
 
3934
 
        while (num_restart_pending) {
3935
 
                usleep(1);
3936
 
        }
3937
 
 
3938
 
        ast_mutex_lock(&iflock);
3939
 
        /* Destroy all the interfaces and free their memory */
3940
 
        p = iflist;
3941
 
        while (p) {
3942
 
                /* Free any callerid */
3943
 
                if (p->cidspill)
3944
 
                        ast_free(p->cidspill);
3945
 
                pl = p;
3946
 
                p = p->next;
3947
 
                x = pl->channel;
3948
 
                /* Free associated memory */
3949
 
                if (pl)
3950
 
                        destroy_dahdi_pvt(&pl);
3951
 
                if (option_verbose > 2)
3952
 
                        ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
3953
 
        }
3954
 
        iflist = NULL;
3955
 
        ifcount = 0;
3956
 
        ast_mutex_unlock(&iflock);
3957
 
}
3958
 
 
3959
 
#if defined(HAVE_PRI)
3960
 
static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
3961
 
 
3962
 
static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
3963
 
{
3964
 
        /* Data will be our digit string */
3965
 
        struct dahdi_pvt *p;
3966
 
        char *digits = (char *) data;
3967
 
 
3968
 
        if (ast_strlen_zero(digits)) {
3969
 
                ast_debug(1, "No digit string sent to application!\n");
3970
 
                return -1;
3971
 
        }
3972
 
 
3973
 
        p = (struct dahdi_pvt *)chan->tech_pvt;
3974
 
 
3975
 
        if (!p) {
3976
 
                ast_debug(1, "Unable to find technology private\n");
3977
 
                return -1;
3978
 
        }
3979
 
 
3980
 
        ast_mutex_lock(&p->lock);
3981
 
 
3982
 
        if (!p->pri || !p->call) {
3983
 
                ast_debug(1, "Unable to find pri or call on channel!\n");
3984
 
                ast_mutex_unlock(&p->lock);
3985
 
                return -1;
3986
 
        }
3987
 
 
3988
 
        if (!pri_grab(p, p->pri)) {
3989
 
                pri_keypad_facility(p->pri->pri, p->call, digits);
3990
 
                pri_rel(p->pri);
3991
 
        } else {
3992
 
                ast_debug(1, "Unable to grab pri to send keypad facility!\n");
3993
 
                ast_mutex_unlock(&p->lock);
3994
 
                return -1;
3995
 
        }
3996
 
 
3997
 
        ast_mutex_unlock(&p->lock);
3998
 
 
3999
 
        return 0;
4000
 
}
4001
 
#endif  /* defined(HAVE_PRI) */
4002
 
 
4003
 
#if defined(HAVE_PRI)
4004
 
#if defined(HAVE_PRI_PROG_W_CAUSE)
4005
 
static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
4006
 
 
4007
 
static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
4008
 
{
4009
 
        /* Data will be our digit string */
4010
 
        struct dahdi_pvt *p;
4011
 
        char *parse;
4012
 
        int res = -1;
4013
 
        AST_DECLARE_APP_ARGS(args,
4014
 
                AST_APP_ARG(destination);
4015
 
                AST_APP_ARG(original);
4016
 
                AST_APP_ARG(reason);
4017
 
        );
4018
 
 
4019
 
        if (ast_strlen_zero(data)) {
4020
 
                ast_log(LOG_DEBUG, "No data sent to application!\n");
4021
 
                return -1;
4022
 
        }
4023
 
 
4024
 
        p = (struct dahdi_pvt *)chan->tech_pvt;
4025
 
 
4026
 
        if (!p) {
4027
 
                ast_log(LOG_DEBUG, "Unable to find technology private\n");
4028
 
                return -1;
4029
 
        }
4030
 
 
4031
 
        parse = ast_strdupa(data);
4032
 
        AST_STANDARD_APP_ARGS(args, parse);
4033
 
 
4034
 
        if (ast_strlen_zero(args.destination)) {
4035
 
                ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
4036
 
                return -1;
4037
 
        }
4038
 
 
4039
 
        if (ast_strlen_zero(args.original)) {
4040
 
                ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
4041
 
                args.original = NULL;
4042
 
        }
4043
 
 
4044
 
        if (ast_strlen_zero(args.reason)) {
4045
 
                ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
4046
 
                args.reason = NULL;
4047
 
        }
4048
 
 
4049
 
        ast_mutex_lock(&p->lock);
4050
 
 
4051
 
        if (!p->pri || !p->call) {
4052
 
                ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
4053
 
                ast_mutex_unlock(&p->lock);
4054
 
                return -1;
4055
 
        }
4056
 
 
4057
 
        switch (p->sig) {
4058
 
        case SIG_PRI:
4059
 
                if (!pri_grab(p, p->pri)) {
4060
 
                        if (chan->_state == AST_STATE_RING) {
4061
 
                                res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
4062
 
                        }
4063
 
                        pri_rel(p->pri);
4064
 
                } else {
4065
 
                        ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
4066
 
                        ast_mutex_unlock(&p->lock);
4067
 
                        return -1;
4068
 
                }
4069
 
                break;
4070
 
        }
4071
 
 
4072
 
        ast_mutex_unlock(&p->lock);
4073
 
 
4074
 
        return res;
4075
 
}
4076
 
#endif  /* defined(HAVE_PRI_PROG_W_CAUSE) */
4077
 
#endif  /* defined(HAVE_PRI) */
4078
 
 
4079
 
#if defined(HAVE_PRI)
4080
 
static int pri_is_up(struct dahdi_pri *pri)
4081
 
{
4082
 
        int x;
4083
 
        for (x = 0; x < NUM_DCHANS; x++) {
4084
 
                if (pri->dchanavail[x] == DCHAN_AVAILABLE)
4085
 
                        return 1;
4086
 
        }
4087
 
        return 0;
4088
 
}
4089
 
#endif  /* defined(HAVE_PRI) */
4090
 
 
4091
 
#if defined(HAVE_PRI)
4092
 
static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
4093
 
{
4094
 
        bearer->owner = &inuse;
4095
 
        bearer->realcall = crv;
4096
 
        crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
4097
 
        if (crv->subs[SUB_REAL].owner)
4098
 
                ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
4099
 
        crv->bearer = bearer;
4100
 
        crv->call = bearer->call;
4101
 
        crv->pri = pri;
4102
 
        return 0;
4103
 
}
4104
 
#endif  /* defined(HAVE_PRI) */
4105
 
 
4106
 
#if defined(HAVE_PRI)
4107
 
static char *pri_order(int level)
4108
 
{
4109
 
        switch (level) {
4110
 
        case 0:
4111
 
                return "Primary";
4112
 
        case 1:
4113
 
                return "Secondary";
4114
 
        case 2:
4115
 
                return "Tertiary";
4116
 
        case 3:
4117
 
                return "Quaternary";
4118
 
        default:
4119
 
                return "<Unknown>";
4120
 
        }
4121
 
}
4122
 
#endif  /* defined(HAVE_PRI) */
4123
 
 
4124
 
#if defined(HAVE_PRI)
4125
 
/* Returns fd of the active dchan */
4126
 
static int pri_active_dchan_fd(struct dahdi_pri *pri)
4127
 
{
4128
 
        int x = -1;
4129
 
 
4130
 
        for (x = 0; x < NUM_DCHANS; x++) {
4131
 
                if ((pri->dchans[x] == pri->pri))
4132
 
                        break;
4133
 
        }
4134
 
 
4135
 
        return pri->fds[x];
4136
 
}
4137
 
#endif  /* defined(HAVE_PRI) */
4138
 
 
4139
 
#if defined(HAVE_PRI)
4140
 
static int pri_find_dchan(struct dahdi_pri *pri)
4141
 
{
4142
 
        int oldslot = -1;
4143
 
        struct pri *old;
4144
 
        int newslot = -1;
4145
 
        int x;
4146
 
        old = pri->pri;
4147
 
        for (x = 0; x < NUM_DCHANS; x++) {
4148
 
                if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
4149
 
                        newslot = x;
4150
 
                if (pri->dchans[x] == old) {
4151
 
                        oldslot = x;
4152
 
                }
4153
 
        }
4154
 
        if (newslot < 0) {
4155
 
                newslot = 0;
4156
 
                /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
4157
 
                if (pri->sig != SIG_BRI_PTMP) {
4158
 
                        ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
4159
 
                                pri->dchannels[newslot]);
4160
 
                }
4161
 
        }
4162
 
        if (old && (oldslot != newslot))
4163
 
                ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
4164
 
                        pri->dchannels[oldslot], pri->dchannels[newslot]);
4165
 
        pri->pri = pri->dchans[newslot];
4166
 
        return 0;
4167
 
}
4168
 
#endif  /* defined(HAVE_PRI) */
4169
 
 
4170
 
#if defined(HAVE_OPENR2)
4171
 
static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
4172
 
 
4173
 
static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
4174
 
{
4175
 
        /* data is whether to accept with charge or no charge */
4176
 
        openr2_call_mode_t accept_mode;
4177
 
        int res, timeout, maxloops;
4178
 
        struct ast_frame *f;
4179
 
        struct dahdi_pvt *p;
4180
 
        char *parse;
4181
 
        AST_DECLARE_APP_ARGS(args,
4182
 
                        AST_APP_ARG(charge);
4183
 
        );
4184
 
 
4185
 
        if (ast_strlen_zero(data)) {
4186
 
                ast_log(LOG_DEBUG, "No data sent to application!\n");
4187
 
                return -1;
4188
 
        }
4189
 
 
4190
 
        if (chan->tech != &dahdi_tech) {
4191
 
                ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
4192
 
                return -1;
4193
 
        }
4194
 
 
4195
 
        p = (struct dahdi_pvt *)chan->tech_pvt;
4196
 
        if (!p) {
4197
 
                ast_log(LOG_DEBUG, "Unable to find technology private!\n");
4198
 
                return -1;
4199
 
        }
4200
 
 
4201
 
        parse = ast_strdupa(data);
4202
 
        AST_STANDARD_APP_ARGS(args, parse);
4203
 
 
4204
 
        if (ast_strlen_zero(args.charge)) {
4205
 
                ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
4206
 
                return -1;
4207
 
        }
4208
 
 
4209
 
        ast_mutex_lock(&p->lock);
4210
 
        if (!p->mfcr2 || !p->mfcr2call) {
4211
 
                ast_mutex_unlock(&p->lock);
4212
 
                ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
4213
 
                return -1;
4214
 
        }
4215
 
 
4216
 
        if (p->mfcr2_call_accepted) {
4217
 
                ast_mutex_unlock(&p->lock);
4218
 
                ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
4219
 
                return 0;
4220
 
        }
4221
 
        accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
4222
 
        if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
4223
 
                ast_mutex_unlock(&p->lock);
4224
 
                ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
4225
 
                return -1;
4226
 
        }
4227
 
        ast_mutex_unlock(&p->lock);
4228
 
 
4229
 
        res = 0;
4230
 
        timeout = 100;
4231
 
        maxloops = 50; /* wait up to 5 seconds */
4232
 
        /* we need to read() until the call is accepted */
4233
 
        while (maxloops > 0) {
4234
 
                maxloops--;
4235
 
                if (ast_check_hangup(chan)) {
4236
 
                        break;
4237
 
                }
4238
 
                res = ast_waitfor(chan, timeout);
4239
 
                if (res < 0) {
4240
 
                        ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
4241
 
                        res = -1;
4242
 
                        break;
4243
 
                }
4244
 
                if (res == 0) {
4245
 
                        continue;
4246
 
                }
4247
 
                f = ast_read(chan);
4248
 
                if (!f) {
4249
 
                        ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
4250
 
                        res = -1;
4251
 
                        break;
4252
 
                }
4253
 
                if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
4254
 
                        ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
4255
 
                        ast_frfree(f);
4256
 
                        res = -1;
4257
 
                        break;
4258
 
                }
4259
 
                ast_frfree(f);
4260
 
                ast_mutex_lock(&p->lock);
4261
 
                if (p->mfcr2_call_accepted) {
4262
 
                        ast_mutex_unlock(&p->lock);
4263
 
                        ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
4264
 
                        break;
4265
 
                }
4266
 
                ast_mutex_unlock(&p->lock);
4267
 
        }
4268
 
        if (res == -1) {
4269
 
                ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
4270
 
        }
4271
 
        return res;
4272
 
}
4273
 
 
4274
 
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
4275
 
{
4276
 
        openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
4277
 
        switch (cause) {
4278
 
        case AST_CAUSE_USER_BUSY:
4279
 
        case AST_CAUSE_CALL_REJECTED:
4280
 
        case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
4281
 
                r2cause = OR2_CAUSE_BUSY_NUMBER;
4282
 
                break;
4283
 
 
4284
 
        case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
4285
 
        case AST_CAUSE_SWITCH_CONGESTION:
4286
 
                r2cause = OR2_CAUSE_NETWORK_CONGESTION;
4287
 
                break;
4288
 
 
4289
 
        case AST_CAUSE_UNALLOCATED:
4290
 
                r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
4291
 
                break;
4292
 
 
4293
 
        case AST_CAUSE_NETWORK_OUT_OF_ORDER:
4294
 
        case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
4295
 
                r2cause = OR2_CAUSE_OUT_OF_ORDER;
4296
 
                break;
4297
 
 
4298
 
        case AST_CAUSE_NO_ANSWER:
4299
 
        case AST_CAUSE_NO_USER_RESPONSE:
4300
 
                r2cause = OR2_CAUSE_NO_ANSWER;
4301
 
                break;
4302
 
 
4303
 
        default:
4304
 
                r2cause = OR2_CAUSE_NORMAL_CLEARING;
4305
 
                break;
4306
 
        }
4307
 
        ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
4308
 
                        cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
4309
 
        return r2cause;
4310
 
}
4311
 
#endif
4312
 
 
4313
 
static int dahdi_hangup(struct ast_channel *ast)
4314
 
{
4315
 
        int res;
4316
 
        int idx,x, law;
4317
 
        /*static int restore_gains(struct dahdi_pvt *p);*/
4318
 
        struct dahdi_pvt *p = ast->tech_pvt;
4319
 
        struct dahdi_pvt *tmp = NULL;
4320
 
        struct dahdi_pvt *prev = NULL;
4321
 
        struct dahdi_params par;
4322
 
 
4323
 
        ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
4324
 
        if (!ast->tech_pvt) {
4325
 
                ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
4326
 
                return 0;
4327
 
        }
4328
 
 
4329
 
        ast_mutex_lock(&p->lock);
4330
 
 
4331
 
        idx = dahdi_get_index(ast, p, 1);
4332
 
 
4333
 
        if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
4334
 
                x = 1;
4335
 
                ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
4336
 
                p->cid_num[0] = '\0';
4337
 
                p->cid_name[0] = '\0';
4338
 
        }
4339
 
 
4340
 
        x = 0;
4341
 
        dahdi_confmute(p, 0);
4342
 
        p->muting = 0;
4343
 
        restore_gains(p);
4344
 
        if (p->origcid_num) {
4345
 
                ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
4346
 
                ast_free(p->origcid_num);
4347
 
                p->origcid_num = NULL;
4348
 
        }
4349
 
        if (p->origcid_name) {
4350
 
                ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
4351
 
                ast_free(p->origcid_name);
4352
 
                p->origcid_name = NULL;
4353
 
        }
4354
 
        if (p->dsp)
4355
 
                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
4356
 
        p->exten[0] = '\0';
4357
 
 
4358
 
        ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
4359
 
                p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4360
 
        p->ignoredtmf = 0;
4361
 
 
4362
 
        if (idx > -1) {
4363
 
                /* Real channel, do some fixup */
4364
 
                p->subs[idx].owner = NULL;
4365
 
                p->subs[idx].needanswer = 0;
4366
 
                p->subs[idx].needflash = 0;
4367
 
                p->subs[idx].needringing = 0;
4368
 
                p->subs[idx].needbusy = 0;
4369
 
                p->subs[idx].needcongestion = 0;
4370
 
                p->subs[idx].linear = 0;
4371
 
                p->subs[idx].needcallerid = 0;
4372
 
                p->polarity = POLARITY_IDLE;
4373
 
                dahdi_setlinear(p->subs[idx].dfd, 0);
4374
 
                if (idx == SUB_REAL) {
4375
 
                        if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
4376
 
                                ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
4377
 
                                if (p->subs[SUB_CALLWAIT].inthreeway) {
4378
 
                                        /* We had flipped over to answer a callwait and now it's gone */
4379
 
                                        ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
4380
 
                                        /* Move to the call-wait, but un-own us until they flip back. */
4381
 
                                        swap_subs(p, SUB_CALLWAIT, SUB_REAL);
4382
 
                                        unalloc_sub(p, SUB_CALLWAIT);
4383
 
                                        p->owner = NULL;
4384
 
                                } else {
4385
 
                                        /* The three way hung up, but we still have a call wait */
4386
 
                                        ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
4387
 
                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
4388
 
                                        unalloc_sub(p, SUB_THREEWAY);
4389
 
                                        if (p->subs[SUB_REAL].inthreeway) {
4390
 
                                                /* This was part of a three way call.  Immediately make way for
4391
 
                                                   another call */
4392
 
                                                ast_debug(1, "Call was complete, setting owner to former third call\n");
4393
 
                                                p->owner = p->subs[SUB_REAL].owner;
4394
 
                                        } else {
4395
 
                                                /* This call hasn't been completed yet...  Set owner to NULL */
4396
 
                                                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
4397
 
                                                p->owner = NULL;
4398
 
                                        }
4399
 
                                        p->subs[SUB_REAL].inthreeway = 0;
4400
 
                                }
4401
 
                        } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
4402
 
                                /* Move to the call-wait and switch back to them. */
4403
 
                                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
4404
 
                                unalloc_sub(p, SUB_CALLWAIT);
4405
 
                                p->owner = p->subs[SUB_REAL].owner;
4406
 
                                if (p->owner->_state != AST_STATE_UP)
4407
 
                                        p->subs[SUB_REAL].needanswer = 1;
4408
 
                                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
4409
 
                                        ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4410
 
                        } else if (p->subs[SUB_THREEWAY].dfd > -1) {
4411
 
                                swap_subs(p, SUB_THREEWAY, SUB_REAL);
4412
 
                                unalloc_sub(p, SUB_THREEWAY);
4413
 
                                if (p->subs[SUB_REAL].inthreeway) {
4414
 
                                        /* This was part of a three way call.  Immediately make way for
4415
 
                                           another call */
4416
 
                                        ast_debug(1, "Call was complete, setting owner to former third call\n");
4417
 
                                        p->owner = p->subs[SUB_REAL].owner;
4418
 
                                } else {
4419
 
                                        /* This call hasn't been completed yet...  Set owner to NULL */
4420
 
                                        ast_debug(1, "Call was incomplete, setting owner to NULL\n");
4421
 
                                        p->owner = NULL;
4422
 
                                }
4423
 
                                p->subs[SUB_REAL].inthreeway = 0;
4424
 
                        }
4425
 
                } else if (idx == SUB_CALLWAIT) {
4426
 
                        /* Ditch the holding callwait call, and immediately make it availabe */
4427
 
                        if (p->subs[SUB_CALLWAIT].inthreeway) {
4428
 
                                /* This is actually part of a three way, placed on hold.  Place the third part
4429
 
                                   on music on hold now */
4430
 
                                if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4431
 
                                        ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4432
 
                                                S_OR(p->mohsuggest, NULL),
4433
 
                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4434
 
                                }
4435
 
                                p->subs[SUB_THREEWAY].inthreeway = 0;
4436
 
                                /* Make it the call wait now */
4437
 
                                swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
4438
 
                                unalloc_sub(p, SUB_THREEWAY);
4439
 
                        } else
4440
 
                                unalloc_sub(p, SUB_CALLWAIT);
4441
 
                } else if (idx == SUB_THREEWAY) {
4442
 
                        if (p->subs[SUB_CALLWAIT].inthreeway) {
4443
 
                                /* The other party of the three way call is currently in a call-wait state.
4444
 
                                   Start music on hold for them, and take the main guy out of the third call */
4445
 
                                if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4446
 
                                        ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4447
 
                                                S_OR(p->mohsuggest, NULL),
4448
 
                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4449
 
                                }
4450
 
                                p->subs[SUB_CALLWAIT].inthreeway = 0;
4451
 
                        }
4452
 
                        p->subs[SUB_REAL].inthreeway = 0;
4453
 
                        /* If this was part of a three way call index, let us make
4454
 
                           another three way call */
4455
 
                        unalloc_sub(p, SUB_THREEWAY);
4456
 
                } else {
4457
 
                        /* This wasn't any sort of call, but how are we an index? */
4458
 
                        ast_log(LOG_WARNING, "Index found but not any type of call?\n");
4459
 
                }
4460
 
        }
4461
 
 
4462
 
        if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
4463
 
                p->owner = NULL;
4464
 
                p->ringt = 0;
4465
 
                p->distinctivering = 0;
4466
 
                p->confirmanswer = 0;
4467
 
                p->cidrings = 1;
4468
 
                p->outgoing = 0;
4469
 
                p->digital = 0;
4470
 
                p->faxhandled = 0;
4471
 
                p->pulsedial = 0;
4472
 
                p->onhooktime = time(NULL);
4473
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
4474
 
                p->proceeding = 0;
4475
 
                p->dialing = 0;
4476
 
                p->progress = 0;
4477
 
                p->alerting = 0;
4478
 
                p->setup_ack = 0;
4479
 
                p->rlt = 0;
4480
 
#endif
4481
 
                if (p->dsp) {
4482
 
                        ast_dsp_free(p->dsp);
4483
 
                        p->dsp = NULL;
4484
 
                }
4485
 
 
4486
 
                if (p->faxbuffersinuse) {
4487
 
                        /* faxbuffers are in use, revert them */
4488
 
                        struct dahdi_bufferinfo bi = {
4489
 
                                .txbufpolicy = p->buf_policy,
4490
 
                                .rxbufpolicy = p->buf_policy,
4491
 
                                .bufsize = p->bufsize,
4492
 
                                .numbufs = p->buf_no
4493
 
                        };
4494
 
                        int bpres;
4495
 
 
4496
 
                        if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
4497
 
                                ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
4498
 
                        }
4499
 
                        p->faxbuffersinuse = 0;
4500
 
                }
4501
 
 
4502
 
                law = DAHDI_LAW_DEFAULT;
4503
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
4504
 
                if (res < 0)
4505
 
                        ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
4506
 
                /* Perform low level hangup if no owner left */
4507
 
#ifdef HAVE_SS7
4508
 
                if (p->ss7) {
4509
 
                        if (p->ss7call) {
4510
 
                                if (!ss7_grab(p, p->ss7)) {
4511
 
                                        if (!p->alreadyhungup) {
4512
 
                                                const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
4513
 
                                                int icause = ast->hangupcause ? ast->hangupcause : -1;
4514
 
 
4515
 
                                                if (cause) {
4516
 
                                                        if (atoi(cause))
4517
 
                                                                icause = atoi(cause);
4518
 
                                                }
4519
 
                                                isup_rel(p->ss7->ss7, p->ss7call, icause);
4520
 
                                                ss7_rel(p->ss7);
4521
 
                                                p->alreadyhungup = 1;
4522
 
                                        } else
4523
 
                                                ast_log(LOG_WARNING, "Trying to hangup twice!\n");
4524
 
                                } else {
4525
 
                                        ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
4526
 
                                        res = -1;
4527
 
                                }
4528
 
                        }
4529
 
                }
4530
 
#endif
4531
 
#ifdef HAVE_OPENR2
4532
 
                p->cid_num[0] = '\0';
4533
 
                p->cid_name[0] = '\0';
4534
 
                if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
4535
 
                        ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
4536
 
                        /* If it's an incoming call, check the mfcr2_forced_release setting */
4537
 
                        if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
4538
 
                                dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
4539
 
                        } else {
4540
 
                                const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
4541
 
                                int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
4542
 
                                openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
4543
 
                                                                                      : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
4544
 
                                dahdi_r2_disconnect_call(p, r2cause);
4545
 
                        }
4546
 
                } else if (p->mfcr2call) {
4547
 
                        ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
4548
 
                        /* since ast_request() was called but not ast_call() we have not yet dialed
4549
 
                        and the openr2 stack will not call on_call_end callback, we need to unset
4550
 
                        the mfcr2call flag and bump the monitor count so the monitor thread can take
4551
 
                        care of this channel events from now on */
4552
 
                        p->mfcr2call = 0;
4553
 
                }
4554
 
#endif
4555
 
#ifdef HAVE_PRI
4556
 
                if (p->pri) {
4557
 
#ifdef SUPPORT_USERUSER
4558
 
                        const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
4559
 
#endif
4560
 
 
4561
 
                        /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
4562
 
                        if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
4563
 
                                if (!pri_grab(p, p->pri)) {
4564
 
                                        if (p->alreadyhungup) {
4565
 
                                                ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
4566
 
 
4567
 
#ifdef SUPPORT_USERUSER
4568
 
                                                pri_call_set_useruser(p->call, useruser);
4569
 
#endif
4570
 
 
4571
 
                                                pri_hangup(p->pri->pri, p->call, -1);
4572
 
                                                p->call = NULL;
4573
 
                                                if (p->bearer)
4574
 
                                                        p->bearer->call = NULL;
4575
 
                                        } else {
4576
 
                                                const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
4577
 
                                                int icause = ast->hangupcause ? ast->hangupcause : -1;
4578
 
                                                ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
4579
 
 
4580
 
#ifdef SUPPORT_USERUSER
4581
 
                                                pri_call_set_useruser(p->call, useruser);
4582
 
#endif
4583
 
 
4584
 
                                                p->alreadyhungup = 1;
4585
 
                                                if (p->bearer)
4586
 
                                                        p->bearer->alreadyhungup = 1;
4587
 
                                                if (cause) {
4588
 
                                                        if (atoi(cause))
4589
 
                                                                icause = atoi(cause);
4590
 
                                                }
4591
 
                                                pri_hangup(p->pri->pri, p->call, icause);
4592
 
                                        }
4593
 
                                        if (res < 0)
4594
 
                                                ast_log(LOG_WARNING, "pri_disconnect failed\n");
4595
 
                                        pri_rel(p->pri);
4596
 
                                } else {
4597
 
                                        ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4598
 
                                        res = -1;
4599
 
                                }
4600
 
                        } else {
4601
 
                                if (p->bearer)
4602
 
                                        ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
4603
 
                                p->call = NULL;
4604
 
                                res = 0;
4605
 
                        }
4606
 
                }
4607
 
#endif
4608
 
                if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
4609
 
                        && (p->sig != SIG_BRI)
4610
 
                        && (p->sig != SIG_BRI_PTMP))
4611
 
                        && (p->sig != SIG_MFCR2))
4612
 
                        res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
4613
 
                if (res < 0) {
4614
 
                        ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
4615
 
                }
4616
 
                switch (p->sig) {
4617
 
                case SIG_FXOGS:
4618
 
                case SIG_FXOLS:
4619
 
                case SIG_FXOKS:
4620
 
                        memset(&par, 0, sizeof(par));
4621
 
                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
4622
 
                        if (!res) {
4623
 
#if 0
4624
 
                                ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
4625
 
#endif
4626
 
                                /* If they're off hook, try playing congestion */
4627
 
                                if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
4628
 
                                        tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4629
 
                                else
4630
 
                                        tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4631
 
                                p->fxsoffhookstate = par.rxisoffhook;
4632
 
                        }
4633
 
                        break;
4634
 
                case SIG_FXSGS:
4635
 
                case SIG_FXSLS:
4636
 
                case SIG_FXSKS:
4637
 
                        /* Make sure we're not made available for at least two seconds assuming
4638
 
                           we were actually used for an inbound or outbound call. */
4639
 
                        if (ast->_state != AST_STATE_RESERVED) {
4640
 
                                time(&p->guardtime);
4641
 
                                p->guardtime += 2;
4642
 
                        }
4643
 
                        break;
4644
 
                default:
4645
 
                        tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4646
 
                }
4647
 
                if (p->cidspill)
4648
 
                        ast_free(p->cidspill);
4649
 
                if (p->sig)
4650
 
                        dahdi_disable_ec(p);
4651
 
                x = 0;
4652
 
                ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
4653
 
                ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
4654
 
                p->didtdd = 0;
4655
 
                p->cidspill = NULL;
4656
 
                p->callwaitcas = 0;
4657
 
                p->callwaiting = p->permcallwaiting;
4658
 
                p->hidecallerid = p->permhidecallerid;
4659
 
                p->waitingfordt.tv_sec = 0;
4660
 
                p->dialing = 0;
4661
 
                p->rdnis[0] = '\0';
4662
 
                update_conf(p);
4663
 
                reset_conf(p);
4664
 
                /* Restore data mode */
4665
 
                if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
4666
 
                        x = 0;
4667
 
                        ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
4668
 
                }
4669
 
#ifdef HAVE_PRI
4670
 
                if (p->bearer) {
4671
 
                        ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
4672
 
                        /* Free up the bearer channel as well, and
4673
 
                           don't use its file descriptor anymore */
4674
 
                        update_conf(p->bearer);
4675
 
                        reset_conf(p->bearer);
4676
 
                        p->bearer->owner = NULL;
4677
 
                        p->bearer->realcall = NULL;
4678
 
                        p->bearer = NULL;
4679
 
                        p->subs[SUB_REAL].dfd = -1;
4680
 
                        p->pri = NULL;
4681
 
                }
4682
 
#endif
4683
 
                if (num_restart_pending == 0)
4684
 
                        restart_monitor();
4685
 
        }
4686
 
 
4687
 
        p->callwaitingrepeat = 0;
4688
 
        p->cidcwexpire = 0;
4689
 
        p->oprmode = 0;
4690
 
        ast->tech_pvt = NULL;
4691
 
        ast_mutex_unlock(&p->lock);
4692
 
        ast_module_unref(ast_module_info->self);
4693
 
        ast_verb(3, "Hungup '%s'\n", ast->name);
4694
 
 
4695
 
        ast_mutex_lock(&iflock);
4696
 
 
4697
 
        if (p->restartpending) {
4698
 
                num_restart_pending--;
4699
 
        }
4700
 
 
4701
 
        tmp = iflist;
4702
 
        prev = NULL;
4703
 
        if (p->destroy) {
4704
 
                while (tmp) {
4705
 
                        if (tmp == p) {
4706
 
                                destroy_channel(prev, tmp, 0);
4707
 
                                break;
4708
 
                        } else {
4709
 
                                prev = tmp;
4710
 
                                tmp = tmp->next;
4711
 
                        }
4712
 
                }
4713
 
        }
4714
 
        ast_mutex_unlock(&iflock);
4715
 
        return 0;
4716
 
}
4717
 
 
4718
 
static int dahdi_answer(struct ast_channel *ast)
4719
 
{
4720
 
        struct dahdi_pvt *p = ast->tech_pvt;
4721
 
        int res = 0;
4722
 
        int idx;
4723
 
        int oldstate = ast->_state;
4724
 
        ast_setstate(ast, AST_STATE_UP);
4725
 
        ast_mutex_lock(&p->lock);
4726
 
        idx = dahdi_get_index(ast, p, 0);
4727
 
        if (idx < 0)
4728
 
                idx = SUB_REAL;
4729
 
        /* nothing to do if a radio channel */
4730
 
        if ((p->radio || (p->oprmode < 0))) {
4731
 
                ast_mutex_unlock(&p->lock);
4732
 
                return 0;
4733
 
        }
4734
 
        switch (p->sig) {
4735
 
        case SIG_FXSLS:
4736
 
        case SIG_FXSGS:
4737
 
        case SIG_FXSKS:
4738
 
                p->ringt = 0;
4739
 
                /* Fall through */
4740
 
        case SIG_EM:
4741
 
        case SIG_EM_E1:
4742
 
        case SIG_EMWINK:
4743
 
        case SIG_FEATD:
4744
 
        case SIG_FEATDMF:
4745
 
        case SIG_FEATDMF_TA:
4746
 
        case SIG_E911:
4747
 
        case SIG_FGC_CAMA:
4748
 
        case SIG_FGC_CAMAMF:
4749
 
        case SIG_FEATB:
4750
 
        case SIG_SF:
4751
 
        case SIG_SFWINK:
4752
 
        case SIG_SF_FEATD:
4753
 
        case SIG_SF_FEATDMF:
4754
 
        case SIG_SF_FEATB:
4755
 
        case SIG_FXOLS:
4756
 
        case SIG_FXOGS:
4757
 
        case SIG_FXOKS:
4758
 
                /* Pick up the line */
4759
 
                ast_debug(1, "Took %s off hook\n", ast->name);
4760
 
                if (p->hanguponpolarityswitch) {
4761
 
                        p->polaritydelaytv = ast_tvnow();
4762
 
                }
4763
 
                res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4764
 
                tone_zone_play_tone(p->subs[idx].dfd, -1);
4765
 
                p->dialing = 0;
4766
 
                if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
4767
 
                        if (oldstate == AST_STATE_RINGING) {
4768
 
                                ast_debug(1, "Finally swapping real and threeway\n");
4769
 
                                tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
4770
 
                                swap_subs(p, SUB_THREEWAY, SUB_REAL);
4771
 
                                p->owner = p->subs[SUB_REAL].owner;
4772
 
                        }
4773
 
                }
4774
 
                if (p->sig & __DAHDI_SIG_FXS) {
4775
 
                        dahdi_enable_ec(p);
4776
 
                        dahdi_train_ec(p);
4777
 
                }
4778
 
                break;
4779
 
#ifdef HAVE_PRI
4780
 
        case SIG_BRI:
4781
 
        case SIG_BRI_PTMP:
4782
 
        case SIG_PRI:
4783
 
                /* Send a pri acknowledge */
4784
 
                if (!pri_grab(p, p->pri)) {
4785
 
                        p->proceeding = 1;
4786
 
                        p->dialing = 0;
4787
 
                        res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
4788
 
                        pri_rel(p->pri);
4789
 
                } else {
4790
 
                        ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4791
 
                        res = -1;
4792
 
                }
4793
 
                break;
4794
 
#endif
4795
 
#ifdef HAVE_SS7
4796
 
        case SIG_SS7:
4797
 
                if (!ss7_grab(p, p->ss7)) {
4798
 
                        p->proceeding = 1;
4799
 
                        res = isup_anm(p->ss7->ss7, p->ss7call);
4800
 
                        ss7_rel(p->ss7);
4801
 
                } else {
4802
 
                        ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
4803
 
                        res = -1;
4804
 
                }
4805
 
                break;
4806
 
#endif
4807
 
#ifdef HAVE_OPENR2
4808
 
        case SIG_MFCR2:
4809
 
                if (!p->mfcr2_call_accepted) {
4810
 
                        /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
4811
 
                           openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
4812
 
                        p->mfcr2_answer_pending = 1;
4813
 
                        if (p->mfcr2_charge_calls) {
4814
 
                                ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
4815
 
                                openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
4816
 
                        } else {
4817
 
                                ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
4818
 
                                openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
4819
 
                        }
4820
 
                } else {
4821
 
                        ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
4822
 
                        dahdi_r2_answer(p);
4823
 
                }
4824
 
                break;
4825
 
#endif
4826
 
        case 0:
4827
 
                ast_mutex_unlock(&p->lock);
4828
 
                return 0;
4829
 
        default:
4830
 
                ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
4831
 
                res = -1;
4832
 
        }
4833
 
        ast_mutex_unlock(&p->lock);
4834
 
        return res;
4835
 
}
4836
 
 
4837
 
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
4838
 
{
4839
 
        char *cp;
4840
 
        signed char *scp;
4841
 
        int x;
4842
 
        int idx;
4843
 
        struct dahdi_pvt *p = chan->tech_pvt, *pp;
4844
 
        struct oprmode *oprmode;
4845
 
 
4846
 
 
4847
 
        /* all supported options require data */
4848
 
        if (!data || (datalen < 1)) {
4849
 
                errno = EINVAL;
4850
 
                return -1;
4851
 
        }
4852
 
 
4853
 
        switch (option) {
4854
 
        case AST_OPTION_TXGAIN:
4855
 
                scp = (signed char *) data;
4856
 
                idx = dahdi_get_index(chan, p, 0);
4857
 
                if (idx < 0) {
4858
 
                        ast_log(LOG_WARNING, "No index in TXGAIN?\n");
4859
 
                        return -1;
4860
 
                }
4861
 
                ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
4862
 
                return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
4863
 
        case AST_OPTION_RXGAIN:
4864
 
                scp = (signed char *) data;
4865
 
                idx = dahdi_get_index(chan, p, 0);
4866
 
                if (idx < 0) {
4867
 
                        ast_log(LOG_WARNING, "No index in RXGAIN?\n");
4868
 
                        return -1;
4869
 
                }
4870
 
                ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
4871
 
                return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
4872
 
        case AST_OPTION_TONE_VERIFY:
4873
 
                if (!p->dsp)
4874
 
                        break;
4875
 
                cp = (char *) data;
4876
 
                switch (*cp) {
4877
 
                case 1:
4878
 
                        ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
4879
 
                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
4880
 
                        break;
4881
 
                case 2:
4882
 
                        ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
4883
 
                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
4884
 
                        break;
4885
 
                default:
4886
 
                        ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
4887
 
                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
4888
 
                        break;
4889
 
                }
4890
 
                break;
4891
 
        case AST_OPTION_TDD:
4892
 
                /* turn on or off TDD */
4893
 
                cp = (char *) data;
4894
 
                p->mate = 0;
4895
 
                if (!*cp) { /* turn it off */
4896
 
                        ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
4897
 
                        if (p->tdd)
4898
 
                                tdd_free(p->tdd);
4899
 
                        p->tdd = 0;
4900
 
                        break;
4901
 
                }
4902
 
                ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
4903
 
                        (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
4904
 
                dahdi_disable_ec(p);
4905
 
                /* otherwise, turn it on */
4906
 
                if (!p->didtdd) { /* if havent done it yet */
4907
 
                        unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
4908
 
                        unsigned char *buf;
4909
 
                        int size, res, fd, len;
4910
 
                        struct pollfd fds[1];
4911
 
 
4912
 
                        buf = mybuf;
4913
 
                        memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
4914
 
                        ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
4915
 
                        len = 40000;
4916
 
                        idx = dahdi_get_index(chan, p, 0);
4917
 
                        if (idx < 0) {
4918
 
                                ast_log(LOG_WARNING, "No index in TDD?\n");
4919
 
                                return -1;
4920
 
                        }
4921
 
                        fd = p->subs[idx].dfd;
4922
 
                        while (len) {
4923
 
                                if (ast_check_hangup(chan))
4924
 
                                        return -1;
4925
 
                                size = len;
4926
 
                                if (size > READ_SIZE)
4927
 
                                        size = READ_SIZE;
4928
 
                                fds[0].fd = fd;
4929
 
                                fds[0].events = POLLPRI | POLLOUT;
4930
 
                                fds[0].revents = 0;
4931
 
                                res = poll(fds, 1, -1);
4932
 
                                if (!res) {
4933
 
                                        ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
4934
 
                                        continue;
4935
 
                                }
4936
 
                                /* if got exception */
4937
 
                                if (fds[0].revents & POLLPRI)
4938
 
                                        return -1;
4939
 
                                if (!(fds[0].revents & POLLOUT)) {
4940
 
                                        ast_debug(1, "write fd not ready on channel %d\n", p->channel);
4941
 
                                        continue;
4942
 
                                }
4943
 
                                res = write(fd, buf, size);
4944
 
                                if (res != size) {
4945
 
                                        if (res == -1) return -1;
4946
 
                                        ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
4947
 
                                        break;
4948
 
                                }
4949
 
                                len -= size;
4950
 
                                buf += size;
4951
 
                        }
4952
 
                        p->didtdd = 1; /* set to have done it now */
4953
 
                }
4954
 
                if (*cp == 2) { /* Mate mode */
4955
 
                        if (p->tdd)
4956
 
                                tdd_free(p->tdd);
4957
 
                        p->tdd = 0;
4958
 
                        p->mate = 1;
4959
 
                        break;
4960
 
                }
4961
 
                if (!p->tdd) { /* if we dont have one yet */
4962
 
                        p->tdd = tdd_new(); /* allocate one */
4963
 
                }
4964
 
                break;
4965
 
        case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
4966
 
                if (!p->dsp)
4967
 
                        break;
4968
 
                cp = (char *) data;
4969
 
                ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
4970
 
                        *cp ? "ON" : "OFF", (int) *cp, chan->name);
4971
 
                ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
4972
 
                break;
4973
 
        case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
4974
 
                cp = (char *) data;
4975
 
                if (!*cp) {
4976
 
                        ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
4977
 
                        x = 0;
4978
 
                        dahdi_disable_ec(p);
4979
 
                } else {
4980
 
                        ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
4981
 
                        x = 1;
4982
 
                }
4983
 
                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
4984
 
                        ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
4985
 
                break;
4986
 
        case AST_OPTION_OPRMODE:  /* Operator services mode */
4987
 
                oprmode = (struct oprmode *) data;
4988
 
                /* We don't support operator mode across technologies */
4989
 
                if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
4990
 
                        ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
4991
 
                                        chan->tech->type, oprmode->peer->tech->type);
4992
 
                        errno = EINVAL;
4993
 
                        return -1;
4994
 
                }
4995
 
                pp = oprmode->peer->tech_pvt;
4996
 
                p->oprmode = pp->oprmode = 0;
4997
 
                /* setup peers */
4998
 
                p->oprpeer = pp;
4999
 
                pp->oprpeer = p;
5000
 
                /* setup modes, if any */
5001
 
                if (oprmode->mode)
5002
 
                {
5003
 
                        pp->oprmode = oprmode->mode;
5004
 
                        p->oprmode = -oprmode->mode;
5005
 
                }
5006
 
                ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
5007
 
                        oprmode->mode, chan->name,oprmode->peer->name);
5008
 
                break;
5009
 
        case AST_OPTION_ECHOCAN:
5010
 
                cp = (char *) data;
5011
 
                if (*cp) {
5012
 
                        ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
5013
 
                        dahdi_enable_ec(p);
5014
 
                } else {
5015
 
                        ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
5016
 
                        dahdi_disable_ec(p);
5017
 
                }
5018
 
                break;
5019
 
        }
5020
 
        errno = 0;
5021
 
 
5022
 
        return 0;
5023
 
}
5024
 
 
5025
 
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
5026
 
{
5027
 
        struct dahdi_pvt *p = chan->tech_pvt;
5028
 
 
5029
 
        if (!strcasecmp(data, "rxgain")) {
5030
 
                ast_mutex_lock(&p->lock);
5031
 
                snprintf(buf, len, "%f", p->rxgain);
5032
 
                ast_mutex_unlock(&p->lock);
5033
 
        } else if (!strcasecmp(data, "txgain")) {
5034
 
                ast_mutex_lock(&p->lock);
5035
 
                snprintf(buf, len, "%f", p->txgain);
5036
 
                ast_mutex_unlock(&p->lock);
5037
 
        } else {
5038
 
                ast_copy_string(buf, "", len);
5039
 
        }
5040
 
        return 0;
5041
 
}
5042
 
 
5043
 
 
5044
 
static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
5045
 
{
5046
 
        /* Unlink a specific slave or all slaves/masters from a given master */
5047
 
        int x;
5048
 
        int hasslaves;
5049
 
        if (!master)
5050
 
                return;
5051
 
        if (needlock) {
5052
 
                ast_mutex_lock(&master->lock);
5053
 
                if (slave) {
5054
 
                        while (ast_mutex_trylock(&slave->lock)) {
5055
 
                                DEADLOCK_AVOIDANCE(&master->lock);
5056
 
                        }
5057
 
                }
5058
 
        }
5059
 
        hasslaves = 0;
5060
 
        for (x = 0; x < MAX_SLAVES; x++) {
5061
 
                if (master->slaves[x]) {
5062
 
                        if (!slave || (master->slaves[x] == slave)) {
5063
 
                                /* Take slave out of the conference */
5064
 
                                ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
5065
 
                                conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
5066
 
                                conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
5067
 
                                master->slaves[x]->master = NULL;
5068
 
                                master->slaves[x] = NULL;
5069
 
                        } else
5070
 
                                hasslaves = 1;
5071
 
                }
5072
 
                if (!hasslaves)
5073
 
                        master->inconference = 0;
5074
 
        }
5075
 
        if (!slave) {
5076
 
                if (master->master) {
5077
 
                        /* Take master out of the conference */
5078
 
                        conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
5079
 
                        conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
5080
 
                        hasslaves = 0;
5081
 
                        for (x = 0; x < MAX_SLAVES; x++) {
5082
 
                                if (master->master->slaves[x] == master)
5083
 
                                        master->master->slaves[x] = NULL;
5084
 
                                else if (master->master->slaves[x])
5085
 
                                        hasslaves = 1;
5086
 
                        }
5087
 
                        if (!hasslaves)
5088
 
                                master->master->inconference = 0;
5089
 
                }
5090
 
                master->master = NULL;
5091
 
        }
5092
 
        update_conf(master);
5093
 
        if (needlock) {
5094
 
                if (slave)
5095
 
                        ast_mutex_unlock(&slave->lock);
5096
 
                ast_mutex_unlock(&master->lock);
5097
 
        }
5098
 
}
5099
 
 
5100
 
static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
5101
 
        int x;
5102
 
        if (!slave || !master) {
5103
 
                ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
5104
 
                return;
5105
 
        }
5106
 
        for (x = 0; x < MAX_SLAVES; x++) {
5107
 
                if (!master->slaves[x]) {
5108
 
                        master->slaves[x] = slave;
5109
 
                        break;
5110
 
                }
5111
 
        }
5112
 
        if (x >= MAX_SLAVES) {
5113
 
                ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
5114
 
                master->slaves[MAX_SLAVES - 1] = slave;
5115
 
        }
5116
 
        if (slave->master)
5117
 
                ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
5118
 
        slave->master = master;
5119
 
 
5120
 
        ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
5121
 
}
5122
 
 
5123
 
static void disable_dtmf_detect(struct dahdi_pvt *p)
5124
 
{
5125
 
        int val;
5126
 
 
5127
 
        p->ignoredtmf = 1;
5128
 
 
5129
 
        val = 0;
5130
 
        ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
5131
 
 
5132
 
        if (!p->hardwaredtmf && p->dsp) {
5133
 
                p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
5134
 
                ast_dsp_set_features(p->dsp, p->dsp_features);
5135
 
        }
5136
 
}
5137
 
 
5138
 
static void enable_dtmf_detect(struct dahdi_pvt *p)
5139
 
{
5140
 
        int val;
5141
 
 
5142
 
        if (p->channel == CHAN_PSEUDO)
5143
 
                return;
5144
 
 
5145
 
        p->ignoredtmf = 0;
5146
 
 
5147
 
        val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5148
 
        ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
5149
 
 
5150
 
        if (!p->hardwaredtmf && p->dsp) {
5151
 
                p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
5152
 
                ast_dsp_set_features(p->dsp, p->dsp_features);
5153
 
        }
5154
 
}
5155
 
 
5156
 
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)
5157
 
{
5158
 
        struct ast_channel *who;
5159
 
        struct dahdi_pvt *p0, *p1, *op0, *op1;
5160
 
        struct dahdi_pvt *master = NULL, *slave = NULL;
5161
 
        struct ast_frame *f;
5162
 
        int inconf = 0;
5163
 
        int nothingok = 1;
5164
 
        int ofd0, ofd1;
5165
 
        int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
5166
 
        int os0 = -1, os1 = -1;
5167
 
        int priority = 0;
5168
 
        struct ast_channel *oc0, *oc1;
5169
 
        enum ast_bridge_result res;
5170
 
 
5171
 
#ifdef PRI_2BCT
5172
 
        int triedtopribridge = 0;
5173
 
        q931_call *q931c0 = NULL, *q931c1 = NULL;
5174
 
#endif
5175
 
 
5176
 
        /* For now, don't attempt to native bridge if either channel needs DTMF detection.
5177
 
           There is code below to handle it properly until DTMF is actually seen,
5178
 
           but due to currently unresolved issues it's ignored...
5179
 
        */
5180
 
 
5181
 
        if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
5182
 
                return AST_BRIDGE_FAILED_NOWARN;
5183
 
 
5184
 
        ast_channel_lock(c0);
5185
 
        while (ast_channel_trylock(c1)) {
5186
 
                CHANNEL_DEADLOCK_AVOIDANCE(c0);
5187
 
        }
5188
 
 
5189
 
        p0 = c0->tech_pvt;
5190
 
        p1 = c1->tech_pvt;
5191
 
        /* cant do pseudo-channels here */
5192
 
        if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
5193
 
                ast_channel_unlock(c0);
5194
 
                ast_channel_unlock(c1);
5195
 
                return AST_BRIDGE_FAILED_NOWARN;
5196
 
        }
5197
 
 
5198
 
        oi0 = dahdi_get_index(c0, p0, 0);
5199
 
        oi1 = dahdi_get_index(c1, p1, 0);
5200
 
        if ((oi0 < 0) || (oi1 < 0)) {
5201
 
                ast_channel_unlock(c0);
5202
 
                ast_channel_unlock(c1);
5203
 
                return AST_BRIDGE_FAILED;
5204
 
        }
5205
 
 
5206
 
        op0 = p0 = c0->tech_pvt;
5207
 
        op1 = p1 = c1->tech_pvt;
5208
 
        ofd0 = c0->fds[0];
5209
 
        ofd1 = c1->fds[0];
5210
 
        oc0 = p0->owner;
5211
 
        oc1 = p1->owner;
5212
 
 
5213
 
        if (ast_mutex_trylock(&p0->lock)) {
5214
 
                /* Don't block, due to potential for deadlock */
5215
 
                ast_channel_unlock(c0);
5216
 
                ast_channel_unlock(c1);
5217
 
                ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
5218
 
                return AST_BRIDGE_RETRY;
5219
 
        }
5220
 
        if (ast_mutex_trylock(&p1->lock)) {
5221
 
                /* Don't block, due to potential for deadlock */
5222
 
                ast_mutex_unlock(&p0->lock);
5223
 
                ast_channel_unlock(c0);
5224
 
                ast_channel_unlock(c1);
5225
 
                ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
5226
 
                return AST_BRIDGE_RETRY;
5227
 
        }
5228
 
 
5229
 
        if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
5230
 
                if (p0->owner && p1->owner) {
5231
 
                        /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
5232
 
                        if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
5233
 
                                master = p0;
5234
 
                                slave = p1;
5235
 
                                inconf = 1;
5236
 
                        } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
5237
 
                                master = p1;
5238
 
                                slave = p0;
5239
 
                                inconf = 1;
5240
 
                        } else {
5241
 
                                ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
5242
 
                                ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
5243
 
                                        p0->channel,
5244
 
                                        oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
5245
 
                                        p0->subs[SUB_REAL].inthreeway, p0->channel,
5246
 
                                        oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
5247
 
                                        p1->subs[SUB_REAL].inthreeway);
5248
 
                        }
5249
 
                        nothingok = 0;
5250
 
                }
5251
 
        } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
5252
 
                if (p1->subs[SUB_THREEWAY].inthreeway) {
5253
 
                        master = p1;
5254
 
                        slave = p0;
5255
 
                        nothingok = 0;
5256
 
                }
5257
 
        } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
5258
 
                if (p0->subs[SUB_THREEWAY].inthreeway) {
5259
 
                        master = p0;
5260
 
                        slave = p1;
5261
 
                        nothingok = 0;
5262
 
                }
5263
 
        } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
5264
 
                /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
5265
 
                   don't put us in anything */
5266
 
                if (p1->subs[SUB_CALLWAIT].inthreeway) {
5267
 
                        master = p1;
5268
 
                        slave = p0;
5269
 
                        nothingok = 0;
5270
 
                }
5271
 
        } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
5272
 
                /* Same as previous */
5273
 
                if (p0->subs[SUB_CALLWAIT].inthreeway) {
5274
 
                        master = p0;
5275
 
                        slave = p1;
5276
 
                        nothingok = 0;
5277
 
                }
5278
 
        }
5279
 
        ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
5280
 
                master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
5281
 
        if (master && slave) {
5282
 
                /* Stop any tones, or play ringtone as appropriate.  If they're bridged
5283
 
                   in an active threeway call with a channel that is ringing, we should
5284
 
                   indicate ringing. */
5285
 
                if ((oi1 == SUB_THREEWAY) &&
5286
 
                        p1->subs[SUB_THREEWAY].inthreeway &&
5287
 
                        p1->subs[SUB_REAL].owner &&
5288
 
                        p1->subs[SUB_REAL].inthreeway &&
5289
 
                        (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
5290
 
                        ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
5291
 
                        tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
5292
 
                        os1 = p1->subs[SUB_REAL].owner->_state;
5293
 
                } else {
5294
 
                        ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
5295
 
                        tone_zone_play_tone(p0->subs[oi0].dfd, -1);
5296
 
                }
5297
 
                if ((oi0 == SUB_THREEWAY) &&
5298
 
                        p0->subs[SUB_THREEWAY].inthreeway &&
5299
 
                        p0->subs[SUB_REAL].owner &&
5300
 
                        p0->subs[SUB_REAL].inthreeway &&
5301
 
                        (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
5302
 
                        ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
5303
 
                        tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
5304
 
                        os0 = p0->subs[SUB_REAL].owner->_state;
5305
 
                } else {
5306
 
                        ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
5307
 
                        tone_zone_play_tone(p1->subs[oi0].dfd, -1);
5308
 
                }
5309
 
                if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
5310
 
                        if (!p0->echocanbridged || !p1->echocanbridged) {
5311
 
                                /* Disable echo cancellation if appropriate */
5312
 
                                dahdi_disable_ec(p0);
5313
 
                                dahdi_disable_ec(p1);
5314
 
                        }
5315
 
                }
5316
 
                dahdi_link(slave, master);
5317
 
                master->inconference = inconf;
5318
 
        } else if (!nothingok)
5319
 
                ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
5320
 
 
5321
 
        update_conf(p0);
5322
 
        update_conf(p1);
5323
 
        t0 = p0->subs[SUB_REAL].inthreeway;
5324
 
        t1 = p1->subs[SUB_REAL].inthreeway;
5325
 
 
5326
 
        ast_mutex_unlock(&p0->lock);
5327
 
        ast_mutex_unlock(&p1->lock);
5328
 
 
5329
 
        ast_channel_unlock(c0);
5330
 
        ast_channel_unlock(c1);
5331
 
 
5332
 
        /* Native bridge failed */
5333
 
        if ((!master || !slave) && !nothingok) {
5334
 
                dahdi_enable_ec(p0);
5335
 
                dahdi_enable_ec(p1);
5336
 
                return AST_BRIDGE_FAILED;
5337
 
        }
5338
 
 
5339
 
        ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
5340
 
 
5341
 
        if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
5342
 
                disable_dtmf_detect(op0);
5343
 
 
5344
 
        if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
5345
 
                disable_dtmf_detect(op1);
5346
 
 
5347
 
        for (;;) {
5348
 
                struct ast_channel *c0_priority[2] = {c0, c1};
5349
 
                struct ast_channel *c1_priority[2] = {c1, c0};
5350
 
 
5351
 
                /* Here's our main loop...  Start by locking things, looking for private parts,
5352
 
                   and then balking if anything is wrong */
5353
 
 
5354
 
                ast_channel_lock(c0);
5355
 
                while (ast_channel_trylock(c1)) {
5356
 
                        CHANNEL_DEADLOCK_AVOIDANCE(c0);
5357
 
                }
5358
 
 
5359
 
                p0 = c0->tech_pvt;
5360
 
                p1 = c1->tech_pvt;
5361
 
 
5362
 
                if (op0 == p0)
5363
 
                        i0 = dahdi_get_index(c0, p0, 1);
5364
 
                if (op1 == p1)
5365
 
                        i1 = dahdi_get_index(c1, p1, 1);
5366
 
 
5367
 
                ast_channel_unlock(c0);
5368
 
                ast_channel_unlock(c1);
5369
 
 
5370
 
                if (!timeoutms ||
5371
 
                        (op0 != p0) ||
5372
 
                        (op1 != p1) ||
5373
 
                        (ofd0 != c0->fds[0]) ||
5374
 
                        (ofd1 != c1->fds[0]) ||
5375
 
                        (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
5376
 
                        (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
5377
 
                        (oc0 != p0->owner) ||
5378
 
                        (oc1 != p1->owner) ||
5379
 
                        (t0 != p0->subs[SUB_REAL].inthreeway) ||
5380
 
                        (t1 != p1->subs[SUB_REAL].inthreeway) ||
5381
 
                        (oi0 != i0) ||
5382
 
                        (oi1 != i1)) {
5383
 
                        ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
5384
 
                                op0->channel, oi0, op1->channel, oi1);
5385
 
                        res = AST_BRIDGE_RETRY;
5386
 
                        goto return_from_bridge;
5387
 
                }
5388
 
 
5389
 
#ifdef PRI_2BCT
5390
 
                q931c0 = p0->call;
5391
 
                q931c1 = p1->call;
5392
 
                if (p0->transfer && p1->transfer
5393
 
                        && q931c0 && q931c1
5394
 
                        && !triedtopribridge) {
5395
 
                        pri_channel_bridge(q931c0, q931c1);
5396
 
                        triedtopribridge = 1;
5397
 
                }
5398
 
#endif
5399
 
 
5400
 
                who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
5401
 
                if (!who) {
5402
 
                        ast_debug(1, "Ooh, empty read...\n");
5403
 
                        continue;
5404
 
                }
5405
 
                f = ast_read(who);
5406
 
                if (!f || (f->frametype == AST_FRAME_CONTROL)) {
5407
 
                        *fo = f;
5408
 
                        *rc = who;
5409
 
                        res = AST_BRIDGE_COMPLETE;
5410
 
                        goto return_from_bridge;
5411
 
                }
5412
 
                if (f->frametype == AST_FRAME_DTMF) {
5413
 
                        if ((who == c0) && p0->pulsedial) {
5414
 
                                ast_write(c1, f);
5415
 
                        } else if ((who == c1) && p1->pulsedial) {
5416
 
                                ast_write(c0, f);
5417
 
                        } else {
5418
 
                                *fo = f;
5419
 
                                *rc = who;
5420
 
                                res = AST_BRIDGE_COMPLETE;
5421
 
                                goto return_from_bridge;
5422
 
                        }
5423
 
                }
5424
 
                ast_frfree(f);
5425
 
 
5426
 
                /* Swap who gets priority */
5427
 
                priority = !priority;
5428
 
        }
5429
 
 
5430
 
return_from_bridge:
5431
 
        if (op0 == p0)
5432
 
                dahdi_enable_ec(p0);
5433
 
 
5434
 
        if (op1 == p1)
5435
 
                dahdi_enable_ec(p1);
5436
 
 
5437
 
        if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
5438
 
                enable_dtmf_detect(op0);
5439
 
 
5440
 
        if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
5441
 
                enable_dtmf_detect(op1);
5442
 
 
5443
 
        dahdi_unlink(slave, master, 1);
5444
 
 
5445
 
        return res;
5446
 
}
5447
 
 
5448
 
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
5449
 
{
5450
 
        struct dahdi_pvt *p = newchan->tech_pvt;
5451
 
        int x;
5452
 
        ast_mutex_lock(&p->lock);
5453
 
        ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
5454
 
        if (p->owner == oldchan) {
5455
 
                p->owner = newchan;
5456
 
        }
5457
 
        for (x = 0; x < 3; x++)
5458
 
                if (p->subs[x].owner == oldchan) {
5459
 
                        if (!x)
5460
 
                                dahdi_unlink(NULL, p, 0);
5461
 
                        p->subs[x].owner = newchan;
5462
 
                }
5463
 
        if (newchan->_state == AST_STATE_RINGING)
5464
 
                dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
5465
 
        update_conf(p);
5466
 
        ast_mutex_unlock(&p->lock);
5467
 
        return 0;
5468
 
}
5469
 
 
5470
 
static int dahdi_ring_phone(struct dahdi_pvt *p)
5471
 
{
5472
 
        int x;
5473
 
        int res;
5474
 
        /* Make sure our transmit state is on hook */
5475
 
        x = 0;
5476
 
        x = DAHDI_ONHOOK;
5477
 
        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
5478
 
        do {
5479
 
                x = DAHDI_RING;
5480
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
5481
 
                if (res) {
5482
 
                        switch (errno) {
5483
 
                        case EBUSY:
5484
 
                        case EINTR:
5485
 
                                /* Wait just in case */
5486
 
                                usleep(10000);
5487
 
                                continue;
5488
 
                        case EINPROGRESS:
5489
 
                                res = 0;
5490
 
                                break;
5491
 
                        default:
5492
 
                                ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
5493
 
                                res = 0;
5494
 
                        }
5495
 
                }
5496
 
        } while (res);
5497
 
        return res;
5498
 
}
5499
 
 
5500
 
static void *ss_thread(void *data);
5501
 
 
5502
 
static int attempt_transfer(struct dahdi_pvt *p)
5503
 
{
5504
 
        /* In order to transfer, we need at least one of the channels to
5505
 
           actually be in a call bridge.  We can't conference two applications
5506
 
           together (but then, why would we want to?) */
5507
 
        if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
5508
 
                /* The three-way person we're about to transfer to could still be in MOH, so
5509
 
                   stop if now if appropriate */
5510
 
                if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
5511
 
                        ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
5512
 
                if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
5513
 
                        ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
5514
 
                }
5515
 
                if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
5516
 
                        tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
5517
 
                }
5518
 
                 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
5519
 
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
5520
 
                                        ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
5521
 
                        return -1;
5522
 
                }
5523
 
                /* Orphan the channel after releasing the lock */
5524
 
                ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5525
 
                unalloc_sub(p, SUB_THREEWAY);
5526
 
        } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
5527
 
                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
5528
 
                if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
5529
 
                        ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
5530
 
                }
5531
 
                if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
5532
 
                        tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
5533
 
                }
5534
 
                if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
5535
 
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
5536
 
                                        ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
5537
 
                        return -1;
5538
 
                }
5539
 
                /* Three-way is now the REAL */
5540
 
                swap_subs(p, SUB_THREEWAY, SUB_REAL);
5541
 
                ast_channel_unlock(p->subs[SUB_REAL].owner);
5542
 
                unalloc_sub(p, SUB_THREEWAY);
5543
 
                /* Tell the caller not to hangup */
5544
 
                return 1;
5545
 
        } else {
5546
 
                ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
5547
 
                        p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
5548
 
                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
5549
 
                return -1;
5550
 
        }
5551
 
        return 0;
5552
 
}
5553
 
 
5554
 
static int check_for_conference(struct dahdi_pvt *p)
5555
 
{
5556
 
        struct dahdi_confinfo ci;
5557
 
        /* Fine if we already have a master, etc */
5558
 
        if (p->master || (p->confno > -1))
5559
 
                return 0;
5560
 
        memset(&ci, 0, sizeof(ci));
5561
 
        if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
5562
 
                ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
5563
 
                return 0;
5564
 
        }
5565
 
        /* If we have no master and don't have a confno, then
5566
 
           if we're in a conference, it's probably a MeetMe room or
5567
 
           some such, so don't let us 3-way out! */
5568
 
        if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
5569
 
                ast_verb(3, "Avoiding 3-way call when in an external conference\n");
5570
 
                return 1;
5571
 
        }
5572
 
        return 0;
5573
 
}
5574
 
 
5575
 
/*! Checks channel for alarms
5576
 
 * \param p a channel to check for alarms.
5577
 
 * \returns the alarms on the span to which the channel belongs, or alarms on
5578
 
 *          the channel if no span alarms.
5579
 
 */
5580
 
static int get_alarms(struct dahdi_pvt *p)
5581
 
{
5582
 
        int res;
5583
 
        struct dahdi_spaninfo zi;
5584
 
        struct dahdi_params params;
5585
 
 
5586
 
        memset(&zi, 0, sizeof(zi));
5587
 
        zi.spanno = p->span;
5588
 
 
5589
 
        if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
5590
 
                if (zi.alarms != DAHDI_ALARM_NONE)
5591
 
                        return zi.alarms;
5592
 
        } else {
5593
 
                ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
5594
 
                return 0;
5595
 
        }
5596
 
 
5597
 
        /* No alarms on the span. Check for channel alarms. */
5598
 
        memset(&params, 0, sizeof(params));
5599
 
        if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
5600
 
                return params.chan_alarms;
5601
 
 
5602
 
        ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
5603
 
 
5604
 
        return DAHDI_ALARM_NONE;
5605
 
}
5606
 
 
5607
 
static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
5608
 
{
5609
 
        struct dahdi_pvt *p = ast->tech_pvt;
5610
 
        struct ast_frame *f = *dest;
5611
 
 
5612
 
        ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
5613
 
 
5614
 
        if (p->confirmanswer) {
5615
 
                ast_debug(1, "Confirm answer on %s!\n", ast->name);
5616
 
                /* Upon receiving a DTMF digit, consider this an answer confirmation instead
5617
 
                   of a DTMF digit */
5618
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5619
 
                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
5620
 
                *dest = &p->subs[idx].f;
5621
 
                /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
5622
 
                p->confirmanswer = 0;
5623
 
        } else if (p->callwaitcas) {
5624
 
                if ((f->subclass == 'A') || (f->subclass == 'D')) {
5625
 
                        ast_debug(1, "Got some DTMF, but it's for the CAS\n");
5626
 
                        if (p->cidspill)
5627
 
                                ast_free(p->cidspill);
5628
 
                        send_cwcidspill(p);
5629
 
                }
5630
 
                p->callwaitcas = 0;
5631
 
                p->subs[idx].f.frametype = AST_FRAME_NULL;
5632
 
                p->subs[idx].f.subclass = 0;
5633
 
                *dest = &p->subs[idx].f;
5634
 
        } else if (f->subclass == 'f') {
5635
 
                /* Fax tone -- Handle and return NULL */
5636
 
                if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
5637
 
                        /* If faxbuffers are configured, use them for the fax transmission */
5638
 
                        if (p->usefaxbuffers && !p->faxbuffersinuse) {
5639
 
                                struct dahdi_bufferinfo bi = {
5640
 
                                        .txbufpolicy = p->faxbuf_policy,
5641
 
                                        .bufsize = p->bufsize,
5642
 
                                        .numbufs = p->faxbuf_no
5643
 
                                };
5644
 
                                int res;
5645
 
 
5646
 
                                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
5647
 
                                        ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
5648
 
                                } else {
5649
 
                                        p->faxbuffersinuse = 1;
5650
 
                                }
5651
 
                        }
5652
 
                        p->faxhandled = 1;
5653
 
                        if (strcmp(ast->exten, "fax")) {
5654
 
                                const char *target_context = S_OR(ast->macrocontext, ast->context);
5655
 
 
5656
 
                                /* We need to unlock 'ast' here because ast_exists_extension has the
5657
 
                                 * potential to start autoservice on the channel. Such action is prone
5658
 
                                 * to deadlock.
5659
 
                                 */
5660
 
                                ast_mutex_unlock(&p->lock);
5661
 
                                ast_channel_unlock(ast);
5662
 
                                if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
5663
 
                                        ast_channel_lock(ast);
5664
 
                                        ast_mutex_lock(&p->lock);
5665
 
                                        ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
5666
 
                                        /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
5667
 
                                        pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
5668
 
                                        if (ast_async_goto(ast, target_context, "fax", 1))
5669
 
                                                ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
5670
 
                                } else {
5671
 
                                        ast_channel_lock(ast);
5672
 
                                        ast_mutex_lock(&p->lock);
5673
 
                                        ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
5674
 
                                }
5675
 
                        } else {
5676
 
                                ast_debug(1, "Already in a fax extension, not redirecting\n");
5677
 
                        }
5678
 
                } else {
5679
 
                        ast_debug(1, "Fax already handled\n");
5680
 
                }
5681
 
                dahdi_confmute(p, 0);
5682
 
                p->subs[idx].f.frametype = AST_FRAME_NULL;
5683
 
                p->subs[idx].f.subclass = 0;
5684
 
                *dest = &p->subs[idx].f;
5685
 
        }
5686
 
}
5687
 
 
5688
 
static void handle_alarms(struct dahdi_pvt *p, int alms)
5689
 
{
5690
 
        const char *alarm_str = alarm2str(alms);
5691
 
 
5692
 
        ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
5693
 
        manager_event(EVENT_FLAG_SYSTEM, "Alarm",
5694
 
                "Alarm: %s\r\n"
5695
 
                "Channel: %d\r\n",
5696
 
                alarm_str, p->channel);
5697
 
}
5698
 
 
5699
 
static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
5700
 
{
5701
 
        int res, x;
5702
 
        int idx, mysig;
5703
 
        char *c;
5704
 
        struct dahdi_pvt *p = ast->tech_pvt;
5705
 
        pthread_t threadid;
5706
 
        struct ast_channel *chan;
5707
 
        struct ast_frame *f;
5708
 
 
5709
 
        idx = dahdi_get_index(ast, p, 0);
5710
 
        mysig = p->sig;
5711
 
        if (p->outsigmod > -1)
5712
 
                mysig = p->outsigmod;
5713
 
        p->subs[idx].f.frametype = AST_FRAME_NULL;
5714
 
        p->subs[idx].f.subclass = 0;
5715
 
        p->subs[idx].f.datalen = 0;
5716
 
        p->subs[idx].f.samples = 0;
5717
 
        p->subs[idx].f.mallocd = 0;
5718
 
        p->subs[idx].f.offset = 0;
5719
 
        p->subs[idx].f.src = "dahdi_handle_event";
5720
 
        p->subs[idx].f.data.ptr = NULL;
5721
 
        f = &p->subs[idx].f;
5722
 
 
5723
 
        if (idx < 0)
5724
 
                return &p->subs[idx].f;
5725
 
        if (p->fake_event) {
5726
 
                res = p->fake_event;
5727
 
                p->fake_event = 0;
5728
 
        } else
5729
 
                res = dahdi_get_event(p->subs[idx].dfd);
5730
 
 
5731
 
        ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
5732
 
 
5733
 
        if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
5734
 
                p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
5735
 
                ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
5736
 
#ifdef HAVE_PRI
5737
 
                if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
5738
 
                        /* absorb event */
5739
 
                } else {
5740
 
#endif
5741
 
                        dahdi_confmute(p, 0);
5742
 
                        p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
5743
 
                        p->subs[idx].f.subclass = res & 0xff;
5744
 
#ifdef HAVE_PRI
5745
 
                }
5746
 
#endif
5747
 
                dahdi_handle_dtmfup(ast, idx, &f);
5748
 
                return f;
5749
 
        }
5750
 
 
5751
 
        if (res & DAHDI_EVENT_DTMFDOWN) {
5752
 
                ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
5753
 
                /* Mute conference */
5754
 
                dahdi_confmute(p, 1);
5755
 
                p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
5756
 
                p->subs[idx].f.subclass = res & 0xff;
5757
 
                return &p->subs[idx].f;
5758
 
        }
5759
 
 
5760
 
        switch (res) {
5761
 
                case DAHDI_EVENT_EC_DISABLED:
5762
 
                        ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
5763
 
                        p->echocanon = 0;
5764
 
                        break;
5765
 
                case DAHDI_EVENT_BITSCHANGED:
5766
 
#ifdef HAVE_OPENR2
5767
 
                        if (p->sig != SIG_MFCR2) {
5768
 
                                ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
5769
 
                        } else {
5770
 
                                ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
5771
 
                                openr2_chan_handle_cas(p->r2chan);
5772
 
                        }
5773
 
#else
5774
 
                        ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
5775
 
#endif
5776
 
                case DAHDI_EVENT_PULSE_START:
5777
 
                        /* Stop tone if there's a pulse start and the PBX isn't started */
5778
 
                        if (!ast->pbx)
5779
 
                                tone_zone_play_tone(p->subs[idx].dfd, -1);
5780
 
                        break;
5781
 
                case DAHDI_EVENT_DIALCOMPLETE:
5782
 
#ifdef HAVE_OPENR2
5783
 
                        if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
5784
 
                                /* we don't need to do anything for this event for R2 signaling
5785
 
                                   if the call is being setup */
5786
 
                                break;
5787
 
                        }
5788
 
#endif
5789
 
                        if (p->inalarm) break;
5790
 
                        if ((p->radio || (p->oprmode < 0))) break;
5791
 
                        if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
5792
 
                                ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
5793
 
                                return NULL;
5794
 
                        }
5795
 
                        if (!x) { /* if not still dialing in driver */
5796
 
                                dahdi_enable_ec(p);
5797
 
                                if (p->echobreak) {
5798
 
                                        dahdi_train_ec(p);
5799
 
                                        ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
5800
 
                                        p->dop.op = DAHDI_DIAL_OP_REPLACE;
5801
 
                                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
5802
 
                                        p->echobreak = 0;
5803
 
                                } else {
5804
 
                                        p->dialing = 0;
5805
 
                                        if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
5806
 
                                                /* if thru with dialing after offhook */
5807
 
                                                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
5808
 
                                                        ast_setstate(ast, AST_STATE_UP);
5809
 
                                                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5810
 
                                                        p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
5811
 
                                                        break;
5812
 
                                                } else { /* if to state wait for offhook to dial rest */
5813
 
                                                        /* we now wait for off hook */
5814
 
                                                        ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
5815
 
                                                }
5816
 
                                        }
5817
 
                                        if (ast->_state == AST_STATE_DIALING) {
5818
 
                                                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
5819
 
                                                        ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
5820
 
                                                } else if (p->confirmanswer || (!p->dialednone
5821
 
                                                        && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
5822
 
                                                                || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
5823
 
                                                                || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
5824
 
                                                                || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
5825
 
                                                                || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
5826
 
                                                                || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
5827
 
                                                                || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
5828
 
                                                                || (mysig == SIG_SF_FEATB)))) {
5829
 
                                                        ast_setstate(ast, AST_STATE_RINGING);
5830
 
                                                } else if (!p->answeronpolarityswitch) {
5831
 
                                                        ast_setstate(ast, AST_STATE_UP);
5832
 
                                                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5833
 
                                                        p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
5834
 
                                                        /* If aops=0 and hops=1, this is necessary */
5835
 
                                                        p->polarity = POLARITY_REV;
5836
 
                                                } else {
5837
 
                                                        /* Start clean, so we can catch the change to REV polarity when party answers */
5838
 
                                                        p->polarity = POLARITY_IDLE;
5839
 
                                                }
5840
 
                                        }
5841
 
                                }
5842
 
                        }
5843
 
                        break;
5844
 
                case DAHDI_EVENT_ALARM:
5845
 
#ifdef HAVE_PRI
5846
 
                        if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
5847
 
                                if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
5848
 
                                        /* T309 is not enabled : hangup calls when alarm occurs */
5849
 
                                        if (p->call) {
5850
 
                                                if (p->pri && p->pri->pri) {
5851
 
                                                        if (!pri_grab(p, p->pri)) {
5852
 
                                                                pri_hangup(p->pri->pri, p->call, -1);
5853
 
                                                                pri_destroycall(p->pri->pri, p->call);
5854
 
                                                                p->call = NULL;
5855
 
                                                                pri_rel(p->pri);
5856
 
                                                        } else
5857
 
                                                                ast_log(LOG_WARNING, "Failed to grab PRI!\n");
5858
 
                                                } else
5859
 
                                                        ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
5860
 
                                        }
5861
 
                                        if (p->owner)
5862
 
                                                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
5863
 
                                }
5864
 
                        }
5865
 
                        if (p->bearer)
5866
 
                                p->bearer->inalarm = 1;
5867
 
                        else
5868
 
#endif
5869
 
                        p->inalarm = 1;
5870
 
                        res = get_alarms(p);
5871
 
                        handle_alarms(p, res);
5872
 
#ifdef HAVE_PRI
5873
 
                        if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
5874
 
                                /* fall through intentionally */
5875
 
                        } else {
5876
 
                                break;
5877
 
                        }
5878
 
#endif
5879
 
#ifdef HAVE_SS7
5880
 
                        if (p->sig == SIG_SS7)
5881
 
                                break;
5882
 
#endif
5883
 
#ifdef HAVE_OPENR2
5884
 
                        if (p->sig == SIG_MFCR2)
5885
 
                                break;
5886
 
#endif
5887
 
                case DAHDI_EVENT_ONHOOK:
5888
 
                        if (p->radio) {
5889
 
                                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5890
 
                                p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
5891
 
                                break;
5892
 
                        }
5893
 
                        if (p->oprmode < 0)
5894
 
                        {
5895
 
                                if (p->oprmode != -1) break;
5896
 
                                if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
5897
 
                                {
5898
 
                                        /* Make sure it starts ringing */
5899
 
                                        dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
5900
 
                                        dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
5901
 
                                        save_conference(p->oprpeer);
5902
 
                                        tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
5903
 
                                }
5904
 
                                break;
5905
 
                        }
5906
 
                        switch (p->sig) {
5907
 
                        case SIG_FXOLS:
5908
 
                        case SIG_FXOGS:
5909
 
                        case SIG_FXOKS:
5910
 
                                p->onhooktime = time(NULL);
5911
 
                                p->fxsoffhookstate = 0;
5912
 
                                p->msgstate = -1;
5913
 
                                /* Check for some special conditions regarding call waiting */
5914
 
                                if (idx == SUB_REAL) {
5915
 
                                        /* The normal line was hung up */
5916
 
                                        if (p->subs[SUB_CALLWAIT].owner) {
5917
 
                                                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
5918
 
                                                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
5919
 
                                                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
5920
 
                                                unalloc_sub(p, SUB_CALLWAIT);
5921
 
#if 0
5922
 
                                                p->subs[idx].needanswer = 0;
5923
 
                                                p->subs[idx].needringing = 0;
5924
 
#endif
5925
 
                                                p->callwaitingrepeat = 0;
5926
 
                                                p->cidcwexpire = 0;
5927
 
                                                p->owner = NULL;
5928
 
                                                /* Don't start streaming audio yet if the incoming call isn't up yet */
5929
 
                                                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
5930
 
                                                        p->dialing = 1;
5931
 
                                                dahdi_ring_phone(p);
5932
 
                                        } else if (p->subs[SUB_THREEWAY].owner) {
5933
 
                                                unsigned int mssinceflash;
5934
 
                                                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
5935
 
                                                   the private structure -- not especially easy or clean */
5936
 
                                                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
5937
 
                                                        /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
5938
 
                                                        DLA_UNLOCK(&p->lock);
5939
 
                                                        CHANNEL_DEADLOCK_AVOIDANCE(ast);
5940
 
                                                        /* We can grab ast and p in that order, without worry.  We should make sure
5941
 
                                                           nothing seriously bad has happened though like some sort of bizarre double
5942
 
                                                           masquerade! */
5943
 
                                                        DLA_LOCK(&p->lock);
5944
 
                                                        if (p->owner != ast) {
5945
 
                                                                ast_log(LOG_WARNING, "This isn't good...\n");
5946
 
                                                                return NULL;
5947
 
                                                        }
5948
 
                                                }
5949
 
                                                if (!p->subs[SUB_THREEWAY].owner) {
5950
 
                                                        ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
5951
 
                                                        return NULL;
5952
 
                                                }
5953
 
                                                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
5954
 
                                                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
5955
 
                                                if (mssinceflash < MIN_MS_SINCE_FLASH) {
5956
 
                                                        /* It hasn't been long enough since the last flashook.  This is probably a bounce on
5957
 
                                                           hanging up.  Hangup both channels now */
5958
 
                                                        if (p->subs[SUB_THREEWAY].owner)
5959
 
                                                                ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
5960
 
                                                        p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
5961
 
                                                        ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
5962
 
                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5963
 
                                                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
5964
 
                                                        if (p->transfer) {
5965
 
                                                                /* In any case this isn't a threeway call anymore */
5966
 
                                                                p->subs[SUB_REAL].inthreeway = 0;
5967
 
                                                                p->subs[SUB_THREEWAY].inthreeway = 0;
5968
 
                                                                /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
5969
 
                                                                if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
5970
 
                                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5971
 
                                                                        /* Swap subs and dis-own channel */
5972
 
                                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
5973
 
                                                                        p->owner = NULL;
5974
 
                                                                        /* Ring the phone */
5975
 
                                                                        dahdi_ring_phone(p);
5976
 
                                                                } else {
5977
 
                                                                        if ((res = attempt_transfer(p)) < 0) {
5978
 
                                                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
5979
 
                                                                                if (p->subs[SUB_THREEWAY].owner)
5980
 
                                                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5981
 
                                                                        } else if (res) {
5982
 
                                                                                /* Don't actually hang up at this point */
5983
 
                                                                                if (p->subs[SUB_THREEWAY].owner)
5984
 
                                                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5985
 
                                                                                break;
5986
 
                                                                        }
5987
 
                                                                }
5988
 
                                                        } else {
5989
 
                                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
5990
 
                                                                if (p->subs[SUB_THREEWAY].owner)
5991
 
                                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5992
 
                                                        }
5993
 
                                                } else {
5994
 
                                                        ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
5995
 
                                                        /* Swap subs and dis-own channel */
5996
 
                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
5997
 
                                                        p->owner = NULL;
5998
 
                                                        /* Ring the phone */
5999
 
                                                        dahdi_ring_phone(p);
6000
 
                                                }
6001
 
                                        }
6002
 
                                } else {
6003
 
                                        ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
6004
 
                                }
6005
 
                                /* Fall through */
6006
 
                        default:
6007
 
                                dahdi_disable_ec(p);
6008
 
                                return NULL;
6009
 
                        }
6010
 
                        break;
6011
 
                case DAHDI_EVENT_RINGOFFHOOK:
6012
 
                        if (p->inalarm) break;
6013
 
                        if (p->oprmode < 0)
6014
 
                        {
6015
 
                                if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
6016
 
                                {
6017
 
                                        /* Make sure it stops ringing */
6018
 
                                        dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
6019
 
                                        tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
6020
 
                                        restore_conference(p->oprpeer);
6021
 
                                }
6022
 
                                break;
6023
 
                        }
6024
 
                        if (p->radio)
6025
 
                        {
6026
 
                                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6027
 
                                p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
6028
 
                                break;
6029
 
                        }
6030
 
                        /* for E911, its supposed to wait for offhook then dial
6031
 
                           the second half of the dial string */
6032
 
                        if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
6033
 
                                c = strchr(p->dialdest, '/');
6034
 
                                if (c)
6035
 
                                        c++;
6036
 
                                else
6037
 
                                        c = p->dialdest;
6038
 
                                if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
6039
 
                                else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
6040
 
                                if (strlen(p->dop.dialstr) > 4) {
6041
 
                                        memset(p->echorest, 'w', sizeof(p->echorest) - 1);
6042
 
                                        strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
6043
 
                                        p->echorest[sizeof(p->echorest) - 1] = '\0';
6044
 
                                        p->echobreak = 1;
6045
 
                                        p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
6046
 
                                } else
6047
 
                                        p->echobreak = 0;
6048
 
                                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
6049
 
                                        int saveerr = errno;
6050
 
 
6051
 
                                        x = DAHDI_ONHOOK;
6052
 
                                        ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
6053
 
                                        ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
6054
 
                                        return NULL;
6055
 
                                        }
6056
 
                                p->dialing = 1;
6057
 
                                return &p->subs[idx].f;
6058
 
                        }
6059
 
                        switch (p->sig) {
6060
 
                        case SIG_FXOLS:
6061
 
                        case SIG_FXOGS:
6062
 
                        case SIG_FXOKS:
6063
 
                                p->fxsoffhookstate = 1;
6064
 
                                switch (ast->_state) {
6065
 
                                case AST_STATE_RINGING:
6066
 
                                        dahdi_enable_ec(p);
6067
 
                                        dahdi_train_ec(p);
6068
 
                                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6069
 
                                        p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
6070
 
                                        /* Make sure it stops ringing */
6071
 
                                        dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
6072
 
                                        ast_debug(1, "channel %d answered\n", p->channel);
6073
 
                                        if (p->cidspill) {
6074
 
                                                /* Cancel any running CallerID spill */
6075
 
                                                ast_free(p->cidspill);
6076
 
                                                p->cidspill = NULL;
6077
 
                                        }
6078
 
                                        p->dialing = 0;
6079
 
                                        p->callwaitcas = 0;
6080
 
                                        if (p->confirmanswer) {
6081
 
                                                /* Ignore answer if "confirm answer" is enabled */
6082
 
                                                p->subs[idx].f.frametype = AST_FRAME_NULL;
6083
 
                                                p->subs[idx].f.subclass = 0;
6084
 
                                        } else if (!ast_strlen_zero(p->dop.dialstr)) {
6085
 
                                                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
6086
 
                                                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
6087
 
                                                if (res < 0) {
6088
 
                                                        ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
6089
 
                                                        p->dop.dialstr[0] = '\0';
6090
 
                                                        return NULL;
6091
 
                                                } else {
6092
 
                                                        ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
6093
 
                                                        p->subs[idx].f.frametype = AST_FRAME_NULL;
6094
 
                                                        p->subs[idx].f.subclass = 0;
6095
 
                                                        p->dialing = 1;
6096
 
                                                }
6097
 
                                                p->dop.dialstr[0] = '\0';
6098
 
                                                ast_setstate(ast, AST_STATE_DIALING);
6099
 
                                        } else
6100
 
                                                ast_setstate(ast, AST_STATE_UP);
6101
 
                                        return &p->subs[idx].f;
6102
 
                                case AST_STATE_DOWN:
6103
 
                                        ast_setstate(ast, AST_STATE_RING);
6104
 
                                        ast->rings = 1;
6105
 
                                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6106
 
                                        p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
6107
 
                                        ast_debug(1, "channel %d picked up\n", p->channel);
6108
 
                                        return &p->subs[idx].f;
6109
 
                                case AST_STATE_UP:
6110
 
                                        /* Make sure it stops ringing */
6111
 
                                        dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
6112
 
                                        /* Okay -- probably call waiting*/
6113
 
                                        if (ast_bridged_channel(p->owner))
6114
 
                                                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
6115
 
                                        p->subs[idx].needunhold = 1;
6116
 
                                        break;
6117
 
                                case AST_STATE_RESERVED:
6118
 
                                        /* Start up dialtone */
6119
 
                                        if (has_voicemail(p))
6120
 
                                                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6121
 
                                        else
6122
 
                                                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6123
 
                                        break;
6124
 
                                default:
6125
 
                                        ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
6126
 
                                }
6127
 
                                break;
6128
 
                        case SIG_FXSLS:
6129
 
                        case SIG_FXSGS:
6130
 
                        case SIG_FXSKS:
6131
 
                                if (ast->_state == AST_STATE_RING) {
6132
 
                                        p->ringt = p->ringt_base;
6133
 
                                }
6134
 
 
6135
 
                                /* If we get a ring then we cannot be in
6136
 
                                 * reversed polarity. So we reset to idle */
6137
 
                                ast_debug(1, "Setting IDLE polarity due "
6138
 
                                        "to ring. Old polarity was %d\n",
6139
 
                                        p->polarity);
6140
 
                                p->polarity = POLARITY_IDLE;
6141
 
 
6142
 
                                /* Fall through */
6143
 
                        case SIG_EM:
6144
 
                        case SIG_EM_E1:
6145
 
                        case SIG_EMWINK:
6146
 
                        case SIG_FEATD:
6147
 
                        case SIG_FEATDMF:
6148
 
                        case SIG_FEATDMF_TA:
6149
 
                        case SIG_E911:
6150
 
                        case SIG_FGC_CAMA:
6151
 
                        case SIG_FGC_CAMAMF:
6152
 
                        case SIG_FEATB:
6153
 
                        case SIG_SF:
6154
 
                        case SIG_SFWINK:
6155
 
                        case SIG_SF_FEATD:
6156
 
                        case SIG_SF_FEATDMF:
6157
 
                        case SIG_SF_FEATB:
6158
 
                                if (ast->_state == AST_STATE_PRERING)
6159
 
                                        ast_setstate(ast, AST_STATE_RING);
6160
 
                                if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
6161
 
                                        ast_debug(1, "Ring detected\n");
6162
 
                                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6163
 
                                        p->subs[idx].f.subclass = AST_CONTROL_RING;
6164
 
                                } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
6165
 
                                        ast_debug(1, "Line answered\n");
6166
 
                                        if (p->confirmanswer) {
6167
 
                                                p->subs[idx].f.frametype = AST_FRAME_NULL;
6168
 
                                                p->subs[idx].f.subclass = 0;
6169
 
                                        } else {
6170
 
                                                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6171
 
                                                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
6172
 
                                                ast_setstate(ast, AST_STATE_UP);
6173
 
                                        }
6174
 
                                } else if (ast->_state != AST_STATE_RING)
6175
 
                                        ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
6176
 
                                break;
6177
 
                        default:
6178
 
                                ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
6179
 
                        }
6180
 
                        break;
6181
 
                case DAHDI_EVENT_RINGBEGIN:
6182
 
                        switch (p->sig) {
6183
 
                        case SIG_FXSLS:
6184
 
                        case SIG_FXSGS:
6185
 
                        case SIG_FXSKS:
6186
 
                                if (ast->_state == AST_STATE_RING) {
6187
 
                                        p->ringt = p->ringt_base;
6188
 
                                }
6189
 
                                break;
6190
 
                        }
6191
 
                        break;
6192
 
                case DAHDI_EVENT_RINGEROFF:
6193
 
                        if (p->inalarm) break;
6194
 
                        if ((p->radio || (p->oprmode < 0))) break;
6195
 
                        ast->rings++;
6196
 
                        if ((ast->rings > p->cidrings) && (p->cidspill)) {
6197
 
                                ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
6198
 
                                ast_free(p->cidspill);
6199
 
                                p->cidspill = NULL;
6200
 
                                p->callwaitcas = 0;
6201
 
                        }
6202
 
                        p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6203
 
                        p->subs[idx].f.subclass = AST_CONTROL_RINGING;
6204
 
                        break;
6205
 
                case DAHDI_EVENT_RINGERON:
6206
 
                        break;
6207
 
                case DAHDI_EVENT_NOALARM:
6208
 
                        p->inalarm = 0;
6209
 
#ifdef HAVE_PRI
6210
 
                        /* Extremely unlikely but just in case */
6211
 
                        if (p->bearer)
6212
 
                                p->bearer->inalarm = 0;
6213
 
#endif
6214
 
                        ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
6215
 
                        manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6216
 
                                                                "Channel: %d\r\n", p->channel);
6217
 
                        break;
6218
 
                case DAHDI_EVENT_WINKFLASH:
6219
 
                        if (p->inalarm) break;
6220
 
                        if (p->radio) break;
6221
 
                        if (p->oprmode < 0) break;
6222
 
                        if (p->oprmode > 1)
6223
 
                        {
6224
 
                                struct dahdi_params par;
6225
 
 
6226
 
                                memset(&par, 0, sizeof(par));
6227
 
                                if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
6228
 
                                {
6229
 
                                        if (!par.rxisoffhook)
6230
 
                                        {
6231
 
                                                /* Make sure it stops ringing */
6232
 
                                                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
6233
 
                                                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
6234
 
                                                save_conference(p);
6235
 
                                                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6236
 
                                        }
6237
 
                                }
6238
 
                                break;
6239
 
                        }
6240
 
                        /* Remember last time we got a flash-hook */
6241
 
                        p->flashtime = ast_tvnow();
6242
 
                        switch (mysig) {
6243
 
                        case SIG_FXOLS:
6244
 
                        case SIG_FXOGS:
6245
 
                        case SIG_FXOKS:
6246
 
                                ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
6247
 
                                        idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6248
 
                                p->callwaitcas = 0;
6249
 
 
6250
 
                                if (idx != SUB_REAL) {
6251
 
                                        ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
6252
 
                                        goto winkflashdone;
6253
 
                                }
6254
 
 
6255
 
                                if (p->subs[SUB_CALLWAIT].owner) {
6256
 
                                        /* Swap to call-wait */
6257
 
                                        swap_subs(p, SUB_REAL, SUB_CALLWAIT);
6258
 
                                        tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6259
 
                                        p->owner = p->subs[SUB_REAL].owner;
6260
 
                                        ast_debug(1, "Making %s the new owner\n", p->owner->name);
6261
 
                                        if (p->owner->_state == AST_STATE_RINGING) {
6262
 
                                                ast_setstate(p->owner, AST_STATE_UP);
6263
 
                                                p->subs[SUB_REAL].needanswer = 1;
6264
 
                                        }
6265
 
                                        p->callwaitingrepeat = 0;
6266
 
                                        p->cidcwexpire = 0;
6267
 
                                        /* Start music on hold if appropriate */
6268
 
                                        if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
6269
 
                                                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
6270
 
                                                        S_OR(p->mohsuggest, NULL),
6271
 
                                                        !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
6272
 
                                        }
6273
 
                                        p->subs[SUB_CALLWAIT].needhold = 1;
6274
 
                                        if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
6275
 
                                                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
6276
 
                                                        S_OR(p->mohsuggest, NULL),
6277
 
                                                        !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
6278
 
                                        }
6279
 
                                        p->subs[SUB_REAL].needunhold = 1;
6280
 
                                } else if (!p->subs[SUB_THREEWAY].owner) {
6281
 
                                        if (!p->threewaycalling) {
6282
 
                                                /* Just send a flash if no 3-way calling */
6283
 
                                                p->subs[SUB_REAL].needflash = 1;
6284
 
                                                goto winkflashdone;
6285
 
                                        } else if (!check_for_conference(p)) {
6286
 
                                                char cid_num[256];
6287
 
                                                char cid_name[256];
6288
 
 
6289
 
                                                cid_num[0] = 0;
6290
 
                                                cid_name[0] = 0;
6291
 
                                                if (p->dahditrcallerid && p->owner) {
6292
 
                                                        if (p->owner->cid.cid_num)
6293
 
                                                                ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
6294
 
                                                        if (p->owner->cid.cid_name)
6295
 
                                                                ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
6296
 
                                                }
6297
 
                                                /* XXX This section needs much more error checking!!! XXX */
6298
 
                                                /* Start a 3-way call if feasible */
6299
 
                                                if (!((ast->pbx) ||
6300
 
                                                        (ast->_state == AST_STATE_UP) ||
6301
 
                                                        (ast->_state == AST_STATE_RING))) {
6302
 
                                                        ast_debug(1, "Flash when call not up or ringing\n");
6303
 
                                                        goto winkflashdone;
6304
 
                                                }
6305
 
                                                if (alloc_sub(p, SUB_THREEWAY)) {
6306
 
                                                        ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
6307
 
                                                        goto winkflashdone;
6308
 
                                                }
6309
 
                                                /* Make new channel */
6310
 
                                                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
6311
 
                                                if (p->dahditrcallerid) {
6312
 
                                                        if (!p->origcid_num)
6313
 
                                                                p->origcid_num = ast_strdup(p->cid_num);
6314
 
                                                        if (!p->origcid_name)
6315
 
                                                                p->origcid_name = ast_strdup(p->cid_name);
6316
 
                                                        ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
6317
 
                                                        ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
6318
 
                                                }
6319
 
                                                /* Swap things around between the three-way and real call */
6320
 
                                                swap_subs(p, SUB_THREEWAY, SUB_REAL);
6321
 
                                                /* Disable echo canceller for better dialing */
6322
 
                                                dahdi_disable_ec(p);
6323
 
                                                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
6324
 
                                                if (res)
6325
 
                                                        ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
6326
 
                                                p->owner = chan;
6327
 
                                                if (!chan) {
6328
 
                                                        ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
6329
 
                                                } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
6330
 
                                                        ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
6331
 
                                                        res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6332
 
                                                        dahdi_enable_ec(p);
6333
 
                                                        ast_hangup(chan);
6334
 
                                                } else {
6335
 
                                                        struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
6336
 
                                                        int way3bridge = 0, cdr3way = 0;
6337
 
 
6338
 
                                                        if (!other) {
6339
 
                                                                other = ast_bridged_channel(p->subs[SUB_REAL].owner);
6340
 
                                                        } else
6341
 
                                                                way3bridge = 1;
6342
 
 
6343
 
                                                        if (p->subs[SUB_THREEWAY].owner->cdr)
6344
 
                                                                cdr3way = 1;
6345
 
 
6346
 
                                                        ast_verb(3, "Started three way call on channel %d\n", p->channel);
6347
 
 
6348
 
                                                        /* Start music on hold if appropriate */
6349
 
                                                        if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6350
 
                                                                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
6351
 
                                                                        S_OR(p->mohsuggest, NULL),
6352
 
                                                                        !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
6353
 
                                                        }
6354
 
                                                        p->subs[SUB_THREEWAY].needhold = 1;
6355
 
                                                }
6356
 
                                        }
6357
 
                                } else {
6358
 
                                        /* Already have a 3 way call */
6359
 
                                        if (p->subs[SUB_THREEWAY].inthreeway) {
6360
 
                                                /* Call is already up, drop the last person */
6361
 
                                                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
6362
 
                                                /* If the primary call isn't answered yet, use it */
6363
 
                                                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
6364
 
                                                        /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
6365
 
                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
6366
 
                                                        p->owner = p->subs[SUB_REAL].owner;
6367
 
                                                }
6368
 
                                                /* Drop the last call and stop the conference */
6369
 
                                                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
6370
 
                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
6371
 
                                                p->subs[SUB_REAL].inthreeway = 0;
6372
 
                                                p->subs[SUB_THREEWAY].inthreeway = 0;
6373
 
                                        } else {
6374
 
                                                /* Lets see what we're up to */
6375
 
                                                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
6376
 
                                                        (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
6377
 
                                                        int otherindex = SUB_THREEWAY;
6378
 
                                                        struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
6379
 
                                                        int way3bridge = 0, cdr3way = 0;
6380
 
 
6381
 
                                                        if (!other) {
6382
 
                                                                other = ast_bridged_channel(p->subs[SUB_REAL].owner);
6383
 
                                                        } else
6384
 
                                                                way3bridge = 1;
6385
 
 
6386
 
                                                        if (p->subs[SUB_THREEWAY].owner->cdr)
6387
 
                                                                cdr3way = 1;
6388
 
 
6389
 
                                                        ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
6390
 
                                                        /* Put them in the threeway, and flip */
6391
 
                                                        p->subs[SUB_THREEWAY].inthreeway = 1;
6392
 
                                                        p->subs[SUB_REAL].inthreeway = 1;
6393
 
                                                        if (ast->_state == AST_STATE_UP) {
6394
 
                                                                swap_subs(p, SUB_THREEWAY, SUB_REAL);
6395
 
                                                                otherindex = SUB_REAL;
6396
 
                                                        }
6397
 
                                                        if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
6398
 
                                                                ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
6399
 
                                                        p->subs[otherindex].needunhold = 1;
6400
 
                                                        p->owner = p->subs[SUB_REAL].owner;
6401
 
                                                        if (ast->_state == AST_STATE_RINGING) {
6402
 
                                                                ast_debug(1, "Enabling ringtone on real and threeway\n");
6403
 
                                                                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6404
 
                                                                res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
6405
 
                                                        }
6406
 
                                                } else {
6407
 
                                                        ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
6408
 
                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
6409
 
                                                        p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
6410
 
                                                        p->owner = p->subs[SUB_REAL].owner;
6411
 
                                                        if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
6412
 
                                                                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6413
 
                                                        p->subs[SUB_REAL].needunhold = 1;
6414
 
                                                        dahdi_enable_ec(p);
6415
 
                                                }
6416
 
                                        }
6417
 
                                }
6418
 
winkflashdone:
6419
 
                                update_conf(p);
6420
 
                                break;
6421
 
                        case SIG_EM:
6422
 
                        case SIG_EM_E1:
6423
 
                        case SIG_FEATD:
6424
 
                        case SIG_SF:
6425
 
                        case SIG_SFWINK:
6426
 
                        case SIG_SF_FEATD:
6427
 
                        case SIG_FXSLS:
6428
 
                        case SIG_FXSGS:
6429
 
                                if (option_debug) {
6430
 
                                        if (p->dialing)
6431
 
                                                ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
6432
 
                                        else
6433
 
                                                ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
6434
 
                                }
6435
 
                                break;
6436
 
                        case SIG_FEATDMF_TA:
6437
 
                                switch (p->whichwink) {
6438
 
                                case 0:
6439
 
                                        ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
6440
 
                                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
6441
 
                                        break;
6442
 
                                case 1:
6443
 
                                        ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
6444
 
                                        break;
6445
 
                                case 2:
6446
 
                                        ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
6447
 
                                        return NULL;
6448
 
                                }
6449
 
                                p->whichwink++;
6450
 
                                /* Fall through */
6451
 
                        case SIG_FEATDMF:
6452
 
                        case SIG_E911:
6453
 
                        case SIG_FGC_CAMAMF:
6454
 
                        case SIG_FGC_CAMA:
6455
 
                        case SIG_FEATB:
6456
 
                        case SIG_SF_FEATDMF:
6457
 
                        case SIG_SF_FEATB:
6458
 
                        case SIG_EMWINK:
6459
 
                                /* FGD MF and EMWINK *Must* wait for wink */
6460
 
                                if (!ast_strlen_zero(p->dop.dialstr)) {
6461
 
                                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
6462
 
                                        if (res < 0) {
6463
 
                                                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
6464
 
                                                p->dop.dialstr[0] = '\0';
6465
 
                                                return NULL;
6466
 
                                        } else
6467
 
                                                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
6468
 
                                }
6469
 
                                p->dop.dialstr[0] = '\0';
6470
 
                                break;
6471
 
                        default:
6472
 
                                ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
6473
 
                        }
6474
 
                        break;
6475
 
                case DAHDI_EVENT_HOOKCOMPLETE:
6476
 
                        if (p->inalarm) break;
6477
 
                        if ((p->radio || (p->oprmode < 0))) break;
6478
 
                        if (p->waitingfordt.tv_sec) break;
6479
 
                        switch (mysig) {
6480
 
                        case SIG_FXSLS:  /* only interesting for FXS */
6481
 
                        case SIG_FXSGS:
6482
 
                        case SIG_FXSKS:
6483
 
                        case SIG_EM:
6484
 
                        case SIG_EM_E1:
6485
 
                        case SIG_EMWINK:
6486
 
                        case SIG_FEATD:
6487
 
                        case SIG_SF:
6488
 
                        case SIG_SFWINK:
6489
 
                        case SIG_SF_FEATD:
6490
 
                                if (!ast_strlen_zero(p->dop.dialstr)) {
6491
 
                                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
6492
 
                                        if (res < 0) {
6493
 
                                                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
6494
 
                                                p->dop.dialstr[0] = '\0';
6495
 
                                                return NULL;
6496
 
                                        } else
6497
 
                                                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
6498
 
                                }
6499
 
                                p->dop.dialstr[0] = '\0';
6500
 
                                p->dop.op = DAHDI_DIAL_OP_REPLACE;
6501
 
                                break;
6502
 
                        case SIG_FEATDMF:
6503
 
                        case SIG_FEATDMF_TA:
6504
 
                        case SIG_E911:
6505
 
                        case SIG_FGC_CAMA:
6506
 
                        case SIG_FGC_CAMAMF:
6507
 
                        case SIG_FEATB:
6508
 
                        case SIG_SF_FEATDMF:
6509
 
                        case SIG_SF_FEATB:
6510
 
                                ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
6511
 
                                break;
6512
 
                        default:
6513
 
                                break;
6514
 
                        }
6515
 
                        break;
6516
 
                case DAHDI_EVENT_POLARITY:
6517
 
                        /*
6518
 
                         * If we get a Polarity Switch event, this could be
6519
 
                         * due to line seizure, remote end connect or remote end disconnect.
6520
 
                         *
6521
 
                         * Check to see if we should change the polarity state and
6522
 
                         * mark the channel as UP or if this is an indication
6523
 
                         * of remote end disconnect.
6524
 
                         */
6525
 
 
6526
 
                        if (p->polarityonanswerdelay > 0) {
6527
 
                                /* check if event is not too soon after OffHook or Answer */
6528
 
                                if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
6529
 
                                        switch (ast->_state) {
6530
 
                                        case AST_STATE_DIALING:                 /*!< Digits (or equivalent) have been dialed */
6531
 
                                        case AST_STATE_RINGING:                 /*!< Remote end is ringing */
6532
 
                                                if (p->answeronpolarityswitch) {
6533
 
                                                        ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
6534
 
                                                        ast_setstate(p->owner, AST_STATE_UP);
6535
 
                                                        p->polarity = POLARITY_REV;
6536
 
                                                        if (p->hanguponpolarityswitch) {
6537
 
                                                                p->polaritydelaytv = ast_tvnow();
6538
 
                                                        }
6539
 
                                                } else {
6540
 
                                                        ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
6541
 
                                                }
6542
 
                                                break;
6543
 
 
6544
 
                                        case AST_STATE_UP:                      /*!< Line is up */
6545
 
                                        case AST_STATE_RING:                    /*!< Line is ringing */
6546
 
                                                if (p->hanguponpolarityswitch) {
6547
 
                                                        ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
6548
 
                                                        ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
6549
 
                                                        p->polarity = POLARITY_IDLE;
6550
 
                                                } else {
6551
 
                                                        ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
6552
 
                                                }
6553
 
                                                break;
6554
 
 
6555
 
                                        case AST_STATE_DOWN:                    /*!< Channel is down and available */
6556
 
                                        case AST_STATE_RESERVED:                /*!< Channel is down, but reserved */
6557
 
                                        case AST_STATE_OFFHOOK:                 /*!< Channel is off hook */
6558
 
                                        case AST_STATE_BUSY:                    /*!< Line is busy */
6559
 
                                        case AST_STATE_DIALING_OFFHOOK:         /*!< Digits (or equivalent) have been dialed while offhook */
6560
 
                                        case AST_STATE_PRERING:                 /*!< Channel has detected an incoming call and is waiting for ring */
6561
 
                                        default:
6562
 
                                                if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
6563
 
                                                        ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
6564
 
                                                }
6565
 
                                        }
6566
 
 
6567
 
                                } else {
6568
 
                                        /* event is too soon after OffHook or Answer */
6569
 
                                        switch (ast->_state) {
6570
 
                                        case AST_STATE_DIALING:                 /*!< Digits (or equivalent) have been dialed */
6571
 
                                        case AST_STATE_RINGING:                 /*!< Remote end is ringing */
6572
 
                                                if (p->answeronpolarityswitch) {
6573
 
                                                        ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
6574
 
                                                }
6575
 
                                                break;
6576
 
 
6577
 
                                        case AST_STATE_UP:                      /*!< Line is up */
6578
 
                                        case AST_STATE_RING:                    /*!< Line is ringing */
6579
 
                                                if (p->hanguponpolarityswitch) {
6580
 
                                                        ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
6581
 
                                                }
6582
 
                                                break;
6583
 
 
6584
 
                                        default:        
6585
 
                                                if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
6586
 
                                                        ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
6587
 
                                                }
6588
 
                                        }
6589
 
                                }
6590
 
                        }
6591
 
 
6592
 
                        /* Added more log_debug information below to provide a better indication of what is going on */
6593
 
                        ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
6594
 
                        break;
6595
 
                default:
6596
 
                        ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
6597
 
        }
6598
 
        return &p->subs[idx].f;
6599
 
}
6600
 
 
6601
 
static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
6602
 
{
6603
 
        struct dahdi_pvt *p = ast->tech_pvt;
6604
 
        int res;
6605
 
        int usedindex=-1;
6606
 
        int idx;
6607
 
        struct ast_frame *f;
6608
 
 
6609
 
 
6610
 
        idx = dahdi_get_index(ast, p, 1);
6611
 
 
6612
 
        p->subs[idx].f.frametype = AST_FRAME_NULL;
6613
 
        p->subs[idx].f.datalen = 0;
6614
 
        p->subs[idx].f.samples = 0;
6615
 
        p->subs[idx].f.mallocd = 0;
6616
 
        p->subs[idx].f.offset = 0;
6617
 
        p->subs[idx].f.subclass = 0;
6618
 
        p->subs[idx].f.delivery = ast_tv(0,0);
6619
 
        p->subs[idx].f.src = "dahdi_exception";
6620
 
        p->subs[idx].f.data.ptr = NULL;
6621
 
 
6622
 
 
6623
 
        if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
6624
 
                /* If nobody owns us, absorb the event appropriately, otherwise
6625
 
                   we loop indefinitely.  This occurs when, during call waiting, the
6626
 
                   other end hangs up our channel so that it no longer exists, but we
6627
 
                   have neither FLASH'd nor ONHOOK'd to signify our desire to
6628
 
                   change to the other channel. */
6629
 
                if (p->fake_event) {
6630
 
                        res = p->fake_event;
6631
 
                        p->fake_event = 0;
6632
 
                } else
6633
 
                        res = dahdi_get_event(p->subs[SUB_REAL].dfd);
6634
 
                /* Switch to real if there is one and this isn't something really silly... */
6635
 
                if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
6636
 
                        (res != DAHDI_EVENT_HOOKCOMPLETE)) {
6637
 
                        ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
6638
 
                        p->owner = p->subs[SUB_REAL].owner;
6639
 
                        if (p->owner && ast_bridged_channel(p->owner))
6640
 
                                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
6641
 
                        p->subs[SUB_REAL].needunhold = 1;
6642
 
                }
6643
 
                switch (res) {
6644
 
                case DAHDI_EVENT_ONHOOK:
6645
 
                        dahdi_disable_ec(p);
6646
 
                        if (p->owner) {
6647
 
                                ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
6648
 
                                dahdi_ring_phone(p);
6649
 
                                p->callwaitingrepeat = 0;
6650
 
                                p->cidcwexpire = 0;
6651
 
                        } else
6652
 
                                ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
6653
 
                        update_conf(p);
6654
 
                        break;
6655
 
                case DAHDI_EVENT_RINGOFFHOOK:
6656
 
                        dahdi_enable_ec(p);
6657
 
                        dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6658
 
                        if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
6659
 
                                p->subs[SUB_REAL].needanswer = 1;
6660
 
                                p->dialing = 0;
6661
 
                        }
6662
 
                        break;
6663
 
                case DAHDI_EVENT_HOOKCOMPLETE:
6664
 
                case DAHDI_EVENT_RINGERON:
6665
 
                case DAHDI_EVENT_RINGEROFF:
6666
 
                        /* Do nothing */
6667
 
                        break;
6668
 
                case DAHDI_EVENT_WINKFLASH:
6669
 
                        p->flashtime = ast_tvnow();
6670
 
                        if (p->owner) {
6671
 
                                ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
6672
 
                                if (p->owner->_state != AST_STATE_UP) {
6673
 
                                        /* Answer if necessary */
6674
 
                                        usedindex = dahdi_get_index(p->owner, p, 0);
6675
 
                                        if (usedindex > -1) {
6676
 
                                                p->subs[usedindex].needanswer = 1;
6677
 
                                        }
6678
 
                                        ast_setstate(p->owner, AST_STATE_UP);
6679
 
                                }
6680
 
                                p->callwaitingrepeat = 0;
6681
 
                                p->cidcwexpire = 0;
6682
 
                                if (ast_bridged_channel(p->owner))
6683
 
                                        ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
6684
 
                                p->subs[SUB_REAL].needunhold = 1;
6685
 
                        } else
6686
 
                                ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
6687
 
                        update_conf(p);
6688
 
                        break;
6689
 
                default:
6690
 
                        ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
6691
 
                }
6692
 
                f = &p->subs[idx].f;
6693
 
                return f;
6694
 
        }
6695
 
        if (!(p->radio || (p->oprmode < 0)))
6696
 
                ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
6697
 
        /* If it's not us, return NULL immediately */
6698
 
        if (ast != p->owner) {
6699
 
                ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
6700
 
                f = &p->subs[idx].f;
6701
 
                return f;
6702
 
        }
6703
 
        f = dahdi_handle_event(ast);
6704
 
        return f;
6705
 
}
6706
 
 
6707
 
static struct ast_frame *dahdi_exception(struct ast_channel *ast)
6708
 
{
6709
 
        struct dahdi_pvt *p = ast->tech_pvt;
6710
 
        struct ast_frame *f;
6711
 
        ast_mutex_lock(&p->lock);
6712
 
        f = __dahdi_exception(ast);
6713
 
        ast_mutex_unlock(&p->lock);
6714
 
        return f;
6715
 
}
6716
 
 
6717
 
static struct ast_frame *dahdi_read(struct ast_channel *ast)
6718
 
{
6719
 
        struct dahdi_pvt *p = ast->tech_pvt;
6720
 
        int res;
6721
 
        int idx;
6722
 
        void *readbuf;
6723
 
        struct ast_frame *f;
6724
 
 
6725
 
        while (ast_mutex_trylock(&p->lock)) {
6726
 
                CHANNEL_DEADLOCK_AVOIDANCE(ast);
6727
 
        }
6728
 
 
6729
 
        idx = dahdi_get_index(ast, p, 0);
6730
 
 
6731
 
        /* Hang up if we don't really exist */
6732
 
        if (idx < 0)    {
6733
 
                ast_log(LOG_WARNING, "We dont exist?\n");
6734
 
                ast_mutex_unlock(&p->lock);
6735
 
                return NULL;
6736
 
        }
6737
 
 
6738
 
        if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
6739
 
                ast_mutex_unlock(&p->lock);
6740
 
                return NULL;
6741
 
        }
6742
 
 
6743
 
        p->subs[idx].f.frametype = AST_FRAME_NULL;
6744
 
        p->subs[idx].f.datalen = 0;
6745
 
        p->subs[idx].f.samples = 0;
6746
 
        p->subs[idx].f.mallocd = 0;
6747
 
        p->subs[idx].f.offset = 0;
6748
 
        p->subs[idx].f.subclass = 0;
6749
 
        p->subs[idx].f.delivery = ast_tv(0,0);
6750
 
        p->subs[idx].f.src = "dahdi_read";
6751
 
        p->subs[idx].f.data.ptr = NULL;
6752
 
 
6753
 
        /* make sure it sends initial key state as first frame */
6754
 
        if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
6755
 
        {
6756
 
                struct dahdi_params ps;
6757
 
 
6758
 
                memset(&ps, 0, sizeof(ps));
6759
 
                ps.channo = p->channel;
6760
 
                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
6761
 
                        ast_mutex_unlock(&p->lock);
6762
 
                        return NULL;
6763
 
                }
6764
 
                p->firstradio = 1;
6765
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6766
 
                if (ps.rxisoffhook)
6767
 
                {
6768
 
                        p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
6769
 
                }
6770
 
                else
6771
 
                {
6772
 
                        p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
6773
 
                }
6774
 
                ast_mutex_unlock(&p->lock);
6775
 
                return &p->subs[idx].f;
6776
 
        }
6777
 
        if (p->ringt == 1) {
6778
 
                ast_mutex_unlock(&p->lock);
6779
 
                return NULL;
6780
 
        }
6781
 
        else if (p->ringt > 0)
6782
 
                p->ringt--;
6783
 
 
6784
 
#ifdef HAVE_OPENR2
6785
 
        if (p->mfcr2) {
6786
 
                openr2_chan_process_event(p->r2chan);
6787
 
        }
6788
 
#endif
6789
 
 
6790
 
        if (p->subs[idx].needringing) {
6791
 
                /* Send ringing frame if requested */
6792
 
                p->subs[idx].needringing = 0;
6793
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6794
 
                p->subs[idx].f.subclass = AST_CONTROL_RINGING;
6795
 
                ast_setstate(ast, AST_STATE_RINGING);
6796
 
                ast_mutex_unlock(&p->lock);
6797
 
                return &p->subs[idx].f;
6798
 
        }
6799
 
 
6800
 
        if (p->subs[idx].needbusy) {
6801
 
                /* Send busy frame if requested */
6802
 
                p->subs[idx].needbusy = 0;
6803
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6804
 
                p->subs[idx].f.subclass = AST_CONTROL_BUSY;
6805
 
                ast_mutex_unlock(&p->lock);
6806
 
                return &p->subs[idx].f;
6807
 
        }
6808
 
 
6809
 
        if (p->subs[idx].needcongestion) {
6810
 
                /* Send congestion frame if requested */
6811
 
                p->subs[idx].needcongestion = 0;
6812
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6813
 
                p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
6814
 
                ast_mutex_unlock(&p->lock);
6815
 
                return &p->subs[idx].f;
6816
 
        }
6817
 
 
6818
 
        if (p->subs[idx].needcallerid) {
6819
 
                ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
6820
 
                                                        S_OR(p->lastcid_name, NULL),
6821
 
                                                        S_OR(p->lastcid_num, NULL)
6822
 
                                                        );
6823
 
                p->subs[idx].needcallerid = 0;
6824
 
        }
6825
 
 
6826
 
        if (p->subs[idx].needanswer) {
6827
 
                /* Send answer frame if requested */
6828
 
                p->subs[idx].needanswer = 0;
6829
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6830
 
                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
6831
 
                ast_mutex_unlock(&p->lock);
6832
 
                return &p->subs[idx].f;
6833
 
        }
6834
 
#ifdef HAVE_OPENR2
6835
 
        if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
6836
 
                /* openr2 took care of reading and handling any event
6837
 
                  (needanswer, needbusy etc), if we continue we will read()
6838
 
                  twice, lets just return a null frame. This should only
6839
 
                  happen when openr2 is dialing out */
6840
 
                ast_mutex_unlock(&p->lock);
6841
 
                return &ast_null_frame;
6842
 
        }
6843
 
#endif
6844
 
 
6845
 
        if (p->subs[idx].needflash) {
6846
 
                /* Send answer frame if requested */
6847
 
                p->subs[idx].needflash = 0;
6848
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6849
 
                p->subs[idx].f.subclass = AST_CONTROL_FLASH;
6850
 
                ast_mutex_unlock(&p->lock);
6851
 
                return &p->subs[idx].f;
6852
 
        }
6853
 
 
6854
 
        if (p->subs[idx].needhold) {
6855
 
                /* Send answer frame if requested */
6856
 
                p->subs[idx].needhold = 0;
6857
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6858
 
                p->subs[idx].f.subclass = AST_CONTROL_HOLD;
6859
 
                ast_mutex_unlock(&p->lock);
6860
 
                ast_debug(1, "Sending hold on '%s'\n", ast->name);
6861
 
                return &p->subs[idx].f;
6862
 
        }
6863
 
 
6864
 
        if (p->subs[idx].needunhold) {
6865
 
                /* Send answer frame if requested */
6866
 
                p->subs[idx].needunhold = 0;
6867
 
                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
6868
 
                p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
6869
 
                ast_mutex_unlock(&p->lock);
6870
 
                ast_debug(1, "Sending unhold on '%s'\n", ast->name);
6871
 
                return &p->subs[idx].f;
6872
 
        }
6873
 
 
6874
 
        if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
6875
 
                if (!p->subs[idx].linear) {
6876
 
                        p->subs[idx].linear = 1;
6877
 
                        res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
6878
 
                        if (res)
6879
 
                                ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
6880
 
                }
6881
 
        } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
6882
 
                (ast->rawreadformat == AST_FORMAT_ALAW)) {
6883
 
                if (p->subs[idx].linear) {
6884
 
                        p->subs[idx].linear = 0;
6885
 
                        res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
6886
 
                        if (res)
6887
 
                                ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
6888
 
                }
6889
 
        } else {
6890
 
                ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
6891
 
                ast_mutex_unlock(&p->lock);
6892
 
                return NULL;
6893
 
        }
6894
 
        readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
6895
 
        CHECK_BLOCKING(ast);
6896
 
        res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
6897
 
        ast_clear_flag(ast, AST_FLAG_BLOCKING);
6898
 
        /* Check for hangup */
6899
 
        if (res < 0) {
6900
 
                f = NULL;
6901
 
                if (res == -1) {
6902
 
                        if (errno == EAGAIN) {
6903
 
                                /* Return "NULL" frame if there is nobody there */
6904
 
                                ast_mutex_unlock(&p->lock);
6905
 
                                return &p->subs[idx].f;
6906
 
                        } else if (errno == ELAST) {
6907
 
                                f = __dahdi_exception(ast);
6908
 
                        } else
6909
 
                                ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
6910
 
                }
6911
 
                ast_mutex_unlock(&p->lock);
6912
 
                return f;
6913
 
        }
6914
 
        if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
6915
 
                ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
6916
 
                f = __dahdi_exception(ast);
6917
 
                ast_mutex_unlock(&p->lock);
6918
 
                return f;
6919
 
        }
6920
 
        if (p->tdd) { /* if in TDD mode, see if we receive that */
6921
 
                int c;
6922
 
 
6923
 
                c = tdd_feed(p->tdd,readbuf,READ_SIZE);
6924
 
                if (c < 0) {
6925
 
                        ast_debug(1,"tdd_feed failed\n");
6926
 
                        ast_mutex_unlock(&p->lock);
6927
 
                        return NULL;
6928
 
                }
6929
 
                if (c) { /* if a char to return */
6930
 
                        p->subs[idx].f.subclass = 0;
6931
 
                        p->subs[idx].f.frametype = AST_FRAME_TEXT;
6932
 
                        p->subs[idx].f.mallocd = 0;
6933
 
                        p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
6934
 
                        p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
6935
 
                        p->subs[idx].f.datalen = 1;
6936
 
                        *((char *) p->subs[idx].f.data.ptr) = c;
6937
 
                        ast_mutex_unlock(&p->lock);
6938
 
                        return &p->subs[idx].f;
6939
 
                }
6940
 
        }
6941
 
        /* Ensure the CW timer decrements only on a single subchannel */
6942
 
        if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
6943
 
                p->callwaitingrepeat--;
6944
 
        }
6945
 
        if (p->cidcwexpire)
6946
 
                p->cidcwexpire--;
6947
 
        /* Repeat callwaiting */
6948
 
        if (p->callwaitingrepeat == 1) {
6949
 
                p->callwaitrings++;
6950
 
                dahdi_callwait(ast);
6951
 
        }
6952
 
        /* Expire CID/CW */
6953
 
        if (p->cidcwexpire == 1) {
6954
 
                ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
6955
 
                restore_conference(p);
6956
 
        }
6957
 
        if (p->subs[idx].linear) {
6958
 
                p->subs[idx].f.datalen = READ_SIZE * 2;
6959
 
        } else
6960
 
                p->subs[idx].f.datalen = READ_SIZE;
6961
 
 
6962
 
        /* Handle CallerID Transmission */
6963
 
        if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
6964
 
                send_callerid(p);
6965
 
        }
6966
 
 
6967
 
        p->subs[idx].f.frametype = AST_FRAME_VOICE;
6968
 
        p->subs[idx].f.subclass = ast->rawreadformat;
6969
 
        p->subs[idx].f.samples = READ_SIZE;
6970
 
        p->subs[idx].f.mallocd = 0;
6971
 
        p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
6972
 
        p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
6973
 
#if 0
6974
 
        ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
6975
 
#endif
6976
 
        if (p->dialing || /* Transmitting something */
6977
 
                (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
6978
 
                ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
6979
 
                ) {
6980
 
                /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
6981
 
                   don't send anything */
6982
 
                p->subs[idx].f.frametype = AST_FRAME_NULL;
6983
 
                p->subs[idx].f.subclass = 0;
6984
 
                p->subs[idx].f.samples = 0;
6985
 
                p->subs[idx].f.mallocd = 0;
6986
 
                p->subs[idx].f.offset = 0;
6987
 
                p->subs[idx].f.data.ptr = NULL;
6988
 
                p->subs[idx].f.datalen= 0;
6989
 
        }
6990
 
        if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
6991
 
                /* Perform busy detection etc on the dahdi line */
6992
 
                int mute;
6993
 
 
6994
 
                f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
6995
 
 
6996
 
                /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
6997
 
                mute = ast_dsp_was_muted(p->dsp);
6998
 
                if (p->muting != mute) {
6999
 
                        p->muting = mute;
7000
 
                        dahdi_confmute(p, mute);
7001
 
                }
7002
 
 
7003
 
                if (f) {
7004
 
                        if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
7005
 
                                if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
7006
 
                                        /* Treat this as a "hangup" instead of a "busy" on the assumption that
7007
 
                                           a busy */
7008
 
                                        f = NULL;
7009
 
                                }
7010
 
                        } else if (f->frametype == AST_FRAME_DTMF) {
7011
 
#ifdef HAVE_PRI
7012
 
                                if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
7013
 
                                        ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
7014
 
                                        (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
7015
 
                                        /* Don't accept in-band DTMF when in overlap dial mode */
7016
 
                                        f->frametype = AST_FRAME_NULL;
7017
 
                                        f->subclass = 0;
7018
 
                                }
7019
 
#endif
7020
 
                                /* DSP clears us of being pulse */
7021
 
                                p->pulsedial = 0;
7022
 
                        } else if (p->waitingfordt.tv_sec) {
7023
 
                                if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
7024
 
                                        p->waitingfordt.tv_sec = 0;
7025
 
                                        ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
7026
 
                                        f=NULL;
7027
 
                                } else if (f->frametype == AST_FRAME_VOICE) {
7028
 
                                        f->frametype = AST_FRAME_NULL;
7029
 
                                        f->subclass = 0;
7030
 
                                        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) {
7031
 
                                                p->waitingfordt.tv_sec = 0;
7032
 
                                                p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
7033
 
                                                ast_dsp_set_features(p->dsp, p->dsp_features);
7034
 
                                                ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
7035
 
                                                if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
7036
 
                                                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
7037
 
                                                        if (res < 0) {
7038
 
                                                                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
7039
 
                                                                p->dop.dialstr[0] = '\0';
7040
 
                                                                ast_mutex_unlock(&p->lock);
7041
 
                                                                return NULL;
7042
 
                                                        } else {
7043
 
                                                                ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
7044
 
                                                                p->dialing = 1;
7045
 
                                                                p->dop.dialstr[0] = '\0';
7046
 
                                                                p->dop.op = DAHDI_DIAL_OP_REPLACE;
7047
 
                                                                ast_setstate(ast, AST_STATE_DIALING);
7048
 
                                                        }
7049
 
                                                }
7050
 
                                        }
7051
 
                                }
7052
 
                        }
7053
 
                }
7054
 
        } else
7055
 
                f = &p->subs[idx].f;
7056
 
 
7057
 
        if (f && (f->frametype == AST_FRAME_DTMF))
7058
 
                dahdi_handle_dtmfup(ast, idx, &f);
7059
 
 
7060
 
        /* If we have a fake_event, trigger exception to handle it */
7061
 
        if (p->fake_event)
7062
 
                ast_set_flag(ast, AST_FLAG_EXCEPTION);
7063
 
 
7064
 
        ast_mutex_unlock(&p->lock);
7065
 
        return f;
7066
 
}
7067
 
 
7068
 
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
7069
 
{
7070
 
        int sent=0;
7071
 
        int size;
7072
 
        int res;
7073
 
        int fd;
7074
 
        fd = p->subs[idx].dfd;
7075
 
        while (len) {
7076
 
                size = len;
7077
 
                if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
7078
 
                        size = (linear ? READ_SIZE * 2 : READ_SIZE);
7079
 
                res = write(fd, buf, size);
7080
 
                if (res != size) {
7081
 
                        ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
7082
 
                        return sent;
7083
 
                }
7084
 
                len -= size;
7085
 
                buf += size;
7086
 
        }
7087
 
        return sent;
7088
 
}
7089
 
 
7090
 
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
7091
 
{
7092
 
        struct dahdi_pvt *p = ast->tech_pvt;
7093
 
        int res;
7094
 
        int idx;
7095
 
        idx = dahdi_get_index(ast, p, 0);
7096
 
        if (idx < 0) {
7097
 
                ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
7098
 
                return -1;
7099
 
        }
7100
 
 
7101
 
#if 0
7102
 
#ifdef HAVE_PRI
7103
 
        ast_mutex_lock(&p->lock);
7104
 
        if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
7105
 
                if (p->pri->pri) {
7106
 
                        if (!pri_grab(p, p->pri)) {
7107
 
                                        pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
7108
 
                                        pri_rel(p->pri);
7109
 
                        } else
7110
 
                                        ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7111
 
                }
7112
 
                p->proceeding=1;
7113
 
        }
7114
 
        ast_mutex_unlock(&p->lock);
7115
 
#endif
7116
 
#endif
7117
 
        /* Write a frame of (presumably voice) data */
7118
 
        if (frame->frametype != AST_FRAME_VOICE) {
7119
 
                if (frame->frametype != AST_FRAME_IMAGE)
7120
 
                        ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
7121
 
                return 0;
7122
 
        }
7123
 
        if ((frame->subclass != AST_FORMAT_SLINEAR) &&
7124
 
                (frame->subclass != AST_FORMAT_ULAW) &&
7125
 
                (frame->subclass != AST_FORMAT_ALAW)) {
7126
 
                ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
7127
 
                return -1;
7128
 
        }
7129
 
        if (p->dialing) {
7130
 
                ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
7131
 
                return 0;
7132
 
        }
7133
 
        if (!p->owner) {
7134
 
                ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
7135
 
                return 0;
7136
 
        }
7137
 
        if (p->cidspill) {
7138
 
                ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
7139
 
                return 0;
7140
 
        }
7141
 
        /* Return if it's not valid data */
7142
 
        if (!frame->data.ptr || !frame->datalen)
7143
 
                return 0;
7144
 
 
7145
 
        if (frame->subclass == AST_FORMAT_SLINEAR) {
7146
 
                if (!p->subs[idx].linear) {
7147
 
                        p->subs[idx].linear = 1;
7148
 
                        res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
7149
 
                        if (res)
7150
 
                                ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
7151
 
                }
7152
 
                res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
7153
 
        } else {
7154
 
                /* x-law already */
7155
 
                if (p->subs[idx].linear) {
7156
 
                        p->subs[idx].linear = 0;
7157
 
                        res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
7158
 
                        if (res)
7159
 
                                ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
7160
 
                }
7161
 
                res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
7162
 
        }
7163
 
        if (res < 0) {
7164
 
                ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
7165
 
                return -1;
7166
 
        }
7167
 
        return 0;
7168
 
}
7169
 
 
7170
 
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
7171
 
{
7172
 
        struct dahdi_pvt *p = chan->tech_pvt;
7173
 
        int res=-1;
7174
 
        int idx;
7175
 
        int func = DAHDI_FLASH;
7176
 
        ast_mutex_lock(&p->lock);
7177
 
        idx = dahdi_get_index(chan, p, 0);
7178
 
        ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
7179
 
#ifdef HAVE_OPENR2
7180
 
        if (p->mfcr2 && !p->mfcr2_call_accepted) {
7181
 
                ast_mutex_unlock(&p->lock);
7182
 
                /* if this is an R2 call and the call is not yet accepted, we don't want the
7183
 
                   tone indications to mess up with the MF tones */
7184
 
                return 0;
7185
 
        }
7186
 
#endif
7187
 
        if (idx == SUB_REAL) {
7188
 
                switch (condition) {
7189
 
                case AST_CONTROL_BUSY:
7190
 
#ifdef HAVE_PRI
7191
 
                        if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
7192
 
                                chan->hangupcause = AST_CAUSE_USER_BUSY;
7193
 
                                chan->_softhangup |= AST_SOFTHANGUP_DEV;
7194
 
                                res = 0;
7195
 
                        } else if (!p->progress &&
7196
 
                                        ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
7197
 
                                        && p->pri && !p->outgoing) {
7198
 
                                if (p->pri->pri) {
7199
 
                                        if (!pri_grab(p, p->pri)) {
7200
 
#ifdef HAVE_PRI_PROG_W_CAUSE
7201
 
                                                pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
7202
 
#else
7203
 
                                                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
7204
 
#endif
7205
 
                                                pri_rel(p->pri);
7206
 
                                        }
7207
 
                                        else
7208
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7209
 
                                }
7210
 
                                p->progress = 1;
7211
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
7212
 
                        } else
7213
 
#endif
7214
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
7215
 
                        break;
7216
 
                case AST_CONTROL_RINGING:
7217
 
#ifdef HAVE_PRI
7218
 
                        if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
7219
 
                                        && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
7220
 
                                if (p->pri->pri) {
7221
 
                                        if (!pri_grab(p, p->pri)) {
7222
 
                                                pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
7223
 
                                                pri_rel(p->pri);
7224
 
                                        }
7225
 
                                        else
7226
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7227
 
                                }
7228
 
                                p->alerting = 1;
7229
 
                        }
7230
 
 
7231
 
#endif
7232
 
#ifdef HAVE_SS7
7233
 
                        if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
7234
 
                                if (p->ss7->ss7) {
7235
 
                                        ss7_grab(p, p->ss7);
7236
 
 
7237
 
                                        if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
7238
 
                                                p->rlt = 1;
7239
 
                                        if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
7240
 
                                                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
7241
 
                                        p->alerting = 1;
7242
 
                                        ss7_rel(p->ss7);
7243
 
                                }
7244
 
                        }
7245
 
#endif
7246
 
 
7247
 
                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
7248
 
 
7249
 
                        if (chan->_state != AST_STATE_UP) {
7250
 
                                if ((chan->_state != AST_STATE_RING) ||
7251
 
                                        ((p->sig != SIG_FXSKS) &&
7252
 
                                 (p->sig != SIG_FXSLS) &&
7253
 
                                 (p->sig != SIG_FXSGS)))
7254
 
                                ast_setstate(chan, AST_STATE_RINGING);
7255
 
                        }
7256
 
                        break;
7257
 
                case AST_CONTROL_PROCEEDING:
7258
 
                        ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
7259
 
#ifdef HAVE_PRI
7260
 
                        if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
7261
 
                                        && p->pri && !p->outgoing) {
7262
 
                                if (p->pri->pri) {
7263
 
                                        if (!pri_grab(p, p->pri)) {
7264
 
                                                pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
7265
 
                                                pri_rel(p->pri);
7266
 
                                        }
7267
 
                                        else
7268
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7269
 
                                }
7270
 
                                p->proceeding = 1;
7271
 
                                p->dialing = 0;
7272
 
                        }
7273
 
#endif
7274
 
#ifdef HAVE_SS7
7275
 
                        /* This IF sends the FAR for an answered ALEG call */
7276
 
                        if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
7277
 
                                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
7278
 
                                        p->rlt = 1;
7279
 
                        }
7280
 
 
7281
 
                        if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
7282
 
                                if (p->ss7->ss7) {
7283
 
                                        ss7_grab(p, p->ss7);
7284
 
                                        isup_acm(p->ss7->ss7, p->ss7call);
7285
 
                                        p->proceeding = 1;
7286
 
                                        ss7_rel(p->ss7);
7287
 
 
7288
 
                                }
7289
 
                        }
7290
 
#endif
7291
 
                        /* don't continue in ast_indicate */
7292
 
                        res = 0;
7293
 
                        break;
7294
 
                case AST_CONTROL_PROGRESS:
7295
 
                        ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
7296
 
#ifdef HAVE_PRI
7297
 
                        p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
7298
 
                        if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
7299
 
                                        && p->pri && !p->outgoing) {
7300
 
                                if (p->pri->pri) {
7301
 
                                        if (!pri_grab(p, p->pri)) {
7302
 
#ifdef HAVE_PRI_PROG_W_CAUSE
7303
 
                                                pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
7304
 
#else
7305
 
                                                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
7306
 
#endif
7307
 
                                                pri_rel(p->pri);
7308
 
                                        }
7309
 
                                        else
7310
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7311
 
                                }
7312
 
                                p->progress = 1;
7313
 
                        }
7314
 
#endif
7315
 
#ifdef HAVE_SS7
7316
 
                        if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
7317
 
                                if (p->ss7->ss7) {
7318
 
                                        ss7_grab(p, p->ss7);
7319
 
                                        isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
7320
 
                                        p->progress = 1;
7321
 
                                        ss7_rel(p->ss7);
7322
 
                                        /* enable echo canceler here on SS7 calls */
7323
 
                                        dahdi_enable_ec(p);
7324
 
 
7325
 
                                }
7326
 
                        }
7327
 
#endif
7328
 
                        /* don't continue in ast_indicate */
7329
 
                        res = 0;
7330
 
                        break;
7331
 
                case AST_CONTROL_CONGESTION:
7332
 
                        chan->hangupcause = AST_CAUSE_CONGESTION;
7333
 
#ifdef HAVE_PRI
7334
 
                        if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
7335
 
                                chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
7336
 
                                chan->_softhangup |= AST_SOFTHANGUP_DEV;
7337
 
                                res = 0;
7338
 
                        } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
7339
 
                                        && p->pri && !p->outgoing) {
7340
 
                                if (p->pri) {
7341
 
                                        if (!pri_grab(p, p->pri)) {
7342
 
#ifdef HAVE_PRI_PROG_W_CAUSE
7343
 
                                                pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
7344
 
#else
7345
 
                                                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
7346
 
#endif
7347
 
                                                pri_rel(p->pri);
7348
 
                                        } else
7349
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7350
 
                                }
7351
 
                                p->progress = 1;
7352
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
7353
 
                        } else
7354
 
#endif
7355
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
7356
 
                        break;
7357
 
                case AST_CONTROL_HOLD:
7358
 
#ifdef HAVE_PRI
7359
 
                        if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
7360
 
                                if (!pri_grab(p, p->pri)) {
7361
 
                                        res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
7362
 
                                        pri_rel(p->pri);
7363
 
                                } else
7364
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7365
 
                        } else
7366
 
#endif
7367
 
                                ast_moh_start(chan, data, p->mohinterpret);
7368
 
                        break;
7369
 
                case AST_CONTROL_UNHOLD:
7370
 
#ifdef HAVE_PRI
7371
 
                        if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
7372
 
                                if (!pri_grab(p, p->pri)) {
7373
 
                                        res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
7374
 
                                        pri_rel(p->pri);
7375
 
                                } else
7376
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7377
 
                        } else
7378
 
#endif
7379
 
                                ast_moh_stop(chan);
7380
 
                        break;
7381
 
                case AST_CONTROL_RADIO_KEY:
7382
 
                        if (p->radio)
7383
 
                                res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
7384
 
                        res = 0;
7385
 
                        break;
7386
 
                case AST_CONTROL_RADIO_UNKEY:
7387
 
                        if (p->radio)
7388
 
                                res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
7389
 
                        res = 0;
7390
 
                        break;
7391
 
                case AST_CONTROL_FLASH:
7392
 
                        /* flash hookswitch */
7393
 
                        if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
7394
 
                                /* Clear out the dial buffer */
7395
 
                                p->dop.dialstr[0] = '\0';
7396
 
                                if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
7397
 
                                        ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
7398
 
                                                chan->name, strerror(errno));
7399
 
                                } else
7400
 
                                        res = 0;
7401
 
                        } else
7402
 
                                res = 0;
7403
 
                        break;
7404
 
                case AST_CONTROL_SRCUPDATE:
7405
 
                        res = 0;
7406
 
                        break;
7407
 
                case -1:
7408
 
                        res = tone_zone_play_tone(p->subs[idx].dfd, -1);
7409
 
                        break;
7410
 
                }
7411
 
        } else
7412
 
                res = 0;
7413
 
        ast_mutex_unlock(&p->lock);
7414
 
        return res;
7415
 
}
7416
 
 
7417
 
static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
7418
 
{
7419
 
        struct ast_channel *tmp;
7420
 
        int deflaw;
7421
 
        int res;
7422
 
        int x,y;
7423
 
        int features;
7424
 
        struct ast_str *chan_name;
7425
 
        struct ast_variable *v;
7426
 
        struct dahdi_params ps;
7427
 
        if (i->subs[idx].owner) {
7428
 
                ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
7429
 
                return NULL;
7430
 
        }
7431
 
        y = 1;
7432
 
        chan_name = ast_str_alloca(32);
7433
 
        do {
7434
 
#ifdef HAVE_PRI
7435
 
                if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
7436
 
                        ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
7437
 
                else
7438
 
#endif
7439
 
                if (i->channel == CHAN_PSEUDO)
7440
 
                        ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
7441
 
                else
7442
 
                        ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
7443
 
                for (x = 0; x < 3; x++) {
7444
 
                        if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
7445
 
                                break;
7446
 
                }
7447
 
                y++;
7448
 
        } while (x < 3);
7449
 
        tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
7450
 
        if (!tmp)
7451
 
                return NULL;
7452
 
        tmp->tech = &dahdi_tech;
7453
 
        memset(&ps, 0, sizeof(ps));
7454
 
        ps.channo = i->channel;
7455
 
        res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
7456
 
        if (res) {
7457
 
                ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
7458
 
                ps.curlaw = DAHDI_LAW_MULAW;
7459
 
        }
7460
 
        if (ps.curlaw == DAHDI_LAW_ALAW)
7461
 
                deflaw = AST_FORMAT_ALAW;
7462
 
        else
7463
 
                deflaw = AST_FORMAT_ULAW;
7464
 
        if (law) {
7465
 
                if (law == DAHDI_LAW_ALAW)
7466
 
                        deflaw = AST_FORMAT_ALAW;
7467
 
                else
7468
 
                        deflaw = AST_FORMAT_ULAW;
7469
 
        }
7470
 
        ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
7471
 
        tmp->nativeformats = deflaw;
7472
 
        /* Start out assuming ulaw since it's smaller :) */
7473
 
        tmp->rawreadformat = deflaw;
7474
 
        tmp->readformat = deflaw;
7475
 
        tmp->rawwriteformat = deflaw;
7476
 
        tmp->writeformat = deflaw;
7477
 
        i->subs[idx].linear = 0;
7478
 
        dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
7479
 
        features = 0;
7480
 
        if (idx == SUB_REAL) {
7481
 
                if (i->busydetect && CANBUSYDETECT(i))
7482
 
                        features |= DSP_FEATURE_BUSY_DETECT;
7483
 
                if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
7484
 
                        features |= DSP_FEATURE_CALL_PROGRESS;
7485
 
                if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
7486
 
                        features |= DSP_FEATURE_WAITDIALTONE;
7487
 
                if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
7488
 
                        (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
7489
 
                        features |= DSP_FEATURE_FAX_DETECT;
7490
 
                }
7491
 
                x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
7492
 
                if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
7493
 
                        i->hardwaredtmf = 0;
7494
 
                        features |= DSP_FEATURE_DIGIT_DETECT;
7495
 
                } else if (NEED_MFDETECT(i)) {
7496
 
                        i->hardwaredtmf = 1;
7497
 
                        features |= DSP_FEATURE_DIGIT_DETECT;
7498
 
                }
7499
 
        }
7500
 
        if (features) {
7501
 
                if (i->dsp) {
7502
 
                        ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
7503
 
                } else {
7504
 
                        if (i->channel != CHAN_PSEUDO)
7505
 
                                i->dsp = ast_dsp_new();
7506
 
                        else
7507
 
                                i->dsp = NULL;
7508
 
                        if (i->dsp) {
7509
 
                                i->dsp_features = features;
7510
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
7511
 
                                /* We cannot do progress detection until receives PROGRESS message */
7512
 
                                if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
7513
 
                                        /* Remember requested DSP features, don't treat
7514
 
                                           talking as ANSWER */
7515
 
                                        i->dsp_features = features & ~DSP_PROGRESS_TALK;
7516
 
                                        features = 0;
7517
 
                                }
7518
 
#endif
7519
 
                                ast_dsp_set_features(i->dsp, features);
7520
 
                                ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
7521
 
                                if (!ast_strlen_zero(progzone))
7522
 
                                        ast_dsp_set_call_progress_zone(i->dsp, progzone);
7523
 
                                if (i->busydetect && CANBUSYDETECT(i)) {
7524
 
                                        ast_dsp_set_busy_count(i->dsp, i->busycount);
7525
 
                                        ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
7526
 
                                }
7527
 
                        }
7528
 
                }
7529
 
        }
7530
 
 
7531
 
        if (state == AST_STATE_RING)
7532
 
                tmp->rings = 1;
7533
 
        tmp->tech_pvt = i;
7534
 
        if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
7535
 
                /* Only FXO signalled stuff can be picked up */
7536
 
                tmp->callgroup = i->callgroup;
7537
 
                tmp->pickupgroup = i->pickupgroup;
7538
 
        }
7539
 
        if (!ast_strlen_zero(i->parkinglot))
7540
 
                ast_string_field_set(tmp, parkinglot, i->parkinglot);
7541
 
        if (!ast_strlen_zero(i->language))
7542
 
                ast_string_field_set(tmp, language, i->language);
7543
 
        if (!i->owner)
7544
 
                i->owner = tmp;
7545
 
        if (!ast_strlen_zero(i->accountcode))
7546
 
                ast_string_field_set(tmp, accountcode, i->accountcode);
7547
 
        if (i->amaflags)
7548
 
                tmp->amaflags = i->amaflags;
7549
 
        i->subs[idx].owner = tmp;
7550
 
        ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
7551
 
        ast_string_field_set(tmp, call_forward, i->call_forward);
7552
 
        /* If we've been told "no ADSI" then enforce it */
7553
 
        if (!i->adsi)
7554
 
                tmp->adsicpe = AST_ADSI_UNAVAILABLE;
7555
 
        if (!ast_strlen_zero(i->exten))
7556
 
                ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
7557
 
        if (!ast_strlen_zero(i->rdnis))
7558
 
                tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
7559
 
        if (!ast_strlen_zero(i->dnid))
7560
 
                tmp->cid.cid_dnid = ast_strdup(i->dnid);
7561
 
 
7562
 
        /* Don't use ast_set_callerid() here because it will
7563
 
         * generate a needless NewCallerID event */
7564
 
#ifdef PRI_ANI
7565
 
        if (!ast_strlen_zero(i->cid_ani))
7566
 
                tmp->cid.cid_ani = ast_strdup(i->cid_ani);
7567
 
        else
7568
 
                tmp->cid.cid_ani = ast_strdup(i->cid_num);
7569
 
#else
7570
 
        tmp->cid.cid_ani = ast_strdup(i->cid_num);
7571
 
#endif
7572
 
        tmp->cid.cid_pres = i->callingpres;
7573
 
        tmp->cid.cid_ton = i->cid_ton;
7574
 
        tmp->cid.cid_ani2 = i->cid_ani2;
7575
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
7576
 
        tmp->transfercapability = transfercapability;
7577
 
        pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
7578
 
        if (transfercapability & AST_TRANS_CAP_DIGITAL)
7579
 
                i->digital = 1;
7580
 
        /* Assume calls are not idle calls unless we're told differently */
7581
 
        i->isidlecall = 0;
7582
 
        i->alreadyhungup = 0;
7583
 
#endif
7584
 
        /* clear the fake event in case we posted one before we had ast_channel */
7585
 
        i->fake_event = 0;
7586
 
        /* Assure there is no confmute on this channel */
7587
 
        dahdi_confmute(i, 0);
7588
 
        i->muting = 0;
7589
 
        /* Configure the new channel jb */
7590
 
        ast_jb_configure(tmp, &global_jbconf);
7591
 
 
7592
 
        ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
7593
 
 
7594
 
        for (v = i->vars ; v ; v = v->next)
7595
 
                pbx_builtin_setvar_helper(tmp, v->name, v->value);
7596
 
 
7597
 
        if (startpbx) {
7598
 
#ifdef HAVE_OPENR2
7599
 
                if (i->mfcr2call) {
7600
 
                        pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
7601
 
                }
7602
 
#endif
7603
 
                if (ast_pbx_start(tmp)) {
7604
 
                        ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
7605
 
                        ast_hangup(tmp);
7606
 
                        i->owner = NULL;
7607
 
                        return NULL;
7608
 
                }
7609
 
        }
7610
 
 
7611
 
        ast_module_ref(ast_module_info->self);
7612
 
        return tmp;
7613
 
}
7614
 
 
7615
 
 
7616
 
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
7617
 
{
7618
 
        char c;
7619
 
 
7620
 
        *str = 0; /* start with empty output buffer */
7621
 
        for (;;)
7622
 
        {
7623
 
                /* Wait for the first digit (up to specified ms). */
7624
 
                c = ast_waitfordigit(chan, ms);
7625
 
                /* if timeout, hangup or error, return as such */
7626
 
                if (c < 1)
7627
 
                        return c;
7628
 
                *str++ = c;
7629
 
                *str = 0;
7630
 
                if (strchr(term, c))
7631
 
                        return 1;
7632
 
        }
7633
 
}
7634
 
 
7635
 
static int dahdi_wink(struct dahdi_pvt *p, int idx)
7636
 
{
7637
 
        int j;
7638
 
        dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
7639
 
        for (;;)
7640
 
        {
7641
 
                /* set bits of interest */
7642
 
                j = DAHDI_IOMUX_SIGEVENT;
7643
 
                /* wait for some happening */
7644
 
                if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
7645
 
                /* exit loop if we have it */
7646
 
                if (j & DAHDI_IOMUX_SIGEVENT) break;
7647
 
        }
7648
 
        /* get the event info */
7649
 
        if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
7650
 
        return 0;
7651
 
}
7652
 
 
7653
 
/*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
7654
 
 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
7655
 
 * \param on 1 to enable, 0 to disable
7656
 
 *
7657
 
 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
7658
 
 * DAHDI channel). Use this to enable or disable it.
7659
 
 *
7660
 
 * \bug the use of the word "channel" for those dahdichans is really confusing.
7661
 
 */
7662
 
static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
7663
 
{
7664
 
        /* Do not disturb */
7665
 
        dahdichan->dnd = on;
7666
 
        ast_verb(3, "%s DND on channel %d\n",
7667
 
                        on? "Enabled" : "Disabled",
7668
 
                        dahdichan->channel);
7669
 
        manager_event(EVENT_FLAG_SYSTEM, "DNDState",
7670
 
                        "Channel: DAHDI/%d\r\n"
7671
 
                        "Status: %s\r\n", dahdichan->channel,
7672
 
                        on? "enabled" : "disabled");
7673
 
}
7674
 
 
7675
 
static void *ss_thread(void *data)
7676
 
{
7677
 
        struct ast_channel *chan = data;
7678
 
        struct dahdi_pvt *p = chan->tech_pvt;
7679
 
        char exten[AST_MAX_EXTENSION] = "";
7680
 
        char exten2[AST_MAX_EXTENSION] = "";
7681
 
        unsigned char buf[256];
7682
 
        char dtmfcid[300];
7683
 
        char dtmfbuf[300];
7684
 
        struct callerid_state *cs = NULL;
7685
 
        char *name = NULL, *number = NULL;
7686
 
        int distMatches;
7687
 
        int curRingData[3];
7688
 
        int receivedRingT;
7689
 
        int counter1;
7690
 
        int counter;
7691
 
        int samples = 0;
7692
 
        struct ast_smdi_md_message *smdi_msg = NULL;
7693
 
        int flags = 0;
7694
 
        int i;
7695
 
        int timeout;
7696
 
        int getforward = 0;
7697
 
        char *s1, *s2;
7698
 
        int len = 0;
7699
 
        int res;
7700
 
        int idx;
7701
 
 
7702
 
        ast_mutex_lock(&ss_thread_lock);
7703
 
        ss_thread_count++;
7704
 
        ast_mutex_unlock(&ss_thread_lock);
7705
 
        /* in the bizarre case where the channel has become a zombie before we
7706
 
           even get started here, abort safely
7707
 
        */
7708
 
        if (!p) {
7709
 
                ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
7710
 
                ast_hangup(chan);
7711
 
                goto quit;
7712
 
        }
7713
 
        ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
7714
 
        idx = dahdi_get_index(chan, p, 1);
7715
 
        if (idx < 0) {
7716
 
                ast_log(LOG_WARNING, "Huh?\n");
7717
 
                ast_hangup(chan);
7718
 
                goto quit;
7719
 
        }
7720
 
        if (p->dsp)
7721
 
                ast_dsp_digitreset(p->dsp);
7722
 
        switch (p->sig) {
7723
 
#ifdef HAVE_PRI
7724
 
        case SIG_PRI:
7725
 
        case SIG_BRI:
7726
 
        case SIG_BRI_PTMP:
7727
 
                /* Now loop looking for an extension */
7728
 
                ast_copy_string(exten, p->exten, sizeof(exten));
7729
 
                len = strlen(exten);
7730
 
                res = 0;
7731
 
                while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
7732
 
                        if (len && !ast_ignore_pattern(chan->context, exten))
7733
 
                                tone_zone_play_tone(p->subs[idx].dfd, -1);
7734
 
                        else
7735
 
                                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
7736
 
                        if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
7737
 
                                timeout = matchdigittimeout;
7738
 
                        else
7739
 
                                timeout = gendigittimeout;
7740
 
                        res = ast_waitfordigit(chan, timeout);
7741
 
                        if (res < 0) {
7742
 
                                ast_debug(1, "waitfordigit returned < 0...\n");
7743
 
                                ast_hangup(chan);
7744
 
                                goto quit;
7745
 
                        } else if (res) {
7746
 
                                exten[len++] = res;
7747
 
                                exten[len] = '\0';
7748
 
                        } else
7749
 
                                break;
7750
 
                }
7751
 
                /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
7752
 
                if (ast_strlen_zero(exten)) {
7753
 
                        ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
7754
 
                        exten[0] = 's';
7755
 
                        exten[1] = '\0';
7756
 
                }
7757
 
                tone_zone_play_tone(p->subs[idx].dfd, -1);
7758
 
                if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
7759
 
                        /* Start the real PBX */
7760
 
                        ast_copy_string(chan->exten, exten, sizeof(chan->exten));
7761
 
                        if (p->dsp) {
7762
 
                                ast_dsp_digitreset(p->dsp);
7763
 
                        }
7764
 
                        if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
7765
 
                                if (p->pri->pri) {              
7766
 
                                        if (!pri_grab(p, p->pri)) {
7767
 
                                                pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
7768
 
                                                p->proceeding = 1;
7769
 
                                                pri_rel(p->pri);
7770
 
                                        } else {
7771
 
                                                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7772
 
                                        }
7773
 
                                }
7774
 
                        }
7775
 
                        dahdi_enable_ec(p);
7776
 
                        ast_setstate(chan, AST_STATE_RING);
7777
 
                        res = ast_pbx_run(chan);
7778
 
                        if (res) {
7779
 
                                ast_log(LOG_WARNING, "PBX exited non-zero!\n");
7780
 
                        }
7781
 
                } else {
7782
 
                        ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
7783
 
                        chan->hangupcause = AST_CAUSE_UNALLOCATED;
7784
 
                        ast_hangup(chan);
7785
 
                        p->exten[0] = '\0';
7786
 
                        /* Since we send release complete here, we won't get one */
7787
 
                        p->call = NULL;
7788
 
                }
7789
 
                goto quit;
7790
 
                break;
7791
 
#endif
7792
 
        case SIG_FEATD:
7793
 
        case SIG_FEATDMF:
7794
 
        case SIG_FEATDMF_TA:
7795
 
        case SIG_E911:
7796
 
        case SIG_FGC_CAMAMF:
7797
 
        case SIG_FEATB:
7798
 
        case SIG_EMWINK:
7799
 
        case SIG_SF_FEATD:
7800
 
        case SIG_SF_FEATDMF:
7801
 
        case SIG_SF_FEATB:
7802
 
        case SIG_SFWINK:
7803
 
                if (dahdi_wink(p, idx))
7804
 
                        goto quit;
7805
 
                /* Fall through */
7806
 
        case SIG_EM:
7807
 
        case SIG_EM_E1:
7808
 
        case SIG_SF:
7809
 
        case SIG_FGC_CAMA:
7810
 
                res = tone_zone_play_tone(p->subs[idx].dfd, -1);
7811
 
                if (p->dsp)
7812
 
                        ast_dsp_digitreset(p->dsp);
7813
 
                /* set digit mode appropriately */
7814
 
                if (p->dsp) {
7815
 
                        if (NEED_MFDETECT(p))
7816
 
                                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
7817
 
                        else
7818
 
                                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
7819
 
                }
7820
 
                memset(dtmfbuf, 0, sizeof(dtmfbuf));
7821
 
                /* Wait for the first digit only if immediate=no */
7822
 
                if (!p->immediate)
7823
 
                        /* Wait for the first digit (up to 5 seconds). */
7824
 
                        res = ast_waitfordigit(chan, 5000);
7825
 
                else
7826
 
                        res = 0;
7827
 
                if (res > 0) {
7828
 
                        /* save first char */
7829
 
                        dtmfbuf[0] = res;
7830
 
                        switch (p->sig) {
7831
 
                        case SIG_FEATD:
7832
 
                        case SIG_SF_FEATD:
7833
 
                                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
7834
 
                                if (res > 0)
7835
 
                                        res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
7836
 
                                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
7837
 
                                break;
7838
 
                        case SIG_FEATDMF_TA:
7839
 
                                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
7840
 
                                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
7841
 
                                if (dahdi_wink(p, idx)) goto quit;
7842
 
                                dtmfbuf[0] = 0;
7843
 
                                /* Wait for the first digit (up to 5 seconds). */
7844
 
                                res = ast_waitfordigit(chan, 5000);
7845
 
                                if (res <= 0) break;
7846
 
                                dtmfbuf[0] = res;
7847
 
                                /* fall through intentionally */
7848
 
                        case SIG_FEATDMF:
7849
 
                        case SIG_E911:
7850
 
                        case SIG_FGC_CAMAMF:
7851
 
                        case SIG_SF_FEATDMF:
7852
 
                                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
7853
 
                                /* if international caca, do it again to get real ANO */
7854
 
                                if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
7855
 
                                {
7856
 
                                        if (dahdi_wink(p, idx)) goto quit;
7857
 
                                        dtmfbuf[0] = 0;
7858
 
                                        /* Wait for the first digit (up to 5 seconds). */
7859
 
                                        res = ast_waitfordigit(chan, 5000);
7860
 
                                        if (res <= 0) break;
7861
 
                                        dtmfbuf[0] = res;
7862
 
                                        res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
7863
 
                                }
7864
 
                                if (res > 0) {
7865
 
                                        /* if E911, take off hook */
7866
 
                                        if (p->sig == SIG_E911)
7867
 
                                                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
7868
 
                                        res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
7869
 
                                }
7870
 
                                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
7871
 
                                break;
7872
 
                        case SIG_FEATB:
7873
 
                        case SIG_SF_FEATB:
7874
 
                                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
7875
 
                                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
7876
 
                                break;
7877
 
                        case SIG_EMWINK:
7878
 
                                /* if we received a '*', we are actually receiving Feature Group D
7879
 
                                   dial syntax, so use that mode; otherwise, fall through to normal
7880
 
                                   mode
7881
 
                                */
7882
 
                                if (res == '*') {
7883
 
                                        res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
7884
 
                                        if (res > 0)
7885
 
                                                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
7886
 
                                        if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
7887
 
                                        break;
7888
 
                                }
7889
 
                        default:
7890
 
                                /* If we got the first digit, get the rest */
7891
 
                                len = 1;
7892
 
                                dtmfbuf[len] = '\0';
7893
 
                                while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
7894
 
                                        if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
7895
 
                                                timeout = matchdigittimeout;
7896
 
                                        } else {
7897
 
                                                timeout = gendigittimeout;
7898
 
                                        }
7899
 
                                        res = ast_waitfordigit(chan, timeout);
7900
 
                                        if (res < 0) {
7901
 
                                                ast_debug(1, "waitfordigit returned < 0...\n");
7902
 
                                                ast_hangup(chan);
7903
 
                                                goto quit;
7904
 
                                        } else if (res) {
7905
 
                                                dtmfbuf[len++] = res;
7906
 
                                                dtmfbuf[len] = '\0';
7907
 
                                        } else {
7908
 
                                                break;
7909
 
                                        }
7910
 
                                }
7911
 
                                break;
7912
 
                        }
7913
 
                }
7914
 
                if (res == -1) {
7915
 
                        ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
7916
 
                        ast_hangup(chan);
7917
 
                        goto quit;
7918
 
                } else if (res < 0) {
7919
 
                        ast_debug(1, "Got hung up before digits finished\n");
7920
 
                        ast_hangup(chan);
7921
 
                        goto quit;
7922
 
                }
7923
 
 
7924
 
                if (p->sig == SIG_FGC_CAMA) {
7925
 
                        char anibuf[100];
7926
 
 
7927
 
                        if (ast_safe_sleep(chan,1000) == -1) {
7928
 
                                ast_hangup(chan);
7929
 
                                goto quit;
7930
 
                        }
7931
 
                        dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
7932
 
                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
7933
 
                        res = my_getsigstr(chan, anibuf, "#", 10000);
7934
 
                        if ((res > 0) && (strlen(anibuf) > 2)) {
7935
 
                                if (anibuf[strlen(anibuf) - 1] == '#')
7936
 
                                        anibuf[strlen(anibuf) - 1] = 0;
7937
 
                                ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
7938
 
                        }
7939
 
                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
7940
 
                }
7941
 
 
7942
 
                ast_copy_string(exten, dtmfbuf, sizeof(exten));
7943
 
                if (ast_strlen_zero(exten))
7944
 
                        ast_copy_string(exten, "s", sizeof(exten));
7945
 
                if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
7946
 
                        /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
7947
 
                        if (exten[0] == '*') {
7948
 
                                char *stringp=NULL;
7949
 
                                ast_copy_string(exten2, exten, sizeof(exten2));
7950
 
                                /* Parse out extension and callerid */
7951
 
                                stringp=exten2 +1;
7952
 
                                s1 = strsep(&stringp, "*");
7953
 
                                s2 = strsep(&stringp, "*");
7954
 
                                if (s2) {
7955
 
                                        if (!ast_strlen_zero(p->cid_num))
7956
 
                                                ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
7957
 
                                        else
7958
 
                                                ast_set_callerid(chan, s1, NULL, s1);
7959
 
                                        ast_copy_string(exten, s2, sizeof(exten));
7960
 
                                } else
7961
 
                                        ast_copy_string(exten, s1, sizeof(exten));
7962
 
                        } else if (p->sig == SIG_FEATD)
7963
 
                                ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
7964
 
                }
7965
 
                if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
7966
 
                        if (exten[0] == '*') {
7967
 
                                char *stringp=NULL;
7968
 
                                ast_copy_string(exten2, exten, sizeof(exten2));
7969
 
                                /* Parse out extension and callerid */
7970
 
                                stringp=exten2 +1;
7971
 
                                s1 = strsep(&stringp, "#");
7972
 
                                s2 = strsep(&stringp, "#");
7973
 
                                if (s2) {
7974
 
                                        if (!ast_strlen_zero(p->cid_num))
7975
 
                                                ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
7976
 
                                        else
7977
 
                                                if (*(s1 + 2))
7978
 
                                                        ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
7979
 
                                        ast_copy_string(exten, s2 + 1, sizeof(exten));
7980
 
                                } else
7981
 
                                        ast_copy_string(exten, s1 + 2, sizeof(exten));
7982
 
                        } else
7983
 
                                ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
7984
 
                }
7985
 
                if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
7986
 
                        if (exten[0] == '*') {
7987
 
                                char *stringp=NULL;
7988
 
                                ast_copy_string(exten2, exten, sizeof(exten2));
7989
 
                                /* Parse out extension and callerid */
7990
 
                                stringp=exten2 +1;
7991
 
                                s1 = strsep(&stringp, "#");
7992
 
                                s2 = strsep(&stringp, "#");
7993
 
                                if (s2 && (*(s2 + 1) == '0')) {
7994
 
                                        if (*(s2 + 2))
7995
 
                                                ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
7996
 
                                }
7997
 
                                if (s1) ast_copy_string(exten, s1, sizeof(exten));
7998
 
                                else ast_copy_string(exten, "911", sizeof(exten));
7999
 
                        } else
8000
 
                                ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
8001
 
                }
8002
 
                if (p->sig == SIG_FEATB) {
8003
 
                        if (exten[0] == '*') {
8004
 
                                char *stringp=NULL;
8005
 
                                ast_copy_string(exten2, exten, sizeof(exten2));
8006
 
                                /* Parse out extension and callerid */
8007
 
                                stringp=exten2 +1;
8008
 
                                s1 = strsep(&stringp, "#");
8009
 
                                ast_copy_string(exten, exten2 + 1, sizeof(exten));
8010
 
                        } else
8011
 
                                ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
8012
 
                }
8013
 
                if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
8014
 
                        dahdi_wink(p, idx);
8015
 
                        /* some switches require a minimum guard time between
8016
 
                           the last FGD wink and something that answers
8017
 
                           immediately. This ensures it */
8018
 
                        if (ast_safe_sleep(chan,100)) goto quit;
8019
 
                }
8020
 
                dahdi_enable_ec(p);
8021
 
                if (NEED_MFDETECT(p)) {
8022
 
                        if (p->dsp) {
8023
 
                                if (!p->hardwaredtmf)
8024
 
                                        ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
8025
 
                                else {
8026
 
                                        ast_dsp_free(p->dsp);
8027
 
                                        p->dsp = NULL;
8028
 
                                }
8029
 
                        }
8030
 
                }
8031
 
 
8032
 
                if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
8033
 
                        ast_copy_string(chan->exten, exten, sizeof(chan->exten));
8034
 
                        if (p->dsp) ast_dsp_digitreset(p->dsp);
8035
 
                        res = ast_pbx_run(chan);
8036
 
                        if (res) {
8037
 
                                ast_log(LOG_WARNING, "PBX exited non-zero\n");
8038
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8039
 
                        }
8040
 
                        goto quit;
8041
 
                } else {
8042
 
                        ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
8043
 
                        sleep(2);
8044
 
                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
8045
 
                        if (res < 0)
8046
 
                                ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
8047
 
                        else
8048
 
                                sleep(1);
8049
 
                        res = ast_streamfile(chan, "ss-noservice", chan->language);
8050
 
                        if (res >= 0)
8051
 
                                ast_waitstream(chan, "");
8052
 
                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8053
 
                        ast_hangup(chan);
8054
 
                        goto quit;
8055
 
                }
8056
 
                break;
8057
 
        case SIG_FXOLS:
8058
 
        case SIG_FXOGS:
8059
 
        case SIG_FXOKS:
8060
 
                /* Read the first digit */
8061
 
                timeout = firstdigittimeout;
8062
 
                /* If starting a threeway call, never timeout on the first digit so someone
8063
 
                   can use flash-hook as a "hold" feature */
8064
 
                if (p->subs[SUB_THREEWAY].owner)
8065
 
                        timeout = 999999;
8066
 
                while (len < AST_MAX_EXTENSION-1) {
8067
 
                        /* Read digit unless it's supposed to be immediate, in which case the
8068
 
                           only answer is 's' */
8069
 
                        if (p->immediate)
8070
 
                                res = 's';
8071
 
                        else
8072
 
                                res = ast_waitfordigit(chan, timeout);
8073
 
                        timeout = 0;
8074
 
                        if (res < 0) {
8075
 
                                ast_debug(1, "waitfordigit returned < 0...\n");
8076
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, -1);
8077
 
                                ast_hangup(chan);
8078
 
                                goto quit;
8079
 
                        } else if (res) {
8080
 
                                ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
8081
 
                                exten[len++]=res;
8082
 
                                exten[len] = '\0';
8083
 
                        }
8084
 
                        if (!ast_ignore_pattern(chan->context, exten))
8085
 
                                tone_zone_play_tone(p->subs[idx].dfd, -1);
8086
 
                        else
8087
 
                                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
8088
 
                        if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
8089
 
                                if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
8090
 
                                        if (getforward) {
8091
 
                                                /* Record this as the forwarding extension */
8092
 
                                                ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
8093
 
                                                ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
8094
 
                                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8095
 
                                                if (res)
8096
 
                                                        break;
8097
 
                                                usleep(500000);
8098
 
                                                res = tone_zone_play_tone(p->subs[idx].dfd, -1);
8099
 
                                                sleep(1);
8100
 
                                                memset(exten, 0, sizeof(exten));
8101
 
                                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
8102
 
                                                len = 0;
8103
 
                                                getforward = 0;
8104
 
                                        } else {
8105
 
                                                res = tone_zone_play_tone(p->subs[idx].dfd, -1);
8106
 
                                                ast_copy_string(chan->exten, exten, sizeof(chan->exten));
8107
 
                                                if (!ast_strlen_zero(p->cid_num)) {
8108
 
                                                        if (!p->hidecallerid)
8109
 
                                                                ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
8110
 
                                                        else
8111
 
                                                                ast_set_callerid(chan, NULL, NULL, p->cid_num);
8112
 
                                                }
8113
 
                                                if (!ast_strlen_zero(p->cid_name)) {
8114
 
                                                        if (!p->hidecallerid)
8115
 
                                                                ast_set_callerid(chan, NULL, p->cid_name, NULL);
8116
 
                                                }
8117
 
                                                ast_setstate(chan, AST_STATE_RING);
8118
 
                                                dahdi_enable_ec(p);
8119
 
                                                res = ast_pbx_run(chan);
8120
 
                                                if (res) {
8121
 
                                                        ast_log(LOG_WARNING, "PBX exited non-zero\n");
8122
 
                                                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8123
 
                                                }
8124
 
                                                goto quit;
8125
 
                                        }
8126
 
                                } else {
8127
 
                                        /* It's a match, but they just typed a digit, and there is an ambiguous match,
8128
 
                                           so just set the timeout to matchdigittimeout and wait some more */
8129
 
                                        timeout = matchdigittimeout;
8130
 
                                }
8131
 
                        } else if (res == 0) {
8132
 
                                ast_debug(1, "not enough digits (and no ambiguous match)...\n");
8133
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8134
 
                                dahdi_wait_event(p->subs[idx].dfd);
8135
 
                                ast_hangup(chan);
8136
 
                                goto quit;
8137
 
                        } else if (p->callwaiting && !strcmp(exten, "*70")) {
8138
 
                                ast_verb(3, "Disabling call waiting on %s\n", chan->name);
8139
 
                                /* Disable call waiting if enabled */
8140
 
                                p->callwaiting = 0;
8141
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8142
 
                                if (res) {
8143
 
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
8144
 
                                                chan->name, strerror(errno));
8145
 
                                }
8146
 
                                len = 0;
8147
 
                                ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
8148
 
                                memset(exten, 0, sizeof(exten));
8149
 
                                timeout = firstdigittimeout;
8150
 
 
8151
 
                        } else if (!strcmp(exten,ast_pickup_ext())) {
8152
 
                                /* Scan all channels and see if there are any
8153
 
                                 * ringing channels that have call groups
8154
 
                                 * that equal this channels pickup group
8155
 
                                 */
8156
 
                                if (idx == SUB_REAL) {
8157
 
                                        /* Switch us from Third call to Call Wait */
8158
 
                                        if (p->subs[SUB_THREEWAY].owner) {
8159
 
                                                /* If you make a threeway call and the *8# a call, it should actually
8160
 
                                                   look like a callwait */
8161
 
                                                alloc_sub(p, SUB_CALLWAIT);
8162
 
                                                swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
8163
 
                                                unalloc_sub(p, SUB_THREEWAY);
8164
 
                                        }
8165
 
                                        dahdi_enable_ec(p);
8166
 
                                        if (ast_pickup_call(chan)) {
8167
 
                                                ast_debug(1, "No call pickup possible...\n");
8168
 
                                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8169
 
                                                dahdi_wait_event(p->subs[idx].dfd);
8170
 
                                        }
8171
 
                                        ast_hangup(chan);
8172
 
                                        goto quit;
8173
 
                                } else {
8174
 
                                        ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
8175
 
                                        ast_hangup(chan);
8176
 
                                        goto quit;
8177
 
                                }
8178
 
 
8179
 
                        } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
8180
 
                                ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
8181
 
                                /* Disable Caller*ID if enabled */
8182
 
                                p->hidecallerid = 1;
8183
 
                                if (chan->cid.cid_num)
8184
 
                                        ast_free(chan->cid.cid_num);
8185
 
                                chan->cid.cid_num = NULL;
8186
 
                                if (chan->cid.cid_name)
8187
 
                                        ast_free(chan->cid.cid_name);
8188
 
                                chan->cid.cid_name = NULL;
8189
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8190
 
                                if (res) {
8191
 
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
8192
 
                                                chan->name, strerror(errno));
8193
 
                                }
8194
 
                                len = 0;
8195
 
                                memset(exten, 0, sizeof(exten));
8196
 
                                timeout = firstdigittimeout;
8197
 
                        } else if (p->callreturn && !strcmp(exten, "*69")) {
8198
 
                                res = 0;
8199
 
                                if (!ast_strlen_zero(p->lastcid_num)) {
8200
 
                                        res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
8201
 
                                }
8202
 
                                if (!res)
8203
 
                                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8204
 
                                break;
8205
 
                        } else if (!strcmp(exten, "*78")) {
8206
 
                                dahdi_dnd(p, 1);
8207
 
                                /* Do not disturb */
8208
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8209
 
                                getforward = 0;
8210
 
                                memset(exten, 0, sizeof(exten));
8211
 
                                len = 0;
8212
 
                        } else if (!strcmp(exten, "*79")) {
8213
 
                                dahdi_dnd(p, 0);
8214
 
                                /* Do not disturb */
8215
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8216
 
                                getforward = 0;
8217
 
                                memset(exten, 0, sizeof(exten));
8218
 
                                len = 0;
8219
 
                        } else if (p->cancallforward && !strcmp(exten, "*72")) {
8220
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8221
 
                                getforward = 1;
8222
 
                                memset(exten, 0, sizeof(exten));
8223
 
                                len = 0;
8224
 
                        } else if (p->cancallforward && !strcmp(exten, "*73")) {
8225
 
                                ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
8226
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8227
 
                                memset(p->call_forward, 0, sizeof(p->call_forward));
8228
 
                                getforward = 0;
8229
 
                                memset(exten, 0, sizeof(exten));
8230
 
                                len = 0;
8231
 
                        } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
8232
 
                                                p->subs[SUB_THREEWAY].owner &&
8233
 
                                                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
8234
 
                                /* This is a three way call, the main call being a real channel,
8235
 
                                        and we're parking the first call. */
8236
 
                                ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
8237
 
                                ast_verb(3, "Parking call to '%s'\n", chan->name);
8238
 
                                break;
8239
 
                        } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
8240
 
                                ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
8241
 
                                res = ast_db_put("blacklist", p->lastcid_num, "1");
8242
 
                                if (!res) {
8243
 
                                        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8244
 
                                        memset(exten, 0, sizeof(exten));
8245
 
                                        len = 0;
8246
 
                                }
8247
 
                        } else if (p->hidecallerid && !strcmp(exten, "*82")) {
8248
 
                                ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
8249
 
                                /* Enable Caller*ID if enabled */
8250
 
                                p->hidecallerid = 0;
8251
 
                                if (chan->cid.cid_num)
8252
 
                                        ast_free(chan->cid.cid_num);
8253
 
                                chan->cid.cid_num = NULL;
8254
 
                                if (chan->cid.cid_name)
8255
 
                                        ast_free(chan->cid.cid_name);
8256
 
                                chan->cid.cid_name = NULL;
8257
 
                                ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
8258
 
                                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
8259
 
                                if (res) {
8260
 
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
8261
 
                                                chan->name, strerror(errno));
8262
 
                                }
8263
 
                                len = 0;
8264
 
                                memset(exten, 0, sizeof(exten));
8265
 
                                timeout = firstdigittimeout;
8266
 
                        } else if (!strcmp(exten, "*0")) {
8267
 
                                struct ast_channel *nbridge =
8268
 
                                        p->subs[SUB_THREEWAY].owner;
8269
 
                                struct dahdi_pvt *pbridge = NULL;
8270
 
                                /* set up the private struct of the bridged one, if any */
8271
 
                                if (nbridge && ast_bridged_channel(nbridge))
8272
 
                                        pbridge = ast_bridged_channel(nbridge)->tech_pvt;
8273
 
                                if (nbridge && pbridge &&
8274
 
                                        (nbridge->tech == &dahdi_tech) &&
8275
 
                                        (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
8276
 
                                        ISTRUNK(pbridge)) {
8277
 
                                        int func = DAHDI_FLASH;
8278
 
                                        /* Clear out the dial buffer */
8279
 
                                        p->dop.dialstr[0] = '\0';
8280
 
                                        /* flash hookswitch */
8281
 
                                        if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
8282
 
                                                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
8283
 
                                                        nbridge->name, strerror(errno));
8284
 
                                        }
8285
 
                                        swap_subs(p, SUB_REAL, SUB_THREEWAY);
8286
 
                                        unalloc_sub(p, SUB_THREEWAY);
8287
 
                                        p->owner = p->subs[SUB_REAL].owner;
8288
 
                                        if (ast_bridged_channel(p->subs[SUB_REAL].owner))
8289
 
                                                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
8290
 
                                        ast_hangup(chan);
8291
 
                                        goto quit;
8292
 
                                } else {
8293
 
                                        tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8294
 
                                        dahdi_wait_event(p->subs[idx].dfd);
8295
 
                                        tone_zone_play_tone(p->subs[idx].dfd, -1);
8296
 
                                        swap_subs(p, SUB_REAL, SUB_THREEWAY);
8297
 
                                        unalloc_sub(p, SUB_THREEWAY);
8298
 
                                        p->owner = p->subs[SUB_REAL].owner;
8299
 
                                        ast_hangup(chan);
8300
 
                                        goto quit;
8301
 
                                }
8302
 
                        } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
8303
 
                                                        ((exten[0] != '*') || (strlen(exten) > 2))) {
8304
 
                                ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
8305
 
                                break;
8306
 
                        }
8307
 
                        if (!timeout)
8308
 
                                timeout = gendigittimeout;
8309
 
                        if (len && !ast_ignore_pattern(chan->context, exten))
8310
 
                                tone_zone_play_tone(p->subs[idx].dfd, -1);
8311
 
                }
8312
 
                break;
8313
 
        case SIG_FXSLS:
8314
 
        case SIG_FXSGS:
8315
 
        case SIG_FXSKS:
8316
 
#ifdef HAVE_PRI
8317
 
                if (p->pri) {
8318
 
                        /* This is a GR-303 trunk actually.  Wait for the first ring... */
8319
 
                        struct ast_frame *f;
8320
 
                        int res;
8321
 
                        time_t start;
8322
 
 
8323
 
                        time(&start);
8324
 
                        ast_setstate(chan, AST_STATE_RING);
8325
 
                        while (time(NULL) < start + 3) {
8326
 
                                res = ast_waitfor(chan, 1000);
8327
 
                                if (res) {
8328
 
                                        f = ast_read(chan);
8329
 
                                        if (!f) {
8330
 
                                                ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
8331
 
                                                ast_hangup(chan);
8332
 
                                                goto quit;
8333
 
                                        } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
8334
 
                                                res = 1;
8335
 
                                        } else
8336
 
                                                res = 0;
8337
 
                                        ast_frfree(f);
8338
 
                                        if (res) {
8339
 
                                                ast_debug(1, "Got ring!\n");
8340
 
                                                res = 0;
8341
 
                                                break;
8342
 
                                        }
8343
 
                                }
8344
 
                        }
8345
 
                }
8346
 
#endif
8347
 
                /* check for SMDI messages */
8348
 
                if (p->use_smdi && p->smdi_iface) {
8349
 
                        smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
8350
 
 
8351
 
                        if (smdi_msg != NULL) {
8352
 
                                ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
8353
 
 
8354
 
                                if (smdi_msg->type == 'B')
8355
 
                                        pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
8356
 
                                else if (smdi_msg->type == 'N')
8357
 
                                        pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
8358
 
 
8359
 
                                ast_debug(1, "Received SMDI message on %s\n", chan->name);
8360
 
                        } else {
8361
 
                                ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
8362
 
                        }
8363
 
                }
8364
 
 
8365
 
                if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
8366
 
                        number = smdi_msg->calling_st;
8367
 
 
8368
 
                /* If we want caller id, we're in a prering state due to a polarity reversal
8369
 
                 * and we're set to use a polarity reversal to trigger the start of caller id,
8370
 
                 * grab the caller id and wait for ringing to start... */
8371
 
                } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
8372
 
                        /* If set to use DTMF CID signalling, listen for DTMF */
8373
 
                        if (p->cid_signalling == CID_SIG_DTMF) {
8374
 
                                int k = 0;
8375
 
                                cs = NULL;
8376
 
                                ast_debug(1, "Receiving DTMF cid on "
8377
 
                                        "channel %s\n", chan->name);
8378
 
                                dahdi_setlinear(p->subs[idx].dfd, 0);
8379
 
                                res = 2000;
8380
 
                                for (;;) {
8381
 
                                        struct ast_frame *f;
8382
 
                                        res = ast_waitfor(chan, res);
8383
 
                                        if (res <= 0) {
8384
 
                                                ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
8385
 
                                                        "Exiting simple switch\n");
8386
 
                                                ast_hangup(chan);
8387
 
                                                goto quit;
8388
 
                                        }
8389
 
                                        f = ast_read(chan);
8390
 
                                        if (!f)
8391
 
                                                break;
8392
 
                                        if (f->frametype == AST_FRAME_DTMF) {
8393
 
                                                dtmfbuf[k++] = f->subclass;
8394
 
                                                ast_debug(1, "CID got digit '%c'\n", f->subclass);
8395
 
                                                res = 2000;
8396
 
                                        }
8397
 
                                        ast_frfree(f);
8398
 
                                        if (chan->_state == AST_STATE_RING ||
8399
 
                                                chan->_state == AST_STATE_RINGING)
8400
 
                                                break; /* Got ring */
8401
 
                                }
8402
 
                                dtmfbuf[k] = '\0';
8403
 
                                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8404
 
                                /* Got cid and ring. */
8405
 
                                ast_debug(1, "CID got string '%s'\n", dtmfbuf);
8406
 
                                callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
8407
 
                                ast_debug(1, "CID is '%s', flags %d\n",
8408
 
                                        dtmfcid, flags);
8409
 
                                /* If first byte is NULL, we have no cid */
8410
 
                                if (!ast_strlen_zero(dtmfcid))
8411
 
                                        number = dtmfcid;
8412
 
                                else
8413
 
                                        number = NULL;
8414
 
                        /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
8415
 
                        } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
8416
 
                                cs = callerid_new(p->cid_signalling);
8417
 
                                if (cs) {
8418
 
                                        samples = 0;
8419
 
#if 1
8420
 
                                        bump_gains(p);
8421
 
#endif
8422
 
                                        /* Take out of linear mode for Caller*ID processing */
8423
 
                                        dahdi_setlinear(p->subs[idx].dfd, 0);
8424
 
 
8425
 
                                        /* First we wait and listen for the Caller*ID */
8426
 
                                        for (;;) {
8427
 
                                                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
8428
 
                                                if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
8429
 
                                                        ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
8430
 
                                                        callerid_free(cs);
8431
 
                                                        ast_hangup(chan);
8432
 
                                                        goto quit;
8433
 
                                                }
8434
 
                                                if (i & DAHDI_IOMUX_SIGEVENT) {
8435
 
                                                        res = dahdi_get_event(p->subs[idx].dfd);
8436
 
                                                        ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
8437
 
                                                        if (res == DAHDI_EVENT_NOALARM) {
8438
 
                                                                p->inalarm = 0;
8439
 
                                                        }
8440
 
 
8441
 
                                                        if (p->cid_signalling == CID_SIG_V23_JP) {
8442
 
                                                                if (res == DAHDI_EVENT_RINGBEGIN) {
8443
 
                                                                        res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8444
 
                                                                        usleep(1);
8445
 
                                                                }
8446
 
                                                        } else {
8447
 
                                                                res = 0;
8448
 
                                                                break;
8449
 
                                                        }
8450
 
                                                } else if (i & DAHDI_IOMUX_READ) {
8451
 
                                                        res = read(p->subs[idx].dfd, buf, sizeof(buf));
8452
 
                                                        if (res < 0) {
8453
 
                                                                if (errno != ELAST) {
8454
 
                                                                        ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
8455
 
                                                                        callerid_free(cs);
8456
 
                                                                        ast_hangup(chan);
8457
 
                                                                        goto quit;
8458
 
                                                                }
8459
 
                                                                break;
8460
 
                                                        }
8461
 
                                                        samples += res;
8462
 
 
8463
 
                                                        if (p->cid_signalling == CID_SIG_V23_JP) {
8464
 
                                                                res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
8465
 
                                                        } else {
8466
 
                                                                res = callerid_feed(cs, buf, res, AST_LAW(p));
8467
 
                                                        }
8468
 
 
8469
 
                                                        if (res < 0) {
8470
 
                                                                ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
8471
 
                                                                break;
8472
 
                                                        } else if (res)
8473
 
                                                                break;
8474
 
                                                        else if (samples > (8000 * 10))
8475
 
                                                                break;
8476
 
                                                }
8477
 
                                        }
8478
 
                                        if (res == 1) {
8479
 
                                                callerid_get(cs, &name, &number, &flags);
8480
 
                                                ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
8481
 
                                        }
8482
 
 
8483
 
                                        if (p->cid_signalling == CID_SIG_V23_JP) {
8484
 
                                                res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
8485
 
                                                usleep(1);
8486
 
                                                res = 4000;
8487
 
                                        } else {
8488
 
 
8489
 
                                                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
8490
 
                                                res = 2000;
8491
 
                                        }
8492
 
 
8493
 
                                        for (;;) {
8494
 
                                                struct ast_frame *f;
8495
 
                                                res = ast_waitfor(chan, res);
8496
 
                                                if (res <= 0) {
8497
 
                                                        ast_log(LOG_WARNING, "CID timed out waiting for ring. "
8498
 
                                                                "Exiting simple switch\n");
8499
 
                                                        ast_hangup(chan);
8500
 
                                                        goto quit;
8501
 
                                                }
8502
 
                                                if (!(f = ast_read(chan))) {
8503
 
                                                        ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
8504
 
                                                        ast_hangup(chan);
8505
 
                                                        goto quit;
8506
 
                                                }
8507
 
                                                ast_frfree(f);
8508
 
                                                if (chan->_state == AST_STATE_RING ||
8509
 
                                                        chan->_state == AST_STATE_RINGING)
8510
 
                                                        break; /* Got ring */
8511
 
                                        }
8512
 
 
8513
 
                                        /* We must have a ring by now, so, if configured, lets try to listen for
8514
 
                                         * distinctive ringing */
8515
 
                                        if (p->usedistinctiveringdetection) {
8516
 
                                                len = 0;
8517
 
                                                distMatches = 0;
8518
 
                                                /* Clear the current ring data array so we dont have old data in it. */
8519
 
                                                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
8520
 
                                                        curRingData[receivedRingT] = 0;
8521
 
                                                receivedRingT = 0;
8522
 
                                                counter = 0;
8523
 
                                                counter1 = 0;
8524
 
                                                /* Check to see if context is what it should be, if not set to be. */
8525
 
                                                if (strcmp(p->context,p->defcontext) != 0) {
8526
 
                                                        ast_copy_string(p->context, p->defcontext, sizeof(p->context));
8527
 
                                                        ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
8528
 
                                                }
8529
 
 
8530
 
                                                for (;;) {
8531
 
                                                        i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
8532
 
                                                        if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
8533
 
                                                                ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
8534
 
                                                                callerid_free(cs);
8535
 
                                                                ast_hangup(chan);
8536
 
                                                                goto quit;
8537
 
                                                        }
8538
 
                                                        if (i & DAHDI_IOMUX_SIGEVENT) {
8539
 
                                                                res = dahdi_get_event(p->subs[idx].dfd);
8540
 
                                                                ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
8541
 
                                                                if (res == DAHDI_EVENT_NOALARM) {
8542
 
                                                                        p->inalarm = 0;
8543
 
                                                                }
8544
 
                                                                res = 0;
8545
 
                                                                /* Let us detect distinctive ring */
8546
 
 
8547
 
                                                                curRingData[receivedRingT] = p->ringt;
8548
 
 
8549
 
                                                                if (p->ringt < p->ringt_base/2)
8550
 
                                                                        break;
8551
 
                                                                /* Increment the ringT counter so we can match it against
8552
 
                                                                   values in chan_dahdi.conf for distinctive ring */
8553
 
                                                                if (++receivedRingT == ARRAY_LEN(curRingData))
8554
 
                                                                        break;
8555
 
                                                        } else if (i & DAHDI_IOMUX_READ) {
8556
 
                                                                res = read(p->subs[idx].dfd, buf, sizeof(buf));
8557
 
                                                                if (res < 0) {
8558
 
                                                                        if (errno != ELAST) {
8559
 
                                                                                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
8560
 
                                                                                callerid_free(cs);
8561
 
                                                                                ast_hangup(chan);
8562
 
                                                                                goto quit;
8563
 
                                                                        }
8564
 
                                                                        break;
8565
 
                                                                }
8566
 
                                                                if (p->ringt)
8567
 
                                                                        p->ringt--;
8568
 
                                                                if (p->ringt == 1) {
8569
 
                                                                        res = -1;
8570
 
                                                                        break;
8571
 
                                                                }
8572
 
                                                        }
8573
 
                                                }
8574
 
                                                        /* this only shows up if you have n of the dring patterns filled in */
8575
 
                                                ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
8576
 
                                                for (counter = 0; counter < 3; counter++) {
8577
 
                                                        /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
8578
 
                                                        channel */
8579
 
                                                        distMatches = 0;
8580
 
                                                        for (counter1 = 0; counter1 < 3; counter1++) {
8581
 
                                                                ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
8582
 
                                                                if (p->drings.ringnum[counter].ring[counter1] == -1) {
8583
 
                                                                        ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
8584
 
                                                                        curRingData[counter1]);
8585
 
                                                                        distMatches++;
8586
 
                                                                } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
8587
 
                                                                                curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
8588
 
                                                                        ast_verb(3, "Ring pattern matched in range: %d to %d\n",
8589
 
                                                                        (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
8590
 
                                                                        (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
8591
 
                                                                        distMatches++;
8592
 
                                                                }
8593
 
                                                        }
8594
 
 
8595
 
                                                        if (distMatches == 3) {
8596
 
                                                                /* The ring matches, set the context to whatever is for distinctive ring.. */
8597
 
                                                                ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
8598
 
                                                                ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
8599
 
                                                                ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
8600
 
                                                                break;
8601
 
                                                        }
8602
 
                                                }
8603
 
                                        }
8604
 
                                        /* Restore linear mode (if appropriate) for Caller*ID processing */
8605
 
                                        dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8606
 
#if 1
8607
 
                                        restore_gains(p);
8608
 
#endif
8609
 
                                } else
8610
 
                                        ast_log(LOG_WARNING, "Unable to get caller ID space\n");
8611
 
                        } else {
8612
 
                                ast_log(LOG_WARNING, "Channel %s in prering "
8613
 
                                        "state, but I have nothing to do. "
8614
 
                                        "Terminating simple switch, should be "
8615
 
                                        "restarted by the actual ring.\n",
8616
 
                                        chan->name);
8617
 
                                ast_hangup(chan);
8618
 
                                goto quit;
8619
 
                        }
8620
 
                } else if (p->use_callerid && p->cid_start == CID_START_RING) {
8621
 
                        if (p->cid_signalling == CID_SIG_DTMF) {
8622
 
                                int k = 0;
8623
 
                                cs = NULL;
8624
 
                                dahdi_setlinear(p->subs[idx].dfd, 0);
8625
 
                                res = 2000;
8626
 
                                for (;;) {
8627
 
                                        struct ast_frame *f;
8628
 
                                        res = ast_waitfor(chan, res);
8629
 
                                        if (res <= 0) {
8630
 
                                                ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
8631
 
                                                        "Exiting simple switch\n");
8632
 
                                                ast_hangup(chan);
8633
 
                                                return NULL;
8634
 
                                        }
8635
 
                                        f = ast_read(chan);
8636
 
                                        if (f->frametype == AST_FRAME_DTMF) {
8637
 
                                                dtmfbuf[k++] = f->subclass;
8638
 
                                                ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
8639
 
                                                res = 2000;
8640
 
                                        }
8641
 
                                        ast_frfree(f);
8642
 
 
8643
 
                                        if (p->ringt_base == p->ringt)
8644
 
                                                break;
8645
 
                                }
8646
 
                                dtmfbuf[k] = '\0';
8647
 
                                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8648
 
                                /* Got cid and ring. */
8649
 
                                callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
8650
 
                                ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
8651
 
                                        dtmfcid, flags);
8652
 
                                /* If first byte is NULL, we have no cid */
8653
 
                                if (!ast_strlen_zero(dtmfcid))
8654
 
                                        number = dtmfcid;
8655
 
                                else
8656
 
                                        number = NULL;
8657
 
                                /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
8658
 
                        } else {
8659
 
                                /* FSK Bell202 callerID */
8660
 
                                cs = callerid_new(p->cid_signalling);
8661
 
                                if (cs) {
8662
 
#if 1
8663
 
                                        bump_gains(p);
8664
 
#endif
8665
 
                                        samples = 0;
8666
 
                                        len = 0;
8667
 
                                        distMatches = 0;
8668
 
                                        /* Clear the current ring data array so we dont have old data in it. */
8669
 
                                        for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
8670
 
                                                curRingData[receivedRingT] = 0;
8671
 
                                        receivedRingT = 0;
8672
 
                                        counter = 0;
8673
 
                                        counter1 = 0;
8674
 
                                        /* Check to see if context is what it should be, if not set to be. */
8675
 
                                        if (strcmp(p->context,p->defcontext) != 0) {
8676
 
                                                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
8677
 
                                                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
8678
 
                                        }
8679
 
 
8680
 
                                        /* Take out of linear mode for Caller*ID processing */
8681
 
                                        dahdi_setlinear(p->subs[idx].dfd, 0);
8682
 
                                        for (;;) {
8683
 
                                                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
8684
 
                                                if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
8685
 
                                                        ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
8686
 
                                                        callerid_free(cs);
8687
 
                                                        ast_hangup(chan);
8688
 
                                                        goto quit;
8689
 
                                                }
8690
 
                                                if (i & DAHDI_IOMUX_SIGEVENT) {
8691
 
                                                        res = dahdi_get_event(p->subs[idx].dfd);
8692
 
                                                        ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
8693
 
                                                        if (res == DAHDI_EVENT_NOALARM) {
8694
 
                                                                p->inalarm = 0;
8695
 
                                                        }
8696
 
                                                        /* If we get a PR event, they hung up while processing calerid */
8697
 
                                                        if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
8698
 
                                                                ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
8699
 
                                                                p->polarity = POLARITY_IDLE;
8700
 
                                                                callerid_free(cs);
8701
 
                                                                ast_hangup(chan);
8702
 
                                                                goto quit;
8703
 
                                                        }
8704
 
                                                        res = 0;
8705
 
                                                        /* Let us detect callerid when the telco uses distinctive ring */
8706
 
 
8707
 
                                                        curRingData[receivedRingT] = p->ringt;
8708
 
 
8709
 
                                                        if (p->ringt < p->ringt_base/2)
8710
 
                                                                break;
8711
 
                                                        /* Increment the ringT counter so we can match it against
8712
 
                                                           values in chan_dahdi.conf for distinctive ring */
8713
 
                                                        if (++receivedRingT == ARRAY_LEN(curRingData))
8714
 
                                                                break;
8715
 
                                                } else if (i & DAHDI_IOMUX_READ) {
8716
 
                                                        res = read(p->subs[idx].dfd, buf, sizeof(buf));
8717
 
                                                        if (res < 0) {
8718
 
                                                                if (errno != ELAST) {
8719
 
                                                                        ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
8720
 
                                                                        callerid_free(cs);
8721
 
                                                                        ast_hangup(chan);
8722
 
                                                                        goto quit;
8723
 
                                                                }
8724
 
                                                                break;
8725
 
                                                        }
8726
 
                                                        if (p->ringt)
8727
 
                                                                p->ringt--;
8728
 
                                                        if (p->ringt == 1) {
8729
 
                                                                res = -1;
8730
 
                                                                break;
8731
 
                                                        }
8732
 
                                                        samples += res;
8733
 
                                                        res = callerid_feed(cs, buf, res, AST_LAW(p));
8734
 
                                                        if (res < 0) {
8735
 
                                                                ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
8736
 
                                                                break;
8737
 
                                                        } else if (res)
8738
 
                                                                break;
8739
 
                                                        else if (samples > (8000 * 10))
8740
 
                                                                break;
8741
 
                                                }
8742
 
                                        }
8743
 
                                        if (res == 1) {
8744
 
                                                callerid_get(cs, &name, &number, &flags);
8745
 
                                                ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
8746
 
                                        }
8747
 
                                        if (distinctiveringaftercid == 1) {
8748
 
                                                /* Clear the current ring data array so we dont have old data in it. */
8749
 
                                                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
8750
 
                                                        curRingData[receivedRingT] = 0;
8751
 
                                                }
8752
 
                                                receivedRingT = 0;
8753
 
                                                ast_verb(3, "Detecting post-CID distinctive ring\n");
8754
 
                                                for (;;) {
8755
 
                                                        i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
8756
 
                                                        if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
8757
 
                                                                ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
8758
 
                                                                callerid_free(cs);
8759
 
                                                                ast_hangup(chan);
8760
 
                                                                goto quit;
8761
 
                                                        }
8762
 
                                                        if (i & DAHDI_IOMUX_SIGEVENT) {
8763
 
                                                                res = dahdi_get_event(p->subs[idx].dfd);
8764
 
                                                                ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
8765
 
                                                                if (res == DAHDI_EVENT_NOALARM) {
8766
 
                                                                        p->inalarm = 0;
8767
 
                                                                }
8768
 
                                                                res = 0;
8769
 
                                                                /* Let us detect callerid when the telco uses distinctive ring */
8770
 
 
8771
 
                                                                curRingData[receivedRingT] = p->ringt;
8772
 
 
8773
 
                                                                if (p->ringt < p->ringt_base/2)
8774
 
                                                                        break;
8775
 
                                                                /* Increment the ringT counter so we can match it against
8776
 
                                                                   values in chan_dahdi.conf for distinctive ring */
8777
 
                                                                if (++receivedRingT == ARRAY_LEN(curRingData))
8778
 
                                                                        break;
8779
 
                                                        } else if (i & DAHDI_IOMUX_READ) {
8780
 
                                                                res = read(p->subs[idx].dfd, buf, sizeof(buf));
8781
 
                                                                if (res < 0) {
8782
 
                                                                        if (errno != ELAST) {
8783
 
                                                                                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
8784
 
                                                                                callerid_free(cs);
8785
 
                                                                                ast_hangup(chan);
8786
 
                                                                                goto quit;
8787
 
                                                                        }
8788
 
                                                                        break;
8789
 
                                                                }
8790
 
                                                        if (p->ringt)
8791
 
                                                                p->ringt--;
8792
 
                                                                if (p->ringt == 1) {
8793
 
                                                                        res = -1;
8794
 
                                                                        break;
8795
 
                                                                }
8796
 
                                                        }
8797
 
                                                }
8798
 
                                        }
8799
 
                                        if (p->usedistinctiveringdetection) {
8800
 
                                                /* this only shows up if you have n of the dring patterns filled in */
8801
 
                                                ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
8802
 
 
8803
 
                                                for (counter = 0; counter < 3; counter++) {
8804
 
                                                        /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
8805
 
                                                        channel */
8806
 
                                                        /* this only shows up if you have n of the dring patterns filled in */
8807
 
                                                        ast_verb(3, "Checking %d,%d,%d\n",
8808
 
                                                                        p->drings.ringnum[counter].ring[0],
8809
 
                                                                        p->drings.ringnum[counter].ring[1],
8810
 
                                                                        p->drings.ringnum[counter].ring[2]);
8811
 
                                                        distMatches = 0;
8812
 
                                                        for (counter1 = 0; counter1 < 3; counter1++) {
8813
 
                                                                ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
8814
 
                                                                if (p->drings.ringnum[counter].ring[counter1] == -1) {
8815
 
                                                                        ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
8816
 
                                                                        curRingData[counter1]);
8817
 
                                                                        distMatches++;
8818
 
                                                                }
8819
 
                                                                else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
8820
 
                                                                        curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
8821
 
                                                                        ast_verb(3, "Ring pattern matched in range: %d to %d\n",
8822
 
                                                                        (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
8823
 
                                                                        (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
8824
 
                                                                        distMatches++;
8825
 
                                                                }
8826
 
                                                        }
8827
 
                                                        if (distMatches == 3) {
8828
 
                                                                /* The ring matches, set the context to whatever is for distinctive ring.. */
8829
 
                                                                ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
8830
 
                                                                ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
8831
 
                                                                ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
8832
 
                                                                break;
8833
 
                                                        }
8834
 
                                                }
8835
 
                                        }
8836
 
                                        /* Restore linear mode (if appropriate) for Caller*ID processing */
8837
 
                                        dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8838
 
#if 1
8839
 
                                        restore_gains(p);
8840
 
#endif
8841
 
                                        if (res < 0) {
8842
 
                                                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
8843
 
                                        }
8844
 
                                } else
8845
 
                                        ast_log(LOG_WARNING, "Unable to get caller ID space\n");
8846
 
                        }
8847
 
                } else
8848
 
                        cs = NULL;
8849
 
 
8850
 
                if (number)
8851
 
                        ast_shrink_phone_number(number);
8852
 
                ast_set_callerid(chan, number, name, number);
8853
 
 
8854
 
                if (smdi_msg)
8855
 
                        ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
8856
 
 
8857
 
                if (cs)
8858
 
                        callerid_free(cs);
8859
 
                /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
8860
 
                if (flags & CID_MSGWAITING) {
8861
 
                        ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
8862
 
                        notify_message(p->mailbox, 1);
8863
 
                        /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
8864
 
                        if (p->mwimonitor_rpas) {
8865
 
                                ast_hangup(chan);
8866
 
                                return NULL;
8867
 
                        }
8868
 
                } else if (flags & CID_NOMSGWAITING) {
8869
 
                        ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
8870
 
                        notify_message(p->mailbox, 0);
8871
 
                        /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
8872
 
                        if (p->mwimonitor_rpas) {
8873
 
                                ast_hangup(chan);
8874
 
                                return NULL;
8875
 
                        }
8876
 
                }
8877
 
 
8878
 
                ast_setstate(chan, AST_STATE_RING);
8879
 
                chan->rings = 1;
8880
 
                p->ringt = p->ringt_base;
8881
 
                res = ast_pbx_run(chan);
8882
 
                if (res) {
8883
 
                        ast_hangup(chan);
8884
 
                        ast_log(LOG_WARNING, "PBX exited non-zero\n");
8885
 
                }
8886
 
                goto quit;
8887
 
        default:
8888
 
                ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
8889
 
                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8890
 
                if (res < 0)
8891
 
                                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
8892
 
        }
8893
 
        res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
8894
 
        if (res < 0)
8895
 
                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
8896
 
        ast_hangup(chan);
8897
 
quit:
8898
 
        ast_mutex_lock(&ss_thread_lock);
8899
 
        ss_thread_count--;
8900
 
        ast_cond_signal(&ss_thread_complete);
8901
 
        ast_mutex_unlock(&ss_thread_lock);
8902
 
        return NULL;
8903
 
}
8904
 
 
8905
 
struct mwi_thread_data {
8906
 
        struct dahdi_pvt *pvt;
8907
 
        unsigned char buf[READ_SIZE];
8908
 
        size_t len;
8909
 
};
8910
 
 
8911
 
static int calc_energy(const unsigned char *buf, int len, int law)
8912
 
{
8913
 
        int x;
8914
 
        int sum = 0;
8915
 
 
8916
 
        if (!len)
8917
 
                return 0;
8918
 
 
8919
 
        for (x = 0; x < len; x++)
8920
 
                sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
8921
 
 
8922
 
        return sum / len;
8923
 
}
8924
 
 
8925
 
static void *mwi_thread(void *data)
8926
 
{
8927
 
        struct mwi_thread_data *mtd = data;
8928
 
        struct callerid_state *cs;
8929
 
        pthread_t threadid;
8930
 
        int samples = 0;
8931
 
        char *name, *number;
8932
 
        int flags;
8933
 
        int i, res;
8934
 
        unsigned int spill_done = 0;
8935
 
        int spill_result = -1;
8936
 
 
8937
 
        if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
8938
 
                mtd->pvt->mwimonitoractive = 0;
8939
 
 
8940
 
                return NULL;
8941
 
        }
8942
 
 
8943
 
        callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
8944
 
 
8945
 
        bump_gains(mtd->pvt);
8946
 
 
8947
 
        for (;;) {
8948
 
                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
8949
 
                if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
8950
 
                        ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
8951
 
                        goto quit;
8952
 
                }
8953
 
 
8954
 
                if (i & DAHDI_IOMUX_SIGEVENT) {
8955
 
                        struct ast_channel *chan;
8956
 
 
8957
 
                        /* If we get an event, screen out events that we do not act on.
8958
 
                         * Otherwise, cancel and go to the simple switch to let it deal with it.
8959
 
                         */
8960
 
                        res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
8961
 
 
8962
 
                        switch (res) {
8963
 
                        case DAHDI_EVENT_NEONMWI_ACTIVE:
8964
 
                        case DAHDI_EVENT_NEONMWI_INACTIVE:
8965
 
                        case DAHDI_EVENT_NONE:
8966
 
                        case DAHDI_EVENT_BITSCHANGED:
8967
 
                                break;
8968
 
                        case DAHDI_EVENT_NOALARM:
8969
 
                                mtd->pvt->inalarm = 0;
8970
 
                                ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
8971
 
                                manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
8972
 
                                        "Channel: %d\r\n", mtd->pvt->channel);
8973
 
                                break;
8974
 
                        case DAHDI_EVENT_ALARM:
8975
 
                                mtd->pvt->inalarm = 1;
8976
 
                                res = get_alarms(mtd->pvt);
8977
 
                                handle_alarms(mtd->pvt, res);
8978
 
                                break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
8979
 
                        default:
8980
 
                                ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
8981
 
                                callerid_free(cs);
8982
 
 
8983
 
                                restore_gains(mtd->pvt);
8984
 
                                mtd->pvt->ringt = mtd->pvt->ringt_base;
8985
 
 
8986
 
                                if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
8987
 
                                        if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
8988
 
                                                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
8989
 
                                                res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8990
 
                                                if (res < 0)
8991
 
                                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
8992
 
                                                ast_hangup(chan);
8993
 
                                                goto quit;
8994
 
                                        }
8995
 
                                        goto quit_no_clean;
8996
 
 
8997
 
                                } else {
8998
 
                                        ast_log(LOG_WARNING, "Could not create channel to handle call\n");
8999
 
                                }
9000
 
                        }
9001
 
                } else if (i & DAHDI_IOMUX_READ) {
9002
 
                        if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
9003
 
                                if (errno != ELAST) {
9004
 
                                        ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
9005
 
                                        goto quit;
9006
 
                                }
9007
 
                                break;
9008
 
                        }
9009
 
                        samples += res;
9010
 
                        if (!spill_done) {
9011
 
                                if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
9012
 
                                        ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
9013
 
                                        break;
9014
 
                                } else if (spill_result) {
9015
 
                                        spill_done = 1;
9016
 
                                }
9017
 
                        } else {
9018
 
                                /* keep reading data until the energy level drops below the threshold
9019
 
                                   so we don't get another 'trigger' on the remaining carrier signal
9020
 
                                */
9021
 
                                if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
9022
 
                                        break;
9023
 
                        }
9024
 
                        if (samples > (8000 * 4)) /*Termination case - time to give up*/
9025
 
                                break;
9026
 
                }
9027
 
        }
9028
 
 
9029
 
        if (spill_result == 1) {
9030
 
                callerid_get(cs, &name, &number, &flags);
9031
 
                if (flags & CID_MSGWAITING) {
9032
 
                        ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
9033
 
                        notify_message(mtd->pvt->mailbox, 1);
9034
 
                } else if (flags & CID_NOMSGWAITING) {
9035
 
                        ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
9036
 
                        notify_message(mtd->pvt->mailbox, 0);
9037
 
                } else {
9038
 
                        ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
9039
 
                }
9040
 
        }
9041
 
 
9042
 
 
9043
 
quit:
9044
 
        callerid_free(cs);
9045
 
 
9046
 
        restore_gains(mtd->pvt);
9047
 
 
9048
 
quit_no_clean:
9049
 
        mtd->pvt->mwimonitoractive = 0;
9050
 
 
9051
 
        ast_free(mtd);
9052
 
 
9053
 
        return NULL;
9054
 
}
9055
 
 
9056
 
/*
9057
 
* The following three functions (mwi_send_init, mwi_send_process_buffer,
9058
 
* mwi_send_process_event) work with the do_monitor thread to generate mwi spills
9059
 
* that are sent out via FXA port on voicemail state change.  The execution of
9060
 
* the mwi send is state driven and can either generate a ring pulse prior to
9061
 
* sending the fsk spill or simply send an fsk spill.
9062
 
*/
9063
 
static int mwi_send_init(struct dahdi_pvt * pvt)
9064
 
{
9065
 
        int x, res;
9066
 
 
9067
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
9068
 
        /* Determine how this spill is to be sent */
9069
 
        if (pvt->mwisend_rpas) {
9070
 
                pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
9071
 
                pvt->mwisendactive = 1;
9072
 
        } else if (pvt->mwisend_fsk) {
9073
 
                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
9074
 
                pvt->mwisendactive = 1;
9075
 
        } else {
9076
 
                pvt->mwisendactive = 0;
9077
 
                return 0;
9078
 
        }
9079
 
#else
9080
 
        if (mwisend_rpas) {
9081
 
                pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
9082
 
        } else {
9083
 
                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
9084
 
        }
9085
 
        pvt->mwisendactive = 1;
9086
 
#endif
9087
 
 
9088
 
        if (pvt->cidspill) {
9089
 
                ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
9090
 
                ast_free(pvt->cidspill);
9091
 
                pvt->cidspill = NULL;
9092
 
                pvt->cidpos = 0;
9093
 
                pvt->cidlen = 0;
9094
 
        }
9095
 
        pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
9096
 
        if (!pvt->cidspill) {
9097
 
                pvt->mwisendactive = 0;
9098
 
                return -1;
9099
 
        }
9100
 
        x = DAHDI_FLUSH_BOTH;
9101
 
        res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
9102
 
        x = 3000;
9103
 
        ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
9104
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
9105
 
        if (pvt->mwisend_fsk) {
9106
 
#endif
9107
 
                pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
9108
 
                                                                AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
9109
 
                pvt->cidpos = 0;
9110
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
9111
 
        }
9112
 
#endif
9113
 
        return 0;
9114
 
}
9115
 
 
9116
 
static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
9117
 
{
9118
 
        struct timeval  now;
9119
 
        int                     res;
9120
 
 
9121
 
        /* sanity check to catch if this had been interrupted previously
9122
 
        *       i.e. state says there is more to do but there is no spill allocated
9123
 
        */
9124
 
        if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
9125
 
                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
9126
 
        } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
9127
 
                /* Normal processing -- Perform mwi send action */
9128
 
                switch ( pvt->mwisend_data.mwisend_current) {
9129
 
                case MWI_SEND_SA:
9130
 
                        /* Send the Ring Pulse Signal Alert */
9131
 
                        res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
9132
 
                        if (res) {
9133
 
                                ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
9134
 
                                goto quit;
9135
 
                        }
9136
 
                        res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
9137
 
                        pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
9138
 
                        break;
9139
 
                case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
9140
 
                        break;
9141
 
                case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
9142
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
9143
 
                        if (pvt->mwisend_fsk) {
9144
 
#endif
9145
 
                                gettimeofday(&now, NULL);
9146
 
                                if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
9147
 
                                        pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
9148
 
                                }
9149
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
9150
 
                        } else { /* support for mwisendtype=nofsk */
9151
 
                                pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
9152
 
                        }
9153
 
#endif
9154
 
                        break;
9155
 
                case MWI_SEND_SPILL:
9156
 
                        /* We read some number of bytes.  Write an equal amount of data */
9157
 
                        if(0 < num_read) {
9158
 
                                if (num_read > pvt->cidlen - pvt->cidpos)
9159
 
                                        num_read = pvt->cidlen - pvt->cidpos;
9160
 
                                res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
9161
 
                                if (res > 0) {
9162
 
                                        pvt->cidpos += res;
9163
 
                                        if (pvt->cidpos >= pvt->cidlen) {
9164
 
                                                pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
9165
 
                                        }
9166
 
                                } else {
9167
 
                                        ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
9168
 
                                        goto quit;
9169
 
                                }
9170
 
                        }
9171
 
                        break;
9172
 
                case MWI_SEND_CLEANUP:
9173
 
                        /* For now, do nothing */
9174
 
                        pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
9175
 
                        break;
9176
 
                default:
9177
 
                        /* Should not get here, punt*/
9178
 
                        goto quit;
9179
 
                }
9180
 
        }
9181
 
 
9182
 
        if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
9183
 
                if (pvt->cidspill) {
9184
 
                        ast_free(pvt->cidspill);
9185
 
                        pvt->cidspill = NULL;
9186
 
                        pvt->cidpos = 0;
9187
 
                        pvt->cidlen = 0;
9188
 
                }
9189
 
                pvt->mwisendactive = 0;
9190
 
        }
9191
 
        return 0;
9192
 
quit:
9193
 
        if (pvt->cidspill) {
9194
 
                ast_free(pvt->cidspill);
9195
 
                pvt->cidspill = NULL;
9196
 
                pvt->cidpos = 0;
9197
 
                pvt->cidlen = 0;
9198
 
        }
9199
 
        pvt->mwisendactive = 0;
9200
 
        return -1;
9201
 
}
9202
 
 
9203
 
static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
9204
 
{
9205
 
        int handled = 0;
9206
 
 
9207
 
        if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
9208
 
                switch (event) {
9209
 
                case DAHDI_EVENT_RINGEROFF:
9210
 
                        if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
9211
 
                                handled = 1;
9212
 
 
9213
 
                                if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
9214
 
                                        ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
9215
 
                                        if(pvt->cidspill) {
9216
 
                                                ast_free(pvt->cidspill);
9217
 
                                                pvt->cidspill = NULL;
9218
 
                                        }
9219
 
                                        pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
9220
 
                                        pvt->mwisendactive = 0;
9221
 
                                } else {
9222
 
                                        pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
9223
 
                                        gettimeofday(&pvt->mwisend_data.pause, NULL);
9224
 
                                }
9225
 
                        }
9226
 
                        break;
9227
 
                /* Going off hook, I need to punt this spill */
9228
 
                case DAHDI_EVENT_RINGOFFHOOK:
9229
 
                        if (pvt->cidspill) {
9230
 
                                ast_free(pvt->cidspill);
9231
 
                                pvt->cidspill = NULL;
9232
 
                                pvt->cidpos = 0;
9233
 
                                pvt->cidlen = 0;
9234
 
                        }
9235
 
                        pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
9236
 
                        pvt->mwisendactive = 0;
9237
 
                        break;
9238
 
                case DAHDI_EVENT_RINGERON:
9239
 
                case DAHDI_EVENT_HOOKCOMPLETE:
9240
 
                        break;
9241
 
                default:
9242
 
                        break;
9243
 
                }
9244
 
        }
9245
 
        return handled;
9246
 
}
9247
 
 
9248
 
/* destroy a DAHDI channel, identified by its number */
9249
 
static int dahdi_destroy_channel_bynum(int channel)
9250
 
{
9251
 
        struct dahdi_pvt *tmp = NULL;
9252
 
        struct dahdi_pvt *prev = NULL;
9253
 
 
9254
 
        tmp = iflist;
9255
 
        while (tmp) {
9256
 
                if (tmp->channel == channel) {
9257
 
                        int x = DAHDI_FLASH;
9258
 
                        ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
9259
 
                        destroy_channel(prev, tmp, 1);
9260
 
                        ast_module_unref(ast_module_info->self);
9261
 
                        return RESULT_SUCCESS;
9262
 
                }
9263
 
                prev = tmp;
9264
 
                tmp = tmp->next;
9265
 
        }
9266
 
        return RESULT_FAILURE;
9267
 
}
9268
 
 
9269
 
static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
9270
 
{
9271
 
        int res;
9272
 
        pthread_t threadid;
9273
 
        struct ast_channel *chan;
9274
 
 
9275
 
        /* Handle an event on a given channel for the monitor thread. */
9276
 
 
9277
 
        switch (event) {
9278
 
        case DAHDI_EVENT_NONE:
9279
 
        case DAHDI_EVENT_BITSCHANGED:
9280
 
                break;
9281
 
        case DAHDI_EVENT_WINKFLASH:
9282
 
        case DAHDI_EVENT_RINGOFFHOOK:
9283
 
                if (i->inalarm) break;
9284
 
                if (i->radio) break;
9285
 
                /* Got a ring/answer.  What kind of channel are we? */
9286
 
                switch (i->sig) {
9287
 
                case SIG_FXOLS:
9288
 
                case SIG_FXOGS:
9289
 
                case SIG_FXOKS:
9290
 
                        res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9291
 
                        i->fxsoffhookstate = 1;
9292
 
                        if (res && (errno == EBUSY))
9293
 
                                break;
9294
 
                        if (i->cidspill) {
9295
 
                                /* Cancel VMWI spill */
9296
 
                                ast_free(i->cidspill);
9297
 
                                i->cidspill = NULL;
9298
 
                        }
9299
 
                        if (i->immediate) {
9300
 
                                dahdi_enable_ec(i);
9301
 
                                /* The channel is immediately up.  Start right away */
9302
 
                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
9303
 
                                chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
9304
 
                                if (!chan) {
9305
 
                                        ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
9306
 
                                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
9307
 
                                        if (res < 0)
9308
 
                                                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
9309
 
                                }
9310
 
                        } else {
9311
 
                                /* Check for callerid, digits, etc */
9312
 
                                chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
9313
 
                                if (chan) {
9314
 
                                        if (has_voicemail(i))
9315
 
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
9316
 
                                        else
9317
 
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
9318
 
                                        if (res < 0)
9319
 
                                                ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
9320
 
                                        if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
9321
 
                                                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
9322
 
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
9323
 
                                                if (res < 0)
9324
 
                                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
9325
 
                                                ast_hangup(chan);
9326
 
                                        }
9327
 
                                } else
9328
 
                                        ast_log(LOG_WARNING, "Unable to create channel\n");
9329
 
                        }
9330
 
                        break;
9331
 
                case SIG_FXSLS:
9332
 
                case SIG_FXSGS:
9333
 
                case SIG_FXSKS:
9334
 
                                i->ringt = i->ringt_base;
9335
 
                                /* Fall through */
9336
 
                case SIG_EMWINK:
9337
 
                case SIG_FEATD:
9338
 
                case SIG_FEATDMF:
9339
 
                case SIG_FEATDMF_TA:
9340
 
                case SIG_E911:
9341
 
                case SIG_FGC_CAMA:
9342
 
                case SIG_FGC_CAMAMF:
9343
 
                case SIG_FEATB:
9344
 
                case SIG_EM:
9345
 
                case SIG_EM_E1:
9346
 
                case SIG_SFWINK:
9347
 
                case SIG_SF_FEATD:
9348
 
                case SIG_SF_FEATDMF:
9349
 
                case SIG_SF_FEATB:
9350
 
                case SIG_SF:
9351
 
                        /* Check for callerid, digits, etc */
9352
 
                        if (i->cid_start == CID_START_POLARITY_IN) {
9353
 
                                chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
9354
 
                        } else {
9355
 
                                chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
9356
 
                        }
9357
 
 
9358
 
                        if (!chan) {
9359
 
                                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
9360
 
                        } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
9361
 
                                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
9362
 
                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
9363
 
                                if (res < 0) {
9364
 
                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
9365
 
                                }
9366
 
                                ast_hangup(chan);
9367
 
                        }
9368
 
                        break;
9369
 
                default:
9370
 
                        ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
9371
 
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
9372
 
                        if (res < 0)
9373
 
                                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
9374
 
                        return NULL;
9375
 
                }
9376
 
                break;
9377
 
        case DAHDI_EVENT_NOALARM:
9378
 
                i->inalarm = 0;
9379
 
                ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
9380
 
                manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
9381
 
                        "Channel: %d\r\n", i->channel);
9382
 
                break;
9383
 
        case DAHDI_EVENT_ALARM:
9384
 
                i->inalarm = 1;
9385
 
                res = get_alarms(i);
9386
 
                handle_alarms(i, res);
9387
 
                /* fall thru intentionally */
9388
 
        case DAHDI_EVENT_ONHOOK:
9389
 
                if (i->radio)
9390
 
                        break;
9391
 
                /* Back on hook.  Hang up. */
9392
 
                switch (i->sig) {
9393
 
                case SIG_FXOLS:
9394
 
                case SIG_FXOGS:
9395
 
                case SIG_FEATD:
9396
 
                case SIG_FEATDMF:
9397
 
                case SIG_FEATDMF_TA:
9398
 
                case SIG_E911:
9399
 
                case SIG_FGC_CAMA:
9400
 
                case SIG_FGC_CAMAMF:
9401
 
                case SIG_FEATB:
9402
 
                case SIG_EM:
9403
 
                case SIG_EM_E1:
9404
 
                case SIG_EMWINK:
9405
 
                case SIG_SF_FEATD:
9406
 
                case SIG_SF_FEATDMF:
9407
 
                case SIG_SF_FEATB:
9408
 
                case SIG_SF:
9409
 
                case SIG_SFWINK:
9410
 
                case SIG_FXSLS:
9411
 
                case SIG_FXSGS:
9412
 
                case SIG_FXSKS:
9413
 
                case SIG_GR303FXSKS:
9414
 
                        dahdi_disable_ec(i);
9415
 
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
9416
 
                        dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
9417
 
                        break;
9418
 
                case SIG_GR303FXOKS:
9419
 
                case SIG_FXOKS:
9420
 
                        dahdi_disable_ec(i);
9421
 
                        /* Diddle the battery for the zhone */
9422
 
#ifdef ZHONE_HACK
9423
 
                        dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9424
 
                        usleep(1);
9425
 
#endif
9426
 
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
9427
 
                        dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
9428
 
                        break;
9429
 
                case SIG_PRI:
9430
 
                case SIG_SS7:
9431
 
                case SIG_BRI:
9432
 
                case SIG_BRI_PTMP:
9433
 
                        dahdi_disable_ec(i);
9434
 
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
9435
 
                        break;
9436
 
                default:
9437
 
                        ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
9438
 
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
9439
 
                        return NULL;
9440
 
                }
9441
 
                if (i->sig & __DAHDI_SIG_FXO) {
9442
 
                        i->fxsoffhookstate = 0;
9443
 
                }
9444
 
                break;
9445
 
        case DAHDI_EVENT_POLARITY:
9446
 
                switch (i->sig) {
9447
 
                case SIG_FXSLS:
9448
 
                case SIG_FXSKS:
9449
 
                case SIG_FXSGS:
9450
 
                        /* We have already got a PR before the channel was
9451
 
                           created, but it wasn't handled. We need polarity
9452
 
                           to be REV for remote hangup detection to work.
9453
 
                           At least in Spain */
9454
 
                        if (i->hanguponpolarityswitch)
9455
 
                                i->polarity = POLARITY_REV;
9456
 
                        if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
9457
 
                                i->polarity = POLARITY_REV;
9458
 
                                ast_verb(2, "Starting post polarity "
9459
 
                                        "CID detection on channel %d\n",
9460
 
                                        i->channel);
9461
 
                                chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
9462
 
                                if (!chan) {
9463
 
                                        ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
9464
 
                                } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
9465
 
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
9466
 
                                }
9467
 
                        }
9468
 
                        break;
9469
 
                default:
9470
 
                        ast_log(LOG_WARNING, "handle_init_event detected "
9471
 
                                "polarity reversal on non-FXO (SIG_FXS) "
9472
 
                                "interface %d\n", i->channel);
9473
 
                }
9474
 
                break;
9475
 
        case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
9476
 
                ast_log(LOG_NOTICE,
9477
 
                                "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
9478
 
                                i->channel);
9479
 
                return i;
9480
 
        case DAHDI_EVENT_NEONMWI_ACTIVE:
9481
 
                if (i->mwimonitor_neon) {
9482
 
                        notify_message(i->mailbox, 1);
9483
 
                        ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
9484
 
                }
9485
 
                break;
9486
 
        case DAHDI_EVENT_NEONMWI_INACTIVE:
9487
 
                if (i->mwimonitor_neon) {
9488
 
                        notify_message(i->mailbox, 0);
9489
 
                        ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
9490
 
                }
9491
 
                break;
9492
 
        }
9493
 
        return NULL;
9494
 
}
9495
 
 
9496
 
static void *do_monitor(void *data)
9497
 
{
9498
 
        int count, res, res2, spoint, pollres=0;
9499
 
        struct dahdi_pvt *i;
9500
 
        struct dahdi_pvt *last = NULL;
9501
 
        struct dahdi_pvt *doomed;
9502
 
        time_t thispass = 0, lastpass = 0;
9503
 
        int found;
9504
 
        char buf[1024];
9505
 
        struct pollfd *pfds=NULL;
9506
 
        int lastalloc = -1;
9507
 
        /* This thread monitors all the frame relay interfaces which are not yet in use
9508
 
           (and thus do not have a separate thread) indefinitely */
9509
 
        /* From here on out, we die whenever asked */
9510
 
#if 0
9511
 
        if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
9512
 
                ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
9513
 
                return NULL;
9514
 
        }
9515
 
        ast_debug(1, "Monitor starting...\n");
9516
 
#endif
9517
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
9518
 
 
9519
 
        for (;;) {
9520
 
                /* Lock the interface list */
9521
 
                ast_mutex_lock(&iflock);
9522
 
                if (!pfds || (lastalloc != ifcount)) {
9523
 
                        if (pfds) {
9524
 
                                ast_free(pfds);
9525
 
                                pfds = NULL;
9526
 
                        }
9527
 
                        if (ifcount) {
9528
 
                                if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
9529
 
                                        ast_mutex_unlock(&iflock);
9530
 
                                        return NULL;
9531
 
                                }
9532
 
                        }
9533
 
                        lastalloc = ifcount;
9534
 
                }
9535
 
                /* Build the stuff we're going to poll on, that is the socket of every
9536
 
                   dahdi_pvt that does not have an associated owner channel */
9537
 
                count = 0;
9538
 
                i = iflist;
9539
 
                while (i) {
9540
 
                        if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
9541
 
                                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
9542
 
                                        /* This needs to be watched, as it lacks an owner */
9543
 
                                        pfds[count].fd = i->subs[SUB_REAL].dfd;
9544
 
                                        pfds[count].events = POLLPRI;
9545
 
                                        pfds[count].revents = 0;
9546
 
                                        /* If we are monitoring for VMWI or sending CID, we need to
9547
 
                                           read from the channel as well */
9548
 
                                        if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
9549
 
                                                pfds[count].events |= POLLIN;
9550
 
                                        count++;
9551
 
                                }
9552
 
                        }
9553
 
                        i = i->next;
9554
 
                }
9555
 
                /* Okay, now that we know what to do, release the interface lock */
9556
 
                ast_mutex_unlock(&iflock);
9557
 
 
9558
 
                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
9559
 
                pthread_testcancel();
9560
 
                /* Wait at least a second for something to happen */
9561
 
                res = poll(pfds, count, 1000);
9562
 
                pthread_testcancel();
9563
 
                pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
9564
 
 
9565
 
                /* Okay, poll has finished.  Let's see what happened.  */
9566
 
                if (res < 0) {
9567
 
                        if ((errno != EAGAIN) && (errno != EINTR))
9568
 
                                ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
9569
 
                        continue;
9570
 
                }
9571
 
                /* Alright, lock the interface list again, and let's look and see what has
9572
 
                   happened */
9573
 
                ast_mutex_lock(&iflock);
9574
 
                found = 0;
9575
 
                spoint = 0;
9576
 
                lastpass = thispass;
9577
 
                thispass = time(NULL);
9578
 
                i = iflist;
9579
 
                doomed = NULL;
9580
 
                for (i = iflist;; i = i->next) {
9581
 
                        if (doomed) {
9582
 
                                int res;
9583
 
                                res = dahdi_destroy_channel_bynum(doomed->channel);
9584
 
                                if (!res) {
9585
 
                                        ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
9586
 
                                }
9587
 
                                doomed = NULL;
9588
 
                        }
9589
 
                        if (!i) {
9590
 
                                break;
9591
 
                        }
9592
 
 
9593
 
                        if (thispass != lastpass) {
9594
 
                                if (!found && ((i == last) || ((i == iflist) && !last))) {
9595
 
                                        last = i;
9596
 
                                        if (last) {
9597
 
                                                /* Only allow MWI to be initiated on a quiescent fxs port */
9598
 
                                                if (!last->mwisendactive &&     last->sig & __DAHDI_SIG_FXO &&
9599
 
                                                                !last->fxsoffhookstate && !last->owner &&
9600
 
                                                                !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
9601
 
                                                        res = has_voicemail(last);
9602
 
                                                        if (last->msgstate != res) {
9603
 
                                                                /* Set driver resources for signalling VMWI */
9604
 
                                                                res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
9605
 
                                                                if (res2) {
9606
 
                                                                        /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
9607
 
                                                                        ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
9608
 
                                                                }
9609
 
                                                                /* If enabled for FSK spill then initiate it */
9610
 
                                                                if (mwi_send_init(last)) {
9611
 
                                                                        ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
9612
 
                                                                }
9613
 
                                                                last->msgstate = res;
9614
 
                                                                found ++;
9615
 
                                                        }
9616
 
                                                }
9617
 
                                                last = last->next;
9618
 
                                        }
9619
 
                                }
9620
 
                        }
9621
 
                        if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
9622
 
                                if (i->radio && !i->owner)
9623
 
                                {
9624
 
                                        res = dahdi_get_event(i->subs[SUB_REAL].dfd);
9625
 
                                        if (res)
9626
 
                                        {
9627
 
                                                ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
9628
 
                                                /* Don't hold iflock while handling init events */
9629
 
                                                ast_mutex_unlock(&iflock);
9630
 
                                                doomed = handle_init_event(i, res);
9631
 
                                                ast_mutex_lock(&iflock);
9632
 
                                        }
9633
 
                                        continue;
9634
 
                                }
9635
 
                                pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
9636
 
                                if (pollres & POLLIN) {
9637
 
                                        if (i->owner || i->subs[SUB_REAL].owner) {
9638
 
#ifdef HAVE_PRI
9639
 
                                                if (!i->pri)
9640
 
#endif
9641
 
                                                        ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
9642
 
                                                continue;
9643
 
                                        }
9644
 
                                        if (!i->mwimonitor_fsk && !i->mwisendactive) {
9645
 
                                                ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
9646
 
                                                continue;
9647
 
                                        }
9648
 
                                        res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
9649
 
                                        if (res > 0) {
9650
 
                                                if (i->mwimonitor_fsk) {
9651
 
                                                        if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
9652
 
                                                                pthread_attr_t attr;
9653
 
                                                                pthread_t threadid;
9654
 
                                                                struct mwi_thread_data *mtd;
9655
 
 
9656
 
                                                                pthread_attr_init(&attr);
9657
 
                                                                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
9658
 
 
9659
 
                                                                ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
9660
 
                                                                if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
9661
 
                                                                        mtd->pvt = i;
9662
 
                                                                        memcpy(mtd->buf, buf, res);
9663
 
                                                                        mtd->len = res;
9664
 
                                                                        if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
9665
 
                                                                                ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
9666
 
                                                                                ast_free(mtd);
9667
 
                                                                        }
9668
 
                                                                        i->mwimonitoractive = 1;
9669
 
                                                                }
9670
 
                                                        }
9671
 
                                                }
9672
 
                                                if (i->mwisendactive) {
9673
 
                                                        mwi_send_process_buffer(i, res);
9674
 
                                                }
9675
 
                                        } else {
9676
 
                                                ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
9677
 
                                        }
9678
 
                                }
9679
 
                                if (pollres & POLLPRI) {
9680
 
                                        if (i->owner || i->subs[SUB_REAL].owner) {
9681
 
#ifdef HAVE_PRI
9682
 
                                                if (!i->pri)
9683
 
#endif
9684
 
                                                        ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
9685
 
                                                continue;
9686
 
                                        }
9687
 
                                        res = dahdi_get_event(i->subs[SUB_REAL].dfd);
9688
 
                                        ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
9689
 
                                        /* Don't hold iflock while handling init events */
9690
 
                                        ast_mutex_unlock(&iflock);
9691
 
                                        if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
9692
 
                                                doomed = handle_init_event(i, res);
9693
 
                                        }
9694
 
                                        ast_mutex_lock(&iflock);
9695
 
                                }
9696
 
                        }
9697
 
                }
9698
 
                ast_mutex_unlock(&iflock);
9699
 
        }
9700
 
        /* Never reached */
9701
 
        return NULL;
9702
 
 
9703
 
}
9704
 
 
9705
 
static int restart_monitor(void)
9706
 
{
9707
 
        /* If we're supposed to be stopped -- stay stopped */
9708
 
        if (monitor_thread == AST_PTHREADT_STOP)
9709
 
                return 0;
9710
 
        ast_mutex_lock(&monlock);
9711
 
        if (monitor_thread == pthread_self()) {
9712
 
                ast_mutex_unlock(&monlock);
9713
 
                ast_log(LOG_WARNING, "Cannot kill myself\n");
9714
 
                return -1;
9715
 
        }
9716
 
        if (monitor_thread != AST_PTHREADT_NULL) {
9717
 
                /* Wake up the thread */
9718
 
                pthread_kill(monitor_thread, SIGURG);
9719
 
        } else {
9720
 
                /* Start a new monitor */
9721
 
                if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
9722
 
                        ast_mutex_unlock(&monlock);
9723
 
                        ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
9724
 
                        return -1;
9725
 
                }
9726
 
        }
9727
 
        ast_mutex_unlock(&monlock);
9728
 
        return 0;
9729
 
}
9730
 
 
9731
 
#if defined(HAVE_PRI)
9732
 
static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
9733
 
{
9734
 
        int x;
9735
 
        int trunkgroup;
9736
 
        /* Get appropriate trunk group if there is one */
9737
 
        trunkgroup = pris[*span].mastertrunkgroup;
9738
 
        if (trunkgroup) {
9739
 
                /* Select a specific trunk group */
9740
 
                for (x = 0; x < NUM_SPANS; x++) {
9741
 
                        if (pris[x].trunkgroup == trunkgroup) {
9742
 
                                *span = x;
9743
 
                                return 0;
9744
 
                        }
9745
 
                }
9746
 
                ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
9747
 
                *span = -1;
9748
 
        } else {
9749
 
                if (pris[*span].trunkgroup) {
9750
 
                        ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
9751
 
                        *span = -1;
9752
 
                } else if (pris[*span].mastertrunkgroup) {
9753
 
                        ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
9754
 
                        *span = -1;
9755
 
                } else {
9756
 
                        if (si->totalchans == 31) {
9757
 
                                /* E1 */
9758
 
                                pris[*span].dchannels[0] = 16 + offset;
9759
 
                        } else if (si->totalchans == 24) {
9760
 
                                /* T1 or J1 */
9761
 
                                pris[*span].dchannels[0] = 24 + offset;
9762
 
                        } else if (si->totalchans == 3) {
9763
 
                                /* BRI */
9764
 
                                pris[*span].dchannels[0] = 3 + offset;
9765
 
                        } else {
9766
 
                                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);
9767
 
                                *span = -1;
9768
 
                                return 0;
9769
 
                        }
9770
 
                        pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
9771
 
                        pris[*span].offset = offset;
9772
 
                        pris[*span].span = *span + 1;
9773
 
                }
9774
 
        }
9775
 
        return 0;
9776
 
}
9777
 
#endif  /* defined(HAVE_PRI) */
9778
 
 
9779
 
#if defined(HAVE_PRI)
9780
 
static int pri_create_trunkgroup(int trunkgroup, int *channels)
9781
 
{
9782
 
        struct dahdi_spaninfo si;
9783
 
        struct dahdi_params p;
9784
 
        int fd;
9785
 
        int span;
9786
 
        int ospan=0;
9787
 
        int x,y;
9788
 
        for (x = 0; x < NUM_SPANS; x++) {
9789
 
                if (pris[x].trunkgroup == trunkgroup) {
9790
 
                        ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
9791
 
                        return -1;
9792
 
                }
9793
 
        }
9794
 
        for (y = 0; y < NUM_DCHANS; y++) {
9795
 
                if (!channels[y])
9796
 
                        break;
9797
 
                memset(&si, 0, sizeof(si));
9798
 
                memset(&p, 0, sizeof(p));
9799
 
                fd = open("/dev/dahdi/channel", O_RDWR);
9800
 
                if (fd < 0) {
9801
 
                        ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
9802
 
                        return -1;
9803
 
                }
9804
 
                x = channels[y];
9805
 
                if (ioctl(fd, DAHDI_SPECIFY, &x)) {
9806
 
                        ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
9807
 
                        close(fd);
9808
 
                        return -1;
9809
 
                }
9810
 
                if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
9811
 
                        ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
9812
 
                        return -1;
9813
 
                }
9814
 
                if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
9815
 
                        ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
9816
 
                        close(fd);
9817
 
                        return -1;
9818
 
                }
9819
 
                span = p.spanno - 1;
9820
 
                if (pris[span].trunkgroup) {
9821
 
                        ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
9822
 
                        close(fd);
9823
 
                        return -1;
9824
 
                }
9825
 
                if (pris[span].pvts[0]) {
9826
 
                        ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
9827
 
                        close(fd);
9828
 
                        return -1;
9829
 
                }
9830
 
                if (!y) {
9831
 
                        pris[span].trunkgroup = trunkgroup;
9832
 
                        pris[span].offset = channels[y] - p.chanpos;
9833
 
                        ospan = span;
9834
 
                }
9835
 
                pris[ospan].dchannels[y] = channels[y];
9836
 
                pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
9837
 
                pris[span].span = span + 1;
9838
 
                close(fd);
9839
 
        }
9840
 
        return 0;
9841
 
}
9842
 
#endif  /* defined(HAVE_PRI) */
9843
 
 
9844
 
#if defined(HAVE_PRI)
9845
 
static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
9846
 
{
9847
 
        if (pris[span].mastertrunkgroup) {
9848
 
                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);
9849
 
                return -1;
9850
 
        }
9851
 
        pris[span].mastertrunkgroup = trunkgroup;
9852
 
        pris[span].prilogicalspan = logicalspan;
9853
 
        return 0;
9854
 
}
9855
 
#endif  /* defined(HAVE_PRI) */
9856
 
 
9857
 
#if defined(HAVE_SS7)
9858
 
static unsigned int parse_pointcode(const char *pcstring)
9859
 
{
9860
 
        unsigned int code1, code2, code3;
9861
 
        int numvals;
9862
 
 
9863
 
        numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
9864
 
        if (numvals == 1)
9865
 
                return code1;
9866
 
        if (numvals == 3)
9867
 
                return (code1 << 16) | (code2 << 8) | code3;
9868
 
 
9869
 
        return 0;
9870
 
}
9871
 
#endif  /* defined(HAVE_SS7) */
9872
 
 
9873
 
#if defined(HAVE_SS7)
9874
 
static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
9875
 
{
9876
 
        if ((linkset < 0) || (linkset >= NUM_SPANS))
9877
 
                return NULL;
9878
 
        else
9879
 
                return &linksets[linkset - 1];
9880
 
}
9881
 
#endif  /* defined(HAVE_SS7) */
9882
 
 
9883
 
#ifdef HAVE_OPENR2
9884
 
static void dahdi_r2_destroy_links(void)
9885
 
{
9886
 
        int i = 0;
9887
 
        if (!r2links) {
9888
 
                return;
9889
 
        }
9890
 
        for (; i < r2links_count; i++) {
9891
 
                if (r2links[i]->r2master != AST_PTHREADT_NULL) {
9892
 
                        pthread_cancel(r2links[i]->r2master);
9893
 
                        pthread_join(r2links[i]->r2master, NULL);
9894
 
                        openr2_context_delete(r2links[i]->protocol_context);
9895
 
                }
9896
 
                ast_free(r2links[i]);
9897
 
        }
9898
 
        ast_free(r2links);
9899
 
        r2links = NULL;
9900
 
        r2links_count = 0;
9901
 
}
9902
 
 
9903
 
#define R2_LINK_CAPACITY 10
9904
 
static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
9905
 
{
9906
 
        struct dahdi_mfcr2 *new_r2link = NULL;
9907
 
        struct dahdi_mfcr2 **new_r2links = NULL;
9908
 
        /* this function is called just when starting up and no monitor threads have been launched,
9909
 
           no need to lock monitored_count member */
9910
 
        if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
9911
 
                new_r2link = ast_calloc(1, sizeof(**r2links));
9912
 
                if (!new_r2link) {
9913
 
                        ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
9914
 
                        return NULL;
9915
 
                }
9916
 
                new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
9917
 
                if (!new_r2links) {
9918
 
                        ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
9919
 
                        ast_free(new_r2link);
9920
 
                        return NULL;
9921
 
                }
9922
 
                r2links = new_r2links;
9923
 
                new_r2link->r2master = AST_PTHREADT_NULL;
9924
 
                r2links[r2links_count] = new_r2link;
9925
 
                r2links_count++;
9926
 
                ast_log(LOG_DEBUG, "Created new R2 link!\n");
9927
 
        }
9928
 
        return r2links[r2links_count - 1];
9929
 
}
9930
 
 
9931
 
static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
9932
 
{
9933
 
        char tmplogdir[] = "/tmp";
9934
 
        char logdir[OR2_MAX_PATH];
9935
 
        int threshold = 0;
9936
 
        int snres = 0;
9937
 
        r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
9938
 
                        &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
9939
 
                        conf->mfcr2.max_dnis);
9940
 
        if (!r2_link->protocol_context) {
9941
 
                return -1;
9942
 
        }
9943
 
        openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
9944
 
        openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
9945
 
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
9946
 
        openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
9947
 
#endif
9948
 
        openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
9949
 
        openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
9950
 
        openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
9951
 
        openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
9952
 
        openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
9953
 
        if (ast_strlen_zero(conf->mfcr2.logdir)) {
9954
 
                if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
9955
 
                        ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
9956
 
                }
9957
 
        } else {
9958
 
                snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
9959
 
                if (snres >= sizeof(logdir)) {
9960
 
                        ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
9961
 
                        if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
9962
 
                                ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
9963
 
                        }
9964
 
                } else {
9965
 
                        if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
9966
 
                                ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
9967
 
                        }
9968
 
                }
9969
 
        }
9970
 
        if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
9971
 
                if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
9972
 
                        ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
9973
 
                }
9974
 
        }
9975
 
        r2_link->monitored_count = 0;
9976
 
        return 0;
9977
 
}
9978
 
#endif
9979
 
 
9980
 
/* converts a DAHDI sigtype to signalling as can be configured from
9981
 
 * chan_dahdi.conf.
9982
 
 * While both have basically the same values, this will later be the
9983
 
 * place to add filters and sanity checks
9984
 
 */
9985
 
static int sigtype_to_signalling(int sigtype)
9986
 
{
9987
 
        return sigtype;
9988
 
}
9989
 
 
9990
 
static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
9991
 
{
9992
 
        /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
9993
 
        struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
9994
 
        char fn[80];
9995
 
        struct dahdi_bufferinfo bi;
9996
 
 
9997
 
        int res;
9998
 
        int span = 0;
9999
 
        int here = 0;
10000
 
        int x;
10001
 
        struct dahdi_pvt **wlist;
10002
 
        struct dahdi_pvt **wend;
10003
 
        struct dahdi_params p;
10004
 
 
10005
 
        wlist = &iflist;
10006
 
        wend = &ifend;
10007
 
 
10008
 
#ifdef HAVE_PRI
10009
 
        if (pri) {
10010
 
                wlist = &pri->crvs;
10011
 
                wend = &pri->crvend;
10012
 
        }
10013
 
#endif
10014
 
 
10015
 
        tmp2 = *wlist;
10016
 
        prev = NULL;
10017
 
 
10018
 
        while (tmp2) {
10019
 
                if (!tmp2->destroy) {
10020
 
                        if (tmp2->channel == channel) {
10021
 
                                tmp = tmp2;
10022
 
                                here = 1;
10023
 
                                break;
10024
 
                        }
10025
 
                        if (tmp2->channel > channel) {
10026
 
                                break;
10027
 
                        }
10028
 
                }
10029
 
                prev = tmp2;
10030
 
                tmp2 = tmp2->next;
10031
 
        }
10032
 
 
10033
 
        if (!here && reloading != 1) {
10034
 
                if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10035
 
                        if (tmp)
10036
 
                                free(tmp);
10037
 
                        return NULL;
10038
 
                }
10039
 
                ast_mutex_init(&tmp->lock);
10040
 
                ifcount++;
10041
 
                for (x = 0; x < 3; x++)
10042
 
                        tmp->subs[x].dfd = -1;
10043
 
                tmp->channel = channel;
10044
 
                tmp->priindication_oob = conf->chan.priindication_oob;
10045
 
        }
10046
 
 
10047
 
        if (tmp) {
10048
 
                int chan_sig = conf->chan.sig;
10049
 
                if (!here) {
10050
 
                        if ((channel != CHAN_PSEUDO) && !pri) {
10051
 
                                int count = 0;
10052
 
                                snprintf(fn, sizeof(fn), "%d", channel);
10053
 
                                /* Open non-blocking */
10054
 
                                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10055
 
                                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 */
10056
 
                                        usleep(1);
10057
 
                                        tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10058
 
                                        count++;
10059
 
                                }
10060
 
                                /* Allocate a DAHDI structure */
10061
 
                                if (tmp->subs[SUB_REAL].dfd < 0) {
10062
 
                                        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);
10063
 
                                        destroy_dahdi_pvt(&tmp);
10064
 
                                        return NULL;
10065
 
                                }
10066
 
                                memset(&p, 0, sizeof(p));
10067
 
                                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10068
 
                                if (res < 0) {
10069
 
                                        ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10070
 
                                        destroy_dahdi_pvt(&tmp);
10071
 
                                        return NULL;
10072
 
                                }
10073
 
                                if (conf->is_sig_auto)
10074
 
                                        chan_sig = sigtype_to_signalling(p.sigtype);
10075
 
                                if (p.sigtype != (chan_sig & 0x3ffff)) {
10076
 
                                        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));
10077
 
                                        destroy_dahdi_pvt(&tmp);
10078
 
                                        return NULL;
10079
 
                                }
10080
 
                                tmp->law = p.curlaw;
10081
 
                                tmp->span = p.spanno;
10082
 
                                span = p.spanno - 1;
10083
 
                        } else {
10084
 
                                if (channel == CHAN_PSEUDO)
10085
 
                                        chan_sig = 0;
10086
 
                                else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10087
 
                                        ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10088
 
                                        return NULL;
10089
 
                                }
10090
 
                        }
10091
 
#ifdef HAVE_SS7
10092
 
                        if (chan_sig == SIG_SS7) {
10093
 
                                struct dahdi_ss7 *ss7;
10094
 
                                int clear = 0;
10095
 
                                if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10096
 
                                        ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10097
 
                                        destroy_dahdi_pvt(&tmp);
10098
 
                                        return NULL;
10099
 
                                }
10100
 
 
10101
 
                                ss7 = ss7_resolve_linkset(cur_linkset);
10102
 
                                if (!ss7) {
10103
 
                                        ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10104
 
                                        destroy_dahdi_pvt(&tmp);
10105
 
                                        return NULL;
10106
 
                                }
10107
 
                                if (cur_cicbeginswith < 0) {
10108
 
                                        ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10109
 
                                        destroy_dahdi_pvt(&tmp);
10110
 
                                        return NULL;
10111
 
                                }
10112
 
 
10113
 
                                tmp->cic = cur_cicbeginswith++;
10114
 
 
10115
 
                                /* DB: Add CIC's DPC information */
10116
 
                                tmp->dpc = cur_defaultdpc;
10117
 
 
10118
 
                                tmp->ss7 = ss7;
10119
 
                                tmp->ss7call = NULL;
10120
 
                                ss7->pvts[ss7->numchans++] = tmp;
10121
 
 
10122
 
                                ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10123
 
                                ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10124
 
                                ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10125
 
                                ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10126
 
 
10127
 
                                ss7->called_nai = conf->ss7.called_nai;
10128
 
                                ss7->calling_nai = conf->ss7.calling_nai;
10129
 
                        }
10130
 
#endif
10131
 
#ifdef HAVE_OPENR2
10132
 
                        if (chan_sig == SIG_MFCR2 && reloading != 1) {
10133
 
                                struct dahdi_mfcr2 *r2_link;
10134
 
                                r2_link = dahdi_r2_get_link();
10135
 
                                if (!r2_link) {
10136
 
                                        ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10137
 
                                        destroy_dahdi_pvt(&tmp);
10138
 
                                        return NULL;
10139
 
                                }
10140
 
                                if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10141
 
                                        ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10142
 
                                        destroy_dahdi_pvt(&tmp);
10143
 
                                        return NULL;
10144
 
                                }
10145
 
                                if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10146
 
                                        ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10147
 
                                        destroy_dahdi_pvt(&tmp);
10148
 
                                        return NULL;
10149
 
                                }
10150
 
                                r2_link->pvts[r2_link->numchans++] = tmp;
10151
 
                                tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10152
 
                                                                      tmp->subs[SUB_REAL].dfd,
10153
 
                                                                      NULL, NULL);
10154
 
                                if (!tmp->r2chan) {
10155
 
                                        openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10156
 
                                        ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10157
 
                                        destroy_dahdi_pvt(&tmp);
10158
 
                                        return NULL;
10159
 
                                }
10160
 
                                tmp->mfcr2 = r2_link;
10161
 
                                if (conf->mfcr2.call_files) {
10162
 
                                        openr2_chan_enable_call_files(tmp->r2chan);
10163
 
                                }
10164
 
                                openr2_chan_set_client_data(tmp->r2chan, tmp);
10165
 
                                /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10166
 
                                openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10167
 
                                openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10168
 
                                tmp->mfcr2_category = conf->mfcr2.category;
10169
 
                                tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10170
 
                                tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10171
 
                                tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10172
 
                                tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10173
 
                                tmp->mfcr2call = 0;
10174
 
                                tmp->mfcr2_dnis_index = 0;
10175
 
                                tmp->mfcr2_ani_index = 0;
10176
 
                                r2_link->monitored_count++;
10177
 
                        }
10178
 
#endif
10179
 
#ifdef HAVE_PRI
10180
 
                        if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10181
 
                                int offset;
10182
 
                                int myswitchtype;
10183
 
                                int matchesdchan;
10184
 
                                int x,y;
10185
 
                                offset = 0;
10186
 
                                if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10187
 
                                                && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10188
 
                                        ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10189
 
                                        destroy_dahdi_pvt(&tmp);
10190
 
                                        return NULL;
10191
 
                                }
10192
 
                                if (span >= NUM_SPANS) {
10193
 
                                        ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10194
 
                                        destroy_dahdi_pvt(&tmp);
10195
 
                                        return NULL;
10196
 
                                } else {
10197
 
                                        struct dahdi_spaninfo si;
10198
 
                                        si.spanno = 0;
10199
 
                                        if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10200
 
                                                ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10201
 
                                                destroy_dahdi_pvt(&tmp);
10202
 
                                                return NULL;
10203
 
                                        }
10204
 
                                        /* Store the logical span first based upon the real span */
10205
 
                                        tmp->logicalspan = pris[span].prilogicalspan;
10206
 
                                        pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10207
 
                                        if (span < 0) {
10208
 
                                                ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10209
 
                                                destroy_dahdi_pvt(&tmp);
10210
 
                                                return NULL;
10211
 
                                        }
10212
 
                                        if ((chan_sig == SIG_PRI) ||
10213
 
                                                        (chan_sig == SIG_BRI) ||
10214
 
                                                        (chan_sig == SIG_BRI_PTMP))
10215
 
                                                myswitchtype = conf->pri.switchtype;
10216
 
                                        else
10217
 
                                                myswitchtype = PRI_SWITCH_GR303_TMC;
10218
 
                                        /* Make sure this isn't a d-channel */
10219
 
                                        matchesdchan=0;
10220
 
                                        for (x = 0; x < NUM_SPANS; x++) {
10221
 
                                                for (y = 0; y < NUM_DCHANS; y++) {
10222
 
                                                        if (pris[x].dchannels[y] == tmp->channel) {
10223
 
                                                                matchesdchan = 1;
10224
 
                                                                break;
10225
 
                                                        }
10226
 
                                                }
10227
 
                                        }
10228
 
                                        offset = p.chanpos;
10229
 
                                        if (!matchesdchan) {
10230
 
                                                if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10231
 
                                                        ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10232
 
                                                        destroy_dahdi_pvt(&tmp);
10233
 
                                                        return NULL;
10234
 
                                                }
10235
 
                                                if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10236
 
                                                        ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10237
 
                                                        destroy_dahdi_pvt(&tmp);
10238
 
                                                        return NULL;
10239
 
                                                }
10240
 
                                                if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10241
 
                                                        ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10242
 
                                                        destroy_dahdi_pvt(&tmp);
10243
 
                                                        return NULL;
10244
 
                                                }
10245
 
                                                if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10246
 
                                                        ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10247
 
                                                        destroy_dahdi_pvt(&tmp);
10248
 
                                                        return NULL;
10249
 
                                                }
10250
 
                                                if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10251
 
                                                        ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10252
 
                                                        destroy_dahdi_pvt(&tmp);
10253
 
                                                        return NULL;
10254
 
                                                }
10255
 
                                                if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10256
 
                                                        ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10257
 
                                                        destroy_dahdi_pvt(&tmp);
10258
 
                                                        return NULL;
10259
 
                                                }
10260
 
                                                if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10261
 
                                                        ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10262
 
                                                        destroy_dahdi_pvt(&tmp);
10263
 
                                                        return NULL;
10264
 
                                                }
10265
 
                                                if (pris[span].numchans >= MAX_CHANNELS) {
10266
 
                                                        ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10267
 
                                                                pris[span].trunkgroup);
10268
 
                                                        destroy_dahdi_pvt(&tmp);
10269
 
                                                        return NULL;
10270
 
                                                }
10271
 
 
10272
 
                                                pris[span].sig = chan_sig;
10273
 
                                                pris[span].nodetype = conf->pri.nodetype;
10274
 
                                                pris[span].switchtype = myswitchtype;
10275
 
                                                pris[span].nsf = conf->pri.nsf;
10276
 
                                                pris[span].dialplan = conf->pri.dialplan;
10277
 
                                                pris[span].localdialplan = conf->pri.localdialplan;
10278
 
                                                pris[span].pvts[pris[span].numchans++] = tmp;
10279
 
                                                pris[span].minunused = conf->pri.minunused;
10280
 
                                                pris[span].minidle = conf->pri.minidle;
10281
 
                                                pris[span].overlapdial = conf->pri.overlapdial;
10282
 
                                                pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10283
 
                                                pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10284
 
#ifdef HAVE_PRI_INBANDDISCONNECT
10285
 
                                                pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10286
 
#endif
10287
 
                                                pris[span].facilityenable = conf->pri.facilityenable;
10288
 
                                                ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10289
 
                                                ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10290
 
                                                ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10291
 
                                                ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10292
 
                                                ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10293
 
                                                ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10294
 
                                                ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10295
 
                                                pris[span].resetinterval = conf->pri.resetinterval;
10296
 
 
10297
 
                                                tmp->pri = &pris[span];
10298
 
                                                tmp->prioffset = offset;
10299
 
                                                tmp->call = NULL;
10300
 
                                        } else {
10301
 
                                                ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10302
 
                                                destroy_dahdi_pvt(&tmp);
10303
 
                                                return NULL;
10304
 
                                        }
10305
 
                                }
10306
 
                        } else {
10307
 
                                tmp->prioffset = 0;
10308
 
                        }
10309
 
#endif
10310
 
                } else {
10311
 
                        chan_sig = tmp->sig;
10312
 
                        if (tmp->subs[SUB_REAL].dfd > -1) {
10313
 
                                memset(&p, 0, sizeof(p));
10314
 
                                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10315
 
                        }
10316
 
                }
10317
 
                /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10318
 
                switch (chan_sig) {
10319
 
                case SIG_FXSKS:
10320
 
                case SIG_FXSLS:
10321
 
                case SIG_EM:
10322
 
                case SIG_EM_E1:
10323
 
                case SIG_EMWINK:
10324
 
                case SIG_FEATD:
10325
 
                case SIG_FEATDMF:
10326
 
                case SIG_FEATDMF_TA:
10327
 
                case SIG_FEATB:
10328
 
                case SIG_E911:
10329
 
                case SIG_SF:
10330
 
                case SIG_SFWINK:
10331
 
                case SIG_FGC_CAMA:
10332
 
                case SIG_FGC_CAMAMF:
10333
 
                case SIG_SF_FEATD:
10334
 
                case SIG_SF_FEATDMF:
10335
 
                case SIG_SF_FEATB:
10336
 
                        p.starttime = 250;
10337
 
                        break;
10338
 
                }
10339
 
 
10340
 
                if (tmp->radio) {
10341
 
                        /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10342
 
                        p.channo = channel;
10343
 
                        p.rxwinktime = 1;
10344
 
                        p.rxflashtime = 1;
10345
 
                        p.starttime = 1;
10346
 
                        p.debouncetime = 5;
10347
 
                }
10348
 
                if (!tmp->radio) {
10349
 
                        p.channo = channel;
10350
 
                        /* Override timing settings based on config file */
10351
 
                        if (conf->timing.prewinktime >= 0)
10352
 
                                p.prewinktime = conf->timing.prewinktime;
10353
 
                        if (conf->timing.preflashtime >= 0)
10354
 
                                p.preflashtime = conf->timing.preflashtime;
10355
 
                        if (conf->timing.winktime >= 0)
10356
 
                                p.winktime = conf->timing.winktime;
10357
 
                        if (conf->timing.flashtime >= 0)
10358
 
                                p.flashtime = conf->timing.flashtime;
10359
 
                        if (conf->timing.starttime >= 0)
10360
 
                                p.starttime = conf->timing.starttime;
10361
 
                        if (conf->timing.rxwinktime >= 0)
10362
 
                                p.rxwinktime = conf->timing.rxwinktime;
10363
 
                        if (conf->timing.rxflashtime >= 0)
10364
 
                                p.rxflashtime = conf->timing.rxflashtime;
10365
 
                        if (conf->timing.debouncetime >= 0)
10366
 
                                p.debouncetime = conf->timing.debouncetime;
10367
 
                }
10368
 
 
10369
 
                /* dont set parms on a pseudo-channel (or CRV) */
10370
 
                if (tmp->subs[SUB_REAL].dfd >= 0)
10371
 
                {
10372
 
                        res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10373
 
                        if (res < 0) {
10374
 
                                ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10375
 
                                destroy_dahdi_pvt(&tmp);
10376
 
                                return NULL;
10377
 
                        }
10378
 
                }
10379
 
#if 1
10380
 
                if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10381
 
                        memset(&bi, 0, sizeof(bi));
10382
 
                        res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10383
 
                        if (!res) {
10384
 
                                bi.txbufpolicy = conf->chan.buf_policy;
10385
 
                                bi.rxbufpolicy = conf->chan.buf_policy;
10386
 
                                bi.numbufs = conf->chan.buf_no;
10387
 
                                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10388
 
                                if (res < 0) {
10389
 
                                        ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10390
 
                                }
10391
 
                        } else {
10392
 
                                ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10393
 
                        }
10394
 
                        tmp->buf_policy = conf->chan.buf_policy;
10395
 
                        tmp->buf_no = conf->chan.buf_no;
10396
 
                        tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10397
 
                        tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10398
 
                        tmp->faxbuf_no = conf->chan.faxbuf_no;
10399
 
                        /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10400
 
                         * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10401
 
                         * The reason the ioctl call above failed should to be determined before worrying about the
10402
 
                         * faxbuffer-related ioctl calls */
10403
 
                        tmp->bufsize = bi.bufsize;
10404
 
                }
10405
 
#endif
10406
 
                tmp->immediate = conf->chan.immediate;
10407
 
                tmp->transfertobusy = conf->chan.transfertobusy;
10408
 
                if (chan_sig & __DAHDI_SIG_FXS) {
10409
 
                        tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10410
 
                        tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10411
 
                        tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10412
 
                }
10413
 
                tmp->sig = chan_sig;
10414
 
                tmp->outsigmod = conf->chan.outsigmod;
10415
 
                tmp->ringt_base = ringt_base;
10416
 
                tmp->firstradio = 0;
10417
 
                if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10418
 
                        tmp->permcallwaiting = conf->chan.callwaiting;
10419
 
                else
10420
 
                        tmp->permcallwaiting = 0;
10421
 
                /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10422
 
                tmp->destroy = 0;
10423
 
                tmp->drings = conf->chan.drings;
10424
 
 
10425
 
                /* 10 is a nice default. */
10426
 
                if (tmp->drings.ringnum[0].range == 0)
10427
 
                        tmp->drings.ringnum[0].range = 10;
10428
 
                if (tmp->drings.ringnum[1].range == 0)
10429
 
                        tmp->drings.ringnum[1].range = 10;
10430
 
                if (tmp->drings.ringnum[2].range == 0)
10431
 
                        tmp->drings.ringnum[2].range = 10;
10432
 
 
10433
 
                tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10434
 
                tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10435
 
                tmp->threewaycalling = conf->chan.threewaycalling;
10436
 
                tmp->adsi = conf->chan.adsi;
10437
 
                tmp->use_smdi = conf->chan.use_smdi;
10438
 
                tmp->permhidecallerid = conf->chan.hidecallerid;
10439
 
                tmp->callreturn = conf->chan.callreturn;
10440
 
                tmp->echocancel = conf->chan.echocancel;
10441
 
                tmp->echotraining = conf->chan.echotraining;
10442
 
                tmp->pulse = conf->chan.pulse;
10443
 
                if (tmp->echocancel.head.tap_length) {
10444
 
                        tmp->echocanbridged = conf->chan.echocanbridged;
10445
 
                } else {
10446
 
                        if (conf->chan.echocanbridged)
10447
 
                                ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10448
 
                        tmp->echocanbridged = 0;
10449
 
                }
10450
 
                tmp->busydetect = conf->chan.busydetect;
10451
 
                tmp->busycount = conf->chan.busycount;
10452
 
                tmp->busy_tonelength = conf->chan.busy_tonelength;
10453
 
                tmp->busy_quietlength = conf->chan.busy_quietlength;
10454
 
                tmp->callprogress = conf->chan.callprogress;
10455
 
                tmp->waitfordialtone = conf->chan.waitfordialtone;
10456
 
                tmp->cancallforward = conf->chan.cancallforward;
10457
 
                tmp->dtmfrelax = conf->chan.dtmfrelax;
10458
 
                tmp->callwaiting = tmp->permcallwaiting;
10459
 
                tmp->hidecallerid = tmp->permhidecallerid;
10460
 
                tmp->channel = channel;
10461
 
                tmp->stripmsd = conf->chan.stripmsd;
10462
 
                tmp->use_callerid = conf->chan.use_callerid;
10463
 
                tmp->cid_signalling = conf->chan.cid_signalling;
10464
 
                tmp->cid_start = conf->chan.cid_start;
10465
 
                tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10466
 
                tmp->restrictcid = conf->chan.restrictcid;
10467
 
                tmp->use_callingpres = conf->chan.use_callingpres;
10468
 
                tmp->priexclusive = conf->chan.priexclusive;
10469
 
                if (tmp->usedistinctiveringdetection) {
10470
 
                        if (!tmp->use_callerid) {
10471
 
                                ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10472
 
                                tmp->use_callerid = 1;
10473
 
                        }
10474
 
                }
10475
 
 
10476
 
                if (tmp->cid_signalling == CID_SIG_SMDI) {
10477
 
                        if (!tmp->use_smdi) {
10478
 
                                ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10479
 
                                tmp->use_smdi = 1;
10480
 
                        }
10481
 
                }
10482
 
                if (tmp->use_smdi) {
10483
 
                        tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10484
 
                        if (!(tmp->smdi_iface)) {
10485
 
                                ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10486
 
                                tmp->use_smdi = 0;
10487
 
                        }
10488
 
                }
10489
 
 
10490
 
                ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10491
 
                tmp->amaflags = conf->chan.amaflags;
10492
 
                if (!here) {
10493
 
                        tmp->confno = -1;
10494
 
                        tmp->propconfno = -1;
10495
 
                }
10496
 
                tmp->canpark = conf->chan.canpark;
10497
 
                tmp->transfer = conf->chan.transfer;
10498
 
                ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10499
 
                ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10500
 
                ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10501
 
                ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10502
 
                ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10503
 
                ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10504
 
                tmp->cid_ton = 0;
10505
 
                if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP) || (tmp->sig != SIG_MFCR2)) {
10506
 
                        ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10507
 
                        ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10508
 
                } else {
10509
 
                        tmp->cid_num[0] = '\0';
10510
 
                        tmp->cid_name[0] = '\0';
10511
 
                }
10512
 
                ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10513
 
                if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10514
 
                        char *mailbox, *context;
10515
 
                        mailbox = context = ast_strdupa(tmp->mailbox);
10516
 
                        strsep(&context, "@");
10517
 
                        if (ast_strlen_zero(context))
10518
 
                                context = "default";
10519
 
                        tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10520
 
                                AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10521
 
                                AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10522
 
                                AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10523
 
                                AST_EVENT_IE_END);
10524
 
                }
10525
 
                tmp->msgstate = -1;
10526
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10527
 
                tmp->mwisend_setting = conf->chan.mwisend_setting;
10528
 
                tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
10529
 
                tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10530
 
#endif
10531
 
                if (chan_sig & __DAHDI_SIG_FXO) {
10532
 
                        memset(&p, 0, sizeof(p));
10533
 
                        res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10534
 
                        if (!res) {
10535
 
                                tmp->fxsoffhookstate = p.rxisoffhook;
10536
 
                        }
10537
 
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10538
 
                        res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10539
 
#endif
10540
 
                }
10541
 
                tmp->onhooktime = time(NULL);
10542
 
                tmp->group = conf->chan.group;
10543
 
                tmp->callgroup = conf->chan.callgroup;
10544
 
                tmp->pickupgroup= conf->chan.pickupgroup;
10545
 
                if (conf->chan.vars) {
10546
 
                        struct ast_variable *v, *tmpvar;
10547
 
                        for (v = conf->chan.vars ; v ; v = v->next) {
10548
 
                                if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10549
 
                                        tmpvar->next = tmp->vars;
10550
 
                                        tmp->vars = tmpvar;
10551
 
                                }
10552
 
                        }
10553
 
                }
10554
 
                tmp->cid_rxgain = conf->chan.cid_rxgain;
10555
 
                tmp->rxgain = conf->chan.rxgain;
10556
 
                tmp->txgain = conf->chan.txgain;
10557
 
                tmp->tonezone = conf->chan.tonezone;
10558
 
                if (tmp->subs[SUB_REAL].dfd > -1) {
10559
 
                        set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10560
 
                        if (tmp->dsp)
10561
 
                                ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10562
 
                        update_conf(tmp);
10563
 
                        if (!here) {
10564
 
                                if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10565
 
                                    && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10566
 
                                        /* Hang it up to be sure it's good */
10567
 
                                        dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10568
 
                        }
10569
 
                        ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10570
 
#ifdef HAVE_PRI
10571
 
                        /* the dchannel is down so put the channel in alarm */
10572
 
                        if (tmp->pri && !pri_is_up(tmp->pri))
10573
 
                                tmp->inalarm = 1;
10574
 
#endif
10575
 
                        if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10576
 
                                tmp->inalarm = 1;
10577
 
                                handle_alarms(tmp, res);
10578
 
                        }
10579
 
                }
10580
 
 
10581
 
                tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10582
 
                tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10583
 
                tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10584
 
                tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10585
 
                if (!here) {
10586
 
                        tmp->locallyblocked = tmp->remotelyblocked = 0;
10587
 
                        if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10588
 
                                tmp->inservice = 0;
10589
 
                        else /* We default to in service on protocols that don't have a reset */
10590
 
                                tmp->inservice = 1;
10591
 
                }
10592
 
        }
10593
 
        if (tmp && !here) {
10594
 
                /* nothing on the iflist */
10595
 
                if (!*wlist) {
10596
 
                        *wlist = tmp;
10597
 
                        tmp->prev = NULL;
10598
 
                        tmp->next = NULL;
10599
 
                        *wend = tmp;
10600
 
                } else {
10601
 
                        /* at least one member on the iflist */
10602
 
                        struct dahdi_pvt *working = *wlist;
10603
 
 
10604
 
                        /* check if we maybe have to put it on the begining */
10605
 
                        if (working->channel > tmp->channel) {
10606
 
                                tmp->next = *wlist;
10607
 
                                tmp->prev = NULL;
10608
 
                                (*wlist)->prev = tmp;
10609
 
                                *wlist = tmp;
10610
 
                        } else {
10611
 
                        /* go through all the members and put the member in the right place */
10612
 
                                while (working) {
10613
 
                                        /* in the middle */
10614
 
                                        if (working->next) {
10615
 
                                                if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10616
 
                                                        tmp->next = working->next;
10617
 
                                                        tmp->prev = working;
10618
 
                                                        working->next->prev = tmp;
10619
 
                                                        working->next = tmp;
10620
 
                                                        break;
10621
 
                                                }
10622
 
                                        } else {
10623
 
                                        /* the last */
10624
 
                                                if (working->channel < tmp->channel) {
10625
 
                                                        working->next = tmp;
10626
 
                                                        tmp->next = NULL;
10627
 
                                                        tmp->prev = working;
10628
 
                                                        *wend = tmp;
10629
 
                                                        break;
10630
 
                                                }
10631
 
                                        }
10632
 
                                        working = working->next;
10633
 
                                }
10634
 
                        }
10635
 
                }
10636
 
        }
10637
 
        return tmp;
10638
 
}
10639
 
 
10640
 
static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10641
 
{
10642
 
        int res;
10643
 
        struct dahdi_params par;
10644
 
 
10645
 
        /* First, check group matching */
10646
 
        if (groupmatch) {
10647
 
                if ((p->group & groupmatch) != groupmatch)
10648
 
                        return 0;
10649
 
                *groupmatched = 1;
10650
 
        }
10651
 
        /* Check to see if we have a channel match */
10652
 
        if (channelmatch != -1) {
10653
 
                if (p->channel != channelmatch)
10654
 
                        return 0;
10655
 
                *channelmatched = 1;
10656
 
        }
10657
 
        /* We're at least busy at this point */
10658
 
        if (busy) {
10659
 
                if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10660
 
                        *busy = 1;
10661
 
        }
10662
 
        /* If do not disturb, definitely not */
10663
 
        if (p->dnd)
10664
 
                return 0;
10665
 
        /* If guard time, definitely not */
10666
 
        if (p->guardtime && (time(NULL) < p->guardtime))
10667
 
                return 0;
10668
 
 
10669
 
        if (p->locallyblocked || p->remotelyblocked)
10670
 
                return 0;
10671
 
 
10672
 
        /* If no owner definitely available */
10673
 
        if (!p->owner) {
10674
 
#ifdef HAVE_PRI
10675
 
                /* Trust PRI */
10676
 
                if (p->pri) {
10677
 
                        if (p->resetting || p->call)
10678
 
                                return 0;
10679
 
                        else
10680
 
                                return 1;
10681
 
                }
10682
 
#endif
10683
 
#ifdef HAVE_SS7
10684
 
                /* Trust SS7 */
10685
 
                if (p->ss7) {
10686
 
                        if (p->ss7call)
10687
 
                                return 0;
10688
 
                        else
10689
 
                                return 1;
10690
 
                }
10691
 
#endif
10692
 
#ifdef HAVE_OPENR2
10693
 
                /* Trust MFC/R2 */
10694
 
                if (p->mfcr2) {
10695
 
                        if (p->mfcr2call)
10696
 
                                return 0;
10697
 
                        else
10698
 
                                return 1;
10699
 
                }
10700
 
#endif
10701
 
 
10702
 
                /* Trust hook state */
10703
 
                if (p->sig && !(p->radio || (p->oprmode < 0)))
10704
 
                {
10705
 
                        /* Check hook state */
10706
 
                        if (p->subs[SUB_REAL].dfd > -1) {
10707
 
                                memset(&par, 0, sizeof(par));
10708
 
                                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10709
 
                        } else {
10710
 
                                /* Assume not off hook on CVRS */
10711
 
                                res = 0;
10712
 
                                par.rxisoffhook = 0;
10713
 
                        }
10714
 
 
10715
 
                        if (res) {
10716
 
                                ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10717
 
                        }
10718
 
                        else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
10719
 
                                if (par.rxisoffhook) {
10720
 
                                        ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10721
 
                                        /* Not available when the other end is off hook */
10722
 
                                        return 0;
10723
 
                                }
10724
 
                        }
10725
 
#ifdef DAHDI_CHECK_HOOKSTATE
10726
 
                        } else { /* FXO channel case (SIG_FXS--) */
10727
 
                                /* Channel bank (using CAS), "onhook" does not necessarily means out of service, so return 1 */
10728
 
                                if (par.rxbits > -1)
10729
 
                                        return 1;
10730
 
                                /* TDM FXO card, "onhook" means out of service (no battery on the line) */
10731
 
                                if (par.rxisoffhook)
10732
 
                                        return 1;
10733
 
                                else
10734
 
                                        return 0;
10735
 
#endif
10736
 
                }
10737
 
 
10738
 
                return 1;
10739
 
        }
10740
 
 
10741
 
        /* If it's not an FXO, forget about call wait */
10742
 
        if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10743
 
                return 0;
10744
 
 
10745
 
        if (!p->callwaiting) {
10746
 
                /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
10747
 
                return 0;
10748
 
        }
10749
 
 
10750
 
        if (p->subs[SUB_CALLWAIT].dfd > -1) {
10751
 
                /* If there is already a call waiting call, then we can't take a second one */
10752
 
                return 0;
10753
 
        }
10754
 
 
10755
 
        if ((p->owner->_state != AST_STATE_UP) &&
10756
 
                ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10757
 
                /* If the current call is not up, then don't allow the call */
10758
 
                return 0;
10759
 
        }
10760
 
        if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10761
 
                /* Can't take a call wait when the three way calling hasn't been merged yet. */
10762
 
                return 0;
10763
 
        }
10764
 
        /* We're cool */
10765
 
        return 1;
10766
 
}
10767
 
 
10768
 
/* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
10769
 
   structures; it makes no attempt to safely copy regular channel private
10770
 
   structures that might contain reference-counted object pointers and other
10771
 
   scary bits
10772
 
*/
10773
 
static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10774
 
{
10775
 
        struct dahdi_pvt *p;
10776
 
        struct dahdi_bufferinfo bi;
10777
 
        int res;
10778
 
 
10779
 
        if ((p = ast_malloc(sizeof(*p)))) {
10780
 
                memcpy(p, src, sizeof(struct dahdi_pvt));
10781
 
                ast_mutex_init(&p->lock);
10782
 
                p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10783
 
                if (p->subs[SUB_REAL].dfd < 0) {
10784
 
                        ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10785
 
                        destroy_dahdi_pvt(&p);
10786
 
                        return NULL;
10787
 
                }
10788
 
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10789
 
                if (!res) {
10790
 
                        bi.txbufpolicy = src->buf_policy;
10791
 
                        bi.rxbufpolicy = src->buf_policy;
10792
 
                        bi.numbufs = src->buf_no;
10793
 
                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10794
 
                        if (res < 0) {
10795
 
                                ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10796
 
                        }
10797
 
                } else
10798
 
                        ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10799
 
        }
10800
 
        p->destroy = 1;
10801
 
        p->next = iflist;
10802
 
        p->prev = NULL;
10803
 
        iflist = p;
10804
 
        if (iflist->next)
10805
 
                iflist->next->prev = p;
10806
 
        return p;
10807
 
}
10808
 
 
10809
 
#if defined(HAVE_PRI)
10810
 
static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10811
 
{
10812
 
        int x;
10813
 
        if (backwards)
10814
 
                x = pri->numchans;
10815
 
        else
10816
 
                x = 0;
10817
 
        for (;;) {
10818
 
                if (backwards && (x < 0))
10819
 
                        break;
10820
 
                if (!backwards && (x >= pri->numchans))
10821
 
                        break;
10822
 
                if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10823
 
                        ast_debug(1, "Found empty available channel %d/%d\n",
10824
 
                                pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10825
 
                        return x;
10826
 
                }
10827
 
                if (backwards)
10828
 
                        x--;
10829
 
                else
10830
 
                        x++;
10831
 
        }
10832
 
        return -1;
10833
 
}
10834
 
#endif  /* defined(HAVE_PRI) */
10835
 
 
10836
 
static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10837
 
{
10838
 
        ast_group_t groupmatch = 0;
10839
 
        int channelmatch = -1;
10840
 
        int roundrobin = 0;
10841
 
        int callwait = 0;
10842
 
        int busy = 0;
10843
 
        struct dahdi_pvt *p;
10844
 
        struct ast_channel *tmp = NULL;
10845
 
        char *dest=NULL;
10846
 
        int x;
10847
 
        char *s;
10848
 
        char opt=0;
10849
 
        int res=0, y=0;
10850
 
        int backwards = 0;
10851
 
#ifdef HAVE_PRI
10852
 
        int crv;
10853
 
        int bearer = -1;
10854
 
        int trunkgroup;
10855
 
        struct dahdi_pri *pri=NULL;
10856
 
#endif
10857
 
        struct dahdi_pvt *exitpvt, *start, *end;
10858
 
        ast_mutex_t *lock;
10859
 
        int channelmatched = 0;
10860
 
        int groupmatched = 0;
10861
 
 
10862
 
        /*
10863
 
         * data is ---v
10864
 
         * Dial(DAHDI/pseudo[/extension])
10865
 
         * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
10866
 
         * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
10867
 
         * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
10868
 
         *
10869
 
         * g - channel group allocation search forward
10870
 
         * G - channel group allocation search backward
10871
 
         * r - channel group allocation round robin search forward
10872
 
         * R - channel group allocation round robin search backward
10873
 
         *
10874
 
         * c - Wait for DTMF digit to confirm answer
10875
 
         * r<cadance#> - Set distintive ring cadance number
10876
 
         * d - Force bearer capability for ISDN/SS7 call to digital.
10877
 
         */
10878
 
 
10879
 
        /* Assume we're locking the iflock */
10880
 
        lock = &iflock;
10881
 
        start = iflist;
10882
 
        end = ifend;
10883
 
        if (data) {
10884
 
                dest = ast_strdupa((char *)data);
10885
 
        } else {
10886
 
                ast_log(LOG_WARNING, "Channel requested with no data\n");
10887
 
                return NULL;
10888
 
        }
10889
 
        if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10890
 
                /* Retrieve the group number */
10891
 
                char *stringp;
10892
 
 
10893
 
                stringp = dest + 1;
10894
 
                s = strsep(&stringp, "/");
10895
 
                if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10896
 
                        ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10897
 
                        return NULL;
10898
 
                }
10899
 
                groupmatch = ((ast_group_t) 1 << x);
10900
 
                if (toupper(dest[0]) == 'G') {
10901
 
                        if (dest[0] == 'G') {
10902
 
                                backwards = 1;
10903
 
                                p = ifend;
10904
 
                        } else
10905
 
                                p = iflist;
10906
 
                } else {
10907
 
                        if (dest[0] == 'R') {
10908
 
                                backwards = 1;
10909
 
                                p = round_robin[x]?round_robin[x]->prev:ifend;
10910
 
                                if (!p)
10911
 
                                        p = ifend;
10912
 
                        } else {
10913
 
                                p = round_robin[x]?round_robin[x]->next:iflist;
10914
 
                                if (!p)
10915
 
                                        p = iflist;
10916
 
                        }
10917
 
                        roundrobin = 1;
10918
 
                }
10919
 
        } else {
10920
 
                char *stringp;
10921
 
 
10922
 
                stringp = dest;
10923
 
                s = strsep(&stringp, "/");
10924
 
                p = iflist;
10925
 
                if (!strcasecmp(s, "pseudo")) {
10926
 
                        /* Special case for pseudo */
10927
 
                        x = CHAN_PSEUDO;
10928
 
                        channelmatch = x;
10929
 
                }
10930
 
#ifdef HAVE_PRI
10931
 
                else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10932
 
                        if ((trunkgroup < 1) || (crv < 1)) {
10933
 
                                ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10934
 
                                return NULL;
10935
 
                        }
10936
 
                        res--;
10937
 
                        for (x = 0; x < NUM_SPANS; x++) {
10938
 
                                if (pris[x].trunkgroup == trunkgroup) {
10939
 
                                        pri = pris + x;
10940
 
                                        lock = &pri->lock;
10941
 
                                        start = pri->crvs;
10942
 
                                        end = pri->crvend;
10943
 
                                        break;
10944
 
                                }
10945
 
                        }
10946
 
                        if (!pri) {
10947
 
                                ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10948
 
                                return NULL;
10949
 
                        }
10950
 
                        channelmatch = crv;
10951
 
                        p = pris[x].crvs;
10952
 
                }
10953
 
#endif
10954
 
                else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10955
 
                        ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10956
 
                        return NULL;
10957
 
                } else {
10958
 
                        channelmatch = x;
10959
 
                }
10960
 
        }
10961
 
        /* Search for an unowned channel */
10962
 
        ast_mutex_lock(lock);
10963
 
        exitpvt = p;
10964
 
        while (p && !tmp) {
10965
 
                if (roundrobin)
10966
 
                        round_robin[x] = p;
10967
 
#if 0
10968
 
                ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
10969
 
#endif
10970
 
 
10971
 
                if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
10972
 
                        ast_debug(1, "Using channel %d\n", p->channel);
10973
 
                        if (p->inalarm)
10974
 
                                goto next;
10975
 
 
10976
 
                        callwait = (p->owner != NULL);
10977
 
#ifdef HAVE_PRI
10978
 
                        if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10979
 
                                if (p->sig != SIG_FXSKS) {
10980
 
                                        /* Gotta find an actual channel to use for this
10981
 
                                           CRV if this isn't a callwait */
10982
 
                                        bearer = pri_find_empty_chan(pri, 0);
10983
 
                                        if (bearer < 0) {
10984
 
                                                ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10985
 
                                                p = NULL;
10986
 
                                                break;
10987
 
                                        }
10988
 
                                        pri_assign_bearer(p, pri, pri->pvts[bearer]);
10989
 
                                } else {
10990
 
                                        if (alloc_sub(p, 0)) {
10991
 
                                                ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10992
 
                                                p = NULL;
10993
 
                                                break;
10994
 
                                        } else
10995
 
                                                ast_debug(1, "Allocated placeholder pseudo channel\n");
10996
 
 
10997
 
                                        p->pri = pri;
10998
 
                                }
10999
 
                        }
11000
 
#endif
11001
 
#ifdef HAVE_OPENR2
11002
 
                        if (p->mfcr2) {
11003
 
                                ast_mutex_lock(&p->lock);
11004
 
                                if (p->mfcr2call) {
11005
 
                                        ast_mutex_unlock(&p->lock);
11006
 
                                        ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11007
 
                                        goto next;
11008
 
                                }
11009
 
                                p->mfcr2call = 1;
11010
 
                                ast_mutex_unlock(&p->lock);
11011
 
                        }
11012
 
#endif
11013
 
                        if (p->channel == CHAN_PSEUDO) {
11014
 
                                p = duplicate_pseudo(p);
11015
 
                                if (!p) {
11016
 
                                        break;
11017
 
                                }
11018
 
                        }
11019
 
                        if (p->owner) {
11020
 
                                if (alloc_sub(p, SUB_CALLWAIT)) {
11021
 
                                        p = NULL;
11022
 
                                        break;
11023
 
                                }
11024
 
                        }
11025
 
                        p->outgoing = 1;
11026
 
                        tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11027
 
                        if (!tmp) {
11028
 
                                p->outgoing = 0;
11029
 
                        }
11030
 
#ifdef HAVE_PRI
11031
 
                        if (p->bearer) {
11032
 
                                /* Log owner to bearer channel, too */
11033
 
                                p->bearer->owner = tmp;
11034
 
                        }
11035
 
#endif
11036
 
                        /* Make special notes */
11037
 
                        if (res > 1) {
11038
 
                                if (opt == 'c') {
11039
 
                                        /* Confirm answer */
11040
 
                                        p->confirmanswer = 1;
11041
 
                                } else if (opt == 'r') {
11042
 
                                        /* Distinctive ring */
11043
 
                                        if (res < 3)
11044
 
                                                ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11045
 
                                        else
11046
 
                                                p->distinctivering = y;
11047
 
                                } else if (opt == 'd') {
11048
 
                                        /* If this is an ISDN call, make it digital */
11049
 
                                        p->digital = 1;
11050
 
                                        if (tmp)
11051
 
                                                tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11052
 
                                } else {
11053
 
                                        ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11054
 
                                }
11055
 
                        }
11056
 
                        /* Note if the call is a call waiting call */
11057
 
                        if (tmp && callwait)
11058
 
                                tmp->cdrflags |= AST_CDR_CALLWAIT;
11059
 
                        break;
11060
 
                }
11061
 
next:
11062
 
                if (backwards) {
11063
 
                        p = p->prev;
11064
 
                        if (!p)
11065
 
                                p = end;
11066
 
                } else {
11067
 
                        p = p->next;
11068
 
                        if (!p)
11069
 
                                p = start;
11070
 
                }
11071
 
                /* stop when you roll to the one that we started from */
11072
 
                if (p == exitpvt)
11073
 
                        break;
11074
 
        }
11075
 
        ast_mutex_unlock(lock);
11076
 
        restart_monitor();
11077
 
        if (callwait)
11078
 
                *cause = AST_CAUSE_BUSY;
11079
 
        else if (!tmp) {
11080
 
                if (channelmatched) {
11081
 
                        if (busy)
11082
 
                                *cause = AST_CAUSE_BUSY;
11083
 
                } else if (groupmatched) {
11084
 
                        *cause = AST_CAUSE_CONGESTION;
11085
 
                }
11086
 
        }
11087
 
 
11088
 
        return tmp;
11089
 
}
11090
 
 
11091
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
11092
 
static int dahdi_setlaw(int dfd, int law)
11093
 
{
11094
 
        return ioctl(dfd, DAHDI_SETLAW, &law);
11095
 
}
11096
 
#endif  /* defined(HAVE_PRI) || defined(HAVE_SS7) */
11097
 
 
11098
 
#if defined(HAVE_SS7)
11099
 
static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11100
 
{
11101
 
        int i;
11102
 
        int winner = -1;
11103
 
        for (i = 0; i < linkset->numchans; i++) {
11104
 
                if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11105
 
                        winner = i;
11106
 
                        break;
11107
 
                }
11108
 
        }
11109
 
        return winner;
11110
 
}
11111
 
#endif  /* defined(HAVE_SS7) */
11112
 
 
11113
 
#if defined(HAVE_SS7)
11114
 
static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11115
 
{
11116
 
        unsigned char status[32];
11117
 
        struct dahdi_pvt *p = NULL;
11118
 
        int i, offset;
11119
 
 
11120
 
        for (i = 0; i < linkset->numchans; i++) {
11121
 
                if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11122
 
                        p = linkset->pvts[i];
11123
 
                        offset = p->cic - startcic;
11124
 
                        status[offset] = 0;
11125
 
                        if (p->locallyblocked)
11126
 
                                status[offset] |= (1 << 0) | (1 << 4);
11127
 
                        if (p->remotelyblocked)
11128
 
                                status[offset] |= (1 << 1) | (1 << 5);
11129
 
                        if (p->ss7call) {
11130
 
                                if (p->outgoing)
11131
 
                                        status[offset] |= (1 << 3);
11132
 
                                else
11133
 
                                        status[offset] |= (1 << 2);
11134
 
                        } else
11135
 
                                status[offset] |= 0x3 << 2;
11136
 
                }
11137
 
        }
11138
 
 
11139
 
        if (p)
11140
 
                isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11141
 
        else
11142
 
                ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11143
 
 
11144
 
}
11145
 
#endif  /* defined(HAVE_SS7) */
11146
 
 
11147
 
#if defined(HAVE_SS7)
11148
 
static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11149
 
{
11150
 
        int i;
11151
 
 
11152
 
        for (i = 0; i < linkset->numchans; i++) {
11153
 
                if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11154
 
                        ast_mutex_lock(&linkset->pvts[i]->lock);
11155
 
                        if (linkset->pvts[i]->owner)
11156
 
                                linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11157
 
                        ast_mutex_unlock(&linkset->pvts[i]->lock);
11158
 
                }
11159
 
        }
11160
 
}
11161
 
#endif  /* defined(HAVE_SS7) */
11162
 
 
11163
 
#if defined(HAVE_SS7)
11164
 
static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11165
 
{
11166
 
        int i;
11167
 
 
11168
 
        for (i = 0; i < linkset->numchans; i++) {
11169
 
                if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11170
 
                        if (state) {
11171
 
                                if (state[i])
11172
 
                                        linkset->pvts[i]->remotelyblocked = block;
11173
 
                        } else
11174
 
                                linkset->pvts[i]->remotelyblocked = block;
11175
 
                }
11176
 
        }
11177
 
}
11178
 
#endif  /* defined(HAVE_SS7) */
11179
 
 
11180
 
#if defined(HAVE_SS7)
11181
 
static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11182
 
{
11183
 
        int i;
11184
 
 
11185
 
        for (i = 0; i < linkset->numchans; i++) {
11186
 
                if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11187
 
                        linkset->pvts[i]->inservice = 1;
11188
 
        }
11189
 
}
11190
 
#endif  /* defined(HAVE_SS7) */
11191
 
 
11192
 
#if defined(HAVE_SS7)
11193
 
static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11194
 
{
11195
 
        int i, startcic = -1, endcic, dpc;
11196
 
 
11197
 
        if (linkset->numchans <= 0)
11198
 
                return;
11199
 
 
11200
 
        startcic = linkset->pvts[0]->cic;
11201
 
        /* DB: CIC's DPC fix */
11202
 
        dpc = linkset->pvts[0]->dpc;
11203
 
 
11204
 
        for (i = 0; i < linkset->numchans; i++) {
11205
 
                if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
11206
 
                        continue;
11207
 
                } else {
11208
 
                        endcic = linkset->pvts[i]->cic;
11209
 
                        ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11210
 
                        isup_grs(linkset->ss7, startcic, endcic, dpc);
11211
 
 
11212
 
                        /* DB: CIC's DPC fix */
11213
 
                        if (linkset->pvts[i+1]) {
11214
 
                                startcic = linkset->pvts[i+1]->cic;
11215
 
                                dpc = linkset->pvts[i+1]->dpc;
11216
 
                        }
11217
 
                }
11218
 
        }
11219
 
}
11220
 
#endif  /* defined(HAVE_SS7) */
11221
 
 
11222
 
#if defined(HAVE_SS7)
11223
 
static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11224
 
{
11225
 
        if (p->loopedback != enable) {
11226
 
                if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11227
 
                        ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11228
 
                        return;
11229
 
                }
11230
 
                p->loopedback = enable;
11231
 
        }
11232
 
}
11233
 
#endif  /* defined(HAVE_SS7) */
11234
 
 
11235
 
#if defined(HAVE_SS7)
11236
 
/* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
11237
 
static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11238
 
{
11239
 
        struct ss7 *ss7 = linkset->ss7;
11240
 
        int res;
11241
 
        int law = 1;
11242
 
        struct ast_channel *c;
11243
 
        char tmp[256];
11244
 
 
11245
 
        if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11246
 
                ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11247
 
 
11248
 
        if (linkset->type == SS7_ITU)
11249
 
                law = DAHDI_LAW_ALAW;
11250
 
        else
11251
 
                law = DAHDI_LAW_MULAW;
11252
 
 
11253
 
        res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11254
 
        if (res < 0)
11255
 
                ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11256
 
 
11257
 
        if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11258
 
                p->proceeding = 1;
11259
 
                isup_acm(ss7, p->ss7call);
11260
 
        }
11261
 
 
11262
 
        ast_mutex_unlock(&linkset->lock);
11263
 
        c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11264
 
 
11265
 
        if (!c) {
11266
 
                ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11267
 
                /* Holding this lock is assumed entering the function */
11268
 
                ast_mutex_lock(&linkset->lock);
11269
 
                return;
11270
 
        } else
11271
 
                ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11272
 
 
11273
 
        dahdi_enable_ec(p);
11274
 
 
11275
 
        /* We only reference these variables in the context of the ss7_linkset function
11276
 
         * when receiving either and IAM or a COT message.  Since they are only accessed
11277
 
         * from this context, we should be safe to unlock around them */
11278
 
 
11279
 
        ast_mutex_unlock(&p->lock);
11280
 
 
11281
 
        if (!ast_strlen_zero(p->charge_number)) {
11282
 
                pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11283
 
                /* Clear this after we set it */
11284
 
                p->charge_number[0] = 0;
11285
 
        }
11286
 
        if (!ast_strlen_zero(p->gen_add_number)) {
11287
 
                pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11288
 
                /* Clear this after we set it */
11289
 
                p->gen_add_number[0] = 0;
11290
 
        }
11291
 
        if (!ast_strlen_zero(p->jip_number)) {
11292
 
                pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11293
 
                /* Clear this after we set it */
11294
 
                p->jip_number[0] = 0;
11295
 
        }
11296
 
        if (!ast_strlen_zero(p->gen_dig_number)) {
11297
 
                pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11298
 
                /* Clear this after we set it */
11299
 
                p->gen_dig_number[0] = 0;
11300
 
        }
11301
 
        if (!ast_strlen_zero(p->orig_called_num)) {
11302
 
                pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11303
 
                /* Clear this after we set it */
11304
 
                p->orig_called_num[0] = 0;
11305
 
        }
11306
 
 
11307
 
        snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11308
 
        pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11309
 
        /* Clear this after we set it */
11310
 
        p->gen_dig_type = 0;
11311
 
 
11312
 
        snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11313
 
        pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11314
 
        /* Clear this after we set it */
11315
 
        p->gen_dig_scheme = 0;
11316
 
 
11317
 
        if (!ast_strlen_zero(p->lspi_ident)) {
11318
 
                pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11319
 
                /* Clear this after we set it */
11320
 
                p->lspi_ident[0] = 0;
11321
 
        }
11322
 
 
11323
 
        snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11324
 
        pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11325
 
        /* Clear this after we set it */
11326
 
        p->call_ref_ident = 0;
11327
 
 
11328
 
        snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11329
 
        pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11330
 
        /* Clear this after we set it */
11331
 
        p->call_ref_pc = 0;
11332
 
 
11333
 
        snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11334
 
        pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11335
 
        /* Clear this after we set it */
11336
 
        p->calling_party_cat = 0;
11337
 
 
11338
 
        if (!ast_strlen_zero(p->redirecting_num)) {
11339
 
                pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11340
 
                /* Clear this after we set it */
11341
 
                p->redirecting_num[0] = 0;
11342
 
        }
11343
 
        if (!ast_strlen_zero(p->generic_name)) {
11344
 
                pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11345
 
                /* Clear this after we set it */
11346
 
                p->generic_name[0] = 0;
11347
 
        }
11348
 
 
11349
 
        ast_mutex_lock(&p->lock);
11350
 
        ast_mutex_lock(&linkset->lock);
11351
 
}
11352
 
#endif  /* defined(HAVE_SS7) */
11353
 
 
11354
 
#if defined(HAVE_SS7)
11355
 
static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11356
 
{
11357
 
        if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
11358
 
                if (size) {
11359
 
                        *buf = '\0';
11360
 
                }
11361
 
                return;
11362
 
        }
11363
 
        switch (nai) {
11364
 
        case SS7_NAI_INTERNATIONAL:
11365
 
                snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11366
 
                break;
11367
 
        case SS7_NAI_NATIONAL:
11368
 
                snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11369
 
                break;
11370
 
        case SS7_NAI_SUBSCRIBER:
11371
 
                snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11372
 
                break;
11373
 
        case SS7_NAI_UNKNOWN:
11374
 
                snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11375
 
                break;
11376
 
        default:
11377
 
                snprintf(buf, size, "%s", number);
11378
 
                break;
11379
 
        }
11380
 
}
11381
 
#endif  /* defined(HAVE_SS7) */
11382
 
 
11383
 
#if defined(HAVE_SS7)
11384
 
static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11385
 
{
11386
 
        return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11387
 
}
11388
 
#endif  /* defined(HAVE_SS7) */
11389
 
 
11390
 
#if defined(HAVE_SS7)
11391
 
static void *ss7_linkset(void *data)
11392
 
{
11393
 
        int res, i;
11394
 
        struct timeval *next = NULL, tv;
11395
 
        struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11396
 
        struct ss7 *ss7 = linkset->ss7;
11397
 
        ss7_event *e = NULL;
11398
 
        struct dahdi_pvt *p;
11399
 
        int chanpos;
11400
 
        struct pollfd pollers[NUM_DCHANS];
11401
 
        int cic;
11402
 
        unsigned int dpc;
11403
 
        int nextms = 0;
11404
 
 
11405
 
        ss7_start(ss7);
11406
 
 
11407
 
        while(1) {
11408
 
                ast_mutex_lock(&linkset->lock);
11409
 
                if ((next = ss7_schedule_next(ss7))) {
11410
 
                        tv = ast_tvnow();
11411
 
                        tv.tv_sec = next->tv_sec - tv.tv_sec;
11412
 
                        tv.tv_usec = next->tv_usec - tv.tv_usec;
11413
 
                        if (tv.tv_usec < 0) {
11414
 
                                tv.tv_usec += 1000000;
11415
 
                                tv.tv_sec -= 1;
11416
 
                        }
11417
 
                        if (tv.tv_sec < 0) {
11418
 
                                tv.tv_sec = 0;
11419
 
                                tv.tv_usec = 0;
11420
 
                        }
11421
 
                        nextms = tv.tv_sec * 1000;
11422
 
                        nextms += tv.tv_usec / 1000;
11423
 
                }
11424
 
                ast_mutex_unlock(&linkset->lock);
11425
 
 
11426
 
                for (i = 0; i < linkset->numsigchans; i++) {
11427
 
                        pollers[i].fd = linkset->fds[i];
11428
 
                        pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11429
 
                        pollers[i].revents = 0;
11430
 
                }
11431
 
 
11432
 
                res = poll(pollers, linkset->numsigchans, nextms);
11433
 
                if ((res < 0) && (errno != EINTR)) {
11434
 
                        ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11435
 
                } else if (!res) {
11436
 
                        ast_mutex_lock(&linkset->lock);
11437
 
                        ss7_schedule_run(ss7);
11438
 
                        ast_mutex_unlock(&linkset->lock);
11439
 
                        continue;
11440
 
                }
11441
 
 
11442
 
                ast_mutex_lock(&linkset->lock);
11443
 
                for (i = 0; i < linkset->numsigchans; i++) {
11444
 
                        if (pollers[i].revents & POLLPRI) {
11445
 
                                int x;
11446
 
                                if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11447
 
                                        ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11448
 
                                }
11449
 
                                switch (x) {
11450
 
                                case DAHDI_EVENT_OVERRUN:
11451
 
                                        ast_debug(1, "Overrun detected!\n");
11452
 
                                        break;
11453
 
                                case DAHDI_EVENT_BADFCS:
11454
 
                                        ast_debug(1, "Bad FCS\n");
11455
 
                                        break;
11456
 
                                case DAHDI_EVENT_ABORT:
11457
 
                                        ast_debug(1, "HDLC Abort\n");
11458
 
                                        break;
11459
 
                                case DAHDI_EVENT_ALARM:
11460
 
                                        ast_log(LOG_ERROR, "Alarm on link!\n");
11461
 
                                        linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11462
 
                                        linkset->linkstate[i] &= ~LINKSTATE_UP;
11463
 
                                        ss7_link_alarm(ss7, pollers[i].fd);
11464
 
                                        break;
11465
 
                                case DAHDI_EVENT_NOALARM:
11466
 
                                        ast_log(LOG_ERROR, "Alarm cleared on link\n");
11467
 
                                        linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11468
 
                                        linkset->linkstate[i] |= LINKSTATE_STARTING;
11469
 
                                        ss7_link_noalarm(ss7, pollers[i].fd);
11470
 
                                        break;
11471
 
                                default:
11472
 
                                        ast_log(LOG_ERROR, "Got exception %d!\n", x);
11473
 
                                        break;
11474
 
                                }
11475
 
                        }
11476
 
 
11477
 
                        if (pollers[i].revents & POLLIN) {
11478
 
                                res = ss7_read(ss7, pollers[i].fd);
11479
 
                        }
11480
 
 
11481
 
                        if (pollers[i].revents & POLLOUT) {
11482
 
                                res = ss7_write(ss7, pollers[i].fd);
11483
 
                                if (res < 0) {
11484
 
                                        ast_debug(1, "Error in write %s\n", strerror(errno));
11485
 
                                }
11486
 
                        }
11487
 
                }
11488
 
 
11489
 
                while ((e = ss7_check_event(ss7))) {
11490
 
                        switch (e->e) {
11491
 
                        case SS7_EVENT_UP:
11492
 
                                if (linkset->state != LINKSET_STATE_UP) {
11493
 
                                        ast_verbose("--- SS7 Up ---\n");
11494
 
                                        ss7_reset_linkset(linkset);
11495
 
                                }
11496
 
                                linkset->state = LINKSET_STATE_UP;
11497
 
                                break;
11498
 
                        case SS7_EVENT_DOWN:
11499
 
                                ast_verbose("--- SS7 Down ---\n");
11500
 
                                linkset->state = LINKSET_STATE_DOWN;
11501
 
                                for (i = 0; i < linkset->numchans; i++) {
11502
 
                                        struct dahdi_pvt *p = linkset->pvts[i];
11503
 
                                        if (p)
11504
 
                                                p->inalarm = 1;
11505
 
                                }
11506
 
                                break;
11507
 
                        case MTP2_LINK_UP:
11508
 
                                ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11509
 
                                break;
11510
 
                        case MTP2_LINK_DOWN:
11511
 
                                ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11512
 
                                break;
11513
 
                        case ISUP_EVENT_CPG:
11514
 
                                chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11515
 
                                if (chanpos < 0) {
11516
 
                                        ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11517
 
                                        break;
11518
 
                                }
11519
 
                                p = linkset->pvts[chanpos];
11520
 
                                ast_mutex_lock(&p->lock);
11521
 
                                switch (e->cpg.event) {
11522
 
                                case CPG_EVENT_ALERTING:
11523
 
                                        p->alerting = 1;
11524
 
                                        p->subs[SUB_REAL].needringing = 1;
11525
 
                                        break;
11526
 
                                case CPG_EVENT_PROGRESS:
11527
 
                                case CPG_EVENT_INBANDINFO:
11528
 
                                        {
11529
 
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11530
 
                                                ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11531
 
                                                dahdi_queue_frame(p, &f, linkset);
11532
 
                                                p->progress = 1;
11533
 
                                                p->dialing = 0;
11534
 
                                                if (p->dsp && p->dsp_features) {
11535
 
                                                        ast_dsp_set_features(p->dsp, p->dsp_features);
11536
 
                                                        p->dsp_features = 0;
11537
 
                                                }
11538
 
                                        }
11539
 
                                        break;
11540
 
                                default:
11541
 
                                        ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11542
 
                                }
11543
 
 
11544
 
                                ast_mutex_unlock(&p->lock);
11545
 
                                break;
11546
 
                        case ISUP_EVENT_RSC:
11547
 
                                ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11548
 
                                chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11549
 
                                if (chanpos < 0) {
11550
 
                                        ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11551
 
                                        break;
11552
 
                                }
11553
 
                                p = linkset->pvts[chanpos];
11554
 
                                ast_mutex_lock(&p->lock);
11555
 
                                p->inservice = 1;
11556
 
                                p->remotelyblocked = 0;
11557
 
                                dpc = p->dpc;
11558
 
                                isup_set_call_dpc(e->rsc.call, dpc);
11559
 
                                if (p->ss7call)
11560
 
                                        p->ss7call = NULL;
11561
 
                                if (p->owner)
11562
 
                                        p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11563
 
                                ast_mutex_unlock(&p->lock);
11564
 
                                isup_rlc(ss7, e->rsc.call);
11565
 
                                break;
11566
 
                        case ISUP_EVENT_GRS:
11567
 
                                ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11568
 
                                chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11569
 
                                if (chanpos < 0) {
11570
 
                                        ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11571
 
                                        break;
11572
 
                                }
11573
 
                                p = linkset->pvts[chanpos];
11574
 
                                isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11575
 
                                ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11576
 
                                ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11577
 
                                break;
11578
 
                        case ISUP_EVENT_CQM:
11579
 
                                ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11580
 
                                ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11581
 
                                break;
11582
 
                        case ISUP_EVENT_GRA:
11583
 
                                ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11584
 
                                ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11585
 
                                ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11586
 
                                break;
11587
 
                        case ISUP_EVENT_IAM:
11588
 
                                ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
11589
 
                                chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11590
 
                                if (chanpos < 0) {
11591
 
                                        ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11592
 
                                        isup_rel(ss7, e->iam.call, -1);
11593
 
                                        break;
11594
 
                                }
11595
 
                                p = linkset->pvts[chanpos];
11596
 
                                ast_mutex_lock(&p->lock);
11597
 
                                if (p->owner) {
11598
 
                                        if (p->ss7call == e->iam.call) {
11599
 
                                                ast_mutex_unlock(&p->lock);
11600
 
                                                ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11601
 
                                                break;
11602
 
                                        } else {
11603
 
                                                ast_mutex_unlock(&p->lock);
11604
 
                                                ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11605
 
                                                break;
11606
 
                                        }
11607
 
                                }
11608
 
 
11609
 
                                dpc = p->dpc;
11610
 
                                p->ss7call = e->iam.call;
11611
 
                                isup_set_call_dpc(p->ss7call, dpc);
11612
 
 
11613
 
                                if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11614
 
                                        ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11615
 
                                        p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11616
 
                                } else
11617
 
                                        p->cid_num[0] = 0;
11618
 
 
11619
 
                                if (p->immediate) {
11620
 
                                        p->exten[0] = 's';
11621
 
                                        p->exten[1] = '\0';
11622
 
                                } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11623
 
                                        char *st;
11624
 
                                        ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11625
 
                                        st = strchr(p->exten, '#');
11626
 
                                        if (st)
11627
 
                                                *st = '\0';
11628
 
                                        } else
11629
 
                                                p->exten[0] = '\0';
11630
 
 
11631
 
                                p->cid_ani[0] = '\0';
11632
 
                                if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11633
 
                                        ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11634
 
                                else
11635
 
                                        p->cid_name[0] = '\0';
11636
 
 
11637
 
                                p->cid_ani2 = e->iam.oli_ani2;
11638
 
                                p->cid_ton = 0;
11639
 
                                ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11640
 
                                ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11641
 
                                p->gen_add_type = e->iam.gen_add_type;
11642
 
                                p->gen_add_nai = e->iam.gen_add_nai;
11643
 
                                p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11644
 
                                p->gen_add_num_plan = e->iam.gen_add_num_plan;
11645
 
                                ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11646
 
                                p->gen_dig_type = e->iam.gen_dig_type;
11647
 
                                p->gen_dig_scheme = e->iam.gen_dig_scheme;
11648
 
                                ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11649
 
                                ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11650
 
                                ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11651
 
                                ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11652
 
                                p->calling_party_cat = e->iam.calling_party_cat;
11653
 
 
11654
 
                                /* Set DNID */
11655
 
                                if (!ast_strlen_zero(e->iam.called_party_num))
11656
 
                                        ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11657
 
 
11658
 
                                if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11659
 
 
11660
 
                                        if (e->iam.cot_check_required) {
11661
 
                                                dahdi_loopback(p, 1);
11662
 
                                        } else
11663
 
                                                ss7_start_call(p, linkset);
11664
 
                                } else {
11665
 
                                        ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11666
 
                                        p->alreadyhungup = 1;
11667
 
                                        isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11668
 
                                }
11669
 
                                ast_mutex_unlock(&p->lock);
11670
 
                                break;
11671
 
                        case ISUP_EVENT_COT:
11672
 
                                chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11673
 
                                if (chanpos < 0) {
11674
 
                                        ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11675
 
                                        isup_rel(ss7, e->cot.call, -1);
11676
 
                                        break;
11677
 
                                }
11678
 
                                p = linkset->pvts[chanpos];
11679
 
 
11680
 
                                ast_mutex_lock(&p->lock);
11681
 
 
11682
 
                                if (p->loopedback) {
11683
 
                                        dahdi_loopback(p, 0);
11684
 
                                        ss7_start_call(p, linkset);
11685
 
                                }
11686
 
 
11687
 
                                ast_mutex_unlock(&p->lock);
11688
 
 
11689
 
                                break;
11690
 
                        case ISUP_EVENT_CCR:
11691
 
                                ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11692
 
                                chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11693
 
                                if (chanpos < 0) {
11694
 
                                        ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11695
 
                                        break;
11696
 
                                }
11697
 
 
11698
 
                                p = linkset->pvts[chanpos];
11699
 
 
11700
 
                                ast_mutex_lock(&p->lock);
11701
 
                                dahdi_loopback(p, 1);
11702
 
                                ast_mutex_unlock(&p->lock);
11703
 
 
11704
 
                                isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11705
 
                                break;
11706
 
                        case ISUP_EVENT_CVT:
11707
 
                                ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11708
 
                                chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11709
 
                                if (chanpos < 0) {
11710
 
                                        ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11711
 
                                        break;
11712
 
                                }
11713
 
 
11714
 
                                p = linkset->pvts[chanpos];
11715
 
 
11716
 
                                ast_mutex_lock(&p->lock);
11717
 
                                dahdi_loopback(p, 1);
11718
 
                                ast_mutex_unlock(&p->lock);
11719
 
 
11720
 
                                isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11721
 
                                break;
11722
 
                        case ISUP_EVENT_REL:
11723
 
                                chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11724
 
                                if (chanpos < 0) {
11725
 
                                        ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11726
 
                                        break;
11727
 
                                }
11728
 
                                p = linkset->pvts[chanpos];
11729
 
                                ast_mutex_lock(&p->lock);
11730
 
                                if (p->owner) {
11731
 
                                        p->owner->hangupcause = e->rel.cause;
11732
 
                                        p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11733
 
                                } else if (!p->restartpending)
11734
 
                                        ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11735
 
 
11736
 
                                /* End the loopback if we have one */
11737
 
                                dahdi_loopback(p, 0);
11738
 
 
11739
 
                                isup_rlc(ss7, e->rel.call);
11740
 
                                p->ss7call = NULL;
11741
 
 
11742
 
                                ast_mutex_unlock(&p->lock);
11743
 
                                break;
11744
 
                        case ISUP_EVENT_ACM:
11745
 
                                chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11746
 
                                if (chanpos < 0) {
11747
 
                                        ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11748
 
                                        isup_rel(ss7, e->acm.call, -1);
11749
 
                                        break;
11750
 
                                } else {
11751
 
                                        struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11752
 
 
11753
 
                                        p = linkset->pvts[chanpos];
11754
 
 
11755
 
                                        ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11756
 
 
11757
 
                                        if (e->acm.call_ref_ident > 0) {
11758
 
                                                p->rlt = 1; /* Setting it but not using it here*/
11759
 
                                        }
11760
 
 
11761
 
                                        ast_mutex_lock(&p->lock);
11762
 
                                        dahdi_queue_frame(p, &f, linkset);
11763
 
                                        p->proceeding = 1;
11764
 
                                        p->dialing = 0;
11765
 
                                        /* Send alerting if subscriber is free */
11766
 
                                        if (e->acm.called_party_status_ind == 1) {
11767
 
                                                p->alerting = 1;
11768
 
                                                p->subs[SUB_REAL].needringing = 1;
11769
 
                                        }
11770
 
                                        ast_mutex_unlock(&p->lock);
11771
 
                                }
11772
 
                                break;
11773
 
                        case ISUP_EVENT_CGB:
11774
 
                                chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11775
 
                                if (chanpos < 0) {
11776
 
                                        ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11777
 
                                        break;
11778
 
                                }
11779
 
                                p = linkset->pvts[chanpos];
11780
 
                                ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11781
 
                                isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11782
 
                                break;
11783
 
                        case ISUP_EVENT_CGU:
11784
 
                                chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11785
 
                                if (chanpos < 0) {
11786
 
                                        ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11787
 
                                        break;
11788
 
                                }
11789
 
                                p = linkset->pvts[chanpos];
11790
 
                                ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11791
 
                                isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11792
 
                                break;
11793
 
                        case ISUP_EVENT_UCIC:
11794
 
                                chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11795
 
                                if (chanpos < 0) {
11796
 
                                        ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11797
 
                                        break;
11798
 
                                }
11799
 
                                p = linkset->pvts[chanpos];
11800
 
                                ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11801
 
                                ast_mutex_lock(&p->lock);
11802
 
                                p->remotelyblocked = 1;
11803
 
                                p->inservice = 0;
11804
 
                                ast_mutex_unlock(&p->lock);                     //doesn't require a SS7 acknowledgement
11805
 
                                break;
11806
 
                        case ISUP_EVENT_BLO:
11807
 
                                chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11808
 
                                if (chanpos < 0) {
11809
 
                                        ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11810
 
                                        break;
11811
 
                                }
11812
 
                                p = linkset->pvts[chanpos];
11813
 
                                ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11814
 
                                ast_mutex_lock(&p->lock);
11815
 
                                p->remotelyblocked = 1;
11816
 
                                ast_mutex_unlock(&p->lock);
11817
 
                                isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11818
 
                                break;
11819
 
                        case ISUP_EVENT_BLA:
11820
 
                                chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11821
 
                                if (chanpos < 0) {
11822
 
                                        ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11823
 
                                        break;
11824
 
                                }
11825
 
                                ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11826
 
                                p = linkset->pvts[chanpos];
11827
 
                                ast_mutex_lock(&p->lock);
11828
 
                                p->locallyblocked = 1;
11829
 
                                ast_mutex_unlock(&p->lock);
11830
 
                                break;
11831
 
                        case ISUP_EVENT_UBL:
11832
 
                                chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11833
 
                                if (chanpos < 0) {
11834
 
                                        ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11835
 
                                        break;
11836
 
                                }
11837
 
                                p = linkset->pvts[chanpos];
11838
 
                                ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11839
 
                                ast_mutex_lock(&p->lock);
11840
 
                                p->remotelyblocked = 0;
11841
 
                                ast_mutex_unlock(&p->lock);
11842
 
                                isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11843
 
                                break;
11844
 
                        case ISUP_EVENT_UBA:
11845
 
                                chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11846
 
                                if (chanpos < 0) {
11847
 
                                        ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11848
 
                                        break;
11849
 
                                }
11850
 
                                p = linkset->pvts[chanpos];
11851
 
                                ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11852
 
                                ast_mutex_lock(&p->lock);
11853
 
                                p->locallyblocked = 0;
11854
 
                                ast_mutex_unlock(&p->lock);
11855
 
                                break;
11856
 
                        case ISUP_EVENT_CON:
11857
 
                        case ISUP_EVENT_ANM:
11858
 
                                if (e->e == ISUP_EVENT_CON)
11859
 
                                        cic = e->con.cic;
11860
 
                                else
11861
 
                                        cic = e->anm.cic;
11862
 
 
11863
 
                                chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11864
 
                                if (chanpos < 0) {
11865
 
                                        ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11866
 
                                        isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11867
 
                                        break;
11868
 
                                } else {
11869
 
                                        p = linkset->pvts[chanpos];
11870
 
                                        ast_mutex_lock(&p->lock);
11871
 
                                        p->subs[SUB_REAL].needanswer = 1;
11872
 
                                        if (p->dsp && p->dsp_features) {
11873
 
                                                ast_dsp_set_features(p->dsp, p->dsp_features);
11874
 
                                                p->dsp_features = 0;
11875
 
                                        }
11876
 
                                        dahdi_enable_ec(p);
11877
 
                                        ast_mutex_unlock(&p->lock);
11878
 
                                }
11879
 
                                break;
11880
 
                        case ISUP_EVENT_RLC:
11881
 
                                chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
11882
 
                                if (chanpos < 0) {
11883
 
                                        ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
11884
 
                                        break;
11885
 
                                } else {
11886
 
                                        p = linkset->pvts[chanpos];
11887
 
                                        ast_mutex_lock(&p->lock);
11888
 
                                        if (p->alreadyhungup)
11889
 
                                                p->ss7call = NULL;
11890
 
                                        else
11891
 
                                                ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
11892
 
                                        ast_mutex_unlock(&p->lock);
11893
 
                                        }
11894
 
                                        break;
11895
 
                        case ISUP_EVENT_FAA:
11896
 
                                chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
11897
 
                                if (chanpos < 0) {
11898
 
                                        ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
11899
 
                                        break;
11900
 
                                } else {
11901
 
                                        p = linkset->pvts[chanpos];
11902
 
                                        ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
11903
 
                                        ast_mutex_lock(&p->lock);
11904
 
                                        if (p->alreadyhungup){
11905
 
                                                p->ss7call = NULL;
11906
 
                                                ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
11907
 
                                        }
11908
 
                                        ast_mutex_unlock(&p->lock);
11909
 
                                }
11910
 
                                break;
11911
 
                        default:
11912
 
                                ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
11913
 
                                break;
11914
 
                        }
11915
 
                }
11916
 
                ast_mutex_unlock(&linkset->lock);
11917
 
        }
11918
 
 
11919
 
        return 0;
11920
 
}
11921
 
#endif  /* defined(HAVE_SS7) */
11922
 
 
11923
 
#if defined(HAVE_SS7)
11924
 
static void dahdi_ss7_message(struct ss7 *ss7, char *s)
11925
 
{
11926
 
#if 0
11927
 
        int i;
11928
 
 
11929
 
        for (i = 0; i < NUM_SPANS; i++)
11930
 
                if (linksets[i].ss7 == ss7)
11931
 
                        break;
11932
 
 
11933
 
        ast_verbose("[%d] %s", i+1, s);
11934
 
#else
11935
 
        ast_verbose("%s", s);
11936
 
#endif
11937
 
}
11938
 
#endif  /* defined(HAVE_SS7) */
11939
 
 
11940
 
#if defined(HAVE_SS7)
11941
 
static void dahdi_ss7_error(struct ss7 *ss7, char *s)
11942
 
{
11943
 
#if 0
11944
 
        int i;
11945
 
 
11946
 
        for (i = 0; i < NUM_SPANS; i++)
11947
 
                if (linksets[i].ss7 == ss7)
11948
 
                        break;
11949
 
 
11950
 
#else
11951
 
        ast_log(LOG_ERROR, "%s", s);
11952
 
#endif
11953
 
}
11954
 
#endif  /* defined(HAVE_SS7) */
11955
 
 
11956
 
#if defined(HAVE_OPENR2)
11957
 
static void *mfcr2_monitor(void *data)
11958
 
{
11959
 
        struct dahdi_mfcr2 *mfcr2 = data;
11960
 
        /* we should be using pthread_key_create
11961
 
           and allocate pollers dynamically.
11962
 
           I think do_monitor() could be leaking, since it
11963
 
           could be cancelled at any time and is not
11964
 
           using thread keys, why?, */
11965
 
        struct pollfd pollers[sizeof(mfcr2->pvts)];
11966
 
        int res = 0;
11967
 
        int i = 0;
11968
 
        int oldstate = 0;
11969
 
        int quit_loop = 0;
11970
 
        int maxsleep = 20;
11971
 
        int was_idle = 0;
11972
 
        int pollsize = 0;
11973
 
        /* now that we're ready to get calls, unblock our side and
11974
 
           get current line state */
11975
 
        for (i = 0; i < mfcr2->numchans; i++) {
11976
 
                openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
11977
 
                openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
11978
 
        }
11979
 
        while (1) {
11980
 
                /* we trust here that the mfcr2 channel list will not ever change once
11981
 
                   the module is loaded */
11982
 
                pollsize = 0;
11983
 
                for (i = 0; i < mfcr2->numchans; i++) {
11984
 
                        pollers[i].revents = 0;
11985
 
                        pollers[i].events = 0;
11986
 
                        if (mfcr2->pvts[i]->owner) {
11987
 
                                continue;
11988
 
                        }
11989
 
                        if (!mfcr2->pvts[i]->r2chan) {
11990
 
                                ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
11991
 
                                quit_loop = 1;
11992
 
                                break;
11993
 
                        }
11994
 
                        openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
11995
 
                        pollers[i].events = POLLIN | POLLPRI;
11996
 
                        pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
11997
 
                        pollsize++;
11998
 
                }
11999
 
                if (quit_loop) {
12000
 
                        break;
12001
 
                }
12002
 
                if (pollsize == 0) {
12003
 
                        if (!was_idle) {
12004
 
                                ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12005
 
                                was_idle = 1;
12006
 
                        }
12007
 
                        poll(NULL, 0, maxsleep);
12008
 
                        continue;
12009
 
                }
12010
 
                was_idle = 0;
12011
 
                /* probably poll() is a valid cancel point, lets just be on the safe side
12012
 
                   by calling pthread_testcancel */
12013
 
                pthread_testcancel();
12014
 
                res = poll(pollers, mfcr2->numchans, maxsleep);
12015
 
                pthread_testcancel();
12016
 
                if ((res < 0) && (errno != EINTR)) {
12017
 
                        ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12018
 
                        break;
12019
 
                }
12020
 
                /* do we want to allow to cancel while processing events? */
12021
 
                pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12022
 
                for (i = 0; i < mfcr2->numchans; i++) {
12023
 
                        if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12024
 
                                openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12025
 
                        }
12026
 
                }
12027
 
                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12028
 
        }
12029
 
        ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12030
 
        return 0;
12031
 
}
12032
 
#endif /* HAVE_OPENR2 */
12033
 
 
12034
 
#if defined(HAVE_PRI)
12035
 
static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12036
 
{
12037
 
        struct dahdi_pvt *p;
12038
 
        p = pri->crvs;
12039
 
        while (p) {
12040
 
                if (p->channel == crv)
12041
 
                        return p;
12042
 
                p = p->next;
12043
 
        }
12044
 
        return NULL;
12045
 
}
12046
 
#endif  /* defined(HAVE_PRI) */
12047
 
 
12048
 
#if defined(HAVE_PRI)
12049
 
static int pri_find_principle(struct dahdi_pri *pri, int channel)
12050
 
{
12051
 
        int x;
12052
 
        int span = PRI_SPAN(channel);
12053
 
        int spanfd;
12054
 
        struct dahdi_params param;
12055
 
        int principle = -1;
12056
 
        int explicit = PRI_EXPLICIT(channel);
12057
 
        channel = PRI_CHANNEL(channel);
12058
 
 
12059
 
        if (!explicit) {
12060
 
                spanfd = pri_active_dchan_fd(pri);
12061
 
                memset(&param, 0, sizeof(param));
12062
 
                if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12063
 
                        return -1;
12064
 
                span = pris[param.spanno - 1].prilogicalspan;
12065
 
        }
12066
 
 
12067
 
        for (x = 0; x < pri->numchans; x++) {
12068
 
                if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12069
 
                        principle = x;
12070
 
                        break;
12071
 
                }
12072
 
        }
12073
 
 
12074
 
        return principle;
12075
 
}
12076
 
#endif  /* defined(HAVE_PRI) */
12077
 
 
12078
 
#if defined(HAVE_PRI)
12079
 
static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12080
 
{
12081
 
        int x;
12082
 
        struct dahdi_pvt *crv;
12083
 
        if (!c) {
12084
 
                if (principle < 0)
12085
 
                        return -1;
12086
 
                return principle;
12087
 
        }
12088
 
        if ((principle > -1) &&
12089
 
                (principle < pri->numchans) &&
12090
 
                (pri->pvts[principle]) &&
12091
 
                (pri->pvts[principle]->call == c))
12092
 
                return principle;
12093
 
        /* First, check for other bearers */
12094
 
        for (x = 0; x < pri->numchans; x++) {
12095
 
                if (!pri->pvts[x])
12096
 
                        continue;
12097
 
                if (pri->pvts[x]->call == c) {
12098
 
                        /* Found our call */
12099
 
                        if (principle != x) {
12100
 
                                struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12101
 
 
12102
 
                                ast_verb(3, "Moving call from channel %d to channel %d\n",
12103
 
                                         old->channel, new->channel);
12104
 
                                if (new->owner) {
12105
 
                                        ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12106
 
                                                old->channel, new->channel, new->channel);
12107
 
                                        return -1;
12108
 
                                }
12109
 
                                /* Fix it all up now */
12110
 
                                new->owner = old->owner;
12111
 
                                old->owner = NULL;
12112
 
                                if (new->owner) {
12113
 
                                        ast_string_field_build(new->owner, name,
12114
 
                                                "DAHDI/%d:%d-%d", pri->trunkgroup,
12115
 
                                                new->channel, 1);
12116
 
                                        new->owner->tech_pvt = new;
12117
 
                                        ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12118
 
                                        new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12119
 
                                        old->subs[SUB_REAL].owner = NULL;
12120
 
                                } else
12121
 
                                        ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
12122
 
                                new->call = old->call;
12123
 
                                old->call = NULL;
12124
 
 
12125
 
                                /* Copy any DSP that may be present */
12126
 
                                new->dsp = old->dsp;
12127
 
                                new->dsp_features = old->dsp_features;
12128
 
                                old->dsp = NULL;
12129
 
                                old->dsp_features = 0;
12130
 
                        }
12131
 
                        return principle;
12132
 
                }
12133
 
        }
12134
 
        /* Now check for a CRV with no bearer */
12135
 
        crv = pri->crvs;
12136
 
        while (crv) {
12137
 
                if (crv->call == c) {
12138
 
                        /* This is our match...  Perform some basic checks */
12139
 
                        if (crv->bearer)
12140
 
                                ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12141
 
                        else if (pri->pvts[principle]->owner)
12142
 
                                ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12143
 
                        else {
12144
 
                                /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
12145
 
                                   wakeup the potential sleeper */
12146
 
                                dahdi_close_sub(crv, SUB_REAL);
12147
 
                                pri->pvts[principle]->call = crv->call;
12148
 
                                pri_assign_bearer(crv, pri, pri->pvts[principle]);
12149
 
                                ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12150
 
                                        pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12151
 
                                        pri->trunkgroup, crv->channel);
12152
 
                                wakeup_sub(crv, SUB_REAL, pri);
12153
 
                        }
12154
 
                        return principle;
12155
 
                }
12156
 
                crv = crv->next;
12157
 
        }
12158
 
        ast_log(LOG_WARNING, "Call specified, but not found?\n");
12159
 
        return -1;
12160
 
}
12161
 
#endif  /* defined(HAVE_PRI) */
12162
 
 
12163
 
#if defined(HAVE_PRI)
12164
 
static void *do_idle_thread(void *vchan)
12165
 
{
12166
 
        struct ast_channel *chan = vchan;
12167
 
        struct dahdi_pvt *pvt = chan->tech_pvt;
12168
 
        struct ast_frame *f;
12169
 
        char ex[80];
12170
 
        /* Wait up to 30 seconds for an answer */
12171
 
        int newms, ms = 30000;
12172
 
        ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12173
 
        snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12174
 
        if (ast_call(chan, ex, 0)) {
12175
 
                ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12176
 
                ast_hangup(chan);
12177
 
                return NULL;
12178
 
        }
12179
 
        while ((newms = ast_waitfor(chan, ms)) > 0) {
12180
 
                f = ast_read(chan);
12181
 
                if (!f) {
12182
 
                        /* Got hangup */
12183
 
                        break;
12184
 
                }
12185
 
                if (f->frametype == AST_FRAME_CONTROL) {
12186
 
                        switch (f->subclass) {
12187
 
                        case AST_CONTROL_ANSWER:
12188
 
                                /* Launch the PBX */
12189
 
                                ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12190
 
                                ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12191
 
                                chan->priority = 1;
12192
 
                                ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12193
 
                                ast_pbx_run(chan);
12194
 
                                /* It's already hungup, return immediately */
12195
 
                                return NULL;
12196
 
                        case AST_CONTROL_BUSY:
12197
 
                                ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12198
 
                                break;
12199
 
                        case AST_CONTROL_CONGESTION:
12200
 
                                ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12201
 
                                break;
12202
 
                        };
12203
 
                }
12204
 
                ast_frfree(f);
12205
 
                ms = newms;
12206
 
        }
12207
 
        /* Hangup the channel since nothing happend */
12208
 
        ast_hangup(chan);
12209
 
        return NULL;
12210
 
}
12211
 
#endif  /* defined(HAVE_PRI) */
12212
 
 
12213
 
#if defined(HAVE_PRI)
12214
 
#ifndef PRI_RESTART
12215
 
#error "Upgrade your libpri"
12216
 
#endif
12217
 
static void dahdi_pri_message(struct pri *pri, char *s)
12218
 
{
12219
 
        int x, y;
12220
 
        int dchan = -1, span = -1;
12221
 
        int dchancount = 0;
12222
 
 
12223
 
        if (pri) {
12224
 
                for (x = 0; x < NUM_SPANS; x++) {
12225
 
                        for (y = 0; y < NUM_DCHANS; y++) {
12226
 
                                if (pris[x].dchans[y])
12227
 
                                        dchancount++;
12228
 
 
12229
 
                                if (pris[x].dchans[y] == pri)
12230
 
                                        dchan = y;
12231
 
                        }
12232
 
                        if (dchan >= 0) {
12233
 
                                span = x;
12234
 
                                break;
12235
 
                        }
12236
 
                        dchancount = 0;
12237
 
                }
12238
 
                if (dchancount > 1 && (span > -1))
12239
 
                        ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12240
 
                else if (span > -1)
12241
 
                        ast_verbose("%d %s", span+1, s);
12242
 
                else
12243
 
                        ast_verbose("%s", s);
12244
 
        } else
12245
 
                ast_verbose("%s", s);
12246
 
 
12247
 
        ast_mutex_lock(&pridebugfdlock);
12248
 
 
12249
 
        if (pridebugfd >= 0) {
12250
 
                if (write(pridebugfd, s, strlen(s)) < 0) {
12251
 
                        ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12252
 
                }
12253
 
        }
12254
 
 
12255
 
        ast_mutex_unlock(&pridebugfdlock);
12256
 
}
12257
 
#endif  /* defined(HAVE_PRI) */
12258
 
 
12259
 
#if defined(HAVE_PRI)
12260
 
static void dahdi_pri_error(struct pri *pri, char *s)
12261
 
{
12262
 
        int x, y;
12263
 
        int dchan = -1, span = -1;
12264
 
        int dchancount = 0;
12265
 
 
12266
 
        if (pri) {
12267
 
                for (x = 0; x < NUM_SPANS; x++) {
12268
 
                        for (y = 0; y < NUM_DCHANS; y++) {
12269
 
                                if (pris[x].dchans[y])
12270
 
                                        dchancount++;
12271
 
 
12272
 
                                if (pris[x].dchans[y] == pri)
12273
 
                                        dchan = y;
12274
 
                        }
12275
 
                        if (dchan >= 0) {
12276
 
                                span = x;
12277
 
                                break;
12278
 
                        }
12279
 
                        dchancount = 0;
12280
 
                }
12281
 
                if ((dchancount > 1) && (span > -1))
12282
 
                        ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12283
 
                else if (span > -1)
12284
 
                        ast_log(LOG_ERROR, "%d %s", span+1, s);
12285
 
                else
12286
 
                        ast_log(LOG_ERROR, "%s", s);
12287
 
        } else
12288
 
                ast_log(LOG_ERROR, "%s", s);
12289
 
 
12290
 
        ast_mutex_lock(&pridebugfdlock);
12291
 
 
12292
 
        if (pridebugfd >= 0) {
12293
 
                if (write(pridebugfd, s, strlen(s)) < 0) {
12294
 
                        ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12295
 
                }
12296
 
        }
12297
 
 
12298
 
        ast_mutex_unlock(&pridebugfdlock);
12299
 
}
12300
 
#endif  /* defined(HAVE_PRI) */
12301
 
 
12302
 
#if defined(HAVE_PRI)
12303
 
static int pri_check_restart(struct dahdi_pri *pri)
12304
 
{
12305
 
        do {
12306
 
                pri->resetpos++;
12307
 
        } while ((pri->resetpos < pri->numchans) &&
12308
 
                (!pri->pvts[pri->resetpos] ||
12309
 
                pri->pvts[pri->resetpos]->call ||
12310
 
                pri->pvts[pri->resetpos]->resetting));
12311
 
        if (pri->resetpos < pri->numchans) {
12312
 
                /* Mark the channel as resetting and restart it */
12313
 
                pri->pvts[pri->resetpos]->resetting = 1;
12314
 
                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12315
 
        } else {
12316
 
                pri->resetting = 0;
12317
 
                time(&pri->lastreset);
12318
 
        }
12319
 
        return 0;
12320
 
}
12321
 
#endif  /* defined(HAVE_PRI) */
12322
 
 
12323
 
#if defined(HAVE_PRI)
12324
 
static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12325
 
{
12326
 
        int x;
12327
 
        int redo;
12328
 
        ast_mutex_unlock(&pri->lock);
12329
 
        ast_mutex_lock(&p->lock);
12330
 
        do {
12331
 
                redo = 0;
12332
 
                for (x = 0; x < 3; x++) {
12333
 
                        while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12334
 
                                redo++;
12335
 
                                DEADLOCK_AVOIDANCE(&p->lock);
12336
 
                        }
12337
 
                        if (p->subs[x].owner) {
12338
 
                                ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12339
 
                                ast_channel_unlock(p->subs[x].owner);
12340
 
                        }
12341
 
                }
12342
 
        } while (redo);
12343
 
        ast_mutex_unlock(&p->lock);
12344
 
        ast_mutex_lock(&pri->lock);
12345
 
        return 0;
12346
 
}
12347
 
#endif  /* defined(HAVE_PRI) */
12348
 
 
12349
 
#if defined(HAVE_PRI)
12350
 
static char * redirectingreason2str(int redirectingreason)
12351
 
{
12352
 
        switch (redirectingreason) {
12353
 
        case 0:
12354
 
                return "UNKNOWN";
12355
 
        case 1:
12356
 
                return "BUSY";
12357
 
        case 2:
12358
 
                return "NO_REPLY";
12359
 
        case 0xF:
12360
 
                return "UNCONDITIONAL";
12361
 
        default:
12362
 
                return "NOREDIRECT";
12363
 
        }
12364
 
}
12365
 
#endif  /* defined(HAVE_PRI) */
12366
 
 
12367
 
#if defined(HAVE_PRI)
12368
 
static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12369
 
{
12370
 
        if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
12371
 
                snprintf(buf, size, "%s", number);
12372
 
                return;
12373
 
        }
12374
 
        if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12375
 
                if (size) {
12376
 
                        *buf = '\0';
12377
 
                }
12378
 
                return;
12379
 
        }
12380
 
        switch (plan) {
12381
 
        case PRI_INTERNATIONAL_ISDN:            /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
12382
 
                snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12383
 
                break;
12384
 
        case PRI_NATIONAL_ISDN:                 /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
12385
 
                snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12386
 
                break;
12387
 
        case PRI_LOCAL_ISDN:                    /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
12388
 
                snprintf(buf, size, "%s%s", pri->localprefix, number);
12389
 
                break;
12390
 
        case PRI_PRIVATE:                       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
12391
 
                snprintf(buf, size, "%s%s", pri->privateprefix, number);
12392
 
                break;
12393
 
        case PRI_UNKNOWN:                       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
12394
 
                snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12395
 
                break;
12396
 
        default:                                /* other Q.931 dialplan => don't twiddle with callingnum */
12397
 
                snprintf(buf, size, "%s", number);
12398
 
                break;
12399
 
        }
12400
 
}
12401
 
#endif  /* defined(HAVE_PRI) */
12402
 
 
12403
 
#if defined(HAVE_PRI)
12404
 
static void *pri_dchannel(void *vpri)
12405
 
{
12406
 
        struct dahdi_pri *pri = vpri;
12407
 
        pri_event *e;
12408
 
        struct pollfd fds[NUM_DCHANS];
12409
 
        int res;
12410
 
        int chanpos = 0;
12411
 
        int x;
12412
 
        int haveidles;
12413
 
        int activeidles;
12414
 
        int nextidle = -1;
12415
 
        struct ast_channel *c;
12416
 
        struct timeval tv, lowest, *next;
12417
 
        struct timeval lastidle = ast_tvnow();
12418
 
        int doidling=0;
12419
 
        char *cc;
12420
 
        char idlen[80];
12421
 
        struct ast_channel *idle;
12422
 
        pthread_t p;
12423
 
        time_t t;
12424
 
        int i, which=-1;
12425
 
        int numdchans;
12426
 
        int cause=0;
12427
 
        struct dahdi_pvt *crv;
12428
 
        pthread_t threadid;
12429
 
        char ani2str[6];
12430
 
        char plancallingnum[256];
12431
 
        char plancallingani[256];
12432
 
        char calledtonstr[10];
12433
 
 
12434
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12435
 
 
12436
 
        gettimeofday(&lastidle, NULL);
12437
 
        if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12438
 
                /* Need to do idle dialing, check to be sure though */
12439
 
                cc = strchr(pri->idleext, '@');
12440
 
                if (cc) {
12441
 
                        *cc = '\0';
12442
 
                        cc++;
12443
 
                        ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12444
 
#if 0
12445
 
                        /* Extensions may not be loaded yet */
12446
 
                        if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12447
 
                                ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12448
 
                        else
12449
 
#endif
12450
 
                                doidling = 1;
12451
 
                } else
12452
 
                        ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12453
 
        }
12454
 
        for (;;) {
12455
 
                for (i = 0; i < NUM_DCHANS; i++) {
12456
 
                        if (!pri->dchannels[i])
12457
 
                                break;
12458
 
                        fds[i].fd = pri->fds[i];
12459
 
                        fds[i].events = POLLIN | POLLPRI;
12460
 
                        fds[i].revents = 0;
12461
 
                }
12462
 
                numdchans = i;
12463
 
                time(&t);
12464
 
                ast_mutex_lock(&pri->lock);
12465
 
                if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12466
 
                        if (pri->resetting && pri_is_up(pri)) {
12467
 
                                if (pri->resetpos < 0)
12468
 
                                        pri_check_restart(pri);
12469
 
                        } else {
12470
 
                                if (!pri->resetting     && (t - pri->lastreset) >= pri->resetinterval) {
12471
 
                                        pri->resetting = 1;
12472
 
                                        pri->resetpos = -1;
12473
 
                                }
12474
 
                        }
12475
 
                }
12476
 
                /* Look for any idle channels if appropriate */
12477
 
                if (doidling && pri_is_up(pri)) {
12478
 
                        nextidle = -1;
12479
 
                        haveidles = 0;
12480
 
                        activeidles = 0;
12481
 
                        for (x = pri->numchans; x >= 0; x--) {
12482
 
                                if (pri->pvts[x] && !pri->pvts[x]->owner &&
12483
 
                                        !pri->pvts[x]->call) {
12484
 
                                        if (haveidles < pri->minunused) {
12485
 
                                                haveidles++;
12486
 
                                        } else if (!pri->pvts[x]->resetting) {
12487
 
                                                nextidle = x;
12488
 
                                                break;
12489
 
                                        }
12490
 
                                } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12491
 
                                        activeidles++;
12492
 
                        }
12493
 
                        if (nextidle > -1) {
12494
 
                                if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12495
 
                                        /* Don't create a new idle call more than once per second */
12496
 
                                        snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12497
 
                                        idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12498
 
                                        if (idle) {
12499
 
                                                pri->pvts[nextidle]->isidlecall = 1;
12500
 
                                                if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12501
 
                                                        ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12502
 
                                                        dahdi_hangup(idle);
12503
 
                                                }
12504
 
                                        } else
12505
 
                                                ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12506
 
                                        lastidle = ast_tvnow();
12507
 
                                }
12508
 
                        } else if ((haveidles < pri->minunused) &&
12509
 
                                (activeidles > pri->minidle)) {
12510
 
                                /* Mark something for hangup if there is something
12511
 
                                   that can be hungup */
12512
 
                                for (x = pri->numchans; x >= 0; x--) {
12513
 
                                        /* find a candidate channel */
12514
 
                                        if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12515
 
                                                pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12516
 
                                                haveidles++;
12517
 
                                                /* Stop if we have enough idle channels or
12518
 
                                                  can't spare any more active idle ones */
12519
 
                                                if ((haveidles >= pri->minunused) ||
12520
 
                                                        (activeidles <= pri->minidle))
12521
 
                                                        break;
12522
 
                                        }
12523
 
                                }
12524
 
                        }
12525
 
                }
12526
 
                /* Start with reasonable max */
12527
 
                lowest = ast_tv(60, 0);
12528
 
                for (i = 0; i < NUM_DCHANS; i++) {
12529
 
                        /* Find lowest available d-channel */
12530
 
                        if (!pri->dchannels[i])
12531
 
                                break;
12532
 
                        if ((next = pri_schedule_next(pri->dchans[i]))) {
12533
 
                                /* We need relative time here */
12534
 
                                tv = ast_tvsub(*next, ast_tvnow());
12535
 
                                if (tv.tv_sec < 0) {
12536
 
                                        tv = ast_tv(0,0);
12537
 
                                }
12538
 
                                if (doidling || pri->resetting) {
12539
 
                                        if (tv.tv_sec > 1) {
12540
 
                                                tv = ast_tv(1, 0);
12541
 
                                        }
12542
 
                                } else {
12543
 
                                        if (tv.tv_sec > 60) {
12544
 
                                                tv = ast_tv(60, 0);
12545
 
                                        }
12546
 
                                }
12547
 
                        } else if (doidling || pri->resetting) {
12548
 
                                /* Make sure we stop at least once per second if we're
12549
 
                                   monitoring idle channels */
12550
 
                                tv = ast_tv(1,0);
12551
 
                        } else {
12552
 
                                /* Don't poll for more than 60 seconds */
12553
 
                                tv = ast_tv(60, 0);
12554
 
                        }
12555
 
                        if (!i || ast_tvcmp(tv, lowest) < 0) {
12556
 
                                lowest = tv;
12557
 
                        }
12558
 
                }
12559
 
                ast_mutex_unlock(&pri->lock);
12560
 
 
12561
 
                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12562
 
                pthread_testcancel();
12563
 
                e = NULL;
12564
 
                res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12565
 
                pthread_testcancel();
12566
 
                pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12567
 
 
12568
 
                ast_mutex_lock(&pri->lock);
12569
 
                if (!res) {
12570
 
                        for (which = 0; which < NUM_DCHANS; which++) {
12571
 
                                if (!pri->dchans[which])
12572
 
                                        break;
12573
 
                                /* Just a timeout, run the scheduler */
12574
 
                                e = pri_schedule_run(pri->dchans[which]);
12575
 
                                if (e)
12576
 
                                        break;
12577
 
                        }
12578
 
                } else if (res > -1) {
12579
 
                        for (which = 0; which < NUM_DCHANS; which++) {
12580
 
                                if (!pri->dchans[which])
12581
 
                                        break;
12582
 
                                if (fds[which].revents & POLLPRI) {
12583
 
                                        /* Check for an event */
12584
 
                                        x = 0;
12585
 
                                        res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12586
 
                                        if (x) {
12587
 
                                                ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
12588
 
                                                manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12589
 
                                                        "PRIEvent: %s\r\n"
12590
 
                                                        "PRIEventCode: %d\r\n"
12591
 
                                                        "D-channel: %s\r\n"
12592
 
                                                        "Span: %d\r\n",
12593
 
                                                        event2str(x),
12594
 
                                                        x,
12595
 
                                                        pri_order(which),
12596
 
                                                        pri->span
12597
 
                                                        );
12598
 
                                        }
12599
 
                                        /* Keep track of alarm state */
12600
 
                                        if (x == DAHDI_EVENT_ALARM) {
12601
 
                                                pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12602
 
                                                pri_find_dchan(pri);
12603
 
                                        } else if (x == DAHDI_EVENT_NOALARM) {
12604
 
                                                pri->dchanavail[which] |= DCHAN_NOTINALARM;
12605
 
                                                pri_restart(pri->dchans[which]);
12606
 
                                        }
12607
 
 
12608
 
                                        ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12609
 
                                } else if (fds[which].revents & POLLIN) {
12610
 
                                        e = pri_check_event(pri->dchans[which]);
12611
 
                                }
12612
 
                                if (e)
12613
 
                                        break;
12614
 
                        }
12615
 
                } else if (errno != EINTR)
12616
 
                        ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12617
 
 
12618
 
                if (e) {
12619
 
                        if (pri->debug)
12620
 
                                pri_dump_event(pri->dchans[which], e);
12621
 
 
12622
 
                        if (e->e != PRI_EVENT_DCHAN_DOWN) {
12623
 
                                if (!(pri->dchanavail[which] & DCHAN_UP)) {
12624
 
                                        ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12625
 
                                }
12626
 
                                pri->dchanavail[which] |= DCHAN_UP;
12627
 
                        } else if (pri->sig != SIG_BRI_PTMP) {
12628
 
                                if (pri->dchanavail[which] & DCHAN_UP) {
12629
 
                                        ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12630
 
                                }
12631
 
                                pri->dchanavail[which] &= ~DCHAN_UP;
12632
 
                        }
12633
 
 
12634
 
                        if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12635
 
                                /* Must be an NFAS group that has the secondary dchan active */
12636
 
                                pri->pri = pri->dchans[which];
12637
 
 
12638
 
                        switch (e->e) {
12639
 
                        case PRI_EVENT_DCHAN_UP:
12640
 
                                if (!pri->pri) pri_find_dchan(pri);
12641
 
 
12642
 
                                /* Note presense of D-channel */
12643
 
                                time(&pri->lastreset);
12644
 
 
12645
 
                                /* Restart in 5 seconds */
12646
 
                                if (pri->resetinterval > -1) {
12647
 
                                        pri->lastreset -= pri->resetinterval;
12648
 
                                        pri->lastreset += 5;
12649
 
                                }
12650
 
                                pri->resetting = 0;
12651
 
                                /* Take the channels from inalarm condition */
12652
 
                                for (i = 0; i < pri->numchans; i++)
12653
 
                                        if (pri->pvts[i]) {
12654
 
                                                pri->pvts[i]->inalarm = 0;
12655
 
                                        }
12656
 
                                break;
12657
 
                        case PRI_EVENT_DCHAN_DOWN:
12658
 
                                pri_find_dchan(pri);
12659
 
                                if (!pri_is_up(pri)) {
12660
 
                                        pri->resetting = 0;
12661
 
                                        /* Hangup active channels and put them in alarm mode */
12662
 
                                        for (i = 0; i < pri->numchans; i++) {
12663
 
                                                struct dahdi_pvt *p = pri->pvts[i];
12664
 
                                                if (p) {
12665
 
                                                        if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12666
 
                                                                /* T309 is not enabled : hangup calls when alarm occurs */
12667
 
                                                                if (p->call) {
12668
 
                                                                        if (p->pri && p->pri->pri) {
12669
 
                                                                                pri_hangup(p->pri->pri, p->call, -1);
12670
 
                                                                                pri_destroycall(p->pri->pri, p->call);
12671
 
                                                                                p->call = NULL;
12672
 
                                                                        } else
12673
 
                                                                                ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12674
 
                                                                }
12675
 
                                                                if (p->realcall) {
12676
 
                                                                        pri_hangup_all(p->realcall, pri);
12677
 
                                                                } else if (p->owner)
12678
 
                                                                        p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12679
 
                                                        }
12680
 
                                                        /* For PTMP connections with non persistent layer 2 we want
12681
 
                                                         * to *not* declare inalarm unless there actually is an alarm */
12682
 
                                                        if (p->sig != SIG_BRI_PTMP) {
12683
 
                                                                p->inalarm = 1;
12684
 
                                                        }
12685
 
                                                }
12686
 
                                        }
12687
 
                                }
12688
 
                                break;
12689
 
                        case PRI_EVENT_RESTART:
12690
 
                                if (e->restart.channel > -1) {
12691
 
                                        chanpos = pri_find_principle(pri, e->restart.channel);
12692
 
                                        if (chanpos < 0)
12693
 
                                                ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12694
 
                                                        PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12695
 
                                        else {
12696
 
                                                ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12697
 
                                                                PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12698
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12699
 
                                                if (pri->pvts[chanpos]->call) {
12700
 
                                                        pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12701
 
                                                        pri->pvts[chanpos]->call = NULL;
12702
 
                                                }
12703
 
                                                /* Force soft hangup if appropriate */
12704
 
                                                if (pri->pvts[chanpos]->realcall)
12705
 
                                                        pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12706
 
                                                else if (pri->pvts[chanpos]->owner)
12707
 
                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12708
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12709
 
                                        }
12710
 
                                } else {
12711
 
                                        ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12712
 
                                        for (x = 0; x < pri->numchans; x++)
12713
 
                                                if (pri->pvts[x]) {
12714
 
                                                        ast_mutex_lock(&pri->pvts[x]->lock);
12715
 
                                                        if (pri->pvts[x]->call) {
12716
 
                                                                pri_destroycall(pri->pri, pri->pvts[x]->call);
12717
 
                                                                pri->pvts[x]->call = NULL;
12718
 
                                                        }
12719
 
                                                        if (pri->pvts[x]->realcall)
12720
 
                                                                pri_hangup_all(pri->pvts[x]->realcall, pri);
12721
 
                                                        else if (pri->pvts[x]->owner)
12722
 
                                                                pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12723
 
                                                        ast_mutex_unlock(&pri->pvts[x]->lock);
12724
 
                                                }
12725
 
                                }
12726
 
                                break;
12727
 
                        case PRI_EVENT_KEYPAD_DIGIT:
12728
 
                                chanpos = pri_find_principle(pri, e->digit.channel);
12729
 
                                if (chanpos < 0) {
12730
 
                                        ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12731
 
                                                PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12732
 
                                } else {
12733
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12734
 
                                        if (chanpos > -1) {
12735
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12736
 
                                                /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
12737
 
                                                if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12738
 
                                                        /* how to do that */
12739
 
                                                        int digitlen = strlen(e->digit.digits);
12740
 
                                                        char digit;
12741
 
                                                        int i;
12742
 
                                                        for (i = 0; i < digitlen; i++) {
12743
 
                                                                digit = e->digit.digits[i];
12744
 
                                                                {
12745
 
                                                                        struct ast_frame f = { AST_FRAME_DTMF, digit, };
12746
 
                                                                        dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12747
 
                                                                }
12748
 
                                                        }
12749
 
                                                }
12750
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12751
 
                                        }
12752
 
                                }
12753
 
                                break;
12754
 
 
12755
 
                        case PRI_EVENT_INFO_RECEIVED:
12756
 
                                chanpos = pri_find_principle(pri, e->ring.channel);
12757
 
                                if (chanpos < 0) {
12758
 
                                        ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12759
 
                                                PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12760
 
                                } else {
12761
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12762
 
                                        if (chanpos > -1) {
12763
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12764
 
                                                /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
12765
 
                                                if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12766
 
                                                        /* how to do that */
12767
 
                                                        int digitlen = strlen(e->ring.callednum);
12768
 
                                                        char digit;
12769
 
                                                        int i;
12770
 
                                                        for (i = 0; i < digitlen; i++) {
12771
 
                                                                digit = e->ring.callednum[i];
12772
 
                                                                {
12773
 
                                                                        struct ast_frame f = { AST_FRAME_DTMF, digit, };
12774
 
                                                                        dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12775
 
                                                                }
12776
 
                                                        }
12777
 
                                                }
12778
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12779
 
                                        }
12780
 
                                }
12781
 
                                break;
12782
 
                        case PRI_EVENT_RING:
12783
 
                                crv = NULL;
12784
 
                                if (e->ring.channel == -1)
12785
 
                                        chanpos = pri_find_empty_chan(pri, 1);
12786
 
                                else
12787
 
                                        chanpos = pri_find_principle(pri, e->ring.channel);
12788
 
                                /* if no channel specified find one empty */
12789
 
                                if (chanpos < 0) {
12790
 
                                        ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12791
 
                                                PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12792
 
                                } else {
12793
 
                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
12794
 
                                        if (pri->pvts[chanpos]->owner) {
12795
 
                                                if (pri->pvts[chanpos]->call == e->ring.call) {
12796
 
                                                        ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12797
 
                                                                PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12798
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12799
 
                                                        break;
12800
 
                                                } else {
12801
 
                                                        /* This is where we handle initial glare */
12802
 
                                                        ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
12803
 
                                                        PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12804
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12805
 
                                                        chanpos = -1;
12806
 
                                                }
12807
 
                                        }
12808
 
                                        if (chanpos > -1)
12809
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12810
 
                                }
12811
 
                                if ((chanpos < 0) && (e->ring.flexible))
12812
 
                                        chanpos = pri_find_empty_chan(pri, 1);
12813
 
                                if (chanpos > -1) {
12814
 
                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
12815
 
                                        if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12816
 
                                                /* Should be safe to lock CRV AFAIK while bearer is still locked */
12817
 
                                                crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12818
 
                                                if (crv)
12819
 
                                                        ast_mutex_lock(&crv->lock);
12820
 
                                                if (!crv || crv->owner) {
12821
 
                                                        pri->pvts[chanpos]->call = NULL;
12822
 
                                                        if (crv) {
12823
 
                                                                if (crv->owner)
12824
 
                                                                        crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12825
 
                                                                ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12826
 
                                                        } else
12827
 
                                                                ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12828
 
                                                        pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12829
 
                                                        if (crv)
12830
 
                                                                ast_mutex_unlock(&crv->lock);
12831
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12832
 
                                                        break;
12833
 
                                                }
12834
 
                                        }
12835
 
                                        pri->pvts[chanpos]->call = e->ring.call;
12836
 
                                        apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12837
 
                                        if (pri->pvts[chanpos]->use_callerid) {
12838
 
                                                ast_shrink_phone_number(plancallingnum);
12839
 
                                                ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12840
 
#ifdef PRI_ANI
12841
 
                                                if (!ast_strlen_zero(e->ring.callingani)) {
12842
 
                                                        apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12843
 
                                                        ast_shrink_phone_number(plancallingani);
12844
 
                                                        ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12845
 
                                                } else {
12846
 
                                                        pri->pvts[chanpos]->cid_ani[0] = '\0';
12847
 
                                                }
12848
 
#endif
12849
 
                                                ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12850
 
                                                pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
12851
 
                                        } else {
12852
 
                                                pri->pvts[chanpos]->cid_num[0] = '\0';
12853
 
                                                pri->pvts[chanpos]->cid_ani[0] = '\0';
12854
 
                                                pri->pvts[chanpos]->cid_name[0] = '\0';
12855
 
                                                pri->pvts[chanpos]->cid_ton = 0;
12856
 
                                        }
12857
 
                                        apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12858
 
                                                e->ring.redirectingnum, e->ring.callingplanrdnis);
12859
 
                                        /* If immediate=yes go to s|1 */
12860
 
                                        if (pri->pvts[chanpos]->immediate) {
12861
 
                                                ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12862
 
                                                pri->pvts[chanpos]->exten[0] = 's';
12863
 
                                                pri->pvts[chanpos]->exten[1] = '\0';
12864
 
                                        }
12865
 
                                        /* Get called number */
12866
 
                                        else if (!ast_strlen_zero(e->ring.callednum)) {
12867
 
                                                ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12868
 
                                                ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12869
 
                                        } else if (pri->overlapdial)
12870
 
                                                pri->pvts[chanpos]->exten[0] = '\0';
12871
 
                                        else {
12872
 
                                                /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
12873
 
                                                pri->pvts[chanpos]->exten[0] = 's';
12874
 
                                                pri->pvts[chanpos]->exten[1] = '\0';
12875
 
                                        }
12876
 
                                        /* Set DNID on all incoming calls -- even immediate */
12877
 
                                        if (!ast_strlen_zero(e->ring.callednum))
12878
 
                                                ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12879
 
                                        /* No number yet, but received "sending complete"? */
12880
 
                                        if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
12881
 
                                                ast_verb(3, "Going to extension s|1 because of Complete received\n");
12882
 
                                                pri->pvts[chanpos]->exten[0] = 's';
12883
 
                                                pri->pvts[chanpos]->exten[1] = '\0';
12884
 
                                        }
12885
 
 
12886
 
                                        /* Make sure extension exists (or in overlap dial mode, can exist) */
12887
 
                                        if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
12888
 
                                                ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12889
 
                                                /* Setup law */
12890
 
                                                int law;
12891
 
                                                if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
12892
 
                                                        /* Set to audio mode at this point */
12893
 
                                                        law = 1;
12894
 
                                                        if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
12895
 
                                                                ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
12896
 
                                                }
12897
 
                                                if (e->ring.layer1 == PRI_LAYER_1_ALAW)
12898
 
                                                        law = DAHDI_LAW_ALAW;
12899
 
                                                else
12900
 
                                                        law = DAHDI_LAW_MULAW;
12901
 
                                                res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
12902
 
                                                if (res < 0)
12903
 
                                                        ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
12904
 
                                                res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
12905
 
                                                if (res < 0)
12906
 
                                                        ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
12907
 
                                                if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
12908
 
                                                        /* Just announce proceeding */
12909
 
                                                        pri->pvts[chanpos]->proceeding = 1;
12910
 
                                                        pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
12911
 
                                                } else {
12912
 
                                                        if (pri->switchtype != PRI_SWITCH_GR303_TMC)
12913
 
                                                                pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12914
 
                                                        else
12915
 
                                                                pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12916
 
                                                }
12917
 
                                                /* Get the use_callingpres state */
12918
 
                                                pri->pvts[chanpos]->callingpres = e->ring.callingpres;
12919
 
 
12920
 
                                                /* Start PBX */
12921
 
                                                if (!e->ring.complete
12922
 
                                                        && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
12923
 
                                                        && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12924
 
                                                        /*
12925
 
                                                         * Release the PRI lock while we create the channel
12926
 
                                                         * so other threads can send D channel messages.
12927
 
                                                         */
12928
 
                                                        ast_mutex_unlock(&pri->lock);
12929
 
                                                        if (crv) {
12930
 
                                                                /* Set bearer and such */
12931
 
                                                                pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
12932
 
                                                                c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12933
 
                                                                pri->pvts[chanpos]->owner = &inuse;
12934
 
                                                                ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
12935
 
                                                        } else {
12936
 
                                                                c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12937
 
                                                        }
12938
 
                                                        ast_mutex_lock(&pri->lock);
12939
 
                                                        if (c) {
12940
 
                                                                if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12941
 
                                                                        pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12942
 
                                                                }
12943
 
                                                                if (e->ring.ani2 >= 0) {
12944
 
                                                                        snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12945
 
                                                                        pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12946
 
                                                                        pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12947
 
                                                                }
12948
 
 
12949
 
#ifdef SUPPORT_USERUSER
12950
 
                                                                if (!ast_strlen_zero(e->ring.useruserinfo)) {
12951
 
                                                                        pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12952
 
                                                                }
12953
 
#endif
12954
 
 
12955
 
                                                                snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
12956
 
                                                                pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
12957
 
                                                                if (e->ring.redirectingreason >= 0)
12958
 
                                                                        pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
12959
 
                                                        }
12960
 
                                                        if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
12961
 
                                                                ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
12962
 
                                                                        plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
12963
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12964
 
                                                        } else {
12965
 
                                                                ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
12966
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12967
 
                                                                if (c)
12968
 
                                                                        ast_hangup(c);
12969
 
                                                                else {
12970
 
                                                                        pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
12971
 
                                                                        pri->pvts[chanpos]->call = NULL;
12972
 
                                                                }
12973
 
                                                        }
12974
 
                                                } else {
12975
 
                                                        /*
12976
 
                                                         * Release the PRI lock while we create the channel
12977
 
                                                         * so other threads can send D channel messages.
12978
 
                                                         */
12979
 
                                                        ast_mutex_unlock(&pri->lock);
12980
 
                                                        c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
12981
 
                                                        ast_mutex_lock(&pri->lock);
12982
 
                                                        if (c) {
12983
 
                                                                /*
12984
 
                                                                 * It is reasonably safe to set the following
12985
 
                                                                 * channel variables while the PRI and DAHDI private
12986
 
                                                                 * structures are locked.  The PBX has not been
12987
 
                                                                 * started yet and it is unlikely that any other task
12988
 
                                                                 * will do anything with the channel we have just
12989
 
                                                                 * created.
12990
 
                                                                 */
12991
 
                                                                if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12992
 
                                                                        pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12993
 
                                                                }
12994
 
                                                                if (e->ring.ani2 >= 0) {
12995
 
                                                                        snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12996
 
                                                                        pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12997
 
                                                                        pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12998
 
                                                                }
12999
 
 
13000
 
#ifdef SUPPORT_USERUSER
13001
 
                                                                if (!ast_strlen_zero(e->ring.useruserinfo)) {
13002
 
                                                                        pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13003
 
                                                                }
13004
 
#endif
13005
 
 
13006
 
                                                                if (e->ring.redirectingreason >= 0)
13007
 
                                                                        pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13008
 
 
13009
 
                                                                snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13010
 
                                                                pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13011
 
                                                        }
13012
 
                                                        if (c && !ast_pbx_start(c)) {
13013
 
                                                                ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13014
 
                                                                        plancallingnum, pri->pvts[chanpos]->exten,
13015
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13016
 
 
13017
 
                                                                dahdi_enable_ec(pri->pvts[chanpos]);
13018
 
                                                        } else {
13019
 
                                                                ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13020
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13021
 
                                                                if (c) {
13022
 
                                                                        ast_hangup(c);
13023
 
                                                                } else {
13024
 
                                                                        pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13025
 
                                                                        pri->pvts[chanpos]->call = NULL;
13026
 
                                                                }
13027
 
                                                        }
13028
 
                                                }
13029
 
                                        } else {
13030
 
                                                ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
13031
 
                                                        pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13032
 
                                                        pri->pvts[chanpos]->prioffset, pri->span);
13033
 
                                                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13034
 
                                                pri->pvts[chanpos]->call = NULL;
13035
 
                                                pri->pvts[chanpos]->exten[0] = '\0';
13036
 
                                        }
13037
 
                                        if (crv)
13038
 
                                                ast_mutex_unlock(&crv->lock);
13039
 
                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13040
 
                                } else {
13041
 
                                        if (e->ring.flexible)
13042
 
                                                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13043
 
                                        else
13044
 
                                                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13045
 
                                }
13046
 
                                break;
13047
 
                        case PRI_EVENT_RINGING:
13048
 
                                chanpos = pri_find_principle(pri, e->ringing.channel);
13049
 
                                if (chanpos < 0) {
13050
 
                                        ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13051
 
                                                PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13052
 
                                } else {
13053
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13054
 
                                        if (chanpos < 0) {
13055
 
                                                ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13056
 
                                                        PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13057
 
                                        } else {
13058
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13059
 
                                                if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13060
 
                                                        dahdi_enable_ec(pri->pvts[chanpos]);
13061
 
                                                        pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13062
 
                                                        pri->pvts[chanpos]->alerting = 1;
13063
 
                                                } else
13064
 
                                                        ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13065
 
 
13066
 
                                                if (
13067
 
#ifdef PRI_PROGRESS_MASK
13068
 
                                                        e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13069
 
#else
13070
 
                                                        e->ringing.progress == 8
13071
 
#endif
13072
 
                                                        ) {
13073
 
                                                        /* Now we can do call progress detection */
13074
 
                                                        if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13075
 
                                                                /* RINGING detection isn't required because we got ALERTING signal */
13076
 
                                                                ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13077
 
                                                                pri->pvts[chanpos]->dsp_features = 0;
13078
 
                                                        }
13079
 
                                                }
13080
 
 
13081
 
#ifdef SUPPORT_USERUSER
13082
 
                                                if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13083
 
                                                        struct ast_channel *owner = pri->pvts[chanpos]->owner;
13084
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13085
 
                                                        pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13086
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13087
 
                                                }
13088
 
#endif
13089
 
 
13090
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13091
 
                                        }
13092
 
                                }
13093
 
                                break;
13094
 
                        case PRI_EVENT_PROGRESS:
13095
 
                                /* Get chan value if e->e is not PRI_EVNT_RINGING */
13096
 
                                chanpos = pri_find_principle(pri, e->proceeding.channel);
13097
 
                                if (chanpos > -1) {
13098
 
                                        if ((!pri->pvts[chanpos]->progress)
13099
 
#ifdef PRI_PROGRESS_MASK
13100
 
                                                || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13101
 
#else
13102
 
                                                || (e->proceeding.progress == 8)
13103
 
#endif
13104
 
                                                ) {
13105
 
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13106
 
 
13107
 
                                                if (e->proceeding.cause > -1) {
13108
 
                                                        ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13109
 
 
13110
 
                                                        /* Work around broken, out of spec USER_BUSY cause in a progress message */
13111
 
                                                        if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13112
 
                                                                if (pri->pvts[chanpos]->owner) {
13113
 
                                                                        ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13114
 
 
13115
 
                                                                        pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13116
 
                                                                        f.subclass = AST_CONTROL_BUSY;
13117
 
                                                                }
13118
 
                                                        }
13119
 
                                                }
13120
 
 
13121
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13122
 
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13123
 
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13124
 
                                                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13125
 
                                                if (
13126
 
#ifdef PRI_PROGRESS_MASK
13127
 
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13128
 
#else
13129
 
                                                        e->proceeding.progress == 8
13130
 
#endif
13131
 
                                                        ) {
13132
 
                                                        /* Now we can do call progress detection */
13133
 
                                                        if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13134
 
                                                                ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13135
 
                                                                pri->pvts[chanpos]->dsp_features = 0;
13136
 
                                                        }
13137
 
                                                        /* Bring voice path up */
13138
 
                                                        f.subclass = AST_CONTROL_PROGRESS;
13139
 
                                                        dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13140
 
                                                }
13141
 
                                                pri->pvts[chanpos]->progress = 1;
13142
 
                                                pri->pvts[chanpos]->dialing = 0;
13143
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13144
 
                                        }
13145
 
                                }
13146
 
                                break;
13147
 
                        case PRI_EVENT_PROCEEDING:
13148
 
                                chanpos = pri_find_principle(pri, e->proceeding.channel);
13149
 
                                if (chanpos > -1) {
13150
 
                                        if (!pri->pvts[chanpos]->proceeding) {
13151
 
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13152
 
 
13153
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13154
 
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13155
 
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13156
 
                                                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13157
 
                                                if (
13158
 
#ifdef PRI_PROGRESS_MASK
13159
 
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13160
 
#else
13161
 
                                                        e->proceeding.progress == 8
13162
 
#endif
13163
 
                                                        ) {
13164
 
                                                        /* Now we can do call progress detection */
13165
 
                                                        if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13166
 
                                                                ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13167
 
                                                                pri->pvts[chanpos]->dsp_features = 0;
13168
 
                                                        }
13169
 
                                                        /* Bring voice path up */
13170
 
                                                        f.subclass = AST_CONTROL_PROGRESS;
13171
 
                                                        dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13172
 
                                                }
13173
 
                                                pri->pvts[chanpos]->proceeding = 1;
13174
 
                                                pri->pvts[chanpos]->dialing = 0;
13175
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13176
 
                                        }
13177
 
                                }
13178
 
                                break;
13179
 
                        case PRI_EVENT_FACNAME:
13180
 
                                chanpos = pri_find_principle(pri, e->facname.channel);
13181
 
                                if (chanpos < 0) {
13182
 
                                        ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13183
 
                                                PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13184
 
                                } else {
13185
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13186
 
                                        if (chanpos < 0) {
13187
 
                                                ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13188
 
                                                        PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13189
 
                                        } else {
13190
 
                                                /* Re-use *69 field for PRI */
13191
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13192
 
                                                ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13193
 
                                                ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13194
 
                                                pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
13195
 
                                                dahdi_enable_ec(pri->pvts[chanpos]);
13196
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13197
 
                                        }
13198
 
                                }
13199
 
                                break;
13200
 
                        case PRI_EVENT_ANSWER:
13201
 
                                chanpos = pri_find_principle(pri, e->answer.channel);
13202
 
                                if (chanpos < 0) {
13203
 
                                        ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13204
 
                                                PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13205
 
                                } else {
13206
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13207
 
                                        if (chanpos < 0) {
13208
 
                                                ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13209
 
                                                        PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13210
 
                                        } else {
13211
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13212
 
                                                /* Now we can do call progress detection */
13213
 
 
13214
 
                                                /* We changed this so it turns on the DSP no matter what... progress or no progress.
13215
 
                                                 * By this time, we need DTMF detection and other features that were previously disabled
13216
 
                                                 * -- Matt F */
13217
 
                                                if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13218
 
                                                        ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13219
 
                                                        pri->pvts[chanpos]->dsp_features = 0;
13220
 
                                                }
13221
 
                                                if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13222
 
                                                        ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13223
 
                                                        x = DAHDI_START;
13224
 
                                                        res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13225
 
                                                        if (res < 0) {
13226
 
                                                                if (errno != EINPROGRESS) {
13227
 
                                                                        ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13228
 
                                                                }
13229
 
                                                        }
13230
 
                                                } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13231
 
                                                        pri->pvts[chanpos]->dialing = 1;
13232
 
                                                        /* Send any "w" waited stuff */
13233
 
                                                        res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13234
 
                                                        if (res < 0) {
13235
 
                                                                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13236
 
                                                                pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13237
 
                                                        } else
13238
 
                                                                ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13239
 
 
13240
 
                                                        pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13241
 
                                                } else if (pri->pvts[chanpos]->confirmanswer) {
13242
 
                                                        ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13243
 
                                                } else {
13244
 
                                                        pri->pvts[chanpos]->dialing = 0;
13245
 
                                                        pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13246
 
                                                        /* Enable echo cancellation if it's not on already */
13247
 
                                                        dahdi_enable_ec(pri->pvts[chanpos]);
13248
 
                                                }
13249
 
 
13250
 
#ifdef SUPPORT_USERUSER
13251
 
                                                if (!ast_strlen_zero(e->answer.useruserinfo)) {
13252
 
                                                        struct ast_channel *owner = pri->pvts[chanpos]->owner;
13253
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13254
 
                                                        pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13255
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13256
 
                                                }
13257
 
#endif
13258
 
 
13259
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13260
 
                                        }
13261
 
                                }
13262
 
                                break;
13263
 
                        case PRI_EVENT_HANGUP:
13264
 
                                chanpos = pri_find_principle(pri, e->hangup.channel);
13265
 
                                if (chanpos < 0) {
13266
 
                                        ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13267
 
                                                PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13268
 
                                } else {
13269
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13270
 
                                        if (chanpos > -1) {
13271
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13272
 
                                                if (!pri->pvts[chanpos]->alreadyhungup) {
13273
 
                                                        /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
13274
 
                                                        pri->pvts[chanpos]->alreadyhungup = 1;
13275
 
                                                        if (pri->pvts[chanpos]->realcall)
13276
 
                                                                pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13277
 
                                                        else if (pri->pvts[chanpos]->owner) {
13278
 
                                                                /* Queue a BUSY instead of a hangup if our cause is appropriate */
13279
 
                                                                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13280
 
                                                                switch (pri->pvts[chanpos]->owner->_state) {
13281
 
                                                                case AST_STATE_BUSY:
13282
 
                                                                case AST_STATE_UP:
13283
 
                                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13284
 
                                                                        break;
13285
 
                                                                default:
13286
 
                                                                        switch (e->hangup.cause) {
13287
 
                                                                        case PRI_CAUSE_USER_BUSY:
13288
 
                                                                                pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13289
 
                                                                                break;
13290
 
                                                                        case PRI_CAUSE_CALL_REJECTED:
13291
 
                                                                        case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13292
 
                                                                        case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13293
 
                                                                        case PRI_CAUSE_SWITCH_CONGESTION:
13294
 
                                                                        case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13295
 
                                                                        case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13296
 
                                                                                pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13297
 
                                                                                break;
13298
 
                                                                        default:
13299
 
                                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13300
 
                                                                        }
13301
 
                                                                        break;
13302
 
                                                                }
13303
 
                                                        }
13304
 
                                                        ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13305
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13306
 
                                                } else {
13307
 
                                                        pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13308
 
                                                        pri->pvts[chanpos]->call = NULL;
13309
 
                                                }
13310
 
                                                if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13311
 
                                                        ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13312
 
                                                                        PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13313
 
                                                        pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13314
 
                                                        pri->pvts[chanpos]->resetting = 1;
13315
 
                                                }
13316
 
                                                if (e->hangup.aoc_units > -1)
13317
 
                                                        ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13318
 
                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13319
 
 
13320
 
#ifdef SUPPORT_USERUSER
13321
 
                                                if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13322
 
                                                        struct ast_channel *owner = pri->pvts[chanpos]->owner;
13323
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13324
 
                                                        pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13325
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13326
 
                                                }
13327
 
#endif
13328
 
 
13329
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13330
 
                                        } else {
13331
 
                                                ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13332
 
                                                        PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13333
 
                                        }
13334
 
                                }
13335
 
                                break;
13336
 
#ifndef PRI_EVENT_HANGUP_REQ
13337
 
#error please update libpri
13338
 
#endif
13339
 
                        case PRI_EVENT_HANGUP_REQ:
13340
 
                                chanpos = pri_find_principle(pri, e->hangup.channel);
13341
 
                                if (chanpos < 0) {
13342
 
                                        ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13343
 
                                                PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13344
 
                                } else {
13345
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13346
 
                                        if (chanpos > -1) {
13347
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13348
 
                                                if (pri->pvts[chanpos]->realcall)
13349
 
                                                        pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13350
 
                                                else if (pri->pvts[chanpos]->owner) {
13351
 
                                                        pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13352
 
                                                        switch (pri->pvts[chanpos]->owner->_state) {
13353
 
                                                        case AST_STATE_BUSY:
13354
 
                                                        case AST_STATE_UP:
13355
 
                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13356
 
                                                                break;
13357
 
                                                        default:
13358
 
                                                                switch (e->hangup.cause) {
13359
 
                                                                case PRI_CAUSE_USER_BUSY:
13360
 
                                                                        pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13361
 
                                                                        break;
13362
 
                                                                case PRI_CAUSE_CALL_REJECTED:
13363
 
                                                                case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13364
 
                                                                case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13365
 
                                                                case PRI_CAUSE_SWITCH_CONGESTION:
13366
 
                                                                case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13367
 
                                                                case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13368
 
                                                                        pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13369
 
                                                                        break;
13370
 
                                                                default:
13371
 
                                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13372
 
                                                                        break;
13373
 
                                                                }
13374
 
                                                                break;
13375
 
                                                        }
13376
 
                                                        ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
13377
 
                                                        if (e->hangup.aoc_units > -1)
13378
 
                                                                ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13379
 
                                                                                pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13380
 
                                                } else {
13381
 
                                                        pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13382
 
                                                        pri->pvts[chanpos]->call = NULL;
13383
 
                                                }
13384
 
                                                if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13385
 
                                                        ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13386
 
                                                                        PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13387
 
                                                        pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13388
 
                                                        pri->pvts[chanpos]->resetting = 1;
13389
 
                                                }
13390
 
 
13391
 
#ifdef SUPPORT_USERUSER
13392
 
                                                if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13393
 
                                                        struct ast_channel *owner = pri->pvts[chanpos]->owner;
13394
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13395
 
                                                        pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13396
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13397
 
                                                }
13398
 
#endif
13399
 
 
13400
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13401
 
                                        } else {
13402
 
                                                ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13403
 
                                        }
13404
 
                                }
13405
 
                                break;
13406
 
                        case PRI_EVENT_HANGUP_ACK:
13407
 
                                chanpos = pri_find_principle(pri, e->hangup.channel);
13408
 
                                if (chanpos < 0) {
13409
 
                                        ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13410
 
                                                PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13411
 
                                } else {
13412
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13413
 
                                        if (chanpos > -1) {
13414
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13415
 
                                                pri->pvts[chanpos]->call = NULL;
13416
 
                                                pri->pvts[chanpos]->resetting = 0;
13417
 
                                                if (pri->pvts[chanpos]->owner) {
13418
 
                                                        ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13419
 
                                                }
13420
 
 
13421
 
#ifdef SUPPORT_USERUSER
13422
 
                                                if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13423
 
                                                        struct ast_channel *owner = pri->pvts[chanpos]->owner;
13424
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13425
 
                                                        pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13426
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13427
 
                                                }
13428
 
#endif
13429
 
 
13430
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13431
 
                                        }
13432
 
                                }
13433
 
                                break;
13434
 
                        case PRI_EVENT_CONFIG_ERR:
13435
 
                                ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
13436
 
                                break;
13437
 
                        case PRI_EVENT_RESTART_ACK:
13438
 
                                chanpos = pri_find_principle(pri, e->restartack.channel);
13439
 
                                if (chanpos < 0) {
13440
 
                                        /* Sometime switches (e.g. I421 / British Telecom) don't give us the
13441
 
                                           channel number, so we have to figure it out...  This must be why
13442
 
                                           everybody resets exactly a channel at a time. */
13443
 
                                        for (x = 0; x < pri->numchans; x++) {
13444
 
                                                if (pri->pvts[x] && pri->pvts[x]->resetting) {
13445
 
                                                        chanpos = x;
13446
 
                                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13447
 
                                                        ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13448
 
                                                                pri->pvts[chanpos]->prioffset, pri->span);
13449
 
                                                        if (pri->pvts[chanpos]->realcall)
13450
 
                                                                pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13451
 
                                                        else if (pri->pvts[chanpos]->owner) {
13452
 
                                                                ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13453
 
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
13454
 
                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13455
 
                                                        }
13456
 
                                                        pri->pvts[chanpos]->resetting = 0;
13457
 
                                                        ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13458
 
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
13459
 
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13460
 
                                                        if (pri->resetting)
13461
 
                                                                pri_check_restart(pri);
13462
 
                                                        break;
13463
 
                                                }
13464
 
                                        }
13465
 
                                        if (chanpos < 0) {
13466
 
                                                ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13467
 
                                                        PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13468
 
                                        }
13469
 
                                } else {
13470
 
                                        if (pri->pvts[chanpos]) {
13471
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13472
 
                                                if (pri->pvts[chanpos]->realcall)
13473
 
                                                        pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13474
 
                                                else if (pri->pvts[chanpos]->owner) {
13475
 
                                                        ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13476
 
                                                                PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13477
 
                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13478
 
                                                }
13479
 
                                                pri->pvts[chanpos]->resetting = 0;
13480
 
                                                pri->pvts[chanpos]->inservice = 1;
13481
 
                                                ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13482
 
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
13483
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13484
 
                                                if (pri->resetting)
13485
 
                                                        pri_check_restart(pri);
13486
 
                                        }
13487
 
                                }
13488
 
                                break;
13489
 
                        case PRI_EVENT_SETUP_ACK:
13490
 
                                chanpos = pri_find_principle(pri, e->setup_ack.channel);
13491
 
                                if (chanpos < 0) {
13492
 
                                        ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13493
 
                                                PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13494
 
                                } else {
13495
 
                                        chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13496
 
                                        if (chanpos > -1) {
13497
 
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13498
 
                                                pri->pvts[chanpos]->setup_ack = 1;
13499
 
                                                /* Send any queued digits */
13500
 
                                                for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13501
 
                                                        ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13502
 
                                                        pri_information(pri->pri, pri->pvts[chanpos]->call,
13503
 
                                                                pri->pvts[chanpos]->dialdest[x]);
13504
 
                                                }
13505
 
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13506
 
                                        } else
13507
 
                                                ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13508
 
                                }
13509
 
                                break;
13510
 
                        case PRI_EVENT_NOTIFY:
13511
 
                                chanpos = pri_find_principle(pri, e->notify.channel);
13512
 
                                if (chanpos < 0) {
13513
 
                                        ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13514
 
                                                PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13515
 
                                } else if (!pri->discardremoteholdretrieval) {
13516
 
                                        struct ast_frame f = { AST_FRAME_CONTROL, };
13517
 
                                        ast_mutex_lock(&pri->pvts[chanpos]->lock);
13518
 
                                        switch (e->notify.info) {
13519
 
                                        case PRI_NOTIFY_REMOTE_HOLD:
13520
 
                                                f.subclass = AST_CONTROL_HOLD;
13521
 
                                                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13522
 
                                                break;
13523
 
                                        case PRI_NOTIFY_REMOTE_RETRIEVAL:
13524
 
                                                f.subclass = AST_CONTROL_UNHOLD;
13525
 
                                                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13526
 
                                                break;
13527
 
                                        }
13528
 
                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13529
 
                                }
13530
 
                                break;
13531
 
                        default:
13532
 
                                ast_debug(1, "Event: %d\n", e->e);
13533
 
                        }
13534
 
                }
13535
 
                ast_mutex_unlock(&pri->lock);
13536
 
        }
13537
 
        /* Never reached */
13538
 
        return NULL;
13539
 
}
13540
 
#endif  /* defined(HAVE_PRI) */
13541
 
 
13542
 
#if defined(HAVE_PRI)
13543
 
static int start_pri(struct dahdi_pri *pri)
13544
 
{
13545
 
        int res, x;
13546
 
        struct dahdi_params p;
13547
 
        struct dahdi_bufferinfo bi;
13548
 
        struct dahdi_spaninfo si;
13549
 
        int i;
13550
 
 
13551
 
        for (i = 0; i < NUM_DCHANS; i++) {
13552
 
                if (!pri->dchannels[i])
13553
 
                        break;
13554
 
                pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13555
 
                x = pri->dchannels[i];
13556
 
                if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13557
 
                        ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13558
 
                        return -1;
13559
 
                }
13560
 
                memset(&p, 0, sizeof(p));
13561
 
                res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13562
 
                if (res) {
13563
 
                        dahdi_close_pri_fd(pri, i);
13564
 
                        ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13565
 
                        return -1;
13566
 
                }
13567
 
                if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13568
 
                        dahdi_close_pri_fd(pri, i);
13569
 
                        ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13570
 
                        return -1;
13571
 
                }
13572
 
                memset(&si, 0, sizeof(si));
13573
 
                res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13574
 
                if (res) {
13575
 
                        dahdi_close_pri_fd(pri, i);
13576
 
                        ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13577
 
                }
13578
 
                if (!si.alarms)
13579
 
                        pri->dchanavail[i] |= DCHAN_NOTINALARM;
13580
 
                else
13581
 
                        pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13582
 
                memset(&bi, 0, sizeof(bi));
13583
 
                bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13584
 
                bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13585
 
                bi.numbufs = 32;
13586
 
                bi.bufsize = 1024;
13587
 
                if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13588
 
                        ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13589
 
                        dahdi_close_pri_fd(pri, i);
13590
 
                        return -1;
13591
 
                }
13592
 
                switch (pri->sig) {
13593
 
                case SIG_BRI:
13594
 
                        pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13595
 
                        break;
13596
 
                case SIG_BRI_PTMP:
13597
 
                        pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13598
 
                        break;
13599
 
                default:
13600
 
                        pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13601
 
                        break;
13602
 
                }
13603
 
                /* Force overlap dial if we're doing GR-303! */
13604
 
                if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13605
 
                        pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13606
 
                pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13607
 
#ifdef HAVE_PRI_PROG_W_CAUSE
13608
 
                pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13609
 
#endif
13610
 
#ifdef HAVE_PRI_INBANDDISCONNECT
13611
 
                pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13612
 
#endif
13613
 
                /* Enslave to master if appropriate */
13614
 
                if (i)
13615
 
                        pri_enslave(pri->dchans[0], pri->dchans[i]);
13616
 
                if (!pri->dchans[i]) {
13617
 
                        dahdi_close_pri_fd(pri, i);
13618
 
                        ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13619
 
                        return -1;
13620
 
                }
13621
 
                pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13622
 
                pri_set_nsf(pri->dchans[i], pri->nsf);
13623
 
#ifdef PRI_GETSET_TIMERS
13624
 
                for (x = 0; x < PRI_MAX_TIMERS; x++) {
13625
 
                        if (pritimers[x] != 0)
13626
 
                                pri_set_timer(pri->dchans[i], x, pritimers[x]);
13627
 
                }
13628
 
#endif
13629
 
        }
13630
 
        /* Assume primary is the one we use */
13631
 
        pri->pri = pri->dchans[0];
13632
 
        pri->resetpos = -1;
13633
 
        if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13634
 
                for (i = 0; i < NUM_DCHANS; i++) {
13635
 
                        if (!pri->dchannels[i])
13636
 
                                break;
13637
 
                        dahdi_close_pri_fd(pri, i);
13638
 
                }
13639
 
                ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13640
 
                return -1;
13641
 
        }
13642
 
        return 0;
13643
 
}
13644
 
#endif  /* defined(HAVE_PRI) */
13645
 
 
13646
 
#if defined(HAVE_PRI)
13647
 
static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13648
 
{
13649
 
        int which, span;
13650
 
        char *ret = NULL;
13651
 
 
13652
 
        if (pos != rpos)
13653
 
                return ret;
13654
 
 
13655
 
        for (which = span = 0; span < NUM_SPANS; span++) {
13656
 
                if (pris[span].pri && ++which > state) {
13657
 
                        if (asprintf(&ret, "%d", span + 1) < 0) {       /* user indexes start from 1 */
13658
 
                                ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13659
 
                        }
13660
 
                        break;
13661
 
                }
13662
 
        }
13663
 
        return ret;
13664
 
}
13665
 
#endif  /* defined(HAVE_PRI) */
13666
 
 
13667
 
#if defined(HAVE_PRI)
13668
 
static char *complete_span_4(const char *line, const char *word, int pos, int state)
13669
 
{
13670
 
        return complete_span_helper(line,word,pos,state,3);
13671
 
}
13672
 
#endif  /* defined(HAVE_PRI) */
13673
 
 
13674
 
#if defined(HAVE_PRI)
13675
 
static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13676
 
{
13677
 
        int myfd;
13678
 
        switch (cmd) {
13679
 
        case CLI_INIT:
13680
 
                e->command = "pri set debug file";
13681
 
                e->usage = "Usage: pri set debug file [output-file]\n"
13682
 
                        "       Sends PRI debug output to the specified output file\n";
13683
 
                return NULL;
13684
 
        case CLI_GENERATE:
13685
 
                return NULL;
13686
 
        }
13687
 
        if (a->argc < 5)
13688
 
                return CLI_SHOWUSAGE;
13689
 
 
13690
 
        if (ast_strlen_zero(a->argv[4]))
13691
 
                return CLI_SHOWUSAGE;
13692
 
 
13693
 
        myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13694
 
        if (myfd < 0) {
13695
 
                ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13696
 
                return CLI_SUCCESS;
13697
 
        }
13698
 
 
13699
 
        ast_mutex_lock(&pridebugfdlock);
13700
 
 
13701
 
        if (pridebugfd >= 0)
13702
 
                close(pridebugfd);
13703
 
 
13704
 
        pridebugfd = myfd;
13705
 
        ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13706
 
        ast_mutex_unlock(&pridebugfdlock);
13707
 
        ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13708
 
        return CLI_SUCCESS;
13709
 
}
13710
 
#endif  /* defined(HAVE_PRI) */
13711
 
 
13712
 
#if defined(HAVE_PRI)
13713
 
static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13714
 
{
13715
 
        int span;
13716
 
        int x;
13717
 
        int level = 0;
13718
 
        switch (cmd) {
13719
 
        case CLI_INIT:
13720
 
                e->command = "pri set debug {on|off|0|1|2} span";
13721
 
                e->usage =
13722
 
                        "Usage: pri set debug {<level>|on|off} span <span>\n"
13723
 
                        "       Enables debugging on a given PRI span\n";
13724
 
                return NULL;
13725
 
        case CLI_GENERATE:
13726
 
                return complete_span_4(a->line, a->word, a->pos, a->n);
13727
 
        }
13728
 
        if (a->argc < 6) {
13729
 
                return CLI_SHOWUSAGE;
13730
 
        }
13731
 
 
13732
 
        if (!strcasecmp(a->argv[3], "on")) {
13733
 
                level = 1;
13734
 
        } else if (!strcasecmp(a->argv[3], "off")) {
13735
 
                level = 0;
13736
 
        } else {
13737
 
                level = atoi(a->argv[3]);
13738
 
        }
13739
 
        span = atoi(a->argv[5]);
13740
 
        if ((span < 1) || (span > NUM_SPANS)) {
13741
 
                ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13742
 
                return CLI_SUCCESS;
13743
 
        }
13744
 
        if (!pris[span-1].pri) {
13745
 
                ast_cli(a->fd, "No PRI running on span %d\n", span);
13746
 
                return CLI_SUCCESS;
13747
 
        }
13748
 
        for (x = 0; x < NUM_DCHANS; x++) {
13749
 
                if (pris[span-1].dchans[x]) {
13750
 
                        if (level == 1) {
13751
 
                                pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13752
 
                                        PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13753
 
                                        PRI_DEBUG_Q921_STATE);
13754
 
                                ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13755
 
                        } else if (level == 0) {
13756
 
                                pri_set_debug(pris[span-1].dchans[x], 0);
13757
 
                                //close the file if it's set
13758
 
                                ast_mutex_lock(&pridebugfdlock);
13759
 
                                close(pridebugfd);
13760
 
                                pridebugfd = -1;
13761
 
                                ast_cli(a->fd, "PRI debug output to file disabled\n");
13762
 
                                ast_mutex_unlock(&pridebugfdlock);
13763
 
                        } else {
13764
 
                                pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13765
 
                                        PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13766
 
                                        PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13767
 
                                ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13768
 
                        }
13769
 
                }
13770
 
        }
13771
 
        return CLI_SUCCESS;
13772
 
}
13773
 
#endif  /* defined(HAVE_PRI) */
13774
 
 
13775
 
#if defined(HAVE_PRI)
13776
 
static void build_status(char *s, size_t len, int status, int active)
13777
 
{
13778
 
        if (!s || len < 1) {
13779
 
                return;
13780
 
        }
13781
 
        s[0] = '\0';
13782
 
        if (status & DCHAN_PROVISIONED)
13783
 
                strncat(s, "Provisioned, ", len - strlen(s) - 1);
13784
 
        if (!(status & DCHAN_NOTINALARM))
13785
 
                strncat(s, "In Alarm, ", len - strlen(s) - 1);
13786
 
        if (status & DCHAN_UP)
13787
 
                strncat(s, "Up", len - strlen(s) - 1);
13788
 
        else
13789
 
                strncat(s, "Down", len - strlen(s) - 1);
13790
 
        if (active)
13791
 
                strncat(s, ", Active", len - strlen(s) - 1);
13792
 
        else
13793
 
                strncat(s, ", Standby", len - strlen(s) - 1);
13794
 
        s[len - 1] = '\0';
13795
 
}
13796
 
#endif  /* defined(HAVE_PRI) */
13797
 
 
13798
 
#if defined(HAVE_PRI)
13799
 
static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13800
 
{
13801
 
        int span;
13802
 
        int x;
13803
 
        char status[256];
13804
 
 
13805
 
        switch (cmd) {
13806
 
        case CLI_INIT:
13807
 
                e->command = "pri show spans";
13808
 
                e->usage =
13809
 
                        "Usage: pri show spans\n"
13810
 
                        "       Displays PRI Information\n";
13811
 
                return NULL;
13812
 
        case CLI_GENERATE:
13813
 
                return NULL;
13814
 
        }
13815
 
 
13816
 
        if (a->argc != 3)
13817
 
                return CLI_SHOWUSAGE;
13818
 
 
13819
 
        for (span = 0; span < NUM_SPANS; span++) {
13820
 
                if (pris[span].pri) {
13821
 
                        for (x = 0; x < NUM_DCHANS; x++) {
13822
 
                                if (pris[span].dchannels[x]) {
13823
 
                                        build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13824
 
                                        ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13825
 
                                }
13826
 
                        }
13827
 
                }
13828
 
        }
13829
 
        return CLI_SUCCESS;
13830
 
}
13831
 
#endif  /* defined(HAVE_PRI) */
13832
 
 
13833
 
#if defined(HAVE_PRI)
13834
 
static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13835
 
{
13836
 
        int span;
13837
 
        int x;
13838
 
        char status[256];
13839
 
        switch (cmd) {
13840
 
        case CLI_INIT:
13841
 
                e->command = "pri show span";
13842
 
                e->usage =
13843
 
                        "Usage: pri show span <span>\n"
13844
 
                        "       Displays PRI Information on a given PRI span\n";
13845
 
                return NULL;
13846
 
        case CLI_GENERATE:
13847
 
                return complete_span_4(a->line, a->word, a->pos, a->n);
13848
 
        }
13849
 
 
13850
 
        if (a->argc < 4)
13851
 
                return CLI_SHOWUSAGE;
13852
 
        span = atoi(a->argv[3]);
13853
 
        if ((span < 1) || (span > NUM_SPANS)) {
13854
 
                ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13855
 
                return CLI_SUCCESS;
13856
 
        }
13857
 
        if (!pris[span-1].pri) {
13858
 
                ast_cli(a->fd, "No PRI running on span %d\n", span);
13859
 
                return CLI_SUCCESS;
13860
 
        }
13861
 
        for (x = 0; x < NUM_DCHANS; x++) {
13862
 
                if (pris[span-1].dchannels[x]) {
13863
 
#ifdef PRI_DUMP_INFO_STR
13864
 
                        char *info_str = NULL;
13865
 
#endif
13866
 
                        ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13867
 
                        build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13868
 
                        ast_cli(a->fd, "Status: %s\n", status);
13869
 
#ifdef PRI_DUMP_INFO_STR
13870
 
                        info_str = pri_dump_info_str(pris[span-1].pri);
13871
 
                        if (info_str) {
13872
 
                                ast_cli(a->fd, "%s", info_str);
13873
 
                                ast_free(info_str);
13874
 
                        }
13875
 
#else
13876
 
                        pri_dump_info(pris[span-1].pri);
13877
 
#endif
13878
 
                        ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13879
 
                }
13880
 
        }
13881
 
        return CLI_SUCCESS;
13882
 
}
13883
 
#endif  /* defined(HAVE_PRI) */
13884
 
 
13885
 
#if defined(HAVE_PRI)
13886
 
static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13887
 
{
13888
 
        int x;
13889
 
        int span;
13890
 
        int count=0;
13891
 
        int debug=0;
13892
 
 
13893
 
        switch (cmd) {
13894
 
        case CLI_INIT:
13895
 
                e->command = "pri show debug";
13896
 
                e->usage =
13897
 
                        "Usage: pri show debug\n"
13898
 
                        "       Show the debug state of pri spans\n";
13899
 
                return NULL;
13900
 
        case CLI_GENERATE:
13901
 
                return NULL;
13902
 
        }
13903
 
 
13904
 
        for (span = 0; span < NUM_SPANS; span++) {
13905
 
                if (pris[span].pri) {
13906
 
                        for (x = 0; x < NUM_DCHANS; x++) {
13907
 
                                debug = 0;
13908
 
                                if (pris[span].dchans[x]) {
13909
 
                                        debug = pri_get_debug(pris[span].dchans[x]);
13910
 
                                        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" );
13911
 
                                        count++;
13912
 
                                }
13913
 
                        }
13914
 
                }
13915
 
 
13916
 
        }
13917
 
        ast_mutex_lock(&pridebugfdlock);
13918
 
        if (pridebugfd >= 0)
13919
 
                ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
13920
 
        ast_mutex_unlock(&pridebugfdlock);
13921
 
 
13922
 
        if (!count)
13923
 
                ast_cli(a->fd, "No debug set or no PRI running\n");
13924
 
        return CLI_SUCCESS;
13925
 
}
13926
 
#endif  /* defined(HAVE_PRI) */
13927
 
 
13928
 
#if defined(HAVE_PRI)
13929
 
static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13930
 
{
13931
 
        switch (cmd) {
13932
 
        case CLI_INIT:
13933
 
                e->command = "pri show version";
13934
 
                e->usage =
13935
 
                        "Usage: pri show version\n"
13936
 
                        "Show libpri version information\n";
13937
 
                return NULL;
13938
 
        case CLI_GENERATE:
13939
 
                return NULL;
13940
 
        }
13941
 
 
13942
 
        ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
13943
 
 
13944
 
        return CLI_SUCCESS;
13945
 
}
13946
 
#endif  /* defined(HAVE_PRI) */
13947
 
 
13948
 
#if defined(HAVE_PRI)
13949
 
static struct ast_cli_entry dahdi_pri_cli[] = {
13950
 
        AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
13951
 
        AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
13952
 
        AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
13953
 
        AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
13954
 
        AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
13955
 
        AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
13956
 
};
13957
 
#endif  /* defined(HAVE_PRI) */
13958
 
 
13959
 
#ifdef HAVE_OPENR2
13960
 
 
13961
 
static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13962
 
{
13963
 
        switch (cmd) {
13964
 
        case CLI_INIT:
13965
 
                e->command = "mfcr2 show version";
13966
 
                e->usage =
13967
 
                        "Usage: mfcr2 show version\n"
13968
 
                        "       Shows the version of the OpenR2 library being used.\n";
13969
 
                return NULL;
13970
 
        case CLI_GENERATE:
13971
 
                return NULL;
13972
 
        }
13973
 
        ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
13974
 
        return CLI_SUCCESS;
13975
 
}
13976
 
 
13977
 
static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13978
 
{
13979
 
#define FORMAT "%4s %40s\n"
13980
 
        int i = 0;
13981
 
        int numvariants = 0;
13982
 
        const openr2_variant_entry_t *variants;
13983
 
        switch (cmd) {
13984
 
        case CLI_INIT:
13985
 
                e->command = "mfcr2 show variants";
13986
 
                e->usage =
13987
 
                        "Usage: mfcr2 show variants\n"
13988
 
                        "       Shows the list of MFC/R2 variants supported.\n";
13989
 
                return NULL;
13990
 
        case CLI_GENERATE:
13991
 
                return NULL;
13992
 
        }
13993
 
        if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
13994
 
                ast_cli(a->fd, "Failed to get list of variants.\n");
13995
 
                return CLI_FAILURE;
13996
 
        }
13997
 
        ast_cli(a->fd, FORMAT, "Variant Code", "Country");
13998
 
        for (i = 0; i < numvariants; i++) {
13999
 
                ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14000
 
        }
14001
 
        return CLI_SUCCESS;
14002
 
#undef FORMAT
14003
 
}
14004
 
 
14005
 
static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14006
 
{
14007
 
#define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14008
 
        int filtertype = 0;
14009
 
        int targetnum = 0;
14010
 
        char channo[5];
14011
 
        char anino[5];
14012
 
        char dnisno[5];
14013
 
        struct dahdi_pvt *p;
14014
 
        openr2_context_t *r2context;
14015
 
        openr2_variant_t r2variant;
14016
 
        switch (cmd) {
14017
 
        case CLI_INIT:
14018
 
                e->command = "mfcr2 show channels [group|context]";
14019
 
                e->usage =
14020
 
                        "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14021
 
                        "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14022
 
                return NULL;
14023
 
        case CLI_GENERATE:
14024
 
                return NULL;
14025
 
        }
14026
 
        if (!((a->argc == 3) || (a->argc == 5))) {
14027
 
                return CLI_SHOWUSAGE;
14028
 
        }
14029
 
        if (a->argc == 5) {
14030
 
                if (!strcasecmp(a->argv[3], "group")) {
14031
 
                        targetnum = atoi(a->argv[4]);
14032
 
                        if ((targetnum < 0) || (targetnum > 63))
14033
 
                                return CLI_SHOWUSAGE;
14034
 
                        targetnum = 1 << targetnum;
14035
 
                        filtertype = 1;
14036
 
                } else if (!strcasecmp(a->argv[3], "context")) {
14037
 
                        filtertype = 2;
14038
 
                } else {
14039
 
                        return CLI_SHOWUSAGE;
14040
 
                }
14041
 
        }
14042
 
        ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14043
 
        ast_mutex_lock(&iflock);
14044
 
        p = iflist;
14045
 
        for (p = iflist; p; p = p->next) {
14046
 
                if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14047
 
                        continue;
14048
 
                }
14049
 
                if (filtertype) {
14050
 
                        switch(filtertype) {
14051
 
                        case 1: /* mfcr2 show channels group <group> */
14052
 
                                if (p->group != targetnum) {
14053
 
                                        continue;
14054
 
                                }
14055
 
                                break;
14056
 
                        case 2: /* mfcr2 show channels context <context> */
14057
 
                                if (strcasecmp(p->context, a->argv[4])) {
14058
 
                                        continue;
14059
 
                                }
14060
 
                                break;
14061
 
                        default:
14062
 
                                ;
14063
 
                        }
14064
 
                }
14065
 
                r2context = openr2_chan_get_context(p->r2chan);
14066
 
                r2variant = openr2_context_get_variant(r2context);
14067
 
                snprintf(channo, sizeof(channo), "%d", p->channel);
14068
 
                snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14069
 
                snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14070
 
                ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14071
 
                                anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14072
 
                                openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14073
 
                                openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14074
 
        }
14075
 
        ast_mutex_unlock(&iflock);
14076
 
        return CLI_SUCCESS;
14077
 
#undef FORMAT
14078
 
}
14079
 
 
14080
 
static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14081
 
{
14082
 
        struct dahdi_pvt *p = NULL;
14083
 
        int channo = 0;
14084
 
        char *toklevel = NULL;
14085
 
        char *saveptr = NULL;
14086
 
        char *logval = NULL;
14087
 
        openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14088
 
        openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14089
 
        switch (cmd) {
14090
 
        case CLI_INIT:
14091
 
                e->command = "mfcr2 set debug";
14092
 
                e->usage =
14093
 
                        "Usage: mfcr2 set debug <loglevel> <channel>\n"
14094
 
                        "       Set a new logging level for the specified channel.\n"
14095
 
                        "       If no channel is specified the logging level will be applied to all channels.\n";
14096
 
                return NULL;
14097
 
        case CLI_GENERATE:
14098
 
                return NULL;
14099
 
        }
14100
 
        if (a->argc < 4) {
14101
 
                return CLI_SHOWUSAGE;
14102
 
        }
14103
 
        channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14104
 
        logval = ast_strdupa(a->argv[3]);
14105
 
        toklevel = strtok_r(logval, ",", &saveptr);
14106
 
        if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14107
 
                ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14108
 
                return CLI_FAILURE;
14109
 
        } else if (OR2_LOG_NOTHING == tmplevel) {
14110
 
                loglevel = tmplevel;
14111
 
        } else {
14112
 
                loglevel |= tmplevel;
14113
 
                while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14114
 
                        if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14115
 
                                ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14116
 
                                continue;
14117
 
                        }
14118
 
                        loglevel |= tmplevel;
14119
 
                }
14120
 
        }
14121
 
        ast_mutex_lock(&iflock);
14122
 
        for (p = iflist; p; p = p->next) {
14123
 
                if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14124
 
                        continue;
14125
 
                }
14126
 
                if ((channo != -1) && (p->channel != channo )) {
14127
 
                        continue;
14128
 
                }
14129
 
                openr2_chan_set_log_level(p->r2chan, loglevel);
14130
 
                if (channo != -1) {
14131
 
                        ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14132
 
                        break;
14133
 
                }
14134
 
        }
14135
 
        if ((channo != -1) && !p) {
14136
 
                ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14137
 
        }
14138
 
        if (channo == -1) {
14139
 
                ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14140
 
        }
14141
 
        ast_mutex_unlock(&iflock);
14142
 
        return CLI_SUCCESS;
14143
 
}
14144
 
 
14145
 
static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14146
 
{
14147
 
        struct dahdi_pvt *p = NULL;
14148
 
        int channo = 0;
14149
 
        switch (cmd) {
14150
 
        case CLI_INIT:
14151
 
                e->command = "mfcr2 call files [on|off]";
14152
 
                e->usage =
14153
 
                        "Usage: mfcr2 call files [on|off] <channel>\n"
14154
 
                        "       Enable call files creation on the specified channel.\n"
14155
 
                        "       If no channel is specified call files creation policy will be applied to all channels.\n";
14156
 
                return NULL;
14157
 
        case CLI_GENERATE:
14158
 
                return NULL;
14159
 
        }
14160
 
        if (a->argc < 4) {
14161
 
                return CLI_SHOWUSAGE;
14162
 
        }
14163
 
        channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14164
 
        ast_mutex_lock(&iflock);
14165
 
        for (p = iflist; p; p = p->next) {
14166
 
                if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14167
 
                        continue;
14168
 
                }
14169
 
                if ((channo != -1) && (p->channel != channo )) {
14170
 
                        continue;
14171
 
                }
14172
 
                if (ast_true(a->argv[3])) {
14173
 
                        openr2_chan_enable_call_files(p->r2chan);
14174
 
                } else {
14175
 
                        openr2_chan_disable_call_files(p->r2chan);
14176
 
                }
14177
 
                if (channo != -1) {
14178
 
                        if (ast_true(a->argv[3])) {
14179
 
                                ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14180
 
                        } else {
14181
 
                                ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14182
 
                        }
14183
 
                        break;
14184
 
                }
14185
 
        }
14186
 
        if ((channo != -1) && !p) {
14187
 
                ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14188
 
        }
14189
 
        if (channo == -1) {
14190
 
                if (ast_true(a->argv[3])) {
14191
 
                        ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14192
 
                } else {
14193
 
                        ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14194
 
                }
14195
 
        }
14196
 
        ast_mutex_unlock(&iflock);
14197
 
        return CLI_SUCCESS;
14198
 
}
14199
 
 
14200
 
static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14201
 
{
14202
 
        struct dahdi_pvt *p = NULL;
14203
 
        int channo = 0;
14204
 
        switch (cmd) {
14205
 
        case CLI_INIT:
14206
 
                e->command = "mfcr2 set idle";
14207
 
                e->usage =
14208
 
                        "Usage: mfcr2 set idle <channel>\n"
14209
 
                        "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14210
 
                        "       Force the given channel into IDLE state.\n"
14211
 
                        "       If no channel is specified, all channels will be set to IDLE.\n";
14212
 
                return NULL;
14213
 
        case CLI_GENERATE:
14214
 
                return NULL;
14215
 
        }
14216
 
        channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14217
 
        ast_mutex_lock(&iflock);
14218
 
        for (p = iflist; p; p = p->next) {
14219
 
                if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14220
 
                        continue;
14221
 
                }
14222
 
                if ((channo != -1) && (p->channel != channo )) {
14223
 
                        continue;
14224
 
                }
14225
 
                openr2_chan_set_idle(p->r2chan);
14226
 
                ast_mutex_lock(&p->lock);
14227
 
                p->locallyblocked = 0;
14228
 
                p->mfcr2call = 0;
14229
 
                ast_mutex_unlock(&p->lock);
14230
 
                if (channo != -1) {
14231
 
                        break;
14232
 
                }
14233
 
        }
14234
 
        if ((channo != -1) && !p) {
14235
 
                ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14236
 
        }
14237
 
        ast_mutex_unlock(&iflock);
14238
 
        return CLI_SUCCESS;
14239
 
}
14240
 
 
14241
 
static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14242
 
{
14243
 
        struct dahdi_pvt *p = NULL;
14244
 
        int channo = 0;
14245
 
        switch (cmd) {
14246
 
        case CLI_INIT:
14247
 
                e->command = "mfcr2 set blocked";
14248
 
                e->usage =
14249
 
                        "Usage: mfcr2 set blocked <channel>\n"
14250
 
                        "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14251
 
                        "       Force the given channel into BLOCKED state.\n"
14252
 
                        "       If no channel is specified, all channels will be set to BLOCKED.\n";
14253
 
                return NULL;
14254
 
        case CLI_GENERATE:
14255
 
                return NULL;
14256
 
        }
14257
 
        channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14258
 
        ast_mutex_lock(&iflock);
14259
 
        for (p = iflist; p; p = p->next) {
14260
 
                if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14261
 
                        continue;
14262
 
                }
14263
 
                if ((channo != -1) && (p->channel != channo )) {
14264
 
                        continue;
14265
 
                }
14266
 
                openr2_chan_set_blocked(p->r2chan);
14267
 
                ast_mutex_lock(&p->lock);
14268
 
                p->locallyblocked = 1;
14269
 
                ast_mutex_unlock(&p->lock);
14270
 
                if (channo != -1) {
14271
 
                        break;
14272
 
                }
14273
 
        }
14274
 
        if ((channo != -1) && !p) {
14275
 
                ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14276
 
        }
14277
 
        ast_mutex_unlock(&iflock);
14278
 
        return CLI_SUCCESS;
14279
 
}
14280
 
 
14281
 
static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14282
 
        AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14283
 
        AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14284
 
        AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14285
 
        AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14286
 
        AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14287
 
        AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14288
 
        AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14289
 
};
14290
 
 
14291
 
#endif /* HAVE_OPENR2 */
14292
 
 
14293
 
static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14294
 
{
14295
 
        int channel;
14296
 
        int ret;
14297
 
        switch (cmd) {
14298
 
        case CLI_INIT:
14299
 
                e->command = "dahdi destroy channel";
14300
 
                e->usage =
14301
 
                        "Usage: dahdi destroy channel <chan num>\n"
14302
 
                        "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14303
 
                return NULL;
14304
 
        case CLI_GENERATE:
14305
 
                return NULL;
14306
 
        }
14307
 
        if (a->argc != 4)
14308
 
                return CLI_SHOWUSAGE;
14309
 
 
14310
 
        channel = atoi(a->argv[3]);
14311
 
        ret = dahdi_destroy_channel_bynum(channel);
14312
 
        return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14313
 
}
14314
 
 
14315
 
static void dahdi_softhangup_all(void)
14316
 
{
14317
 
        struct dahdi_pvt *p;
14318
 
retry:
14319
 
        ast_mutex_lock(&iflock);
14320
 
        for (p = iflist; p; p = p->next) {
14321
 
                ast_mutex_lock(&p->lock);
14322
 
                if (p->owner && !p->restartpending) {
14323
 
                        if (ast_channel_trylock(p->owner)) {
14324
 
                                if (option_debug > 2)
14325
 
                                        ast_verbose("Avoiding deadlock\n");
14326
 
                                /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14327
 
                                ast_mutex_unlock(&p->lock);
14328
 
                                ast_mutex_unlock(&iflock);
14329
 
                                goto retry;
14330
 
                        }
14331
 
                        if (option_debug > 2)
14332
 
                                ast_verbose("Softhanging up on %s\n", p->owner->name);
14333
 
                        ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14334
 
                        p->restartpending = 1;
14335
 
                        num_restart_pending++;
14336
 
                        ast_channel_unlock(p->owner);
14337
 
                }
14338
 
                ast_mutex_unlock(&p->lock);
14339
 
        }
14340
 
        ast_mutex_unlock(&iflock);
14341
 
}
14342
 
 
14343
 
static int setup_dahdi(int reload);
14344
 
static int dahdi_restart(void)
14345
 
{
14346
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
14347
 
        int i, j;
14348
 
#endif
14349
 
        int cancel_code;
14350
 
        struct dahdi_pvt *p;
14351
 
 
14352
 
        ast_mutex_lock(&restart_lock);
14353
 
        ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14354
 
        dahdi_softhangup_all();
14355
 
        ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14356
 
#ifdef HAVE_OPENR2
14357
 
        dahdi_r2_destroy_links();
14358
 
#endif
14359
 
 
14360
 
#if defined(HAVE_PRI)
14361
 
        for (i = 0; i < NUM_SPANS; i++) {
14362
 
                if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14363
 
                        cancel_code = pthread_cancel(pris[i].master);
14364
 
                        pthread_kill(pris[i].master, SIGURG);
14365
 
                        ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14366
 
                        pthread_join(pris[i].master, NULL);
14367
 
                        ast_debug(4, "Joined thread of span %d\n", i);
14368
 
                }
14369
 
        }
14370
 
#endif
14371
 
 
14372
 
#if defined(HAVE_SS7)
14373
 
        for (i = 0; i < NUM_SPANS; i++) {
14374
 
                if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14375
 
                        cancel_code = pthread_cancel(linksets[i].master);
14376
 
                        pthread_kill(linksets[i].master, SIGURG);
14377
 
                        ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14378
 
                        pthread_join(linksets[i].master, NULL);
14379
 
                        ast_debug(4, "Joined thread of span %d\n", i);
14380
 
                }
14381
 
        }
14382
 
#endif
14383
 
 
14384
 
        ast_mutex_lock(&monlock);
14385
 
        if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14386
 
                cancel_code = pthread_cancel(monitor_thread);
14387
 
                pthread_kill(monitor_thread, SIGURG);
14388
 
                ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14389
 
                pthread_join(monitor_thread, NULL);
14390
 
                ast_debug(4, "Joined monitor thread\n");
14391
 
        }
14392
 
        monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14393
 
 
14394
 
        ast_mutex_lock(&ss_thread_lock);
14395
 
        while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14396
 
                int x = DAHDI_FLASH;
14397
 
                ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14398
 
 
14399
 
                for (p = iflist; p; p = p->next) {
14400
 
                        if (p->owner)
14401
 
                                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
14402
 
                        }
14403
 
                        ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14404
 
                }
14405
 
 
14406
 
        /* ensure any created channels before monitor threads were stopped are hungup */
14407
 
        dahdi_softhangup_all();
14408
 
        ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14409
 
        destroy_all_channels();
14410
 
        ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14411
 
 
14412
 
        ast_mutex_unlock(&monlock);
14413
 
 
14414
 
#ifdef HAVE_PRI
14415
 
        for (i = 0; i < NUM_SPANS; i++) {
14416
 
                for (j = 0; j < NUM_DCHANS; j++)
14417
 
                        dahdi_close_pri_fd(&(pris[i]), j);
14418
 
        }
14419
 
 
14420
 
        memset(pris, 0, sizeof(pris));
14421
 
        for (i = 0; i < NUM_SPANS; i++) {
14422
 
                ast_mutex_init(&pris[i].lock);
14423
 
                pris[i].offset = -1;
14424
 
                pris[i].master = AST_PTHREADT_NULL;
14425
 
                for (j = 0; j < NUM_DCHANS; j++)
14426
 
                        pris[i].fds[j] = -1;
14427
 
                }
14428
 
        pri_set_error(dahdi_pri_error);
14429
 
        pri_set_message(dahdi_pri_message);
14430
 
#endif
14431
 
#ifdef HAVE_SS7
14432
 
        for (i = 0; i < NUM_SPANS; i++) {
14433
 
                for (j = 0; j < NUM_DCHANS; j++)
14434
 
                        dahdi_close_ss7_fd(&(linksets[i]), j);
14435
 
        }
14436
 
 
14437
 
        memset(linksets, 0, sizeof(linksets));
14438
 
        for (i = 0; i < NUM_SPANS; i++) {
14439
 
                ast_mutex_init(&linksets[i].lock);
14440
 
                linksets[i].master = AST_PTHREADT_NULL;
14441
 
                for (j = 0; j < NUM_DCHANS; j++)
14442
 
                        linksets[i].fds[j] = -1;
14443
 
        }
14444
 
        ss7_set_error(dahdi_ss7_error);
14445
 
        ss7_set_message(dahdi_ss7_message);
14446
 
#endif
14447
 
 
14448
 
        if (setup_dahdi(2) != 0) {
14449
 
                ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14450
 
                ast_mutex_unlock(&ss_thread_lock);
14451
 
                return 1;
14452
 
        }
14453
 
        ast_mutex_unlock(&ss_thread_lock);
14454
 
        ast_mutex_unlock(&restart_lock);
14455
 
        return 0;
14456
 
}
14457
 
 
14458
 
static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14459
 
{
14460
 
        switch (cmd) {
14461
 
        case CLI_INIT:
14462
 
                e->command = "dahdi restart";
14463
 
                e->usage =
14464
 
                        "Usage: dahdi restart\n"
14465
 
                        "       Restarts the DAHDI channels: destroys them all and then\n"
14466
 
                        "       re-reads them from chan_dahdi.conf.\n"
14467
 
                        "       Note that this will STOP any running CALL on DAHDI channels.\n"
14468
 
                        "";
14469
 
                return NULL;
14470
 
        case CLI_GENERATE:
14471
 
                return NULL;
14472
 
        }
14473
 
        if (a->argc != 2)
14474
 
                return CLI_SHOWUSAGE;
14475
 
 
14476
 
        if (dahdi_restart() != 0)
14477
 
                return CLI_FAILURE;
14478
 
        return CLI_SUCCESS;
14479
 
}
14480
 
 
14481
 
static int action_dahdirestart(struct mansession *s, const struct message *m)
14482
 
{
14483
 
        if (dahdi_restart() != 0) {
14484
 
                astman_send_error(s, m, "Failed rereading DAHDI configuration");
14485
 
                return 1;
14486
 
        }
14487
 
        astman_send_ack(s, m, "DAHDIRestart: Success");
14488
 
        return 0;
14489
 
}
14490
 
 
14491
 
static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14492
 
{
14493
 
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14494
 
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14495
 
        unsigned int targetnum = 0;
14496
 
        int filtertype = 0;
14497
 
        struct dahdi_pvt *tmp = NULL;
14498
 
        char tmps[20] = "";
14499
 
        char statestr[20] = "";
14500
 
        char blockstr[20] = "";
14501
 
        ast_mutex_t *lock;
14502
 
        struct dahdi_pvt *start;
14503
 
#ifdef HAVE_PRI
14504
 
        int trunkgroup;
14505
 
        struct dahdi_pri *pri = NULL;
14506
 
        int x;
14507
 
#endif
14508
 
        switch (cmd) {
14509
 
        case CLI_INIT:
14510
 
                e->command = "dahdi show channels [trunkgroup|group|context]";
14511
 
                e->usage =
14512
 
                        "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14513
 
                        "       Shows a list of available channels with optional filtering\n"
14514
 
                        "       <group> must be a number between 0 and 63\n";
14515
 
                return NULL;
14516
 
        case CLI_GENERATE:
14517
 
                return NULL;
14518
 
        }
14519
 
 
14520
 
        lock = &iflock;
14521
 
        start = iflist;
14522
 
 
14523
 
        /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
14524
 
 
14525
 
        if (!((a->argc == 3) || (a->argc == 5)))
14526
 
                return CLI_SHOWUSAGE;
14527
 
 
14528
 
        if (a->argc == 5) {
14529
 
#ifdef HAVE_PRI
14530
 
                if (!strcasecmp(a->argv[3], "trunkgroup")) {
14531
 
                        /* this option requires no special handling, so leave filtertype to zero */
14532
 
                        if ((trunkgroup = atoi(a->argv[4])) < 1)
14533
 
                                return CLI_SHOWUSAGE;
14534
 
                        for (x = 0; x < NUM_SPANS; x++) {
14535
 
                                if (pris[x].trunkgroup == trunkgroup) {
14536
 
                                        pri = pris + x;
14537
 
                                        break;
14538
 
                                }
14539
 
                        }
14540
 
                        if (pri) {
14541
 
                                start = pri->crvs;
14542
 
                                lock = &pri->lock;
14543
 
                        } else {
14544
 
                                ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14545
 
                                return CLI_FAILURE;
14546
 
                        }
14547
 
                } else
14548
 
#endif
14549
 
                if (!strcasecmp(a->argv[3], "group")) {
14550
 
                        targetnum = atoi(a->argv[4]);
14551
 
                        if ((targetnum < 0) || (targetnum > 63))
14552
 
                                return CLI_SHOWUSAGE;
14553
 
                        targetnum = 1 << targetnum;
14554
 
                        filtertype = 1;
14555
 
                } else if (!strcasecmp(a->argv[3], "context")) {
14556
 
                        filtertype = 2;
14557
 
                }
14558
 
        }
14559
 
 
14560
 
        ast_mutex_lock(lock);
14561
 
#ifdef HAVE_PRI
14562
 
        ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14563
 
#else
14564
 
        ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14565
 
#endif
14566
 
 
14567
 
        tmp = start;
14568
 
        while (tmp) {
14569
 
                if (filtertype) {
14570
 
                        switch(filtertype) {
14571
 
                        case 1: /* dahdi show channels group <group> */
14572
 
                                if (!(tmp->group & targetnum)) {
14573
 
                                        tmp = tmp->next;
14574
 
                                        continue;
14575
 
                                }
14576
 
                                break;
14577
 
                        case 2: /* dahdi show channels context <context> */
14578
 
                                if (strcasecmp(tmp->context, a->argv[4])) {
14579
 
                                        tmp = tmp->next;
14580
 
                                        continue;
14581
 
                                }
14582
 
                                break;
14583
 
                        default:
14584
 
                                ;
14585
 
                        }
14586
 
                }
14587
 
                if (tmp->channel > 0) {
14588
 
                        snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14589
 
                } else
14590
 
                        ast_copy_string(tmps, "pseudo", sizeof(tmps));
14591
 
 
14592
 
                if (tmp->locallyblocked)
14593
 
                        blockstr[0] = 'L';
14594
 
                else
14595
 
                        blockstr[0] = ' ';
14596
 
 
14597
 
                if (tmp->remotelyblocked)
14598
 
                        blockstr[1] = 'R';
14599
 
                else
14600
 
                        blockstr[1] = ' ';
14601
 
 
14602
 
                blockstr[2] = '\0';
14603
 
 
14604
 
                snprintf(statestr, sizeof(statestr), "%s", "In Service");
14605
 
 
14606
 
                ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14607
 
                tmp = tmp->next;
14608
 
        }
14609
 
        ast_mutex_unlock(lock);
14610
 
        return CLI_SUCCESS;
14611
 
#undef FORMAT
14612
 
#undef FORMAT2
14613
 
}
14614
 
 
14615
 
static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14616
 
{
14617
 
        int channel;
14618
 
        struct dahdi_pvt *tmp = NULL;
14619
 
        struct dahdi_confinfo ci;
14620
 
        struct dahdi_params ps;
14621
 
        int x;
14622
 
        ast_mutex_t *lock;
14623
 
        struct dahdi_pvt *start;
14624
 
#ifdef HAVE_PRI
14625
 
        char *c;
14626
 
        int trunkgroup;
14627
 
        struct dahdi_pri *pri=NULL;
14628
 
#endif
14629
 
        switch (cmd) {
14630
 
        case CLI_INIT:
14631
 
                e->command = "dahdi show channel";
14632
 
                e->usage =
14633
 
                        "Usage: dahdi show channel <chan num>\n"
14634
 
                        "       Detailed information about a given channel\n";
14635
 
                return NULL;
14636
 
        case CLI_GENERATE:
14637
 
                return NULL;
14638
 
        }
14639
 
 
14640
 
        lock = &iflock;
14641
 
        start = iflist;
14642
 
 
14643
 
        if (a->argc != 4)
14644
 
                return CLI_SHOWUSAGE;
14645
 
#ifdef HAVE_PRI
14646
 
        if ((c = strchr(a->argv[3], ':'))) {
14647
 
                if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14648
 
                        return CLI_SHOWUSAGE;
14649
 
                if ((trunkgroup < 1) || (channel < 1))
14650
 
                        return CLI_SHOWUSAGE;
14651
 
                for (x = 0; x < NUM_SPANS; x++) {
14652
 
                        if (pris[x].trunkgroup == trunkgroup) {
14653
 
                                pri = pris + x;
14654
 
                                break;
14655
 
                        }
14656
 
                }
14657
 
                if (pri) {
14658
 
                        start = pri->crvs;
14659
 
                        lock = &pri->lock;
14660
 
                } else {
14661
 
                        ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14662
 
                        return CLI_FAILURE;
14663
 
                }
14664
 
        } else
14665
 
#endif
14666
 
                channel = atoi(a->argv[3]);
14667
 
 
14668
 
        ast_mutex_lock(lock);
14669
 
        tmp = start;
14670
 
        while (tmp) {
14671
 
                if (tmp->channel == channel) {
14672
 
#ifdef HAVE_PRI
14673
 
                        if (pri)
14674
 
                                ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14675
 
                        else
14676
 
#endif
14677
 
                        ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14678
 
                        ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14679
 
                        ast_cli(a->fd, "Span: %d\n", tmp->span);
14680
 
                        ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14681
 
                        ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14682
 
                        ast_cli(a->fd, "Context: %s\n", tmp->context);
14683
 
                        ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14684
 
                        ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14685
 
                        ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14686
 
                        ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14687
 
                        if (tmp->vars) {
14688
 
                                struct ast_variable *v;
14689
 
                                ast_cli(a->fd, "Variables:\n");
14690
 
                                for (v = tmp->vars ; v ; v = v->next)
14691
 
                                        ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14692
 
                        }
14693
 
                        ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14694
 
                        ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14695
 
                        ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14696
 
                        ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14697
 
                        ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14698
 
                        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)" : "");
14699
 
                        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)" : "");
14700
 
                        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)" : "");
14701
 
                        ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14702
 
                        ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14703
 
                        ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14704
 
                        ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14705
 
                        ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14706
 
                        if (tmp->busydetect) {
14707
 
#if defined(BUSYDETECT_TONEONLY)
14708
 
                                ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14709
 
#elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14710
 
                                ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14711
 
#endif
14712
 
#ifdef BUSYDETECT_DEBUG
14713
 
                                ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14714
 
#endif
14715
 
                                ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14716
 
                                ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14717
 
                        }
14718
 
                        ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14719
 
                        ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14720
 
                        ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14721
 
                        ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14722
 
                        ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14723
 
                        ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14724
 
                        ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14725
 
                        ast_cli(a->fd, "Echo Cancellation:\n");
14726
 
 
14727
 
                        if (tmp->echocancel.head.tap_length) {
14728
 
                                ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14729
 
                                for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14730
 
                                        ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14731
 
                                }
14732
 
                                ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14733
 
                        } else {
14734
 
                                ast_cli(a->fd, "\tnone\n");
14735
 
                        }
14736
 
                        ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14737
 
                        if (tmp->master)
14738
 
                                ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14739
 
                        for (x = 0; x < MAX_SLAVES; x++) {
14740
 
                                if (tmp->slaves[x])
14741
 
                                        ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14742
 
                        }
14743
 
#ifdef HAVE_OPENR2
14744
 
                        if (tmp->mfcr2) {
14745
 
                                char calldir[OR2_MAX_PATH];
14746
 
                                openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14747
 
                                openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14748
 
                                ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14749
 
                                ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14750
 
                                ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14751
 
                                ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14752
 
                                ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14753
 
                                ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14754
 
                                ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14755
 
                                ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14756
 
                                ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14757
 
#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14758
 
                                ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14759
 
#endif
14760
 
                                ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14761
 
                                ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14762
 
                                ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14763
 
                                ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14764
 
                                ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14765
 
                                ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14766
 
                                ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14767
 
                                ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14768
 
                                ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14769
 
                                ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14770
 
                                ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14771
 
                                ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14772
 
                        }
14773
 
#endif
14774
 
#ifdef HAVE_SS7
14775
 
                        if (tmp->ss7) {
14776
 
                                ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14777
 
                        }
14778
 
#endif
14779
 
#ifdef HAVE_PRI
14780
 
                        if (tmp->pri) {
14781
 
                                ast_cli(a->fd, "PRI Flags: ");
14782
 
                                if (tmp->resetting)
14783
 
                                        ast_cli(a->fd, "Resetting ");
14784
 
                                if (tmp->call)
14785
 
                                        ast_cli(a->fd, "Call ");
14786
 
                                if (tmp->bearer)
14787
 
                                        ast_cli(a->fd, "Bearer ");
14788
 
                                ast_cli(a->fd, "\n");
14789
 
                                if (tmp->logicalspan)
14790
 
                                        ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14791
 
                                else
14792
 
                                        ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14793
 
                        }
14794
 
#endif
14795
 
                        memset(&ci, 0, sizeof(ci));
14796
 
                        ps.channo = tmp->channel;
14797
 
                        if (tmp->subs[SUB_REAL].dfd > -1) {
14798
 
                                memset(&ci, 0, sizeof(ci));
14799
 
                                if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14800
 
                                        ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14801
 
                                }
14802
 
                                if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14803
 
                                        ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14804
 
                                }
14805
 
                                memset(&ps, 0, sizeof(ps));
14806
 
                                if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14807
 
                                        ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14808
 
                                } else {
14809
 
                                        ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14810
 
                                }
14811
 
                        }
14812
 
                        ast_mutex_unlock(lock);
14813
 
                        return CLI_SUCCESS;
14814
 
                }
14815
 
                tmp = tmp->next;
14816
 
        }
14817
 
 
14818
 
        ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14819
 
        ast_mutex_unlock(lock);
14820
 
        return CLI_FAILURE;
14821
 
}
14822
 
 
14823
 
static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14824
 
{
14825
 
        int i, j;
14826
 
        switch (cmd) {
14827
 
        case CLI_INIT:
14828
 
                e->command = "dahdi show cadences";
14829
 
                e->usage =
14830
 
                        "Usage: dahdi show cadences\n"
14831
 
                        "       Shows all cadences currently defined\n";
14832
 
                return NULL;
14833
 
        case CLI_GENERATE:
14834
 
                return NULL;
14835
 
        }
14836
 
        for (i = 0; i < num_cadence; i++) {
14837
 
                char output[1024];
14838
 
                char tmp[16], tmp2[64];
14839
 
                snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14840
 
                term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14841
 
 
14842
 
                for (j = 0; j < 16; j++) {
14843
 
                        if (cadences[i].ringcadence[j] == 0)
14844
 
                                break;
14845
 
                        snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14846
 
                        if (cidrings[i] * 2 - 1 == j)
14847
 
                                term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14848
 
                        else
14849
 
                                term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14850
 
                        if (j != 0)
14851
 
                                strncat(output, ",", sizeof(output) - strlen(output) - 1);
14852
 
                        strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14853
 
                }
14854
 
                ast_cli(a->fd,"%s\n",output);
14855
 
        }
14856
 
        return CLI_SUCCESS;
14857
 
}
14858
 
 
14859
 
/* Based on irqmiss.c */
14860
 
static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14861
 
{
14862
 
        #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14863
 
        #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14864
 
        int span;
14865
 
        int res;
14866
 
        char alarmstr[50];
14867
 
 
14868
 
        int ctl;
14869
 
        struct dahdi_spaninfo s;
14870
 
 
14871
 
        switch (cmd) {
14872
 
        case CLI_INIT:
14873
 
                e->command = "dahdi show status";
14874
 
                e->usage =
14875
 
                        "Usage: dahdi show status\n"
14876
 
                        "       Shows a list of DAHDI cards with status\n";
14877
 
                return NULL;
14878
 
        case CLI_GENERATE:
14879
 
                return NULL;
14880
 
        }
14881
 
        ctl = open("/dev/dahdi/ctl", O_RDWR);
14882
 
        if (ctl < 0) {
14883
 
                ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
14884
 
                return CLI_FAILURE;
14885
 
        }
14886
 
        ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
14887
 
 
14888
 
        for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
14889
 
                s.spanno = span;
14890
 
                res = ioctl(ctl, DAHDI_SPANSTAT, &s);
14891
 
                if (res) {
14892
 
                        continue;
14893
 
                }
14894
 
                alarmstr[0] = '\0';
14895
 
                if (s.alarms > 0) {
14896
 
                        if (s.alarms & DAHDI_ALARM_BLUE)
14897
 
                                strcat(alarmstr, "BLU/");
14898
 
                        if (s.alarms & DAHDI_ALARM_YELLOW)
14899
 
                                strcat(alarmstr, "YEL/");
14900
 
                        if (s.alarms & DAHDI_ALARM_RED)
14901
 
                                strcat(alarmstr, "RED/");
14902
 
                        if (s.alarms & DAHDI_ALARM_LOOPBACK)
14903
 
                                strcat(alarmstr, "LB/");
14904
 
                        if (s.alarms & DAHDI_ALARM_RECOVER)
14905
 
                                strcat(alarmstr, "REC/");
14906
 
                        if (s.alarms & DAHDI_ALARM_NOTOPEN)
14907
 
                                strcat(alarmstr, "NOP/");
14908
 
                        if (!strlen(alarmstr))
14909
 
                                strcat(alarmstr, "UUU/");
14910
 
                        if (strlen(alarmstr)) {
14911
 
                                /* Strip trailing / */
14912
 
                                alarmstr[strlen(alarmstr) - 1] = '\0';
14913
 
                        }
14914
 
                } else {
14915
 
                        if (s.numchans)
14916
 
                                strcpy(alarmstr, "OK");
14917
 
                        else
14918
 
                                strcpy(alarmstr, "UNCONFIGURED");
14919
 
                }
14920
 
 
14921
 
                ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
14922
 
                        s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
14923
 
                        s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
14924
 
                        s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
14925
 
                        "CAS",
14926
 
                        s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
14927
 
                        s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
14928
 
                        s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
14929
 
                        "Unk",
14930
 
                        s.lineconfig & DAHDI_CONFIG_CRC4 ?
14931
 
                        s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL",
14932
 
                        lbostr[s.lbo]
14933
 
                        );
14934
 
        }
14935
 
        close(ctl);
14936
 
 
14937
 
        return CLI_SUCCESS;
14938
 
#undef FORMAT
14939
 
#undef FORMAT2
14940
 
}
14941
 
 
14942
 
static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14943
 
{
14944
 
        int pseudo_fd = -1;
14945
 
        struct dahdi_versioninfo vi;
14946
 
 
14947
 
        switch (cmd) {
14948
 
        case CLI_INIT:
14949
 
                e->command = "dahdi show version";
14950
 
                e->usage =
14951
 
                        "Usage: dahdi show version\n"
14952
 
                        "       Shows the DAHDI version in use\n";
14953
 
                return NULL;
14954
 
        case CLI_GENERATE:
14955
 
                return NULL;
14956
 
        }
14957
 
        if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
14958
 
                ast_cli(a->fd, "Failed to open control file to get version.\n");
14959
 
                return CLI_SUCCESS;
14960
 
        }
14961
 
 
14962
 
        strcpy(vi.version, "Unknown");
14963
 
        strcpy(vi.echo_canceller, "Unknown");
14964
 
 
14965
 
        if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
14966
 
                ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
14967
 
        else
14968
 
                ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
14969
 
 
14970
 
        close(pseudo_fd);
14971
 
 
14972
 
        return CLI_SUCCESS;
14973
 
}
14974
 
 
14975
 
static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14976
 
{
14977
 
        int channel;
14978
 
        int gain;
14979
 
        int tx;
14980
 
        struct dahdi_hwgain hwgain;
14981
 
        struct dahdi_pvt *tmp = NULL;
14982
 
 
14983
 
        switch (cmd) {
14984
 
        case CLI_INIT:
14985
 
                e->command = "dahdi set hwgain";
14986
 
                e->usage =
14987
 
                        "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
14988
 
                        "       Sets the hardware gain on a a given channel, overriding the\n"
14989
 
                        "   value provided at module loadtime, whether the channel is in\n"
14990
 
                        "   use or not.  Changes take effect immediately.\n"
14991
 
                        "   <rx|tx> which direction do you want to change (relative to our module)\n"
14992
 
                        "   <chan num> is the channel number relative to the device\n"
14993
 
                        "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
14994
 
                return NULL;
14995
 
        case CLI_GENERATE:
14996
 
                return NULL;
14997
 
        }
14998
 
 
14999
 
        if (a->argc != 6)
15000
 
                return CLI_SHOWUSAGE;
15001
 
 
15002
 
        if (!strcasecmp("rx", a->argv[3]))
15003
 
                tx = 0; /* rx */
15004
 
        else if (!strcasecmp("tx", a->argv[3]))
15005
 
                tx = 1; /* tx */
15006
 
        else
15007
 
                return CLI_SHOWUSAGE;
15008
 
 
15009
 
        channel = atoi(a->argv[4]);
15010
 
        gain = atof(a->argv[5])*10.0;
15011
 
 
15012
 
        ast_mutex_lock(&iflock);
15013
 
 
15014
 
        for (tmp = iflist; tmp; tmp = tmp->next) {
15015
 
 
15016
 
                if (tmp->channel != channel)
15017
 
                        continue;
15018
 
 
15019
 
                if (tmp->subs[SUB_REAL].dfd == -1)
15020
 
                        break;
15021
 
 
15022
 
                hwgain.newgain = gain;
15023
 
                hwgain.tx = tx;
15024
 
                if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15025
 
                        ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15026
 
                        ast_mutex_unlock(&iflock);
15027
 
                        return CLI_FAILURE;
15028
 
                }
15029
 
                ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15030
 
                        tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15031
 
                break;
15032
 
        }
15033
 
 
15034
 
        ast_mutex_unlock(&iflock);
15035
 
 
15036
 
        if (tmp)
15037
 
                return CLI_SUCCESS;
15038
 
 
15039
 
        ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15040
 
        return CLI_FAILURE;
15041
 
 
15042
 
}
15043
 
 
15044
 
static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15045
 
{
15046
 
        int channel;
15047
 
        float gain;
15048
 
        int tx;
15049
 
        int res;
15050
 
        ast_mutex_t *lock;
15051
 
        struct dahdi_pvt *tmp = NULL;
15052
 
 
15053
 
        switch (cmd) {
15054
 
        case CLI_INIT:
15055
 
                e->command = "dahdi set swgain";
15056
 
                e->usage =
15057
 
                        "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15058
 
                        "       Sets the software gain on a a given channel, overriding the\n"
15059
 
                        "   value provided at module loadtime, whether the channel is in\n"
15060
 
                        "   use or not.  Changes take effect immediately.\n"
15061
 
                        "   <rx|tx> which direction do you want to change (relative to our module)\n"
15062
 
                        "   <chan num> is the channel number relative to the device\n"
15063
 
                        "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15064
 
                return NULL;
15065
 
        case CLI_GENERATE:
15066
 
                return NULL;
15067
 
        }
15068
 
 
15069
 
        lock = &iflock;
15070
 
 
15071
 
        if (a->argc != 6)
15072
 
                return CLI_SHOWUSAGE;
15073
 
 
15074
 
        if (!strcasecmp("rx", a->argv[3]))
15075
 
                tx = 0; /* rx */
15076
 
        else if (!strcasecmp("tx", a->argv[3]))
15077
 
                tx = 1; /* tx */
15078
 
        else
15079
 
                return CLI_SHOWUSAGE;
15080
 
 
15081
 
        channel = atoi(a->argv[4]);
15082
 
        gain = atof(a->argv[5]);
15083
 
 
15084
 
        ast_mutex_lock(lock);
15085
 
        for (tmp = iflist; tmp; tmp = tmp->next) {
15086
 
 
15087
 
                if (tmp->channel != channel)
15088
 
                        continue;
15089
 
 
15090
 
                if (tmp->subs[SUB_REAL].dfd == -1)
15091
 
                        break;
15092
 
 
15093
 
                if (tx)
15094
 
                        res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15095
 
                else
15096
 
                        res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15097
 
 
15098
 
                if (res) {
15099
 
                        ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15100
 
                        ast_mutex_unlock(lock);
15101
 
                        return CLI_FAILURE;
15102
 
                }
15103
 
 
15104
 
                ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15105
 
                        tx ? "tx" : "rx", gain, channel);
15106
 
                break;
15107
 
        }
15108
 
        ast_mutex_unlock(lock);
15109
 
 
15110
 
        if (tmp)
15111
 
                return CLI_SUCCESS;
15112
 
 
15113
 
        ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15114
 
        return CLI_FAILURE;
15115
 
 
15116
 
}
15117
 
 
15118
 
static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15119
 
{
15120
 
        int channel;
15121
 
        int on;
15122
 
        struct dahdi_pvt *dahdi_chan = NULL;
15123
 
 
15124
 
        switch (cmd) {
15125
 
        case CLI_INIT:
15126
 
                e->command = "dahdi set dnd";
15127
 
                e->usage =
15128
 
                        "Usage: dahdi set dnd <chan#> <on|off>\n"
15129
 
                        "       Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15130
 
                        "       Changes take effect immediately.\n"
15131
 
                        "       <chan num> is the channel number\n"
15132
 
                        "       <on|off> Enable or disable DND mode?\n"
15133
 
                        ;
15134
 
                return NULL;
15135
 
        case CLI_GENERATE:
15136
 
                return NULL;
15137
 
        }
15138
 
 
15139
 
        if (a->argc != 5)
15140
 
                return CLI_SHOWUSAGE;
15141
 
 
15142
 
        if ((channel = atoi(a->argv[3])) <= 0) {
15143
 
                ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15144
 
                return CLI_SHOWUSAGE;
15145
 
        }
15146
 
 
15147
 
        if (ast_true(a->argv[4]))
15148
 
                on = 1;
15149
 
        else if (ast_false(a->argv[4]))
15150
 
                on = 0;
15151
 
        else {
15152
 
                ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15153
 
                return CLI_SHOWUSAGE;
15154
 
        }
15155
 
 
15156
 
        ast_mutex_lock(&iflock);
15157
 
        for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15158
 
                if (dahdi_chan->channel != channel)
15159
 
                        continue;
15160
 
 
15161
 
                /* Found the channel. Actually set it */
15162
 
                dahdi_dnd(dahdi_chan, on);
15163
 
                break;
15164
 
        }
15165
 
        ast_mutex_unlock(&iflock);
15166
 
 
15167
 
        if (!dahdi_chan) {
15168
 
                ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15169
 
                return CLI_FAILURE;
15170
 
        }
15171
 
 
15172
 
        return CLI_SUCCESS;
15173
 
}
15174
 
 
15175
 
static struct ast_cli_entry dahdi_cli[] = {
15176
 
        AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15177
 
        AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15178
 
        AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15179
 
        AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15180
 
        AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15181
 
        AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15182
 
        AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15183
 
        AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15184
 
        AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15185
 
        AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15186
 
};
15187
 
 
15188
 
#define TRANSFER        0
15189
 
#define HANGUP          1
15190
 
 
15191
 
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15192
 
{
15193
 
        if (p) {
15194
 
                switch (mode) {
15195
 
                        case TRANSFER:
15196
 
                                p->fake_event = DAHDI_EVENT_WINKFLASH;
15197
 
                                break;
15198
 
                        case HANGUP:
15199
 
                                p->fake_event = DAHDI_EVENT_ONHOOK;
15200
 
                                break;
15201
 
                        default:
15202
 
                                ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15203
 
                }
15204
 
        }
15205
 
        return 0;
15206
 
}
15207
 
static struct dahdi_pvt *find_channel(int channel)
15208
 
{
15209
 
        struct dahdi_pvt *p = iflist;
15210
 
        while (p) {
15211
 
                if (p->channel == channel) {
15212
 
                        break;
15213
 
                }
15214
 
                p = p->next;
15215
 
        }
15216
 
        return p;
15217
 
}
15218
 
 
15219
 
static int action_dahdidndon(struct mansession *s, const struct message *m)
15220
 
{
15221
 
        struct dahdi_pvt *p = NULL;
15222
 
        const char *channel = astman_get_header(m, "DAHDIChannel");
15223
 
 
15224
 
        if (ast_strlen_zero(channel)) {
15225
 
                astman_send_error(s, m, "No channel specified");
15226
 
                return 0;
15227
 
        }
15228
 
        p = find_channel(atoi(channel));
15229
 
        if (!p) {
15230
 
                astman_send_error(s, m, "No such channel");
15231
 
                return 0;
15232
 
        }
15233
 
        p->dnd = 1;
15234
 
        astman_send_ack(s, m, "DND Enabled");
15235
 
        return 0;
15236
 
}
15237
 
 
15238
 
static int action_dahdidndoff(struct mansession *s, const struct message *m)
15239
 
{
15240
 
        struct dahdi_pvt *p = NULL;
15241
 
        const char *channel = astman_get_header(m, "DAHDIChannel");
15242
 
 
15243
 
        if (ast_strlen_zero(channel)) {
15244
 
                astman_send_error(s, m, "No channel specified");
15245
 
                return 0;
15246
 
        }
15247
 
        p = find_channel(atoi(channel));
15248
 
        if (!p) {
15249
 
                astman_send_error(s, m, "No such channel");
15250
 
                return 0;
15251
 
        }
15252
 
        p->dnd = 0;
15253
 
        astman_send_ack(s, m, "DND Disabled");
15254
 
        return 0;
15255
 
}
15256
 
 
15257
 
static int action_transfer(struct mansession *s, const struct message *m)
15258
 
{
15259
 
        struct dahdi_pvt *p = NULL;
15260
 
        const char *channel = astman_get_header(m, "DAHDIChannel");
15261
 
 
15262
 
        if (ast_strlen_zero(channel)) {
15263
 
                astman_send_error(s, m, "No channel specified");
15264
 
                return 0;
15265
 
        }
15266
 
        p = find_channel(atoi(channel));
15267
 
        if (!p) {
15268
 
                astman_send_error(s, m, "No such channel");
15269
 
                return 0;
15270
 
        }
15271
 
        dahdi_fake_event(p,TRANSFER);
15272
 
        astman_send_ack(s, m, "DAHDITransfer");
15273
 
        return 0;
15274
 
}
15275
 
 
15276
 
static int action_transferhangup(struct mansession *s, const struct message *m)
15277
 
{
15278
 
        struct dahdi_pvt *p = NULL;
15279
 
        const char *channel = astman_get_header(m, "DAHDIChannel");
15280
 
 
15281
 
        if (ast_strlen_zero(channel)) {
15282
 
                astman_send_error(s, m, "No channel specified");
15283
 
                return 0;
15284
 
        }
15285
 
        p = find_channel(atoi(channel));
15286
 
        if (!p) {
15287
 
                astman_send_error(s, m, "No such channel");
15288
 
                return 0;
15289
 
        }
15290
 
        dahdi_fake_event(p,HANGUP);
15291
 
        astman_send_ack(s, m, "DAHDIHangup");
15292
 
        return 0;
15293
 
}
15294
 
 
15295
 
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15296
 
{
15297
 
        struct dahdi_pvt *p = NULL;
15298
 
        const char *channel = astman_get_header(m, "DAHDIChannel");
15299
 
        const char *number = astman_get_header(m, "Number");
15300
 
        int i;
15301
 
 
15302
 
        if (ast_strlen_zero(channel)) {
15303
 
                astman_send_error(s, m, "No channel specified");
15304
 
                return 0;
15305
 
        }
15306
 
        if (ast_strlen_zero(number)) {
15307
 
                astman_send_error(s, m, "No number specified");
15308
 
                return 0;
15309
 
        }
15310
 
        p = find_channel(atoi(channel));
15311
 
        if (!p) {
15312
 
                astman_send_error(s, m, "No such channel");
15313
 
                return 0;
15314
 
        }
15315
 
        if (!p->owner) {
15316
 
                astman_send_error(s, m, "Channel does not have it's owner");
15317
 
                return 0;
15318
 
        }
15319
 
        for (i = 0; i < strlen(number); i++) {
15320
 
                struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15321
 
                dahdi_queue_frame(p, &f, NULL);
15322
 
        }
15323
 
        astman_send_ack(s, m, "DAHDIDialOffhook");
15324
 
        return 0;
15325
 
}
15326
 
 
15327
 
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15328
 
{
15329
 
        struct dahdi_pvt *tmp = NULL;
15330
 
        const char *id = astman_get_header(m, "ActionID");
15331
 
        const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15332
 
        char idText[256] = "";
15333
 
        int channels = 0;
15334
 
        int dahdichanquery = -1;
15335
 
        if (!ast_strlen_zero(dahdichannel)) {
15336
 
                dahdichanquery = atoi(dahdichannel);
15337
 
        }
15338
 
 
15339
 
        astman_send_ack(s, m, "DAHDI channel status will follow");
15340
 
        if (!ast_strlen_zero(id))
15341
 
                snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15342
 
 
15343
 
        ast_mutex_lock(&iflock);
15344
 
 
15345
 
        tmp = iflist;
15346
 
        while (tmp) {
15347
 
                if (tmp->channel > 0) {
15348
 
                        int alm = get_alarms(tmp);
15349
 
 
15350
 
                        /* If a specific channel is queried for, only deliver status for that channel */
15351
 
                        if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15352
 
                                continue;
15353
 
 
15354
 
                        channels++;
15355
 
                        if (tmp->owner) {
15356
 
                                /* Add data if we have a current call */
15357
 
                                astman_append(s,
15358
 
                                        "Event: DAHDIShowChannels\r\n"
15359
 
                                        "DAHDIChannel: %d\r\n"
15360
 
                                        "Channel: %s\r\n"
15361
 
                                        "Uniqueid: %s\r\n"
15362
 
                                        "AccountCode: %s\r\n"
15363
 
                                        "Signalling: %s\r\n"
15364
 
                                        "SignallingCode: %d\r\n"
15365
 
                                        "Context: %s\r\n"
15366
 
                                        "DND: %s\r\n"
15367
 
                                        "Alarm: %s\r\n"
15368
 
                                        "%s"
15369
 
                                        "\r\n",
15370
 
                                        tmp->channel,
15371
 
                                        tmp->owner->name,
15372
 
                                        tmp->owner->uniqueid,
15373
 
                                        tmp->owner->accountcode,
15374
 
                                        sig2str(tmp->sig),
15375
 
                                        tmp->sig,
15376
 
                                        tmp->context,
15377
 
                                        tmp->dnd ? "Enabled" : "Disabled",
15378
 
                                        alarm2str(alm), idText);
15379
 
                        } else {
15380
 
                                astman_append(s,
15381
 
                                        "Event: DAHDIShowChannels\r\n"
15382
 
                                        "DAHDIChannel: %d\r\n"
15383
 
                                        "Signalling: %s\r\n"
15384
 
                                        "SignallingCode: %d\r\n"
15385
 
                                        "Context: %s\r\n"
15386
 
                                        "DND: %s\r\n"
15387
 
                                        "Alarm: %s\r\n"
15388
 
                                        "%s"
15389
 
                                        "\r\n",
15390
 
                                        tmp->channel, sig2str(tmp->sig), tmp->sig,
15391
 
                                        tmp->context,
15392
 
                                        tmp->dnd ? "Enabled" : "Disabled",
15393
 
                                        alarm2str(alm), idText);
15394
 
                        }
15395
 
                }
15396
 
 
15397
 
                tmp = tmp->next;
15398
 
        }
15399
 
 
15400
 
        ast_mutex_unlock(&iflock);
15401
 
 
15402
 
        astman_append(s,
15403
 
                "Event: DAHDIShowChannelsComplete\r\n"
15404
 
                "%s"
15405
 
                "Items: %d\r\n"
15406
 
                "\r\n",
15407
 
                idText,
15408
 
                channels);
15409
 
        return 0;
15410
 
}
15411
 
 
15412
 
#if defined(HAVE_SS7)
15413
 
static int linkset_addsigchan(int sigchan)
15414
 
{
15415
 
        struct dahdi_ss7 *link;
15416
 
        int res;
15417
 
        int curfd;
15418
 
        struct dahdi_params p;
15419
 
        struct dahdi_bufferinfo bi;
15420
 
        struct dahdi_spaninfo si;
15421
 
 
15422
 
 
15423
 
        link = ss7_resolve_linkset(cur_linkset);
15424
 
        if (!link) {
15425
 
                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15426
 
                return -1;
15427
 
        }
15428
 
 
15429
 
        if (cur_ss7type < 0) {
15430
 
                ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15431
 
                return -1;
15432
 
        }
15433
 
 
15434
 
        if (!link->ss7)
15435
 
                link->ss7 = ss7_new(cur_ss7type);
15436
 
 
15437
 
        if (!link->ss7) {
15438
 
                ast_log(LOG_ERROR, "Can't create new SS7!\n");
15439
 
                return -1;
15440
 
        }
15441
 
 
15442
 
        link->type = cur_ss7type;
15443
 
 
15444
 
        if (cur_pointcode < 0) {
15445
 
                ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15446
 
                return -1;
15447
 
        } else
15448
 
                ss7_set_pc(link->ss7, cur_pointcode);
15449
 
 
15450
 
        if (sigchan < 0) {
15451
 
                ast_log(LOG_ERROR, "Invalid sigchan!\n");
15452
 
                return -1;
15453
 
        } else {
15454
 
                if (link->numsigchans >= NUM_DCHANS) {
15455
 
                        ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15456
 
                        return -1;
15457
 
                }
15458
 
                curfd = link->numsigchans;
15459
 
 
15460
 
                link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15461
 
                if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15462
 
                        ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15463
 
                        return -1;
15464
 
                }
15465
 
                memset(&p, 0, sizeof(p));
15466
 
                res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15467
 
                if (res) {
15468
 
                        dahdi_close_ss7_fd(link, curfd);
15469
 
                        ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15470
 
                        return -1;
15471
 
                }
15472
 
                if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15473
 
                        dahdi_close_ss7_fd(link, curfd);
15474
 
                        ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15475
 
                        return -1;
15476
 
                }
15477
 
 
15478
 
                memset(&bi, 0, sizeof(bi));
15479
 
                bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15480
 
                bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15481
 
                bi.numbufs = 32;
15482
 
                bi.bufsize = 512;
15483
 
 
15484
 
                if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15485
 
                        ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15486
 
                        dahdi_close_ss7_fd(link, curfd);
15487
 
                        return -1;
15488
 
                }
15489
 
 
15490
 
                if (p.sigtype == DAHDI_SIG_MTP2)
15491
 
                        ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15492
 
                else
15493
 
                        ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15494
 
 
15495
 
                link->numsigchans++;
15496
 
 
15497
 
                memset(&si, 0, sizeof(si));
15498
 
                res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15499
 
                if (res) {
15500
 
                        dahdi_close_ss7_fd(link, curfd);
15501
 
                        ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15502
 
                }
15503
 
 
15504
 
                if (!si.alarms) {
15505
 
                        link->linkstate[curfd] = LINKSTATE_DOWN;
15506
 
                        ss7_link_noalarm(link->ss7, link->fds[curfd]);
15507
 
                } else {
15508
 
                        link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15509
 
                        ss7_link_alarm(link->ss7, link->fds[curfd]);
15510
 
                }
15511
 
        }
15512
 
 
15513
 
        if (cur_adjpointcode < 0) {
15514
 
                ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15515
 
                return -1;
15516
 
        } else {
15517
 
                ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15518
 
        }
15519
 
 
15520
 
        if (cur_defaultdpc < 0) {
15521
 
                ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15522
 
                return -1;
15523
 
        }
15524
 
 
15525
 
        if (cur_networkindicator < 0) {
15526
 
                ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15527
 
                return -1;
15528
 
        } else
15529
 
                ss7_set_network_ind(link->ss7, cur_networkindicator);
15530
 
 
15531
 
        return 0;
15532
 
}
15533
 
#endif  /* defined(HAVE_SS7) */
15534
 
 
15535
 
#if defined(HAVE_SS7)
15536
 
static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15537
 
{
15538
 
        int span;
15539
 
        switch (cmd) {
15540
 
        case CLI_INIT:
15541
 
                e->command = "ss7 set debug {on|off} linkset";
15542
 
                e->usage =
15543
 
                        "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15544
 
                        "       Enables debugging on a given SS7 linkset\n";
15545
 
                return NULL;
15546
 
        case CLI_GENERATE:
15547
 
                return NULL;
15548
 
        }
15549
 
        if (a->argc < 6)
15550
 
                return CLI_SHOWUSAGE;
15551
 
        span = atoi(a->argv[5]);
15552
 
        if ((span < 1) || (span > NUM_SPANS)) {
15553
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15554
 
                return CLI_SUCCESS;
15555
 
        }
15556
 
        if (!linksets[span-1].ss7) {
15557
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15558
 
                return CLI_SUCCESS;
15559
 
        }
15560
 
        if (linksets[span-1].ss7) {
15561
 
                if (strcasecmp(a->argv[3], "on")) {
15562
 
                        ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15563
 
                        ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15564
 
                } else {
15565
 
                        ss7_set_debug(linksets[span-1].ss7, 0);
15566
 
                        ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15567
 
                }
15568
 
        }
15569
 
 
15570
 
        return CLI_SUCCESS;
15571
 
}
15572
 
#endif  /* defined(HAVE_SS7) */
15573
 
 
15574
 
#if defined(HAVE_SS7)
15575
 
static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15576
 
{
15577
 
        int linkset, cic;
15578
 
        int blocked = -1, i;
15579
 
        switch (cmd) {
15580
 
        case CLI_INIT:
15581
 
                e->command = "ss7 block cic";
15582
 
                e->usage =
15583
 
                        "Usage: ss7 block cic <linkset> <CIC>\n"
15584
 
                        "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15585
 
                return NULL;
15586
 
        case CLI_GENERATE:
15587
 
                return NULL;
15588
 
        }
15589
 
        if (a->argc == 5)
15590
 
                linkset = atoi(a->argv[3]);
15591
 
        else
15592
 
                return CLI_SHOWUSAGE;
15593
 
 
15594
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
15595
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15596
 
                return CLI_SUCCESS;
15597
 
        }
15598
 
 
15599
 
        if (!linksets[linkset-1].ss7) {
15600
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15601
 
                return CLI_SUCCESS;
15602
 
        }
15603
 
 
15604
 
        cic = atoi(a->argv[4]);
15605
 
 
15606
 
        if (cic < 1) {
15607
 
                ast_cli(a->fd, "Invalid CIC specified!\n");
15608
 
                return CLI_SUCCESS;
15609
 
        }
15610
 
 
15611
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
15612
 
                if (linksets[linkset-1].pvts[i]->cic == cic) {
15613
 
                        blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15614
 
                        if (!blocked) {
15615
 
                                ast_mutex_lock(&linksets[linkset-1].lock);
15616
 
                                isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15617
 
                                ast_mutex_unlock(&linksets[linkset-1].lock);
15618
 
                        }
15619
 
                }
15620
 
        }
15621
 
 
15622
 
        if (blocked < 0) {
15623
 
                ast_cli(a->fd, "Invalid CIC specified!\n");
15624
 
                return CLI_SUCCESS;
15625
 
        }
15626
 
 
15627
 
        if (!blocked)
15628
 
                ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15629
 
        else
15630
 
                ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15631
 
 
15632
 
        /* Break poll on the linkset so it sends our messages */
15633
 
        pthread_kill(linksets[linkset-1].master, SIGURG);
15634
 
 
15635
 
        return CLI_SUCCESS;
15636
 
}
15637
 
#endif  /* defined(HAVE_SS7) */
15638
 
 
15639
 
#if defined(HAVE_SS7)
15640
 
static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15641
 
{
15642
 
        int linkset;
15643
 
        int i;
15644
 
        switch (cmd) {
15645
 
        case CLI_INIT:
15646
 
                e->command = "ss7 block linkset";
15647
 
                e->usage =
15648
 
                        "Usage: ss7 block linkset <linkset number>\n"
15649
 
                        "       Sends a remote blocking request for all CICs on the given linkset\n";
15650
 
                return NULL;
15651
 
        case CLI_GENERATE:
15652
 
                return NULL;
15653
 
        }
15654
 
        if (a->argc == 4)
15655
 
                linkset = atoi(a->argv[3]);
15656
 
        else
15657
 
                return CLI_SHOWUSAGE;
15658
 
 
15659
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
15660
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15661
 
                return CLI_SUCCESS;
15662
 
        }
15663
 
 
15664
 
        if (!linksets[linkset-1].ss7) {
15665
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15666
 
                return CLI_SUCCESS;
15667
 
        }
15668
 
 
15669
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
15670
 
                ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15671
 
                ast_mutex_lock(&linksets[linkset-1].lock);
15672
 
                isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15673
 
                ast_mutex_unlock(&linksets[linkset-1].lock);
15674
 
        }
15675
 
 
15676
 
        /* Break poll on the linkset so it sends our messages */
15677
 
        pthread_kill(linksets[linkset-1].master, SIGURG);
15678
 
 
15679
 
        return CLI_SUCCESS;
15680
 
}
15681
 
#endif  /* defined(HAVE_SS7) */
15682
 
 
15683
 
#if defined(HAVE_SS7)
15684
 
static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15685
 
{
15686
 
        int linkset, cic;
15687
 
        int i, blocked = -1;
15688
 
        switch (cmd) {
15689
 
        case CLI_INIT:
15690
 
                e->command = "ss7 unblock cic";
15691
 
                e->usage =
15692
 
                        "Usage: ss7 unblock cic <linkset> <CIC>\n"
15693
 
                        "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15694
 
                return NULL;
15695
 
        case CLI_GENERATE:
15696
 
                return NULL;
15697
 
        }
15698
 
 
15699
 
        if (a->argc == 5)
15700
 
                linkset = atoi(a->argv[3]);
15701
 
        else
15702
 
                return CLI_SHOWUSAGE;
15703
 
 
15704
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
15705
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15706
 
                return CLI_SUCCESS;
15707
 
        }
15708
 
 
15709
 
        if (!linksets[linkset-1].ss7) {
15710
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15711
 
                return CLI_SUCCESS;
15712
 
        }
15713
 
 
15714
 
        cic = atoi(a->argv[4]);
15715
 
 
15716
 
        if (cic < 1) {
15717
 
                ast_cli(a->fd, "Invalid CIC specified!\n");
15718
 
                return CLI_SUCCESS;
15719
 
        }
15720
 
 
15721
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
15722
 
                if (linksets[linkset-1].pvts[i]->cic == cic) {
15723
 
                        blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15724
 
                        if (blocked) {
15725
 
                                ast_mutex_lock(&linksets[linkset-1].lock);
15726
 
                                isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15727
 
                                ast_mutex_unlock(&linksets[linkset-1].lock);
15728
 
                        }
15729
 
                }
15730
 
        }
15731
 
 
15732
 
        if (blocked > 0)
15733
 
                ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15734
 
 
15735
 
        /* Break poll on the linkset so it sends our messages */
15736
 
        pthread_kill(linksets[linkset-1].master, SIGURG);
15737
 
 
15738
 
        return CLI_SUCCESS;
15739
 
}
15740
 
#endif  /* defined(HAVE_SS7) */
15741
 
 
15742
 
#if defined(HAVE_SS7)
15743
 
static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15744
 
{
15745
 
        int linkset;
15746
 
        int i;
15747
 
        switch (cmd) {
15748
 
        case CLI_INIT:
15749
 
                e->command = "ss7 unblock linkset";
15750
 
                e->usage =
15751
 
                        "Usage: ss7 unblock linkset <linkset number>\n"
15752
 
                        "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15753
 
                return NULL;
15754
 
        case CLI_GENERATE:
15755
 
                return NULL;
15756
 
        }
15757
 
 
15758
 
        if (a->argc == 4)
15759
 
                linkset = atoi(a->argv[3]);
15760
 
        else
15761
 
                return CLI_SHOWUSAGE;
15762
 
 
15763
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
15764
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15765
 
                return CLI_SUCCESS;
15766
 
        }
15767
 
 
15768
 
        if (!linksets[linkset-1].ss7) {
15769
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15770
 
                return CLI_SUCCESS;
15771
 
        }
15772
 
 
15773
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
15774
 
                ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15775
 
                ast_mutex_lock(&linksets[linkset-1].lock);
15776
 
                isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15777
 
                ast_mutex_unlock(&linksets[linkset-1].lock);
15778
 
        }
15779
 
 
15780
 
        /* Break poll on the linkset so it sends our messages */
15781
 
        pthread_kill(linksets[linkset-1].master, SIGURG);
15782
 
 
15783
 
        return CLI_SUCCESS;
15784
 
}
15785
 
#endif  /* defined(HAVE_SS7) */
15786
 
 
15787
 
#if defined(HAVE_SS7)
15788
 
static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15789
 
{
15790
 
        int linkset;
15791
 
        struct dahdi_ss7 *ss7;
15792
 
        switch (cmd) {
15793
 
        case CLI_INIT:
15794
 
                e->command = "ss7 show linkset";
15795
 
                e->usage =
15796
 
                        "Usage: ss7 show linkset <span>\n"
15797
 
                        "       Shows the status of an SS7 linkset.\n";
15798
 
                return NULL;
15799
 
        case CLI_GENERATE:
15800
 
                return NULL;
15801
 
        }
15802
 
 
15803
 
        if (a->argc < 4)
15804
 
                return CLI_SHOWUSAGE;
15805
 
        linkset = atoi(a->argv[3]);
15806
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
15807
 
                ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15808
 
                return CLI_SUCCESS;
15809
 
        }
15810
 
        if (!linksets[linkset-1].ss7) {
15811
 
                ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15812
 
                return CLI_SUCCESS;
15813
 
        }
15814
 
        if (linksets[linkset-1].ss7)
15815
 
                ss7 = &linksets[linkset-1];
15816
 
 
15817
 
        ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15818
 
 
15819
 
        return CLI_SUCCESS;
15820
 
}
15821
 
#endif  /* defined(HAVE_SS7) */
15822
 
 
15823
 
#if defined(HAVE_SS7)
15824
 
static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15825
 
{
15826
 
        switch (cmd) {
15827
 
        case CLI_INIT:
15828
 
                e->command = "ss7 show version";
15829
 
                e->usage =
15830
 
                        "Usage: ss7 show version\n"
15831
 
                        "       Show the libss7 version\n";
15832
 
                return NULL;
15833
 
        case CLI_GENERATE:
15834
 
                return NULL;
15835
 
        }
15836
 
 
15837
 
        ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15838
 
 
15839
 
        return CLI_SUCCESS;
15840
 
}
15841
 
#endif  /* defined(HAVE_SS7) */
15842
 
 
15843
 
#if defined(HAVE_SS7)
15844
 
static struct ast_cli_entry dahdi_ss7_cli[] = {
15845
 
        AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15846
 
        AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15847
 
        AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15848
 
        AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15849
 
        AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15850
 
        AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15851
 
        AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15852
 
};
15853
 
#endif  /* defined(HAVE_SS7) */
15854
 
 
15855
 
static int __unload_module(void)
15856
 
{
15857
 
        struct dahdi_pvt *p;
15858
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
15859
 
        int i, j;
15860
 
#endif
15861
 
 
15862
 
#ifdef HAVE_PRI
15863
 
        for (i = 0; i < NUM_SPANS; i++) {
15864
 
                if (pris[i].master != AST_PTHREADT_NULL)
15865
 
                        pthread_cancel(pris[i].master);
15866
 
        }
15867
 
        ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15868
 
        ast_unregister_application(dahdi_send_keypad_facility_app);
15869
 
#ifdef HAVE_PRI_PROG_W_CAUSE
15870
 
        ast_unregister_application(dahdi_send_callrerouting_facility_app);
15871
 
#endif
15872
 
#endif
15873
 
#if defined(HAVE_SS7)
15874
 
        for (i = 0; i < NUM_SPANS; i++) {
15875
 
                if (linksets[i].master != AST_PTHREADT_NULL)
15876
 
                        pthread_cancel(linksets[i].master);
15877
 
                }
15878
 
        ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15879
 
#endif
15880
 
#if defined(HAVE_OPENR2)
15881
 
        dahdi_r2_destroy_links();
15882
 
        ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15883
 
        ast_unregister_application(dahdi_accept_r2_call_app);
15884
 
#endif
15885
 
 
15886
 
        ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15887
 
        ast_manager_unregister( "DAHDIDialOffhook" );
15888
 
        ast_manager_unregister( "DAHDIHangup" );
15889
 
        ast_manager_unregister( "DAHDITransfer" );
15890
 
        ast_manager_unregister( "DAHDIDNDoff" );
15891
 
        ast_manager_unregister( "DAHDIDNDon" );
15892
 
        ast_manager_unregister("DAHDIShowChannels");
15893
 
        ast_manager_unregister("DAHDIRestart");
15894
 
        ast_channel_unregister(&dahdi_tech);
15895
 
        ast_mutex_lock(&iflock);
15896
 
        /* Hangup all interfaces if they have an owner */
15897
 
        p = iflist;
15898
 
        while (p) {
15899
 
                if (p->owner)
15900
 
                        ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15901
 
                p = p->next;
15902
 
        }
15903
 
        ast_mutex_unlock(&iflock);
15904
 
        ast_mutex_lock(&monlock);
15905
 
        if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15906
 
                pthread_cancel(monitor_thread);
15907
 
                pthread_kill(monitor_thread, SIGURG);
15908
 
                pthread_join(monitor_thread, NULL);
15909
 
        }
15910
 
        monitor_thread = AST_PTHREADT_STOP;
15911
 
        ast_mutex_unlock(&monlock);
15912
 
 
15913
 
        destroy_all_channels();
15914
 
 
15915
 
#if defined(HAVE_PRI)
15916
 
        for (i = 0; i < NUM_SPANS; i++) {
15917
 
                if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
15918
 
                        pthread_join(pris[i].master, NULL);
15919
 
                for (j = 0; j < NUM_DCHANS; j++) {
15920
 
                        dahdi_close_pri_fd(&(pris[i]), j);
15921
 
                }
15922
 
        }
15923
 
#endif
15924
 
 
15925
 
#if defined(HAVE_SS7)
15926
 
        for (i = 0; i < NUM_SPANS; i++) {
15927
 
                if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15928
 
                        pthread_join(linksets[i].master, NULL);
15929
 
                for (j = 0; j < NUM_DCHANS; j++) {
15930
 
                        dahdi_close_ss7_fd(&(linksets[i]), j);
15931
 
                }
15932
 
        }
15933
 
#endif
15934
 
        ast_cond_destroy(&ss_thread_complete);
15935
 
        return 0;
15936
 
}
15937
 
 
15938
 
static int unload_module(void)
15939
 
{
15940
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
15941
 
        int y;
15942
 
#endif
15943
 
#ifdef HAVE_PRI
15944
 
        for (y = 0; y < NUM_SPANS; y++)
15945
 
                ast_mutex_destroy(&pris[y].lock);
15946
 
#endif
15947
 
#ifdef HAVE_SS7
15948
 
        for (y = 0; y < NUM_SPANS; y++)
15949
 
                ast_mutex_destroy(&linksets[y].lock);
15950
 
#endif /* HAVE_SS7 */
15951
 
        return __unload_module();
15952
 
}
15953
 
 
15954
 
static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
15955
 
{
15956
 
        char *c, *chan;
15957
 
        int x, start, finish;
15958
 
        struct dahdi_pvt *tmp;
15959
 
#ifdef HAVE_PRI
15960
 
        struct dahdi_pri *pri;
15961
 
        int trunkgroup, y;
15962
 
#endif
15963
 
 
15964
 
        if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
15965
 
                ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
15966
 
                return -1;
15967
 
        }
15968
 
 
15969
 
        c = ast_strdupa(value);
15970
 
 
15971
 
#ifdef HAVE_PRI
15972
 
        pri = NULL;
15973
 
        if (iscrv) {
15974
 
                if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
15975
 
                        ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
15976
 
                        return -1;
15977
 
                }
15978
 
                if (trunkgroup < 1) {
15979
 
                        ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
15980
 
                        return -1;
15981
 
                }
15982
 
                c += y;
15983
 
                for (y = 0; y < NUM_SPANS; y++) {
15984
 
                        if (pris[y].trunkgroup == trunkgroup) {
15985
 
                                pri = pris + y;
15986
 
                                break;
15987
 
                        }
15988
 
                }
15989
 
                if (!pri) {
15990
 
                        ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
15991
 
                        return -1;
15992
 
                }
15993
 
        }
15994
 
#endif
15995
 
 
15996
 
        while ((chan = strsep(&c, ","))) {
15997
 
                if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
15998
 
                        /* Range */
15999
 
                } else if (sscanf(chan, "%30d", &start)) {
16000
 
                        /* Just one */
16001
 
                        finish = start;
16002
 
                } else if (!strcasecmp(chan, "pseudo")) {
16003
 
                        finish = start = CHAN_PSEUDO;
16004
 
                        if (found_pseudo)
16005
 
                                *found_pseudo = 1;
16006
 
                } else {
16007
 
                        ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16008
 
                        return -1;
16009
 
                }
16010
 
                if (finish < start) {
16011
 
                        ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16012
 
                        x = finish;
16013
 
                        finish = start;
16014
 
                        start = x;
16015
 
                }
16016
 
 
16017
 
                for (x = start; x <= finish; x++) {
16018
 
#ifdef HAVE_PRI
16019
 
                        tmp = mkintf(x, conf, pri, reload);
16020
 
#else
16021
 
                        tmp = mkintf(x, conf, NULL, reload);
16022
 
#endif
16023
 
 
16024
 
                        if (tmp) {
16025
 
#ifdef HAVE_PRI
16026
 
                                if (pri)
16027
 
                                        ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16028
 
                                else
16029
 
#endif
16030
 
                                        ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16031
 
                        } else {
16032
 
                                ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16033
 
                                        (reload == 1) ? "reconfigure" : "register", value);
16034
 
                                return -1;
16035
 
                        }
16036
 
                }
16037
 
        }
16038
 
 
16039
 
        return 0;
16040
 
}
16041
 
 
16042
 
/** The length of the parameters list of 'dahdichan'.
16043
 
 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16044
 
#define MAX_CHANLIST_LEN 80
16045
 
 
16046
 
static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16047
 
{
16048
 
        char *parse = ast_strdupa(data);
16049
 
        char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16050
 
        unsigned int param_count;
16051
 
        unsigned int x;
16052
 
 
16053
 
        if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16054
 
                return;
16055
 
 
16056
 
        memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16057
 
 
16058
 
        /* first parameter is tap length, process it here */
16059
 
 
16060
 
        x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16061
 
 
16062
 
        if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16063
 
                confp->chan.echocancel.head.tap_length = x;
16064
 
        else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16065
 
                confp->chan.echocancel.head.tap_length = 128;
16066
 
 
16067
 
        /* now process any remaining parameters */
16068
 
 
16069
 
        for (x = 1; x < param_count; x++) {
16070
 
                struct {
16071
 
                        char *name;
16072
 
                        char *value;
16073
 
                } param;
16074
 
 
16075
 
                if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16076
 
                        ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16077
 
                        continue;
16078
 
                }
16079
 
 
16080
 
                if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16081
 
                        ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16082
 
                        continue;
16083
 
                }
16084
 
 
16085
 
                strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16086
 
 
16087
 
                if (param.value) {
16088
 
                        if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16089
 
                                ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16090
 
                                continue;
16091
 
                        }
16092
 
                }
16093
 
                confp->chan.echocancel.head.param_count++;
16094
 
        }
16095
 
}
16096
 
 
16097
 
/*! process_dahdi() - ignore keyword 'channel' and similar */
16098
 
#define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16099
 
/*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16100
 
#define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16101
 
 
16102
 
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16103
 
{
16104
 
        struct dahdi_pvt *tmp;
16105
 
        int y;
16106
 
        int found_pseudo = 0;
16107
 
        char dahdichan[MAX_CHANLIST_LEN] = {};
16108
 
 
16109
 
        for (; v; v = v->next) {
16110
 
                if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16111
 
                        continue;
16112
 
 
16113
 
                /* must have parkinglot in confp before build_channels is called */
16114
 
                if (!strcasecmp(v->name, "parkinglot")) {
16115
 
                        ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16116
 
                }
16117
 
 
16118
 
                /* Create the interface list */
16119
 
                if (!strcasecmp(v->name, "channel")
16120
 
#ifdef HAVE_PRI
16121
 
                        || !strcasecmp(v->name, "crv")
16122
 
#endif
16123
 
                        ) {
16124
 
                        int iscrv;
16125
 
                        if (options & PROC_DAHDI_OPT_NOCHAN) {
16126
 
                                ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16127
 
                                continue;
16128
 
                        }
16129
 
                        iscrv = !strcasecmp(v->name, "crv");
16130
 
                        if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16131
 
                                        return -1;
16132
 
                        ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16133
 
                } else if (!strcasecmp(v->name, "buffers")) {
16134
 
                        int res;
16135
 
                        char policy[21] = "";
16136
 
 
16137
 
                        res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
16138
 
                        if (res != 2) {
16139
 
                                ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
16140
 
                                confp->chan.buf_no = numbufs;
16141
 
                                continue;
16142
 
                        }
16143
 
                        if (confp->chan.buf_no < 0)
16144
 
                                confp->chan.buf_no = numbufs;
16145
 
                        if (!strcasecmp(policy, "full")) {
16146
 
                                confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
16147
 
                        } else if (!strcasecmp(policy, "immediate")) {
16148
 
                                confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16149
 
#ifdef HAVE_DAHDI_HALF_FULL
16150
 
                        } else if (!strcasecmp(policy, "half_full")) {
16151
 
                                confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
16152
 
#endif
16153
 
                        } else {
16154
 
                                ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16155
 
                        }
16156
 
                } else if (!strcasecmp(v->name, "faxbuffers")) {
16157
 
                        int res;
16158
 
                        char policy[21] = "";
16159
 
 
16160
 
                        res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy);
16161
 
                        if (res != 2) {
16162
 
                                ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
16163
 
                                confp->chan.faxbuf_no = numbufs;
16164
 
                                continue;
16165
 
                        }
16166
 
                        confp->chan.usefaxbuffers = 1;
16167
 
                        if (confp->chan.faxbuf_no < 0)
16168
 
                                confp->chan.faxbuf_no = numbufs;
16169
 
                        if (!strcasecmp(policy, "full")) {
16170
 
                                confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
16171
 
                        } else if (!strcasecmp(policy, "immediate")) {
16172
 
                                confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
16173
 
                        } else {
16174
 
                                ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16175
 
                                confp->chan.usefaxbuffers = 0;
16176
 
                        }
16177
 
                } else if (!strcasecmp(v->name, "dahdichan")) {
16178
 
                        ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16179
 
                } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16180
 
                        usedistinctiveringdetection = ast_true(v->value);
16181
 
                } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16182
 
                        distinctiveringaftercid = ast_true(v->value);
16183
 
                } else if (!strcasecmp(v->name, "dring1context")) {
16184
 
                        ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16185
 
                } else if (!strcasecmp(v->name, "dring2context")) {
16186
 
                        ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16187
 
                } else if (!strcasecmp(v->name, "dring3context")) {
16188
 
                        ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16189
 
                } else if (!strcasecmp(v->name, "dring1range")) {
16190
 
                        confp->chan.drings.ringnum[0].range = atoi(v->value);
16191
 
                } else if (!strcasecmp(v->name, "dring2range")) {
16192
 
                        confp->chan.drings.ringnum[1].range = atoi(v->value);
16193
 
                } else if (!strcasecmp(v->name, "dring3range")) {
16194
 
                        confp->chan.drings.ringnum[2].range = atoi(v->value);
16195
 
                } else if (!strcasecmp(v->name, "dring1")) {
16196
 
                        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]);
16197
 
                } else if (!strcasecmp(v->name, "dring2")) {
16198
 
                        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]);
16199
 
                } else if (!strcasecmp(v->name, "dring3")) {
16200
 
                        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]);
16201
 
                } else if (!strcasecmp(v->name, "usecallerid")) {
16202
 
                        confp->chan.use_callerid = ast_true(v->value);
16203
 
                } else if (!strcasecmp(v->name, "cidsignalling")) {
16204
 
                        if (!strcasecmp(v->value, "bell"))
16205
 
                                confp->chan.cid_signalling = CID_SIG_BELL;
16206
 
                        else if (!strcasecmp(v->value, "v23"))
16207
 
                                confp->chan.cid_signalling = CID_SIG_V23;
16208
 
                        else if (!strcasecmp(v->value, "dtmf"))
16209
 
                                confp->chan.cid_signalling = CID_SIG_DTMF;
16210
 
                        else if (!strcasecmp(v->value, "smdi"))
16211
 
                                confp->chan.cid_signalling = CID_SIG_SMDI;
16212
 
                        else if (!strcasecmp(v->value, "v23_jp"))
16213
 
                                confp->chan.cid_signalling = CID_SIG_V23_JP;
16214
 
                        else if (ast_true(v->value))
16215
 
                                confp->chan.cid_signalling = CID_SIG_BELL;
16216
 
                } else if (!strcasecmp(v->name, "cidstart")) {
16217
 
                        if (!strcasecmp(v->value, "ring"))
16218
 
                                confp->chan.cid_start = CID_START_RING;
16219
 
                        else if (!strcasecmp(v->value, "polarity_in"))
16220
 
                                confp->chan.cid_start = CID_START_POLARITY_IN;
16221
 
                        else if (!strcasecmp(v->value, "polarity"))
16222
 
                                confp->chan.cid_start = CID_START_POLARITY;
16223
 
                        else if (ast_true(v->value))
16224
 
                                confp->chan.cid_start = CID_START_RING;
16225
 
                } else if (!strcasecmp(v->name, "threewaycalling")) {
16226
 
                        confp->chan.threewaycalling = ast_true(v->value);
16227
 
                } else if (!strcasecmp(v->name, "cancallforward")) {
16228
 
                        confp->chan.cancallforward = ast_true(v->value);
16229
 
                } else if (!strcasecmp(v->name, "relaxdtmf")) {
16230
 
                        if (ast_true(v->value))
16231
 
                                confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16232
 
                        else
16233
 
                                confp->chan.dtmfrelax = 0;
16234
 
                } else if (!strcasecmp(v->name, "mailbox")) {
16235
 
                        ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16236
 
                } else if (!strcasecmp(v->name, "hasvoicemail")) {
16237
 
                        if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16238
 
                                ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16239
 
                        }
16240
 
                } else if (!strcasecmp(v->name, "adsi")) {
16241
 
                        confp->chan.adsi = ast_true(v->value);
16242
 
                } else if (!strcasecmp(v->name, "usesmdi")) {
16243
 
                        confp->chan.use_smdi = ast_true(v->value);
16244
 
                } else if (!strcasecmp(v->name, "smdiport")) {
16245
 
                        ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16246
 
                } else if (!strcasecmp(v->name, "transfer")) {
16247
 
                        confp->chan.transfer = ast_true(v->value);
16248
 
                } else if (!strcasecmp(v->name, "canpark")) {
16249
 
                        confp->chan.canpark = ast_true(v->value);
16250
 
                } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16251
 
                        confp->chan.echocanbridged = ast_true(v->value);
16252
 
                } else if (!strcasecmp(v->name, "busydetect")) {
16253
 
                        confp->chan.busydetect = ast_true(v->value);
16254
 
                } else if (!strcasecmp(v->name, "busycount")) {
16255
 
                        confp->chan.busycount = atoi(v->value);
16256
 
                } else if (!strcasecmp(v->name, "busypattern")) {
16257
 
                        if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16258
 
                                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16259
 
                        }
16260
 
                } else if (!strcasecmp(v->name, "callprogress")) {
16261
 
                        confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16262
 
                        if (ast_true(v->value))
16263
 
                                confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16264
 
                } else if (!strcasecmp(v->name, "waitfordialtone")) {
16265
 
                        confp->chan.waitfordialtone = atoi(v->value);
16266
 
                } else if (!strcasecmp(v->name, "faxdetect")) {
16267
 
                        confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16268
 
                        if (!strcasecmp(v->value, "incoming")) {
16269
 
                                confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16270
 
                        } else if (!strcasecmp(v->value, "outgoing")) {
16271
 
                                confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16272
 
                        } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16273
 
                                confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16274
 
                } else if (!strcasecmp(v->name, "echocancel")) {
16275
 
                        process_echocancel(confp, v->value, v->lineno);
16276
 
                } else if (!strcasecmp(v->name, "echotraining")) {
16277
 
                        if (sscanf(v->value, "%30d", &y) == 1) {
16278
 
                                if ((y < 10) || (y > 4000)) {
16279
 
                                        ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16280
 
                                } else {
16281
 
                                        confp->chan.echotraining = y;
16282
 
                                }
16283
 
                        } else if (ast_true(v->value)) {
16284
 
                                confp->chan.echotraining = 400;
16285
 
                        } else
16286
 
                                confp->chan.echotraining = 0;
16287
 
                } else if (!strcasecmp(v->name, "hidecallerid")) {
16288
 
                        confp->chan.hidecallerid = ast_true(v->value);
16289
 
                } else if (!strcasecmp(v->name, "hidecalleridname")) {
16290
 
                        confp->chan.hidecalleridname = ast_true(v->value);
16291
 
                } else if (!strcasecmp(v->name, "pulsedial")) {
16292
 
                        confp->chan.pulse = ast_true(v->value);
16293
 
                } else if (!strcasecmp(v->name, "callreturn")) {
16294
 
                        confp->chan.callreturn = ast_true(v->value);
16295
 
                } else if (!strcasecmp(v->name, "callwaiting")) {
16296
 
                        confp->chan.callwaiting = ast_true(v->value);
16297
 
                } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16298
 
                        confp->chan.callwaitingcallerid = ast_true(v->value);
16299
 
                } else if (!strcasecmp(v->name, "context")) {
16300
 
                        ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16301
 
                } else if (!strcasecmp(v->name, "language")) {
16302
 
                        ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16303
 
                } else if (!strcasecmp(v->name, "progzone")) {
16304
 
                        ast_copy_string(progzone, v->value, sizeof(progzone));
16305
 
                } else if (!strcasecmp(v->name, "mohinterpret")
16306
 
                        ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16307
 
                        ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16308
 
                } else if (!strcasecmp(v->name, "mohsuggest")) {
16309
 
                        ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16310
 
                } else if (!strcasecmp(v->name, "parkinglot")) {
16311
 
                        ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16312
 
                } else if (!strcasecmp(v->name, "stripmsd")) {
16313
 
                        ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16314
 
                        confp->chan.stripmsd = atoi(v->value);
16315
 
                } else if (!strcasecmp(v->name, "jitterbuffers")) {
16316
 
                        numbufs = atoi(v->value);
16317
 
                } else if (!strcasecmp(v->name, "group")) {
16318
 
                        confp->chan.group = ast_get_group(v->value);
16319
 
                } else if (!strcasecmp(v->name, "callgroup")) {
16320
 
                        if (!strcasecmp(v->value, "none"))
16321
 
                                confp->chan.callgroup = 0;
16322
 
                        else
16323
 
                                confp->chan.callgroup = ast_get_group(v->value);
16324
 
                } else if (!strcasecmp(v->name, "pickupgroup")) {
16325
 
                        if (!strcasecmp(v->value, "none"))
16326
 
                                confp->chan.pickupgroup = 0;
16327
 
                        else
16328
 
                                confp->chan.pickupgroup = ast_get_group(v->value);
16329
 
                } else if (!strcasecmp(v->name, "setvar")) {
16330
 
                        char *varname = ast_strdupa(v->value), *varval = NULL;
16331
 
                        struct ast_variable *tmpvar;
16332
 
                        if (varname && (varval = strchr(varname, '='))) {
16333
 
                                *varval++ = '\0';
16334
 
                                if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16335
 
                                        tmpvar->next = confp->chan.vars;
16336
 
                                        confp->chan.vars = tmpvar;
16337
 
                                }
16338
 
                        }
16339
 
                } else if (!strcasecmp(v->name, "immediate")) {
16340
 
                        confp->chan.immediate = ast_true(v->value);
16341
 
                } else if (!strcasecmp(v->name, "transfertobusy")) {
16342
 
                        confp->chan.transfertobusy = ast_true(v->value);
16343
 
                } else if (!strcasecmp(v->name, "mwimonitor")) {
16344
 
                        confp->chan.mwimonitor_neon = 0;
16345
 
                        confp->chan.mwimonitor_fsk = 0;
16346
 
                        confp->chan.mwimonitor_rpas = 0;
16347
 
                        if (strcasestr(v->value, "fsk")) {
16348
 
                                confp->chan.mwimonitor_fsk = 1;
16349
 
                        }
16350
 
                        if (strcasestr(v->value, "rpas")) {
16351
 
                                confp->chan.mwimonitor_rpas = 1;
16352
 
                        }
16353
 
                        if (strcasestr(v->value, "neon")) {
16354
 
                                confp->chan.mwimonitor_neon = 1;
16355
 
                        }
16356
 
                        /* If set to true or yes, assume that simple fsk is desired */
16357
 
                        if (ast_true(v->value)) {
16358
 
                                confp->chan.mwimonitor_fsk = 1;
16359
 
                        }
16360
 
                } else if (!strcasecmp(v->name, "cid_rxgain")) {
16361
 
                        if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16362
 
                                ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16363
 
                        }
16364
 
                } else if (!strcasecmp(v->name, "rxgain")) {
16365
 
                        if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16366
 
                                ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16367
 
                        }
16368
 
                } else if (!strcasecmp(v->name, "txgain")) {
16369
 
                        if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16370
 
                                ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16371
 
                        }
16372
 
                } else if (!strcasecmp(v->name, "tonezone")) {
16373
 
                        if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16374
 
                                ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16375
 
                        }
16376
 
                } else if (!strcasecmp(v->name, "callerid")) {
16377
 
                        if (!strcasecmp(v->value, "asreceived")) {
16378
 
                                confp->chan.cid_num[0] = '\0';
16379
 
                                confp->chan.cid_name[0] = '\0';
16380
 
                        } else {
16381
 
                                ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16382
 
                        }
16383
 
                } else if (!strcasecmp(v->name, "fullname")) {
16384
 
                        ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16385
 
                } else if (!strcasecmp(v->name, "cid_number")) {
16386
 
                        ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16387
 
                } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16388
 
                        confp->chan.dahditrcallerid = ast_true(v->value);
16389
 
                } else if (!strcasecmp(v->name, "restrictcid")) {
16390
 
                        confp->chan.restrictcid = ast_true(v->value);
16391
 
                } else if (!strcasecmp(v->name, "usecallingpres")) {
16392
 
                        confp->chan.use_callingpres = ast_true(v->value);
16393
 
                } else if (!strcasecmp(v->name, "accountcode")) {
16394
 
                        ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16395
 
                } else if (!strcasecmp(v->name, "amaflags")) {
16396
 
                        y = ast_cdr_amaflags2int(v->value);
16397
 
                        if (y < 0)
16398
 
                                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16399
 
                        else
16400
 
                                confp->chan.amaflags = y;
16401
 
                } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16402
 
                        confp->chan.polarityonanswerdelay = atoi(v->value);
16403
 
                } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16404
 
                        confp->chan.answeronpolarityswitch = ast_true(v->value);
16405
 
                } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16406
 
                        confp->chan.hanguponpolarityswitch = ast_true(v->value);
16407
 
                } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16408
 
                        confp->chan.sendcalleridafter = atoi(v->value);
16409
 
                } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16410
 
                        ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16411
 
                } else if (!strcasecmp(v->name, "mwisendtype")) {
16412
 
#ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16413
 
                        if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16414
 
                                mwisend_rpas = 1;
16415
 
                        } else {
16416
 
                                mwisend_rpas = 0;
16417
 
                        }
16418
 
#else
16419
 
                        /* Default is fsk, to turn it off you must specify nofsk */
16420
 
                        memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16421
 
                        if (strcasestr(v->value, "nofsk")) {            /* NoFSK */
16422
 
                                confp->chan.mwisend_fsk = 0;
16423
 
                        } else {                                        /* Default FSK */
16424
 
                                confp->chan.mwisend_fsk = 1;
16425
 
                        }
16426
 
                        if (strcasestr(v->value, "rpas")) {             /* Ring Pulse Alert Signal, normally followed by FSK */
16427
 
                                confp->chan.mwisend_rpas = 1;
16428
 
                        } else {
16429
 
                                confp->chan.mwisend_rpas = 0;
16430
 
                        }
16431
 
                        if (strcasestr(v->value, "lrev")) {             /* Line Reversal */
16432
 
                                confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16433
 
                        }
16434
 
                        if (strcasestr(v->value, "hvdc")) {             /* HV 90VDC */
16435
 
                                confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16436
 
                        }
16437
 
                        if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){        /* 90V DC pulses */
16438
 
                                confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16439
 
                        }
16440
 
#endif
16441
 
                } else if (reload != 1) {
16442
 
                         if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16443
 
                                int orig_radio = confp->chan.radio;
16444
 
                                int orig_outsigmod = confp->chan.outsigmod;
16445
 
                                int orig_auto = confp->is_sig_auto;
16446
 
 
16447
 
                                confp->chan.radio = 0;
16448
 
                                confp->chan.outsigmod = -1;
16449
 
                                confp->is_sig_auto = 0;
16450
 
                                if (!strcasecmp(v->value, "em")) {
16451
 
                                        confp->chan.sig = SIG_EM;
16452
 
                                } else if (!strcasecmp(v->value, "em_e1")) {
16453
 
                                        confp->chan.sig = SIG_EM_E1;
16454
 
                                } else if (!strcasecmp(v->value, "em_w")) {
16455
 
                                        confp->chan.sig = SIG_EMWINK;
16456
 
                                } else if (!strcasecmp(v->value, "fxs_ls")) {
16457
 
                                        confp->chan.sig = SIG_FXSLS;
16458
 
                                } else if (!strcasecmp(v->value, "fxs_gs")) {
16459
 
                                        confp->chan.sig = SIG_FXSGS;
16460
 
                                } else if (!strcasecmp(v->value, "fxs_ks")) {
16461
 
                                        confp->chan.sig = SIG_FXSKS;
16462
 
                                } else if (!strcasecmp(v->value, "fxo_ls")) {
16463
 
                                        confp->chan.sig = SIG_FXOLS;
16464
 
                                } else if (!strcasecmp(v->value, "fxo_gs")) {
16465
 
                                        confp->chan.sig = SIG_FXOGS;
16466
 
                                } else if (!strcasecmp(v->value, "fxo_ks")) {
16467
 
                                        confp->chan.sig = SIG_FXOKS;
16468
 
                                } else if (!strcasecmp(v->value, "fxs_rx")) {
16469
 
                                        confp->chan.sig = SIG_FXSKS;
16470
 
                                        confp->chan.radio = 1;
16471
 
                                } else if (!strcasecmp(v->value, "fxo_rx")) {
16472
 
                                        confp->chan.sig = SIG_FXOLS;
16473
 
                                        confp->chan.radio = 1;
16474
 
                                } else if (!strcasecmp(v->value, "fxs_tx")) {
16475
 
                                        confp->chan.sig = SIG_FXSLS;
16476
 
                                        confp->chan.radio = 1;
16477
 
                                } else if (!strcasecmp(v->value, "fxo_tx")) {
16478
 
                                        confp->chan.sig = SIG_FXOGS;
16479
 
                                        confp->chan.radio = 1;
16480
 
                                } else if (!strcasecmp(v->value, "em_rx")) {
16481
 
                                        confp->chan.sig = SIG_EM;
16482
 
                                        confp->chan.radio = 1;
16483
 
                                } else if (!strcasecmp(v->value, "em_tx")) {
16484
 
                                        confp->chan.sig = SIG_EM;
16485
 
                                        confp->chan.radio = 1;
16486
 
                                } else if (!strcasecmp(v->value, "em_rxtx")) {
16487
 
                                        confp->chan.sig = SIG_EM;
16488
 
                                        confp->chan.radio = 2;
16489
 
                                } else if (!strcasecmp(v->value, "em_txrx")) {
16490
 
                                        confp->chan.sig = SIG_EM;
16491
 
                                        confp->chan.radio = 2;
16492
 
                                } else if (!strcasecmp(v->value, "sf")) {
16493
 
                                        confp->chan.sig = SIG_SF;
16494
 
                                } else if (!strcasecmp(v->value, "sf_w")) {
16495
 
                                        confp->chan.sig = SIG_SFWINK;
16496
 
                                } else if (!strcasecmp(v->value, "sf_featd")) {
16497
 
                                        confp->chan.sig = SIG_FEATD;
16498
 
                                } else if (!strcasecmp(v->value, "sf_featdmf")) {
16499
 
                                        confp->chan.sig = SIG_FEATDMF;
16500
 
                                } else if (!strcasecmp(v->value, "sf_featb")) {
16501
 
                                        confp->chan.sig = SIG_SF_FEATB;
16502
 
                                } else if (!strcasecmp(v->value, "sf")) {
16503
 
                                        confp->chan.sig = SIG_SF;
16504
 
                                } else if (!strcasecmp(v->value, "sf_rx")) {
16505
 
                                        confp->chan.sig = SIG_SF;
16506
 
                                        confp->chan.radio = 1;
16507
 
                                } else if (!strcasecmp(v->value, "sf_tx")) {
16508
 
                                        confp->chan.sig = SIG_SF;
16509
 
                                        confp->chan.radio = 1;
16510
 
                                } else if (!strcasecmp(v->value, "sf_rxtx")) {
16511
 
                                        confp->chan.sig = SIG_SF;
16512
 
                                        confp->chan.radio = 2;
16513
 
                                } else if (!strcasecmp(v->value, "sf_txrx")) {
16514
 
                                        confp->chan.sig = SIG_SF;
16515
 
                                        confp->chan.radio = 2;
16516
 
                                } else if (!strcasecmp(v->value, "featd")) {
16517
 
                                        confp->chan.sig = SIG_FEATD;
16518
 
                                } else if (!strcasecmp(v->value, "featdmf")) {
16519
 
                                        confp->chan.sig = SIG_FEATDMF;
16520
 
                                } else if (!strcasecmp(v->value, "featdmf_ta")) {
16521
 
                                        confp->chan.sig = SIG_FEATDMF_TA;
16522
 
                                } else if (!strcasecmp(v->value, "e911")) {
16523
 
                                        confp->chan.sig = SIG_E911;
16524
 
                                } else if (!strcasecmp(v->value, "fgccama")) {
16525
 
                                        confp->chan.sig = SIG_FGC_CAMA;
16526
 
                                } else if (!strcasecmp(v->value, "fgccamamf")) {
16527
 
                                        confp->chan.sig = SIG_FGC_CAMAMF;
16528
 
                                } else if (!strcasecmp(v->value, "featb")) {
16529
 
                                        confp->chan.sig = SIG_FEATB;
16530
 
#ifdef HAVE_PRI
16531
 
                                } else if (!strcasecmp(v->value, "pri_net")) {
16532
 
                                        confp->chan.sig = SIG_PRI;
16533
 
                                        confp->pri.nodetype = PRI_NETWORK;
16534
 
                                } else if (!strcasecmp(v->value, "pri_cpe")) {
16535
 
                                        confp->chan.sig = SIG_PRI;
16536
 
                                        confp->pri.nodetype = PRI_CPE;
16537
 
                                } else if (!strcasecmp(v->value, "bri_cpe")) {
16538
 
                                        confp->chan.sig = SIG_BRI;
16539
 
                                        confp->pri.nodetype = PRI_CPE;
16540
 
                                } else if (!strcasecmp(v->value, "bri_net")) {
16541
 
                                        confp->chan.sig = SIG_BRI;
16542
 
                                        confp->pri.nodetype = PRI_NETWORK;
16543
 
                                } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16544
 
                                        confp->chan.sig = SIG_BRI_PTMP;
16545
 
                                        confp->pri.nodetype = PRI_CPE;
16546
 
                                } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16547
 
                                        confp->chan.sig = SIG_BRI_PTMP;
16548
 
                                        confp->pri.nodetype = PRI_NETWORK;
16549
 
                                } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16550
 
                                        confp->chan.sig = SIG_GR303FXOKS;
16551
 
                                        confp->pri.nodetype = PRI_NETWORK;
16552
 
                                } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16553
 
                                        confp->chan.sig = SIG_GR303FXSKS;
16554
 
                                        confp->pri.nodetype = PRI_CPE;
16555
 
#endif
16556
 
#ifdef HAVE_SS7
16557
 
                                } else if (!strcasecmp(v->value, "ss7")) {
16558
 
                                        confp->chan.sig = SIG_SS7;
16559
 
#endif
16560
 
#ifdef HAVE_OPENR2
16561
 
                                } else if (!strcasecmp(v->value, "mfcr2")) {
16562
 
                                        confp->chan.sig = SIG_MFCR2;
16563
 
#endif
16564
 
                                } else if (!strcasecmp(v->value, "auto")) {
16565
 
                                        confp->is_sig_auto = 1;
16566
 
                                } else {
16567
 
                                        confp->chan.outsigmod = orig_outsigmod;
16568
 
                                        confp->chan.radio = orig_radio;
16569
 
                                        confp->is_sig_auto = orig_auto;
16570
 
                                        ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16571
 
                                }
16572
 
                         } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16573
 
                                if (!strcasecmp(v->value, "em")) {
16574
 
                                        confp->chan.outsigmod = SIG_EM;
16575
 
                                } else if (!strcasecmp(v->value, "em_e1")) {
16576
 
                                        confp->chan.outsigmod = SIG_EM_E1;
16577
 
                                } else if (!strcasecmp(v->value, "em_w")) {
16578
 
                                        confp->chan.outsigmod = SIG_EMWINK;
16579
 
                                } else if (!strcasecmp(v->value, "sf")) {
16580
 
                                        confp->chan.outsigmod = SIG_SF;
16581
 
                                } else if (!strcasecmp(v->value, "sf_w")) {
16582
 
                                        confp->chan.outsigmod = SIG_SFWINK;
16583
 
                                } else if (!strcasecmp(v->value, "sf_featd")) {
16584
 
                                        confp->chan.outsigmod = SIG_FEATD;
16585
 
                                } else if (!strcasecmp(v->value, "sf_featdmf")) {
16586
 
                                        confp->chan.outsigmod = SIG_FEATDMF;
16587
 
                                } else if (!strcasecmp(v->value, "sf_featb")) {
16588
 
                                        confp->chan.outsigmod = SIG_SF_FEATB;
16589
 
                                } else if (!strcasecmp(v->value, "sf")) {
16590
 
                                        confp->chan.outsigmod = SIG_SF;
16591
 
                                } else if (!strcasecmp(v->value, "featd")) {
16592
 
                                        confp->chan.outsigmod = SIG_FEATD;
16593
 
                                } else if (!strcasecmp(v->value, "featdmf")) {
16594
 
                                        confp->chan.outsigmod = SIG_FEATDMF;
16595
 
                                } else if (!strcasecmp(v->value, "featdmf_ta")) {
16596
 
                                        confp->chan.outsigmod = SIG_FEATDMF_TA;
16597
 
                                } else if (!strcasecmp(v->value, "e911")) {
16598
 
                                        confp->chan.outsigmod = SIG_E911;
16599
 
                                } else if (!strcasecmp(v->value, "fgccama")) {
16600
 
                                        confp->chan.outsigmod = SIG_FGC_CAMA;
16601
 
                                } else if (!strcasecmp(v->value, "fgccamamf")) {
16602
 
                                        confp->chan.outsigmod = SIG_FGC_CAMAMF;
16603
 
                                } else if (!strcasecmp(v->value, "featb")) {
16604
 
                                        confp->chan.outsigmod = SIG_FEATB;
16605
 
                                } else {
16606
 
                                        ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16607
 
                                }
16608
 
#ifdef HAVE_PRI
16609
 
                        } else if (!strcasecmp(v->name, "pridialplan")) {
16610
 
                                if (!strcasecmp(v->value, "national")) {
16611
 
                                        confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16612
 
                                } else if (!strcasecmp(v->value, "unknown")) {
16613
 
                                        confp->pri.dialplan = PRI_UNKNOWN + 1;
16614
 
                                } else if (!strcasecmp(v->value, "private")) {
16615
 
                                        confp->pri.dialplan = PRI_PRIVATE + 1;
16616
 
                                } else if (!strcasecmp(v->value, "international")) {
16617
 
                                        confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16618
 
                                } else if (!strcasecmp(v->value, "local")) {
16619
 
                                        confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16620
 
                                } else if (!strcasecmp(v->value, "dynamic")) {
16621
 
                                        confp->pri.dialplan = -1;
16622
 
                                } else if (!strcasecmp(v->value, "redundant")) {
16623
 
                                        confp->pri.dialplan = -2;
16624
 
                                } else {
16625
 
                                        ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16626
 
                                }
16627
 
                        } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16628
 
                                if (!strcasecmp(v->value, "national")) {
16629
 
                                        confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16630
 
                                } else if (!strcasecmp(v->value, "unknown")) {
16631
 
                                        confp->pri.localdialplan = PRI_UNKNOWN + 1;
16632
 
                                } else if (!strcasecmp(v->value, "private")) {
16633
 
                                        confp->pri.localdialplan = PRI_PRIVATE + 1;
16634
 
                                } else if (!strcasecmp(v->value, "international")) {
16635
 
                                        confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16636
 
                                } else if (!strcasecmp(v->value, "local")) {
16637
 
                                        confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16638
 
                                } else if (!strcasecmp(v->value, "dynamic")) {
16639
 
                                        confp->pri.localdialplan = -1;
16640
 
                                } else if (!strcasecmp(v->value, "redundant")) {
16641
 
                                        confp->pri.localdialplan = -2;
16642
 
                                } else {
16643
 
                                        ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16644
 
                                }
16645
 
                        } else if (!strcasecmp(v->name, "switchtype")) {
16646
 
                                if (!strcasecmp(v->value, "national"))
16647
 
                                        confp->pri.switchtype = PRI_SWITCH_NI2;
16648
 
                                else if (!strcasecmp(v->value, "ni1"))
16649
 
                                        confp->pri.switchtype = PRI_SWITCH_NI1;
16650
 
                                else if (!strcasecmp(v->value, "dms100"))
16651
 
                                        confp->pri.switchtype = PRI_SWITCH_DMS100;
16652
 
                                else if (!strcasecmp(v->value, "4ess"))
16653
 
                                        confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16654
 
                                else if (!strcasecmp(v->value, "5ess"))
16655
 
                                        confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16656
 
                                else if (!strcasecmp(v->value, "euroisdn"))
16657
 
                                        confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16658
 
                                else if (!strcasecmp(v->value, "qsig"))
16659
 
                                        confp->pri.switchtype = PRI_SWITCH_QSIG;
16660
 
                                else {
16661
 
                                        ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16662
 
                                        return -1;
16663
 
                                }
16664
 
                        } else if (!strcasecmp(v->name, "nsf")) {
16665
 
                                if (!strcasecmp(v->value, "sdn"))
16666
 
                                        confp->pri.nsf = PRI_NSF_SDN;
16667
 
                                else if (!strcasecmp(v->value, "megacom"))
16668
 
                                        confp->pri.nsf = PRI_NSF_MEGACOM;
16669
 
                                else if (!strcasecmp(v->value, "tollfreemegacom"))
16670
 
                                        confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16671
 
                                else if (!strcasecmp(v->value, "accunet"))
16672
 
                                        confp->pri.nsf = PRI_NSF_ACCUNET;
16673
 
                                else if (!strcasecmp(v->value, "none"))
16674
 
                                        confp->pri.nsf = PRI_NSF_NONE;
16675
 
                                else {
16676
 
                                        ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16677
 
                                        confp->pri.nsf = PRI_NSF_NONE;
16678
 
                                }
16679
 
                        } else if (!strcasecmp(v->name, "priindication")) {
16680
 
                                if (!strcasecmp(v->value, "outofband"))
16681
 
                                        confp->chan.priindication_oob = 1;
16682
 
                                else if (!strcasecmp(v->value, "inband"))
16683
 
                                        confp->chan.priindication_oob = 0;
16684
 
                                else
16685
 
                                        ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16686
 
                                                v->value, v->lineno);
16687
 
                        } else if (!strcasecmp(v->name, "priexclusive")) {
16688
 
                                confp->chan.priexclusive = ast_true(v->value);
16689
 
                        } else if (!strcasecmp(v->name, "internationalprefix")) {
16690
 
                                ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16691
 
                        } else if (!strcasecmp(v->name, "nationalprefix")) {
16692
 
                                ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16693
 
                        } else if (!strcasecmp(v->name, "localprefix")) {
16694
 
                                ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16695
 
                        } else if (!strcasecmp(v->name, "privateprefix")) {
16696
 
                                ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16697
 
                        } else if (!strcasecmp(v->name, "unknownprefix")) {
16698
 
                                ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16699
 
                        } else if (!strcasecmp(v->name, "resetinterval")) {
16700
 
                                if (!strcasecmp(v->value, "never"))
16701
 
                                        confp->pri.resetinterval = -1;
16702
 
                                else if (atoi(v->value) >= 60)
16703
 
                                        confp->pri.resetinterval = atoi(v->value);
16704
 
                                else
16705
 
                                        ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16706
 
                                                v->value, v->lineno);
16707
 
                        } else if (!strcasecmp(v->name, "minunused")) {
16708
 
                                confp->pri.minunused = atoi(v->value);
16709
 
                        } else if (!strcasecmp(v->name, "minidle")) {
16710
 
                                confp->pri.minidle = atoi(v->value);
16711
 
                        } else if (!strcasecmp(v->name, "idleext")) {
16712
 
                                ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16713
 
                        } else if (!strcasecmp(v->name, "idledial")) {
16714
 
                                ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16715
 
                        } else if (!strcasecmp(v->name, "overlapdial")) {
16716
 
                                if (ast_true(v->value)) {
16717
 
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16718
 
                                } else if (!strcasecmp(v->value, "incoming")) {
16719
 
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16720
 
                                } else if (!strcasecmp(v->value, "outgoing")) {
16721
 
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16722
 
                                } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16723
 
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16724
 
                                } else {
16725
 
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16726
 
                                }
16727
 
#ifdef HAVE_PRI_PROG_W_CAUSE
16728
 
                        } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16729
 
                                if (!strcasecmp(v->value, "logical")) {
16730
 
                                        confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16731
 
                                } else if (!strcasecmp(v->value, "physical")) {
16732
 
                                        confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16733
 
                                } else {
16734
 
                                        confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16735
 
                                }
16736
 
#endif
16737
 
                        } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16738
 
                                confp->pri.discardremoteholdretrieval = ast_true(v->value);
16739
 
#ifdef HAVE_PRI_INBANDDISCONNECT
16740
 
                        } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16741
 
                                confp->pri.inbanddisconnect = ast_true(v->value);
16742
 
#endif
16743
 
                        } else if (!strcasecmp(v->name, "pritimer")) {
16744
 
#ifdef PRI_GETSET_TIMERS
16745
 
                                char tmp[20];
16746
 
                                char *timerc;
16747
 
                                char *c;
16748
 
                                int timer;
16749
 
                                int timeridx;
16750
 
 
16751
 
                                ast_copy_string(tmp, v->value, sizeof(tmp));
16752
 
                                c = tmp;
16753
 
                                timerc = strsep(&c, ",");
16754
 
                                if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16755
 
                                        timeridx = pri_timer2idx(timerc);
16756
 
                                        timer = atoi(c);
16757
 
                                        if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16758
 
                                                ast_log(LOG_WARNING,
16759
 
                                                        "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16760
 
                                                        v->lineno);
16761
 
                                        } else if (!timer) {
16762
 
                                                ast_log(LOG_WARNING,
16763
 
                                                        "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16764
 
                                                        c, timerc, v->lineno);
16765
 
                                        } else {
16766
 
                                                pritimers[timeridx] = timer;
16767
 
                                        }
16768
 
                                } else {
16769
 
                                        ast_log(LOG_WARNING,
16770
 
                                                "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16771
 
                                                v->value, v->lineno);
16772
 
                                }
16773
 
 
16774
 
                        } else if (!strcasecmp(v->name, "facilityenable")) {
16775
 
                                confp->pri.facilityenable = ast_true(v->value);
16776
 
#endif /* PRI_GETSET_TIMERS */
16777
 
#endif /* HAVE_PRI */
16778
 
#ifdef HAVE_SS7
16779
 
                        } else if (!strcasecmp(v->name, "ss7type")) {
16780
 
                                if (!strcasecmp(v->value, "itu")) {
16781
 
                                        cur_ss7type = SS7_ITU;
16782
 
                                } else if (!strcasecmp(v->value, "ansi")) {
16783
 
                                        cur_ss7type = SS7_ANSI;
16784
 
                                } else
16785
 
                                        ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16786
 
                        } else if (!strcasecmp(v->name, "linkset")) {
16787
 
                                cur_linkset = atoi(v->value);
16788
 
                        } else if (!strcasecmp(v->name, "pointcode")) {
16789
 
                                cur_pointcode = parse_pointcode(v->value);
16790
 
                        } else if (!strcasecmp(v->name, "adjpointcode")) {
16791
 
                                cur_adjpointcode = parse_pointcode(v->value);
16792
 
                        } else if (!strcasecmp(v->name, "defaultdpc")) {
16793
 
                                cur_defaultdpc = parse_pointcode(v->value);
16794
 
                        } else if (!strcasecmp(v->name, "cicbeginswith")) {
16795
 
                                cur_cicbeginswith = atoi(v->value);
16796
 
                        } else if (!strcasecmp(v->name, "networkindicator")) {
16797
 
                                if (!strcasecmp(v->value, "national"))
16798
 
                                        cur_networkindicator = SS7_NI_NAT;
16799
 
                                else if (!strcasecmp(v->value, "national_spare"))
16800
 
                                        cur_networkindicator = SS7_NI_NAT_SPARE;
16801
 
                                else if (!strcasecmp(v->value, "international"))
16802
 
                                        cur_networkindicator = SS7_NI_INT;
16803
 
                                else if (!strcasecmp(v->value, "international_spare"))
16804
 
                                        cur_networkindicator = SS7_NI_INT_SPARE;
16805
 
                                else
16806
 
                                        cur_networkindicator = -1;
16807
 
                        } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16808
 
                                ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16809
 
                        } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16810
 
                                ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16811
 
                        } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16812
 
                                ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16813
 
                        } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16814
 
                                ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16815
 
                        } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16816
 
                                if (!strcasecmp(v->value, "national")) {
16817
 
                                        confp->ss7.called_nai = SS7_NAI_NATIONAL;
16818
 
                                } else if (!strcasecmp(v->value, "international")) {
16819
 
                                        confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16820
 
                                } else if (!strcasecmp(v->value, "subscriber")) {
16821
 
                                        confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16822
 
                                } else if (!strcasecmp(v->value, "dynamic")) {
16823
 
                                        confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16824
 
                                } else {
16825
 
                                        ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16826
 
                                }
16827
 
                        } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16828
 
                                if (!strcasecmp(v->value, "national")) {
16829
 
                                        confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16830
 
                                } else if (!strcasecmp(v->value, "international")) {
16831
 
                                        confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16832
 
                                } else if (!strcasecmp(v->value, "subscriber")) {
16833
 
                                        confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16834
 
                                } else if (!strcasecmp(v->value, "dynamic")) {
16835
 
                                        confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16836
 
                                } else {
16837
 
                                        ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16838
 
                                }
16839
 
                        } else if (!strcasecmp(v->name, "sigchan")) {
16840
 
                                int sigchan, res;
16841
 
                                sigchan = atoi(v->value);
16842
 
                                res = linkset_addsigchan(sigchan);
16843
 
                                if (res < 0)
16844
 
                                        return -1;
16845
 
 
16846
 
                        } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16847
 
                                struct dahdi_ss7 *link;
16848
 
                                link = ss7_resolve_linkset(cur_linkset);
16849
 
                                if (!link) {
16850
 
                                        ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16851
 
                                        return -1;
16852
 
                                }
16853
 
                                if (ast_true(v->value))
16854
 
                                        link->flags |= LINKSET_FLAG_EXPLICITACM;
16855
 
#endif /* HAVE_SS7 */
16856
 
#ifdef HAVE_OPENR2
16857
 
                        } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16858
 
                                ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16859
 
                                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);
16860
 
                        } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16861
 
                                ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16862
 
                        } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16863
 
                                confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16864
 
                                if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16865
 
                                        ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16866
 
                                        confp->mfcr2.variant = OR2_VAR_ITU;
16867
 
                                }
16868
 
                        } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16869
 
                                confp->mfcr2.mfback_timeout = atoi(v->value);
16870
 
                                if (!confp->mfcr2.mfback_timeout) {
16871
 
                                        ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16872
 
                                        confp->mfcr2.mfback_timeout = -1;
16873
 
                                } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16874
 
                                        ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16875
 
                                }
16876
 
                        } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16877
 
                                confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16878
 
                                if (confp->mfcr2.metering_pulse_timeout > 500) {
16879
 
                                        ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16880
 
                                }
16881
 
                        } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16882
 
                                confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16883
 
                        } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16884
 
                                confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16885
 
                        } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16886
 
                                confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16887
 
                        } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16888
 
                                confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16889
 
                        } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16890
 
                                confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16891
 
                        } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16892
 
                                confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16893
 
                        } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16894
 
                                confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16895
 
                        } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
16896
 
                                confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
16897
 
                        } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16898
 
                                confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16899
 
                        } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16900
 
                                confp->mfcr2.max_ani = atoi(v->value);
16901
 
                                if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16902
 
                                        confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16903
 
                                }
16904
 
                        } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16905
 
                                confp->mfcr2.max_dnis = atoi(v->value);
16906
 
                                if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16907
 
                                        confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16908
 
                                }
16909
 
                        } else if (!strcasecmp(v->name, "mfcr2_category")) {
16910
 
                                confp->mfcr2.category = openr2_proto_get_category(v->value);
16911
 
                                if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
16912
 
                                        confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
16913
 
                                        ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
16914
 
                                                        v->value, v->lineno);
16915
 
                                }
16916
 
                        } else if (!strcasecmp(v->name, "mfcr2_logging")) {
16917
 
                                openr2_log_level_t tmplevel;
16918
 
                                char *clevel;
16919
 
                                char *logval = ast_strdupa(v->value);
16920
 
                                while (logval) {
16921
 
                                        clevel = strsep(&logval,",");
16922
 
                                        if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
16923
 
                                                ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
16924
 
                                                continue;
16925
 
                                        }
16926
 
                                        confp->mfcr2.loglevel |= tmplevel;
16927
 
                                }
16928
 
#endif /* HAVE_OPENR2 */
16929
 
                        } else if (!strcasecmp(v->name, "cadence")) {
16930
 
                                /* setup to scan our argument */
16931
 
                                int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
16932
 
                                int i;
16933
 
                                struct dahdi_ring_cadence new_cadence;
16934
 
                                int cid_location = -1;
16935
 
                                int firstcadencepos = 0;
16936
 
                                char original_args[80];
16937
 
                                int cadence_is_ok = 1;
16938
 
 
16939
 
                                ast_copy_string(original_args, v->value, sizeof(original_args));
16940
 
                                /* 16 cadences allowed (8 pairs) */
16941
 
                                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]);
16942
 
 
16943
 
                                /* Cadence must be even (on/off) */
16944
 
                                if (element_count % 2 == 1) {
16945
 
                                        ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
16946
 
                                        cadence_is_ok = 0;
16947
 
                                }
16948
 
 
16949
 
                                /* Ring cadences cannot be negative */
16950
 
                                for (i = 0; i < element_count; i++) {
16951
 
                                        if (c[i] == 0) {
16952
 
                                                ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
16953
 
                                                cadence_is_ok = 0;
16954
 
                                                break;
16955
 
                                        } else if (c[i] < 0) {
16956
 
                                                if (i % 2 == 1) {
16957
 
                                                        /* Silence duration, negative possibly okay */
16958
 
                                                        if (cid_location == -1) {
16959
 
                                                                cid_location = i;
16960
 
                                                                c[i] *= -1;
16961
 
                                                        } else {
16962
 
                                                                ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
16963
 
                                                                cadence_is_ok = 0;
16964
 
                                                                break;
16965
 
                                                        }
16966
 
                                                } else {
16967
 
                                                        if (firstcadencepos == 0) {
16968
 
                                                                firstcadencepos = i; /* only recorded to avoid duplicate specification */
16969
 
                                                                                        /* duration will be passed negative to the DAHDI driver */
16970
 
                                                        } else {
16971
 
                                                                 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
16972
 
                                                                cadence_is_ok = 0;
16973
 
                                                                break;
16974
 
                                                        }
16975
 
                                                }
16976
 
                                        }
16977
 
                                }
16978
 
 
16979
 
                                /* Substitute our scanned cadence */
16980
 
                                for (i = 0; i < 16; i++) {
16981
 
                                        new_cadence.ringcadence[i] = c[i];
16982
 
                                }
16983
 
 
16984
 
                                if (cadence_is_ok) {
16985
 
                                        /* ---we scanned it without getting annoyed; now some sanity checks--- */
16986
 
                                        if (element_count < 2) {
16987
 
                                                ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
16988
 
                                        } else {
16989
 
                                                if (cid_location == -1) {
16990
 
                                                        /* user didn't say; default to first pause */
16991
 
                                                        cid_location = 1;
16992
 
                                                } else {
16993
 
                                                        /* convert element_index to cidrings value */
16994
 
                                                        cid_location = (cid_location + 1) / 2;
16995
 
                                                }
16996
 
                                                /* ---we like their cadence; try to install it--- */
16997
 
                                                if (!user_has_defined_cadences++)
16998
 
                                                        /* this is the first user-defined cadence; clear the default user cadences */
16999
 
                                                        num_cadence = 0;
17000
 
                                                if ((num_cadence+1) >= NUM_CADENCE_MAX)
17001
 
                                                        ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17002
 
                                                else {
17003
 
                                                        cadences[num_cadence] = new_cadence;
17004
 
                                                        cidrings[num_cadence++] = cid_location;
17005
 
                                                        ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17006
 
                                                }
17007
 
                                        }
17008
 
                                }
17009
 
                        } else if (!strcasecmp(v->name, "ringtimeout")) {
17010
 
                                ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17011
 
                        } else if (!strcasecmp(v->name, "prewink")) {
17012
 
                                confp->timing.prewinktime = atoi(v->value);
17013
 
                        } else if (!strcasecmp(v->name, "preflash")) {
17014
 
                                confp->timing.preflashtime = atoi(v->value);
17015
 
                        } else if (!strcasecmp(v->name, "wink")) {
17016
 
                                confp->timing.winktime = atoi(v->value);
17017
 
                        } else if (!strcasecmp(v->name, "flash")) {
17018
 
                                confp->timing.flashtime = atoi(v->value);
17019
 
                        } else if (!strcasecmp(v->name, "start")) {
17020
 
                                confp->timing.starttime = atoi(v->value);
17021
 
                        } else if (!strcasecmp(v->name, "rxwink")) {
17022
 
                                confp->timing.rxwinktime = atoi(v->value);
17023
 
                        } else if (!strcasecmp(v->name, "rxflash")) {
17024
 
                                confp->timing.rxflashtime = atoi(v->value);
17025
 
                        } else if (!strcasecmp(v->name, "debounce")) {
17026
 
                                confp->timing.debouncetime = atoi(v->value);
17027
 
                        } else if (!strcasecmp(v->name, "toneduration")) {
17028
 
                                int toneduration;
17029
 
                                int ctlfd;
17030
 
                                int res;
17031
 
                                struct dahdi_dialparams dps;
17032
 
 
17033
 
                                ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17034
 
                                if (ctlfd == -1) {
17035
 
                                        ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17036
 
                                        return -1;
17037
 
                                }
17038
 
 
17039
 
                                toneduration = atoi(v->value);
17040
 
                                if (toneduration > -1) {
17041
 
                                        memset(&dps, 0, sizeof(dps));
17042
 
 
17043
 
                                        dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17044
 
                                        res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17045
 
                                        if (res < 0) {
17046
 
                                                ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17047
 
                                                return -1;
17048
 
                                        }
17049
 
                                }
17050
 
                                close(ctlfd);
17051
 
                        } else if (!strcasecmp(v->name, "defaultcic")) {
17052
 
                                ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17053
 
                        } else if (!strcasecmp(v->name, "defaultozz")) {
17054
 
                                ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17055
 
                        } else if (!strcasecmp(v->name, "mwilevel")) {
17056
 
                                mwilevel = atoi(v->value);
17057
 
                        }
17058
 
                } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17059
 
                        ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17060
 
        }
17061
 
        if (dahdichan[0]) {
17062
 
                /* The user has set 'dahdichan' */
17063
 
                /*< \todo pass proper line number instead of 0 */
17064
 
                if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17065
 
                        return -1;
17066
 
                }
17067
 
        }
17068
 
        /*< \todo why check for the pseudo in the per-channel section.
17069
 
         * Any actual use for manual setup of the pseudo channel? */
17070
 
        if (!found_pseudo && reload != 1) {
17071
 
                /* use the default configuration for a channel, so
17072
 
                   that any settings from real configured channels
17073
 
                   don't "leak" into the pseudo channel config
17074
 
                */
17075
 
                struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17076
 
 
17077
 
                tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17078
 
 
17079
 
                if (tmp) {
17080
 
                        ast_verb(3, "Automatically generated pseudo channel\n");
17081
 
                } else {
17082
 
                        ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17083
 
                }
17084
 
        }
17085
 
        return 0;
17086
 
}
17087
 
 
17088
 
static int setup_dahdi(int reload)
17089
 
{
17090
 
        struct ast_config *cfg, *ucfg;
17091
 
        struct ast_variable *v;
17092
 
        struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17093
 
        struct dahdi_chan_conf conf;
17094
 
        struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17095
 
        const char *cat;
17096
 
        int res;
17097
 
 
17098
 
#ifdef HAVE_PRI
17099
 
        char *c;
17100
 
        int spanno;
17101
 
        int i;
17102
 
        int logicalspan;
17103
 
        int trunkgroup;
17104
 
        int dchannels[NUM_DCHANS];
17105
 
#endif
17106
 
 
17107
 
        cfg = ast_config_load(config, config_flags);
17108
 
 
17109
 
        /* Error if we have no config file */
17110
 
        if (!cfg) {
17111
 
                ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17112
 
                return 0;
17113
 
        } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17114
 
                ucfg = ast_config_load("users.conf", config_flags);
17115
 
                if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17116
 
                        return 0;
17117
 
                } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17118
 
                        ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17119
 
                        return 0;
17120
 
                }
17121
 
                ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17122
 
                if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17123
 
                        ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17124
 
                        ast_config_destroy(ucfg);
17125
 
                        return 0;
17126
 
                }
17127
 
        } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17128
 
                ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17129
 
                return 0;
17130
 
        } else {
17131
 
                ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17132
 
                if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17133
 
                        ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17134
 
                        ast_config_destroy(cfg);
17135
 
                        return 0;
17136
 
                }
17137
 
        }
17138
 
 
17139
 
        /* It's a little silly to lock it, but we mind as well just to be sure */
17140
 
        ast_mutex_lock(&iflock);
17141
 
#ifdef HAVE_PRI
17142
 
        if (reload != 1) {
17143
 
                /* Process trunkgroups first */
17144
 
                v = ast_variable_browse(cfg, "trunkgroups");
17145
 
                while (v) {
17146
 
                        if (!strcasecmp(v->name, "trunkgroup")) {
17147
 
                                trunkgroup = atoi(v->value);
17148
 
                                if (trunkgroup > 0) {
17149
 
                                        if ((c = strchr(v->value, ','))) {
17150
 
                                                i = 0;
17151
 
                                                memset(dchannels, 0, sizeof(dchannels));
17152
 
                                                while (c && (i < NUM_DCHANS)) {
17153
 
                                                        dchannels[i] = atoi(c + 1);
17154
 
                                                        if (dchannels[i] < 0) {
17155
 
                                                                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);
17156
 
                                                        } else
17157
 
                                                                i++;
17158
 
                                                        c = strchr(c + 1, ',');
17159
 
                                                }
17160
 
                                                if (i) {
17161
 
                                                        if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17162
 
                                                                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);
17163
 
                                                } else
17164
 
                                                                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");
17165
 
                                                } else
17166
 
                                                        ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17167
 
                                        } else
17168
 
                                                ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17169
 
                                } else
17170
 
                                        ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17171
 
                        } else if (!strcasecmp(v->name, "spanmap")) {
17172
 
                                spanno = atoi(v->value);
17173
 
                                if (spanno > 0) {
17174
 
                                        if ((c = strchr(v->value, ','))) {
17175
 
                                                trunkgroup = atoi(c + 1);
17176
 
                                                if (trunkgroup > 0) {
17177
 
                                                        if ((c = strchr(c + 1, ',')))
17178
 
                                                                logicalspan = atoi(c + 1);
17179
 
                                                        else
17180
 
                                                                logicalspan = 0;
17181
 
                                                        if (logicalspan >= 0) {
17182
 
                                                                if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17183
 
                                                                        ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17184
 
                                                        } else
17185
 
                                                                        ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17186
 
                                                        } else
17187
 
                                                                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);
17188
 
                                                } else
17189
 
                                                        ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17190
 
                                        } else
17191
 
                                                ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17192
 
                                } else
17193
 
                                        ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17194
 
                        } else {
17195
 
                                ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17196
 
                        }
17197
 
                        v = v->next;
17198
 
                }
17199
 
        }
17200
 
#endif
17201
 
 
17202
 
        /* Copy the default jb config over global_jbconf */
17203
 
        memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17204
 
 
17205
 
        mwimonitornotify[0] = '\0';
17206
 
 
17207
 
        v = ast_variable_browse(cfg, "channels");
17208
 
        if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17209
 
                ast_mutex_unlock(&iflock);
17210
 
                ast_config_destroy(cfg);
17211
 
                if (ucfg) {
17212
 
                        ast_config_destroy(ucfg);
17213
 
                }
17214
 
                return res;
17215
 
        }
17216
 
 
17217
 
        /* Now get configuration from all normal sections in chan_dahdi.conf: */
17218
 
        for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17219
 
                /* [channels] and [trunkgroups] are used. Let's also reserve
17220
 
                 * [globals] and [general] for future use
17221
 
                 */
17222
 
                if (!strcasecmp(cat, "general") ||
17223
 
                        !strcasecmp(cat, "trunkgroups") ||
17224
 
                        !strcasecmp(cat, "globals") ||
17225
 
                        !strcasecmp(cat, "channels")) {
17226
 
                        continue;
17227
 
                }
17228
 
 
17229
 
                memcpy(&conf, &base_conf, sizeof(conf));
17230
 
 
17231
 
                if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17232
 
                        ast_mutex_unlock(&iflock);
17233
 
                        ast_config_destroy(cfg);
17234
 
                        if (ucfg) {
17235
 
                                ast_config_destroy(cfg);
17236
 
                        }
17237
 
                        return res;
17238
 
                }
17239
 
        }
17240
 
 
17241
 
        ast_config_destroy(cfg);
17242
 
 
17243
 
        if (ucfg) {
17244
 
                const char *chans;
17245
 
 
17246
 
                process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17247
 
 
17248
 
                for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17249
 
                        if (!strcasecmp(cat, "general")) {
17250
 
                                continue;
17251
 
                        }
17252
 
 
17253
 
                        chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17254
 
 
17255
 
                        if (ast_strlen_zero(chans)) {
17256
 
                                continue;
17257
 
                        }
17258
 
 
17259
 
                        memcpy(&conf, &base_conf, sizeof(conf));
17260
 
 
17261
 
                        if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17262
 
                                ast_config_destroy(ucfg);
17263
 
                                ast_mutex_unlock(&iflock);
17264
 
                                return res;
17265
 
                        }
17266
 
                }
17267
 
                ast_config_destroy(ucfg);
17268
 
        }
17269
 
        ast_mutex_unlock(&iflock);
17270
 
 
17271
 
#ifdef HAVE_PRI
17272
 
        if (reload != 1) {
17273
 
                int x;
17274
 
                for (x = 0; x < NUM_SPANS; x++) {
17275
 
                        if (pris[x].pvts[0]) {
17276
 
                                if (start_pri(pris + x)) {
17277
 
                                        ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17278
 
                                        return -1;
17279
 
                                } else
17280
 
                                        ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17281
 
                        }
17282
 
                }
17283
 
        }
17284
 
#endif
17285
 
#ifdef HAVE_SS7
17286
 
        if (reload != 1) {
17287
 
                int x;
17288
 
                for (x = 0; x < NUM_SPANS; x++) {
17289
 
                        if (linksets[x].ss7) {
17290
 
                                if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17291
 
                                        ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17292
 
                                        return -1;
17293
 
                                } else
17294
 
                                        ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17295
 
                        }
17296
 
                }
17297
 
        }
17298
 
#endif
17299
 
#ifdef HAVE_OPENR2
17300
 
        if (reload != 1) {
17301
 
                int x;
17302
 
                for (x = 0; x < r2links_count; x++) {
17303
 
                        if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17304
 
                                ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17305
 
                                return -1;
17306
 
                        } else {
17307
 
                                ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17308
 
                        }
17309
 
                }
17310
 
        }
17311
 
#endif
17312
 
        /* And start the monitor for the first time */
17313
 
        restart_monitor();
17314
 
        return 0;
17315
 
}
17316
 
 
17317
 
static int load_module(void)
17318
 
{
17319
 
        int res;
17320
 
#if defined(HAVE_PRI) || defined(HAVE_SS7)
17321
 
        int y, i;
17322
 
#endif
17323
 
 
17324
 
#ifdef HAVE_PRI
17325
 
        memset(pris, 0, sizeof(pris));
17326
 
        for (y = 0; y < NUM_SPANS; y++) {
17327
 
                ast_mutex_init(&pris[y].lock);
17328
 
                pris[y].offset = -1;
17329
 
                pris[y].master = AST_PTHREADT_NULL;
17330
 
                for (i = 0; i < NUM_DCHANS; i++)
17331
 
                        pris[y].fds[i] = -1;
17332
 
        }
17333
 
        pri_set_error(dahdi_pri_error);
17334
 
        pri_set_message(dahdi_pri_message);
17335
 
        ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17336
 
#ifdef HAVE_PRI_PROG_W_CAUSE
17337
 
        ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17338
 
#endif
17339
 
#endif
17340
 
#ifdef HAVE_SS7
17341
 
        memset(linksets, 0, sizeof(linksets));
17342
 
        for (y = 0; y < NUM_SPANS; y++) {
17343
 
                ast_mutex_init(&linksets[y].lock);
17344
 
                linksets[y].master = AST_PTHREADT_NULL;
17345
 
                for (i = 0; i < NUM_DCHANS; i++)
17346
 
                        linksets[y].fds[i] = -1;
17347
 
        }
17348
 
        ss7_set_error(dahdi_ss7_error);
17349
 
        ss7_set_message(dahdi_ss7_message);
17350
 
#endif /* HAVE_SS7 */
17351
 
        res = setup_dahdi(0);
17352
 
        /* Make sure we can register our DAHDI channel type */
17353
 
        if (res)
17354
 
                return AST_MODULE_LOAD_DECLINE;
17355
 
        if (ast_channel_register(&dahdi_tech)) {
17356
 
                ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17357
 
                __unload_module();
17358
 
                return AST_MODULE_LOAD_FAILURE;
17359
 
        }
17360
 
#ifdef HAVE_PRI
17361
 
        ast_string_field_init(&inuse, 16);
17362
 
        ast_string_field_set(&inuse, name, "GR-303InUse");
17363
 
        ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17364
 
#endif
17365
 
#ifdef HAVE_SS7
17366
 
        ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17367
 
#endif
17368
 
#ifdef HAVE_OPENR2
17369
 
        ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17370
 
        ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17371
 
#endif
17372
 
 
17373
 
        ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17374
 
 
17375
 
        memset(round_robin, 0, sizeof(round_robin));
17376
 
        ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17377
 
        ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17378
 
        ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17379
 
        ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17380
 
        ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17381
 
        ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17382
 
        ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17383
 
 
17384
 
        ast_cond_init(&ss_thread_complete, NULL);
17385
 
 
17386
 
        return res;
17387
 
}
17388
 
 
17389
 
static int dahdi_sendtext(struct ast_channel *c, const char *text)
17390
 
{
17391
 
#define END_SILENCE_LEN 400
17392
 
#define HEADER_MS 50
17393
 
#define TRAILER_MS 5
17394
 
#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17395
 
#define ASCII_BYTES_PER_CHAR 80
17396
 
 
17397
 
        unsigned char *buf,*mybuf;
17398
 
        struct dahdi_pvt *p = c->tech_pvt;
17399
 
        struct pollfd fds[1];
17400
 
        int size,res,fd,len,x;
17401
 
        int bytes=0;
17402
 
        /* Initial carrier (imaginary) */
17403
 
        float cr = 1.0;
17404
 
        float ci = 0.0;
17405
 
        float scont = 0.0;
17406
 
        int idx;
17407
 
 
17408
 
        idx = dahdi_get_index(c, p, 0);
17409
 
        if (idx < 0) {
17410
 
                ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
17411
 
                return -1;
17412
 
        }
17413
 
        if (!text[0]) return(0); /* if nothing to send, dont */
17414
 
        if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
17415
 
        if (p->mate)
17416
 
                buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17417
 
        else
17418
 
                buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17419
 
        if (!buf)
17420
 
                return -1;
17421
 
        mybuf = buf;
17422
 
        if (p->mate) {
17423
 
                int codec = AST_LAW(p);
17424
 
                for (x = 0; x < HEADER_MS; x++) {       /* 50 ms of Mark */
17425
 
                        PUT_CLID_MARKMS;
17426
 
                }
17427
 
                /* Put actual message */
17428
 
                for (x = 0; text[x]; x++) {
17429
 
                        PUT_CLID(text[x]);
17430
 
                }
17431
 
                for (x = 0; x < TRAILER_MS; x++) {      /* 5 ms of Mark */
17432
 
                        PUT_CLID_MARKMS;
17433
 
                }
17434
 
                len = bytes;
17435
 
                buf = mybuf;
17436
 
        } else {
17437
 
                len = tdd_generate(p->tdd, buf, text);
17438
 
                if (len < 1) {
17439
 
                        ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17440
 
                        ast_free(mybuf);
17441
 
                        return -1;
17442
 
                }
17443
 
        }
17444
 
        memset(buf + len, 0x7f, END_SILENCE_LEN);
17445
 
        len += END_SILENCE_LEN;
17446
 
        fd = p->subs[idx].dfd;
17447
 
        while (len) {
17448
 
                if (ast_check_hangup(c)) {
17449
 
                        ast_free(mybuf);
17450
 
                        return -1;
17451
 
                }
17452
 
                size = len;
17453
 
                if (size > READ_SIZE)
17454
 
                        size = READ_SIZE;
17455
 
                fds[0].fd = fd;
17456
 
                fds[0].events = POLLOUT | POLLPRI;
17457
 
                fds[0].revents = 0;
17458
 
                res = poll(fds, 1, -1);
17459
 
                if (!res) {
17460
 
                        ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17461
 
                        continue;
17462
 
                }
17463
 
                /* if got exception */
17464
 
                if (fds[0].revents & POLLPRI) {
17465
 
                        ast_free(mybuf);
17466
 
                        return -1;
17467
 
                }
17468
 
                if (!(fds[0].revents & POLLOUT)) {
17469
 
                        ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17470
 
                        continue;
17471
 
                }
17472
 
                res = write(fd, buf, size);
17473
 
                if (res != size) {
17474
 
                        if (res == -1) {
17475
 
                                ast_free(mybuf);
17476
 
                                return -1;
17477
 
                        }
17478
 
                        ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17479
 
                        break;
17480
 
                }
17481
 
                len -= size;
17482
 
                buf += size;
17483
 
        }
17484
 
        ast_free(mybuf);
17485
 
        return(0);
17486
 
}
17487
 
 
17488
 
 
17489
 
static int reload(void)
17490
 
{
17491
 
        int res = 0;
17492
 
 
17493
 
        res = setup_dahdi(1);
17494
 
        if (res) {
17495
 
                ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17496
 
                return -1;
17497
 
        }
17498
 
        return 0;
17499
 
}
17500
 
 
17501
 
/* This is a workaround so that menuselect displays a proper description
17502
 
 * AST_MODULE_INFO(, , "DAHDI Telephony"
17503
 
 */
17504
 
 
17505
 
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17506
 
        .load = load_module,
17507
 
        .unload = unload_module,
17508
 
        .reload = reload,
17509
 
        );