Asterisk - The Open Source Telephony Project GIT-master-f36a736
chan_dahdi.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2008, 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 * \ingroup channel_drivers
33 *
34 * \todo Deprecate the "musiconhold" configuration option post 1.4
35 */
36
37/*! \li \ref chan_dahdi.c uses the configuration file \ref chan_dahdi.conf
38 * \addtogroup configuration_file
39 */
40
41/*! \page chan_dahdi.conf chan_dahdi.conf
42 * \verbinclude chan_dahdi.conf.sample
43 */
44
45/*** MODULEINFO
46 <depend>dahdi</depend>
47 <depend>tonezone</depend>
48 <use type="module">res_smdi</use>
49 <use type="external">pri</use>
50 <use type="external">ss7</use>
51 <use type="external">openr2</use>
52 <support_level>core</support_level>
53 ***/
54
55#include "asterisk.h"
56
57#if defined(__NetBSD__) || defined(__FreeBSD__)
58#include <pthread.h>
59#else
60#include <sys/sysmacros.h>
61#endif
62#include <signal.h>
63#include <sys/stat.h>
64#include <math.h>
65
66#include "sig_analog.h"
67/* Analog signaling is currently still present in chan_dahdi for use with
68 * radio. Sig_analog does not currently handle any radio operations. If
69 * radio only uses analog signaling, then the radio handling logic could
70 * be placed in sig_analog and the duplicated code could be removed.
71 */
72
73#if defined(HAVE_PRI)
74#include "sig_pri.h"
75#ifndef PRI_RESTART
76#error "Upgrade your libpri"
77#endif
78#endif /* defined(HAVE_PRI) */
79
80#if defined(HAVE_SS7)
81#include "sig_ss7.h"
82#if !defined(LIBSS7_ABI_COMPATIBILITY)
83#error "Upgrade your libss7"
84#elif LIBSS7_ABI_COMPATIBILITY != 2
85#error "Your installed libss7 is not compatible"
86#endif
87#endif /* defined(HAVE_SS7) */
88
89#if defined(HAVE_OPENR2)
90/* put this here until sig_mfcr2 comes along */
91#define SIG_MFCR2_MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
92#endif /* defined(HAVE_OPENR2) */
93
94#include "asterisk/lock.h"
95#include "asterisk/channel.h"
96#include "asterisk/config.h"
97#include "asterisk/module.h"
98#include "asterisk/pbx.h"
99#include "asterisk/file.h"
100#include "asterisk/ulaw.h"
101#include "asterisk/alaw.h"
102#include "asterisk/callerid.h"
103#include "asterisk/adsi.h"
104#include "asterisk/cli.h"
105#include "asterisk/pickup.h"
106#include "asterisk/features.h"
107#include "asterisk/musiconhold.h"
108#include "asterisk/say.h"
109#include "asterisk/tdd.h"
110#include "asterisk/mwi.h"
111#include "asterisk/dsp.h"
112#include "asterisk/astdb.h"
113#include "asterisk/manager.h"
114#include "asterisk/causes.h"
115#include "asterisk/term.h"
116#include "asterisk/utils.h"
117#include "asterisk/transcap.h"
119#include "asterisk/abstract_jb.h"
120#include "asterisk/smdi.h"
121#include "asterisk/devicestate.h"
122#include "asterisk/paths.h"
123#include "asterisk/ccss.h"
125#include "asterisk/bridge.h"
127#include "asterisk/parking.h"
129#include "chan_dahdi.h"
131
132/*** DOCUMENTATION
133 <application name="DAHDISendKeypadFacility" language="en_US">
134 <synopsis>
135 Send digits out of band over a PRI.
136 </synopsis>
137 <syntax>
138 <parameter name="digits" required="true" />
139 </syntax>
140 <description>
141 <para>This application will send the given string of digits in a Keypad
142 Facility IE over the current channel.</para>
143 </description>
144 </application>
145 <application name="DAHDISendCallreroutingFacility" language="en_US">
146 <synopsis>
147 Send an ISDN call rerouting/deflection facility message.
148 </synopsis>
149 <syntax argsep=",">
150 <parameter name="destination" required="true">
151 <para>Destination number.</para>
152 </parameter>
153 <parameter name="original">
154 <para>Original called number.</para>
155 </parameter>
156 <parameter name="reason">
157 <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
158 </parameter>
159 </syntax>
160 <description>
161 <para>This application will send an ISDN switch specific call
162 rerouting/deflection facility message over the current channel.
163 Supported switches depend upon the version of libpri in use.</para>
164 </description>
165 </application>
166 <application name="DAHDIAcceptR2Call" language="en_US">
167 <synopsis>
168 Accept an R2 call if its not already accepted (you still need to answer it)
169 </synopsis>
170 <syntax>
171 <parameter name="charge" required="true">
172 <para>Yes or No.</para>
173 <para>Whether you want to accept the call with charge or without charge.</para>
174 </parameter>
175 </syntax>
176 <description>
177 <para>This application will Accept the R2 call either with charge or no charge.</para>
178 </description>
179 </application>
180 <function name="POLARITY" language="en_US">
181 <synopsis>
182 Set or get the polarity of a DAHDI channel.
183 </synopsis>
184 <syntax />
185 <description>
186 <para>The POLARITY function can be used to set the polarity of a DAHDI channel.</para>
187 <para>Applies only to FXS channels (using FXO signalling) with supporting hardware.</para>
188 <para>The polarity can be set to the following numeric or named values:</para>
189 <enumlist>
190 <enum name="0" />
191 <enum name="idle" />
192 <enum name="1" />
193 <enum name="reverse" />
194 </enumlist>
195 <para>However, when read, the function will always return 0 or 1.</para>
196 <example title="Set idle polarity">
197 same => n,Set(POLARITY()=0)
198 </example>
199 <example title="Set reverse polarity">
200 same => n,NoOp(Current Polarity: ${POLARITY()})
201 same => n,Set(POLARITY()=reverse)
202 same => n,NoOp(New Polarity: ${POLARITY()})
203 </example>
204 <example title="Reverse the polarity from whatever it is currently">
205 same => n,Set(POLARITY()=${IF($[ "${POLARITY()}" = "1" ]?0:1)})
206 </example>
207 </description>
208 </function>
209 <info name="CHANNEL" language="en_US" tech="DAHDI">
210 <enumlist>
211 <enum name="dahdi_channel">
212 <para>R/O DAHDI channel related to this channel.</para>
213 </enum>
214 <enum name="dahdi_span">
215 <para>R/O DAHDI span related to this channel.</para>
216 </enum>
217 <enum name="dahdi_group">
218 <para>R/O DAHDI logical group related to this channel.</para>
219 </enum>
220 <enum name="dahdi_type">
221 <para>R/O DAHDI channel type, one of:</para>
222 <enumlist>
223 <enum name="analog" />
224 <enum name="mfc/r2" />
225 <enum name="pri" />
226 <enum name="pseudo" />
227 <enum name="ss7" />
228 </enumlist>
229 </enum>
230 <enum name="keypad_digits">
231 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
232 </enum>
233 <enum name="reversecharge">
234 <para>R/O PRI Reverse Charging Indication, one of:</para>
235 <enumlist>
236 <enum name="-1"> <para>None</para></enum>
237 <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
238 </enumlist>
239 </enum>
240 <enum name="no_media_path">
241 <para>R/O PRI Nonzero if the channel has no B channel.
242 The channel is either on hold or a call waiting call.</para>
243 </enum>
244 <enum name="buffers">
245 <para>W/O Change the channel's buffer policy (for the current call only)</para>
246 <para>This option takes two arguments:</para>
247 <para> Number of buffers,</para>
248 <para> Buffer policy being one of:</para>
249 <para> <literal>full</literal></para>
250 <para> <literal>immediate</literal></para>
251 <para> <literal>half</literal></para>
252 </enum>
253 <enum name="echocan_mode">
254 <para>W/O Change the configuration of the active echo
255 canceller on the channel (if any), for the current call
256 only.</para>
257 <para>Possible values are:</para>
258 <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitialized)</para>
259 <para> <literal>off</literal> Disabled</para>
260 <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
261 completely disabled)</para>
262 <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
263 </enum>
264 <enum name="dialmode">
265 <para>R/W Pulse and tone dialing mode of the channel.</para>
266 <para>Disabling tone dialing using this option will not disable the DSP used for DTMF detection.
267 To do that, also set the <literal>digitdetect</literal> option. If digit detection is disabled,
268 DTMF will not be detected, regardless of the <literal>dialmode</literal> setting.
269 The <literal>digitdetect</literal> setting has no impact on pulse dialing detection.</para>
270 <para>If set, overrides the setting in <literal>chan_dahdi.conf</literal> for that channel.</para>
271 <enumlist>
272 <enum name="both" />
273 <enum name="pulse" />
274 <enum name="dtmf" />
275 <enum name="tone" />
276 <enum name="none" />
277 </enumlist>
278 </enum>
279 <enum name="waitfordialtone">
280 <para>W/O Duration in ms for which to wait for dial tone on the current call.</para>
281 <para>This setting is will temporarily override the <literal>waitfordialtone</literal>
282 setting in <literal>chan_dahdi.conf</literal> (typically if that setting is disabled).
283 You must call this in a pre-dial handler when making a call on an analog trunk
284 (e.g. FXS-signalled interface).</para>
285 <para>This allows, for example, being able to barge in on an in-use trunk,
286 if dialed specifically, but allows skipping the trunk when routing calls
287 if dial tone is not present on a channel.</para>
288 <para>This setting will only apply to the current (next) call made on the
289 DAHDI channel, and will not persist for future calls.</para>
290 <para>Please keep in mind that due to the way that chan_dahdi implements dial tone detection,
291 DTMF digits on an in-use channel will temporarily relay to any other channels attempting to use the channel for a call.
292 However, voice transmission will not leak.</para>
293 </enum>
294 </enumlist>
295 </info>
296 <info name="Dial_Resource" language="en_US" tech="DAHDI">
297 <para>DAHDI allows several modifiers to be specified as part of the resource.</para>
298 <para>The general syntax is :</para>
299 <para><literal>Dial(DAHDI/pseudo[/extension])</literal></para>
300 <para><literal>Dial(DAHDI/&lt;channel#&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
301 <para><literal>Dial(DAHDI/(g|G|r|R)&lt;group#(0-63)&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
302 <para>The following modifiers may be used before the channel number:</para>
303 <enumlist>
304 <enum name="g">
305 <para>Search forward, dialing on first available channel in group (lowest to highest).</para>
306 </enum>
307 <enum name="G">
308 <para>Search backward, dialing on first available channel in group (highest to lowest).</para>
309 </enum>
310 <enum name="r">
311 <para>Round robin search forward, picking up from where last left off (lowest to highest).</para>
312 </enum>
313 <enum name="R">
314 <para>Round robin search backward, picking up from where last left off (highest to lowest).</para>
315 </enum>
316 </enumlist>
317 <para>The following modifiers may be used after the channel number:</para>
318 <enumlist>
319 <enum name="c">
320 <para>Wait for DTMF digit <literal>#</literal> before providing answer supervision.</para>
321 <para>This can be useful on outbound calls via FXO ports, as otherwise
322 they would indicate answer immediately.</para>
323 </enum>
324 <enum name="d">
325 <para>Force bearer capability for ISDN/SS7 call to digital.</para>
326 </enum>
327 <enum name="i">
328 <para>ISDN span channel restriction.</para>
329 <para>Used by CC to ensure that the CC recall goes out the same span.
330 Also to make ISDN channel names dialable when the sequence number
331 is stripped off. (Used by DTMF attended transfer feature.)</para>
332 </enum>
333 <enum name="r">
334 <para>Specifies the distinctive ring cadence number to use immediately after
335 specifying this option. There are 4 default built-in cadences, and up to 24
336 total cadences may be configured.</para>
337 </enum>
338 </enumlist>
339 <example title="Dial 555-1212 on first available channel in group 1, searching from highest to lowest">
340 same => n,Dial(DAHDI/g1/5551212)
341 </example>
342 <example title="Ringing FXS channel 4 with ring cadence 2">
343 same => n,Dial(DAHDI/4r2)
344 </example>
345 <example title="Dial 555-1212 on channel 3 and require answer confirmation">
346 same => n,Dial(DAHDI/3c/5551212)
347 </example>
348 </info>
349 <manager name="DAHDITransfer" language="en_US">
350 <synopsis>
351 Transfer DAHDI Channel.
352 </synopsis>
353 <syntax>
354 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
355 <parameter name="DAHDIChannel" required="true">
356 <para>DAHDI channel number to transfer.</para>
357 </parameter>
358 </syntax>
359 <description>
360 <para>Simulate a flash hook event by the user connected to the channel.</para>
361 <note><para>Valid only for analog channels.</para></note>
362 </description>
363 </manager>
364 <manager name="DAHDIHangup" language="en_US">
365 <synopsis>
366 Hangup DAHDI Channel.
367 </synopsis>
368 <syntax>
369 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
370 <parameter name="DAHDIChannel" required="true">
371 <para>DAHDI channel number to hangup.</para>
372 </parameter>
373 </syntax>
374 <description>
375 <para>Simulate an on-hook event by the user connected to the channel.</para>
376 <note><para>Valid only for analog channels.</para></note>
377 </description>
378 </manager>
379 <manager name="DAHDIDialOffhook" language="en_US">
380 <synopsis>
381 Dial over DAHDI channel while offhook.
382 </synopsis>
383 <syntax>
384 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
385 <parameter name="DAHDIChannel" required="true">
386 <para>DAHDI channel number to dial digits.</para>
387 </parameter>
388 <parameter name="Number" required="true">
389 <para>Digits to dial.</para>
390 </parameter>
391 </syntax>
392 <description>
393 <para>Generate DTMF control frames to the bridged peer.</para>
394 </description>
395 </manager>
396 <manager name="DAHDIDNDon" language="en_US">
397 <synopsis>
398 Toggle DAHDI channel Do Not Disturb status ON.
399 </synopsis>
400 <syntax>
401 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
402 <parameter name="DAHDIChannel" required="true">
403 <para>DAHDI channel number to set DND on.</para>
404 </parameter>
405 </syntax>
406 <description>
407 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
408 <note><para>Feature only supported by analog channels.</para></note>
409 </description>
410 </manager>
411 <manager name="DAHDIDNDoff" language="en_US">
412 <synopsis>
413 Toggle DAHDI channel Do Not Disturb status OFF.
414 </synopsis>
415 <syntax>
416 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
417 <parameter name="DAHDIChannel" required="true">
418 <para>DAHDI channel number to set DND off.</para>
419 </parameter>
420 </syntax>
421 <description>
422 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
423 <note><para>Feature only supported by analog channels.</para></note>
424 </description>
425 </manager>
426 <manager name="DAHDIShowChannels" language="en_US">
427 <synopsis>
428 Show status of DAHDI channels.
429 </synopsis>
430 <syntax>
431 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
432 <parameter name="DAHDIChannel">
433 <para>Specify the specific channel number to show. Show all channels if zero or not present.</para>
434 </parameter>
435 </syntax>
436 <description>
437 <para>Similar to the CLI command "dahdi show channels".</para>
438 </description>
439 </manager>
440 <manager name="DAHDIShowStatus" language="en_US">
441 <synopsis>
442 Show status of DAHDI spans.
443 </synopsis>
444 <syntax/>
445 <description>
446 <para>Similar to the CLI command "dahdi show status".</para>
447 </description>
448 </manager>
449 <manager name="DAHDIRestart" language="en_US">
450 <synopsis>
451 Fully Restart DAHDI channels (terminates calls).
452 </synopsis>
453 <syntax>
454 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
455 </syntax>
456 <description>
457 <para>Equivalent to the CLI command "dahdi restart".</para>
458 </description>
459 </manager>
460 <manager name="PRIShowSpans" language="en_US">
461 <synopsis>
462 Show status of PRI spans.
463 </synopsis>
464 <syntax>
465 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
466 <parameter name="Span">
467 <para>Specify the specific span to show. Show all spans if zero or not present.</para>
468 </parameter>
469 </syntax>
470 <description>
471 <para>Similar to the CLI command "pri show spans".</para>
472 </description>
473 </manager>
474 <manager name="PRIDebugSet" language="en_US">
475 <synopsis>
476 Set PRI debug levels for a span
477 </synopsis>
478 <syntax>
479 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
480 <parameter name="Span" required="true">
481 <para>Which span to affect.</para>
482 </parameter>
483 <parameter name="Level" required="true">
484 <para>What debug level to set. May be a numerical value or a text value from the list below</para>
485 <enumlist>
486 <enum name="off" />
487 <enum name="on" />
488 <enum name="hex" />
489 <enum name="intense" />
490 </enumlist>
491 </parameter>
492 </syntax>
493 <description>
494 <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
495 </description>
496 </manager>
497 <manager name="PRIDebugFileSet" language="en_US">
498 <synopsis>
499 Set the file used for PRI debug message output
500 </synopsis>
501 <syntax>
502 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
503 <parameter name="File" required="true">
504 <para>Path of file to write debug output.</para>
505 </parameter>
506 </syntax>
507 <description>
508 <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
509 </description>
510 </manager>
511 <manager name="PRIDebugFileUnset" language="en_US">
512 <synopsis>
513 Disables file output for PRI debug messages
514 </synopsis>
515 <syntax>
516 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
517 </syntax>
518 </manager>
519 <managerEvent language="en_US" name="AlarmClear">
520 <managerEventInstance class="EVENT_FLAG_SYSTEM">
521 <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
522 <syntax>
523 <parameter name="DAHDIChannel">
524 <para>The DAHDI channel on which the alarm was cleared.</para>
525 <note><para>This is not an Asterisk channel identifier.</para></note>
526 </parameter>
527 </syntax>
528 </managerEventInstance>
529 </managerEvent>
530 <managerEvent language="en_US" name="SpanAlarmClear">
531 <managerEventInstance class="EVENT_FLAG_SYSTEM">
532 <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
533 <syntax>
534 <parameter name="Span">
535 <para>The span on which the alarm was cleared.</para>
536 </parameter>
537 </syntax>
538 </managerEventInstance>
539 </managerEvent>
540 <managerEvent language="en_US" name="DNDState">
541 <managerEventInstance class="EVENT_FLAG_SYSTEM">
542 <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
543 <syntax>
544 <parameter name="DAHDIChannel">
545 <para>The DAHDI channel on which DND status changed.</para>
546 <note><para>This is not an Asterisk channel identifier.</para></note>
547 </parameter>
548 <parameter name="Status">
549 <enumlist>
550 <enum name="enabled"/>
551 <enum name="disabled"/>
552 </enumlist>
553 </parameter>
554 </syntax>
555 </managerEventInstance>
556 </managerEvent>
557 <managerEvent language="en_US" name="Alarm">
558 <managerEventInstance class="EVENT_FLAG_SYSTEM">
559 <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
560 <syntax>
561 <parameter name="DAHDIChannel">
562 <para>The channel on which the alarm occurred.</para>
563 <note><para>This is not an Asterisk channel identifier.</para></note>
564 </parameter>
565 <parameter name="Alarm">
566 <para>A textual description of the alarm that occurred.</para>
567 </parameter>
568 </syntax>
569 </managerEventInstance>
570 </managerEvent>
571 <managerEvent language="en_US" name="SpanAlarm">
572 <managerEventInstance class="EVENT_FLAG_SYSTEM">
573 <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
574 <syntax>
575 <parameter name="Span">
576 <para>The span on which the alarm occurred.</para>
577 </parameter>
578 <parameter name="Alarm">
579 <para>A textual description of the alarm that occurred.</para>
580 </parameter>
581 </syntax>
582 </managerEventInstance>
583 </managerEvent>
584 <managerEvent language="en_US" name="DAHDIChannel">
585 <managerEventInstance class="EVENT_FLAG_CALL">
586 <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
587 <syntax>
588 <channel_snapshot/>
589 <parameter name="DAHDIGroup">
590 <para>The DAHDI logical group associated with this channel.</para>
591 </parameter>
592 <parameter name="DAHDISpan">
593 <para>The DAHDI span associated with this channel.</para>
594 </parameter>
595 <parameter name="DAHDIChannel">
596 <para>The DAHDI channel associated with this channel.</para>
597 </parameter>
598 </syntax>
599 </managerEventInstance>
600 </managerEvent>
601 ***/
602
603#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
604
605static const char * const lbostr[] = {
606"0 db (CSU)/0-133 feet (DSX-1)",
607"133-266 feet (DSX-1)",
608"266-399 feet (DSX-1)",
609"399-533 feet (DSX-1)",
610"533-655 feet (DSX-1)",
611"-7.5db (CSU)",
612"-15db (CSU)",
613"-22.5db (CSU)"
614};
615
616/*! Global jitterbuffer configuration - by default, jb is disabled
617 * \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
619{
620 .flags = 0,
621 .max_size = 200,
622 .resync_threshold = 1000,
623 .impl = "fixed",
624 .target_extra = 40,
625};
627
628/*!
629 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
630 * the user hangs up to reset the state machine so ring works properly.
631 * This is used to be able to support kewlstart by putting the zhone in
632 * groundstart mode since their forward disconnect supervision is entirely
633 * broken even though their documentation says it isn't and their support
634 * is entirely unwilling to provide any assistance with their channel banks
635 * even though their web site says they support their products for life.
636 */
637/* #define ZHONE_HACK */
638
639/*! \brief Typically, how many rings before we should send Caller*ID */
640#define DEFAULT_CIDRINGS 1
641
642#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
643
644
645/*! \brief Signaling types that need to use MF detection should be placed in this macro */
646#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))
647
648static const char tdesc[] = "DAHDI Telephony"
649#if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
650 " w/"
651 #if defined(HAVE_PRI)
652 "PRI"
653 #endif /* defined(HAVE_PRI) */
654 #if defined(HAVE_SS7)
655 #if defined(HAVE_PRI)
656 " & "
657 #endif /* defined(HAVE_PRI) */
658 "SS7"
659 #endif /* defined(HAVE_SS7) */
660 #if defined(HAVE_OPENR2)
661 #if defined(HAVE_PRI) || defined(HAVE_SS7)
662 " & "
663 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
664 "MFC/R2"
665 #endif /* defined(HAVE_OPENR2) */
666#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
667;
668
669static const char config[] = "chan_dahdi.conf";
670
671#ifdef LOTS_OF_SPANS
672#define NUM_SPANS DAHDI_MAX_SPANS
673#else
674#define NUM_SPANS 32
675#endif
676
677#define CHAN_PSEUDO -2
678
679#define CALLPROGRESS_PROGRESS 1
680#define CALLPROGRESS_FAX_OUTGOING 2
681#define CALLPROGRESS_FAX_INCOMING 4
682#define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
683
684#define NUM_CADENCE_MAX 25
685static int num_cadence = 4;
687
688static int has_pseudo;
689
690static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
691 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
692 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
693 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
694 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
695};
696
697/*! \brief cidrings says in which pause to transmit the cid information, where the first pause
698 * is 1, the second pause is 2 and so on.
699 */
700
702 2, /*!< Right after first long ring */
703 4, /*!< Right after long part */
704 3, /*!< After third chirp */
705 2, /*!< Second spell */
706};
707
708/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
709static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
710
711#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
712 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
713
714#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
715#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
716
717static char defaultcic[64] = "";
718static char defaultozz[64] = "";
719
720/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
721static char mwimonitornotify[PATH_MAX] = "";
722#ifndef HAVE_DAHDI_LINEREVERSE_VMWI
723static int mwisend_rpas = 0;
724#endif
725
726static char progzone[10] = "";
727
730
731static int numbufs = 4;
732
733static int mwilevel = 512;
734static int dtmfcid_level = 256;
735
736#define REPORT_CHANNEL_ALARMS 1
737#define REPORT_SPAN_ALARMS 2
739
740#ifdef HAVE_PRI
741static int pridebugfd = -1;
742static char pridebugfilename[1024] = "";
743#endif
744
745/*! \brief Protect the interface list (of dahdi_pvt's) */
747
748
749static int ifcount = 0;
750
751#ifdef HAVE_PRI
752AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
753#endif
754
755/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
756 when it's doing something critical. */
758
759/*! \brief This is the thread for the monitor which checks for input on the channels
760 which are not currently in use. */
765static int ss_thread_count = 0;
766static int num_restart_pending = 0;
767
768static int restart_monitor(void);
769
770static int dahdi_sendtext(struct ast_channel *c, const char *text);
771
772/*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
773static inline int dahdi_get_event(int fd)
774{
775 int j;
776 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
777 return -1;
778 return j;
779}
780
781/*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
782static inline int dahdi_wait_event(int fd)
783{
784 int i, j = 0;
785 i = DAHDI_IOMUX_SIGEVENT;
786 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
787 return -1;
788 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
789 return -1;
790 return j;
791}
792
793/*! Chunk size to read -- we use 20ms chunks to make things happy. */
794#define READ_SIZE 160
795
796#define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
797#define MASK_INUSE (1 << 1) /*!< Channel currently in use */
798
799#define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) /*!< 300 ms */
800#define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
801#define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) /*!< 100 ms */
802#define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */
803#define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */
804#define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
805#define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
806
807/*!
808 * \brief Configured ring timeout base.
809 * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
810 */
812
813#if defined(HAVE_SS7)
814
815struct dahdi_ss7 {
816 struct sig_ss7_linkset ss7;
817};
818
819static struct dahdi_ss7 linksets[NUM_SPANS];
820
821static int cur_ss7type = -1;
822static int cur_slc = -1;
823static int cur_linkset = -1;
824static int cur_pointcode = -1;
825static int cur_cicbeginswith = -1;
826static int cur_adjpointcode = -1;
827static int cur_networkindicator = -1;
828static int cur_defaultdpc = -1;
829#endif /* defined(HAVE_SS7) */
830
831#ifdef HAVE_OPENR2
832struct dahdi_mfcr2_conf {
833 openr2_variant_t variant;
834 int mfback_timeout;
835 int metering_pulse_timeout;
836 int max_ani;
837 int max_dnis;
838#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
839 int dtmf_time_on;
840 int dtmf_time_off;
841#endif
842#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
843 int dtmf_end_timeout;
844#endif
845 signed int get_ani_first:2;
846#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
847 signed int skip_category_request:2;
848#endif
849 unsigned int call_files:1;
850 unsigned int allow_collect_calls:1;
851 unsigned int charge_calls:1;
852 unsigned int accept_on_offer:1;
853 unsigned int forced_release:1;
854 unsigned int double_answer:1;
855 signed int immediate_accept:2;
856#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
857 signed int dtmf_dialing:2;
858 signed int dtmf_detection:2;
859#endif
860 char logdir[OR2_MAX_PATH];
861 char r2proto_file[OR2_MAX_PATH];
862 openr2_log_level_t loglevel;
863 openr2_calling_party_category_t category;
864};
865
866/* MFC-R2 pseudo-link structure */
867struct dahdi_mfcr2 {
868 int index; /*!< Unique index for CLI */
869 pthread_t r2master; /*!< Thread of master */
870 openr2_context_t *protocol_context; /*!< OpenR2 context handle */
871 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */
872 int numchans; /*!< Number of channels in this R2 block */
873 int live_chans; /*!< Number of unremoved channels in this R2 block */
874 int nodev; /*!< Link disconnected? */
875 struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */
876};
877
878struct r2link_entry {
879 struct dahdi_mfcr2 mfcr2;
880 AST_LIST_ENTRY(r2link_entry) list;
881};
882static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
883static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
884
885
886/* how many r2links have been malloc'd */
887static int r2links_count = 0;
888
889#endif /* HAVE_OPENR2 */
890
891#ifdef HAVE_PRI
892
893struct dahdi_pri {
894 int dchannels[SIG_PRI_NUM_DCHANS]; /*!< What channel are the dchannels on */
895 int mastertrunkgroup; /*!< What trunk group is our master */
896 int prilogicalspan; /*!< Logical span number within trunk group */
897 struct sig_pri_span pri;
898};
899
900static struct dahdi_pri pris[NUM_SPANS];
901
902#if defined(HAVE_PRI_CCSS)
903/*! DAHDI PRI CCSS agent and monitor type name. */
904static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
905#endif /* defined(HAVE_PRI_CCSS) */
906
907#else
908/*! Shut up the compiler */
909struct dahdi_pri;
910#endif
911
912/* Polarity states */
913#define POLARITY_IDLE 0
914#define POLARITY_REV 1
915
916const char * const subnames[] = {
917 "Real",
918 "Callwait",
919 "Threeway"
920};
921
922static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
923static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
924
925#if defined(HAVE_PRI)
926struct doomed_pri {
927 struct sig_pri_span *pri;
928 AST_LIST_ENTRY(doomed_pri) list;
929};
930static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
931
932static void pri_destroy_span(struct sig_pri_span *pri);
933
934static struct dahdi_parms_pseudo {
935 int buf_no; /*!< Number of buffers */
936 int buf_policy; /*!< Buffer policy */
937 int faxbuf_no; /*!< Number of Fax buffers */
938 int faxbuf_policy; /*!< Fax buffer policy */
939} dahdi_pseudo_parms;
940#endif /* defined(HAVE_PRI) */
941
942/*! \brief Channel configuration from chan_dahdi.conf .
943 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
944 * Generally there is a field here for every possible configuration item.
945 *
946 * The state of fields is saved along the parsing and whenever a 'channel'
947 * statement is reached, the current dahdi_chan_conf is used to configure the
948 * channel (struct dahdi_pvt)
949 *
950 * \see dahdi_chan_init for the default values.
951 */
954#ifdef HAVE_PRI
955 struct dahdi_pri pri;
956#endif
957
958#if defined(HAVE_SS7)
959 struct dahdi_ss7 ss7;
960#endif /* defined(HAVE_SS7) */
961
962#ifdef HAVE_OPENR2
963 struct dahdi_mfcr2_conf mfcr2;
964#endif
965 struct dahdi_params timing;
966 int is_sig_auto; /*!< Use channel signalling from DAHDI? */
967 /*! Continue configuration even if a channel is not there. */
969
970 /*!
971 * \brief The serial port to listen for SMDI data on
972 * \note Set from the "smdiport" string read in from chan_dahdi.conf
973 */
975
976 /*!
977 * \brief Don't create channels below this number
978 * \note by default is 0 (no limit)
979 */
981
982 /*!
983 * \brief Don't create channels above this number (infinity by default)
984 * \note by default is 0 (special value that means "no limit").
985 */
987};
988
989/*! returns a new dahdi_chan_conf with default values (by-value) */
991{
992 /* recall that if a field is not included here it is initialized
993 * to 0 or equivalent
994 */
995 struct dahdi_chan_conf conf = {
996#ifdef HAVE_PRI
997 .pri.pri = {
998 .nsf = PRI_NSF_NONE,
999 .switchtype = PRI_SWITCH_NI2,
1000 .dialplan = PRI_UNKNOWN + 1,
1001 .localdialplan = PRI_NATIONAL_ISDN + 1,
1002 .nodetype = PRI_CPE,
1003 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1004
1005#if defined(HAVE_PRI_CCSS)
1006 .cc_ptmp_recall_mode = 1,/* specificRecall */
1007 .cc_qsig_signaling_link_req = 1,/* retain */
1008 .cc_qsig_signaling_link_rsp = 1,/* retain */
1009#endif /* defined(HAVE_PRI_CCSS) */
1010
1011 .minunused = 2,
1012 .idleext = "",
1013 .idledial = "",
1014 .internationalprefix = "",
1015 .nationalprefix = "",
1016 .localprefix = "",
1017 .privateprefix = "",
1018 .unknownprefix = "",
1019 .colp_send = SIG_PRI_COLP_UPDATE,
1020 .resetinterval = -1,
1021 },
1022#endif
1023#if defined(HAVE_SS7)
1024 .ss7.ss7 = {
1025 .called_nai = SS7_NAI_NATIONAL,
1026 .calling_nai = SS7_NAI_NATIONAL,
1027 .internationalprefix = "",
1028 .nationalprefix = "",
1029 .subscriberprefix = "",
1030 .unknownprefix = "",
1031 .networkroutedprefix = ""
1032 },
1033#endif /* defined(HAVE_SS7) */
1034#ifdef HAVE_OPENR2
1035 .mfcr2 = {
1036 .variant = OR2_VAR_ITU,
1037 .mfback_timeout = -1,
1038 .metering_pulse_timeout = -1,
1039 .max_ani = 10,
1040 .max_dnis = 4,
1041 .get_ani_first = -1,
1042#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1043 .skip_category_request = -1,
1044#endif
1045 .call_files = 0,
1046 .allow_collect_calls = 0,
1047 .charge_calls = 1,
1048 .accept_on_offer = 1,
1049 .forced_release = 0,
1050 .double_answer = 0,
1051 .immediate_accept = -1,
1052#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1053 .dtmf_dialing = -1,
1054 .dtmf_detection = -1,
1055 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1056 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1057#endif
1058#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1059 .dtmf_end_timeout = -1,
1060#endif
1061 .logdir = "",
1062 .r2proto_file = "",
1063 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1064 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1065 },
1066#endif
1067 .chan = {
1068 .context = "default",
1069 .immediatering = 1,
1070 .cid_num = "",
1071 .cid_name = "",
1072 .cid_tag = "",
1073 .mohinterpret = "default",
1074 .mohsuggest = "",
1075 .parkinglot = "",
1076 .transfertobusy = 1,
1077 .dialmode = 0,
1078
1079 .ani_info_digits = 2,
1080 .ani_wink_time = 1000,
1081 .ani_timeout = 10000,
1082
1083 .cid_signalling = CID_SIG_BELL,
1084 .cid_start = CID_START_RING,
1085 .dahditrcallerid = 0,
1086 .use_callerid = 1,
1087 .sig = -1,
1088 .outsigmod = -1,
1089
1090 .cid_rxgain = +5.0,
1091
1092 .tonezone = -1,
1093
1094 .echocancel.head.tap_length = 1,
1095
1096 .busycount = 3,
1097
1098 .accountcode = "",
1099
1100 .mailbox = "",
1101
1102#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1103 .mwisend_fsk = 1,
1104#endif
1105 .polarityonanswerdelay = 600,
1106
1107 .sendcalleridafter = DEFAULT_CIDRINGS,
1108
1109 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1110 .buf_no = numbufs,
1111 .usefaxbuffers = 0,
1112 .cc_params = ast_cc_config_params_init(),
1113 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1114 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1115 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1116 },
1117 .timing = {
1118 .prewinktime = -1,
1119 .preflashtime = -1,
1120 .winktime = -1,
1121 .flashtime = -1,
1122 .starttime = -1,
1123 .rxwinktime = -1,
1124 .rxflashtime = -1,
1125 .debouncetime = -1
1126 },
1127 .is_sig_auto = 1,
1128 .ignore_failed_channels = 1,
1129 .smdi_port = "/dev/ttyS0",
1130 };
1131
1132 return conf;
1133}
1134
1135
1136static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
1137 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
1138 const char *data, int *cause);
1139static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1140static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1141static int dahdi_sendtext(struct ast_channel *c, const char *text);
1142static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1143static int dahdi_hangup(struct ast_channel *ast);
1144static int dahdi_answer(struct ast_channel *ast);
1145static struct ast_frame *dahdi_read(struct ast_channel *ast);
1146static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1147static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1148static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1149static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1150static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1151static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1152static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1153static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1154static int dahdi_devicestate(const char *data);
1155static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1156
1158 .type = "DAHDI",
1159 .description = tdesc,
1160 .requester = dahdi_request,
1161 .send_digit_begin = dahdi_digit_begin,
1162 .send_digit_end = dahdi_digit_end,
1163 .send_text = dahdi_sendtext,
1164 .call = dahdi_call,
1165 .hangup = dahdi_hangup,
1166 .answer = dahdi_answer,
1167 .read = dahdi_read,
1168 .write = dahdi_write,
1169 .exception = dahdi_exception,
1170 .indicate = dahdi_indicate,
1171 .fixup = dahdi_fixup,
1172 .setoption = dahdi_setoption,
1173 .queryoption = dahdi_queryoption,
1174 .func_channel_read = dahdi_func_read,
1175 .func_channel_write = dahdi_func_write,
1176 .devicestate = dahdi_devicestate,
1177 .cc_callback = dahdi_cc_callback,
1178};
1179
1180#define GET_CHANNEL(p) ((p)->channel)
1181
1183{
1184 switch (sig) {
1185 case SIG_FXOLS:
1186 return ANALOG_SIG_FXOLS;
1187 case SIG_FXOGS:
1188 return ANALOG_SIG_FXOGS;
1189 case SIG_FXOKS:
1190 return ANALOG_SIG_FXOKS;
1191 case SIG_FXSLS:
1192 return ANALOG_SIG_FXSLS;
1193 case SIG_FXSGS:
1194 return ANALOG_SIG_FXSGS;
1195 case SIG_FXSKS:
1196 return ANALOG_SIG_FXSKS;
1197 case SIG_EMWINK:
1198 return ANALOG_SIG_EMWINK;
1199 case SIG_EM:
1200 return ANALOG_SIG_EM;
1201 case SIG_EM_E1:
1202 return ANALOG_SIG_EM_E1;
1203 case SIG_FEATD:
1204 return ANALOG_SIG_FEATD;
1205 case SIG_FEATDMF:
1206 return ANALOG_SIG_FEATDMF;
1207 case SIG_E911:
1208 return SIG_E911;
1209 case SIG_FGC_CAMA:
1210 return ANALOG_SIG_FGC_CAMA;
1211 case SIG_FGC_CAMAMF:
1212 return ANALOG_SIG_FGC_CAMAMF;
1213 case SIG_FEATB:
1214 return ANALOG_SIG_FEATB;
1215 case SIG_SFWINK:
1216 return ANALOG_SIG_SFWINK;
1217 case SIG_SF:
1218 return ANALOG_SIG_SF;
1219 case SIG_SF_FEATD:
1220 return ANALOG_SIG_SF_FEATD;
1221 case SIG_SF_FEATDMF:
1222 return ANALOG_SIG_SF_FEATDMF;
1223 case SIG_FEATDMF_TA:
1224 return ANALOG_SIG_FEATDMF_TA;
1225 case SIG_SF_FEATB:
1226 return ANALOG_SIG_FEATB;
1227 default:
1228 return -1;
1229 }
1230}
1231
1232
1234{
1235 switch (tone) {
1237 return DAHDI_TONE_RINGTONE;
1239 return DAHDI_TONE_STUTTER;
1241 return DAHDI_TONE_CONGESTION;
1243 return DAHDI_TONE_DIALTONE;
1245 return DAHDI_TONE_DIALRECALL;
1246 case ANALOG_TONE_INFO:
1247 return DAHDI_TONE_INFO;
1248 default:
1249 return -1;
1250 }
1251}
1252
1253static int analogsub_to_dahdisub(enum analog_sub analogsub)
1254{
1255 int index;
1256
1257 switch (analogsub) {
1258 case ANALOG_SUB_REAL:
1259 index = SUB_REAL;
1260 break;
1262 index = SUB_CALLWAIT;
1263 break;
1265 index = SUB_THREEWAY;
1266 break;
1267 default:
1268 ast_log(LOG_ERROR, "Unidentified sub!\n");
1269 index = SUB_REAL;
1270 }
1271
1272 return index;
1273}
1274
1275/*!
1276 * \internal
1277 * \brief release all members on the doomed pris list
1278 * \since 13.0
1279 *
1280 * Called priodically by the monitor threads to release spans marked for
1281 * removal.
1282 */
1283static void release_doomed_pris(void)
1284{
1285#ifdef HAVE_PRI
1286 struct doomed_pri *entry;
1287
1288 AST_LIST_LOCK(&doomed_pris);
1289 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1290 /* The span destruction must be done with this lock not held */
1291 AST_LIST_UNLOCK(&doomed_pris);
1292 ast_debug(4, "Destroying span %d from doomed queue.\n",
1293 entry->pri->span);
1294 pri_destroy_span(entry->pri);
1295 ast_free(entry);
1296 AST_LIST_LOCK(&doomed_pris);
1297 }
1298 AST_LIST_UNLOCK(&doomed_pris);
1299#endif
1300}
1301
1302#ifdef HAVE_PRI
1303/*!
1304 * \brief Queue a span for destruction
1305 * \since 13.0
1306 *
1307 * \param pri the span to destroy
1308 *
1309 * Add a span to the list of spans to be destroyed later on
1310 * by the monitor thread. Allows destroying a span while holding its
1311 * lock.
1312 */
1313static void pri_queue_for_destruction(struct sig_pri_span *pri)
1314{
1315 struct doomed_pri *entry;
1316
1317 AST_LIST_LOCK(&doomed_pris);
1318 AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1319 if (entry->pri == pri) {
1320 AST_LIST_UNLOCK(&doomed_pris);
1321 return;
1322 }
1323 }
1324 entry = ast_calloc(sizeof(struct doomed_pri), 1);
1325 if (!entry) {
1326 /* Nothing useful to do here. Panic? */
1327 ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
1328 AST_LIST_UNLOCK(&doomed_pris);
1329 return;
1330 }
1331 entry->pri = pri;
1332 ast_debug(4, "Queue span %d for destruction.\n", pri->span);
1333 AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
1334 AST_LIST_UNLOCK(&doomed_pris);
1335}
1336#endif
1337
1338/*!
1339 * \internal
1340 * \brief Send a dial string to DAHDI.
1341 * \since 12.0.0
1342 *
1343 * \param pvt DAHDI private pointer
1344 * \param operation DAHDI dial operation to do to string
1345 * \param dial_str Dial string to send
1346 *
1347 * \retval 0 on success.
1348 * \retval non-zero on error.
1349 */
1350static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
1351{
1352 int res;
1353 int offset;
1354 const char *pos;
1355 struct dahdi_dialoperation zo = {
1356 .op = operation,
1357 };
1358
1359 /* Convert the W's to ww. */
1360 pos = dial_str;
1361 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1362 if (!*pos) {
1363 break;
1364 }
1365 if (*pos == 'W') {
1366 /* Convert 'W' to "ww" */
1367 ++pos;
1368 if (offset >= sizeof(zo.dialstr) - 3) {
1369 /* No room to expand */
1370 break;
1371 }
1372 zo.dialstr[offset] = 'w';
1373 ++offset;
1374 zo.dialstr[offset] = 'w';
1375 continue;
1376 }
1377 zo.dialstr[offset] = *pos++;
1378 }
1379 /* The zo initialization has already terminated the dialstr. */
1380
1381 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1382 pvt->channel, dial_str, zo.dialstr);
1383 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1384 if (res) {
1385 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1386 pvt->channel, dial_str, strerror(errno));
1387 }
1388
1389 return res;
1390}
1391
1393static int bump_gains(struct dahdi_pvt *p);
1394static int dahdi_setlinear(int dfd, int linear);
1395
1396static int my_start_cid_detect(void *pvt, int cid_signalling)
1397{
1398 struct dahdi_pvt *p = pvt;
1399 int index = SUB_REAL;
1401 if (!p->cs) {
1402 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1403 return -1;
1404 }
1405 bump_gains(p);
1406 dahdi_setlinear(p->subs[index].dfd, 0);
1407
1408 return 0;
1409}
1410
1411static int restore_gains(struct dahdi_pvt *p);
1412
1413static int my_stop_cid_detect(void *pvt)
1414{
1415 struct dahdi_pvt *p = pvt;
1416 int index = SUB_REAL;
1417
1418 if (p->cs) {
1419 callerid_free(p->cs);
1420 }
1421
1422 /* Restore linear mode after Caller*ID processing */
1423 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1424 restore_gains(p);
1425
1426 return 0;
1427}
1428
1429static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
1430{
1431 struct dahdi_pvt *p = pvt;
1432 struct analog_pvt *analog_p = p->sig_pvt;
1433 struct pollfd poller;
1434 char *name, *num;
1435 int index = SUB_REAL;
1436 int res;
1437 unsigned char buf[256];
1438 int flags;
1439 int redirecting;
1440
1441 poller.fd = p->subs[SUB_REAL].dfd;
1442 poller.events = POLLPRI | POLLIN;
1443 poller.revents = 0;
1444
1445 res = poll(&poller, 1, timeout);
1446
1447 if (poller.revents & POLLPRI) {
1449 return 1;
1450 }
1451
1452 if (poller.revents & POLLIN) {
1453 /*** NOTES ***/
1454 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1455 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1456 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1457 * a failure and die, and returning 2 means no event was received. */
1458 res = read(p->subs[index].dfd, buf, sizeof(buf));
1459 if (res < 0) {
1460 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1461 return -1;
1462 }
1463
1464 if (analog_p->ringt > 0) {
1465 if (!(--analog_p->ringt)) {
1466 /* only return if we timeout from a ring event */
1467 return -1;
1468 }
1469 }
1470
1471 if (p->cid_signalling == CID_SIG_V23_JP) {
1472 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1473 } else {
1474 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1475 }
1476 if (res < 0) {
1477 /*
1478 * The previous diagnostic message output likely
1479 * explains why it failed.
1480 */
1481 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1482 return -1;
1483 }
1484
1485 if (res == 1) {
1486 struct ast_channel *chan = analog_p->ss_astchan;
1488 if (name)
1490 if (num)
1491 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1492
1494 /* If we got a presentation, we must set it on the channel */
1495 struct ast_party_caller caller;
1496
1498 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1501 ast_party_caller_free(&caller);
1502 }
1503 if (redirecting) {
1504 /* There is a redirecting reason available in the Caller*ID received.
1505 * No idea what the redirecting number is, since the Caller*ID protocol
1506 * has no parameter for that, but at least we know WHY it was redirected. */
1507 ast_channel_redirecting(chan)->reason.code = redirecting;
1508 }
1509
1510 if (flags & CID_QUALIFIER) {
1511 /* This is the inverse of how the qualifier is set in sig_analog */
1512 pbx_builtin_setvar_helper(chan, "CALL_QUALIFIER", "1");
1513 }
1514
1515 ast_debug(1, "CallerID number: %s, name: %s, flags=%d, redirecting=%s\n", num, name, flags, ast_redirecting_reason_name(&ast_channel_redirecting(chan)->reason));
1516 return 0;
1517 }
1518 }
1519
1520 *ev = ANALOG_EVENT_NONE;
1521 return 2;
1522}
1523
1524static const char *event2str(int event);
1525
1526static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
1527{
1528 unsigned char buf[256];
1529 int distMatches;
1530 int curRingData[RING_PATTERNS];
1531 int receivedRingT;
1532 int counter1;
1533 int counter;
1534 int i;
1535 int res;
1536 int checkaftercid = 0;
1537 const char *matched_context;
1538 struct dahdi_pvt *p = pvt;
1539 struct analog_pvt *analog_p = p->sig_pvt;
1540
1541 if (ringdata == NULL) {
1542 ringdata = curRingData;
1543 } else {
1544 checkaftercid = 1;
1545 }
1546
1547 /* We must have a ring by now so lets try to listen for distinctive ringing */
1548 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1549 /* Clear the current ring data array so we don't have old data in it. */
1550 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1551 ringdata[receivedRingT] = 0;
1552 receivedRingT = 0;
1553
1554 if (checkaftercid && distinctiveringaftercid) {
1555 ast_verb(3, "Detecting post-CID distinctive ring\n");
1556 }
1557
1558 for (;;) {
1559 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1560 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1561 if (res) {
1562 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1563 ast_hangup(chan);
1564 return 1;
1565 }
1566 if (i & DAHDI_IOMUX_SIGEVENT) {
1567 res = dahdi_get_event(p->subs[idx].dfd);
1568 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1569 if (res == DAHDI_EVENT_NOALARM) {
1570 p->inalarm = 0;
1571 analog_p->inalarm = 0;
1572 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1573 /* Let us detect distinctive ring */
1574 ringdata[receivedRingT] = analog_p->ringt;
1575
1576 if (analog_p->ringt < analog_p->ringt_base / 2) {
1577 break;
1578 }
1579 /* Increment the ringT counter so we can match it against
1580 values in chan_dahdi.conf for distinctive ring */
1581 if (++receivedRingT == RING_PATTERNS) {
1582 break;
1583 }
1584 }
1585 } else if (i & DAHDI_IOMUX_READ) {
1586 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1587 if (res < 0) {
1588 if (errno != ELAST) {
1589 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1590 ast_hangup(chan);
1591 return 1;
1592 }
1593 break;
1594 }
1595 if (analog_p->ringt > 0) {
1596 if (!(--analog_p->ringt)) {
1597 break;
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1605 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1606 matched_context = p->defcontext;
1607 for (counter = 0; counter < 3; counter++) {
1608 int range = p->drings.ringnum[counter].range;
1609
1610 distMatches = 0;
1611 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1612 p->drings.ringnum[counter].ring[0],
1613 p->drings.ringnum[counter].ring[1],
1614 p->drings.ringnum[counter].ring[2],
1615 range);
1616 for (counter1 = 0; counter1 < 3; counter1++) {
1617 int ring = p->drings.ringnum[counter].ring[counter1];
1618
1619 if (ring == -1) {
1620 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1621 ringdata[counter1]);
1622 distMatches++;
1623 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1624 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1625 ringdata[counter1], ring - range, ring + range);
1626 distMatches++;
1627 } else {
1628 /* The current dring pattern cannot match. */
1629 break;
1630 }
1631 }
1632
1633 if (distMatches == 3) {
1634 /* The ring matches, set the context to whatever is for distinctive ring.. */
1635 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1636 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1637 break;
1638 }
1639 }
1640
1641 /* Set selected distinctive ring context if not already set. */
1642 if (strcmp(p->context, matched_context) != 0) {
1643 ast_copy_string(p->context, matched_context, sizeof(p->context));
1644 ast_channel_context_set(chan, matched_context);
1645 }
1646
1647 return 0;
1648}
1649
1650static int my_stop_callwait(void *pvt)
1651{
1652 struct dahdi_pvt *p = pvt;
1653 p->callwaitingrepeat = 0;
1654 p->cidcwexpire = 0;
1655 p->cid_suppress_expire = 0;
1656
1657 return 0;
1658}
1659
1660static int send_callerid(struct dahdi_pvt *p);
1661static int save_conference(struct dahdi_pvt *p);
1662static int restore_conference(struct dahdi_pvt *p);
1663
1664static int my_callwait(void *pvt)
1665{
1666 struct dahdi_pvt *p = pvt;
1667
1669 if (p->cidspill) {
1670 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1671 ast_free(p->cidspill);
1672 }
1673
1674 /*
1675 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1676 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1677 */
1678 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1679 return -1;
1680 save_conference(p);
1681 /* Silence */
1682 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1683 if (!p->callwaitrings && p->callwaitingcallerid) {
1684 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1685 p->callwaitcas = 1;
1686 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1687 } else {
1688 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1689 p->callwaitcas = 0;
1690 p->cidlen = 2400 + READ_SIZE * 4;
1691 }
1692 p->cidpos = 0;
1693 send_callerid(p);
1694
1695 return 0;
1696}
1697
1698static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
1699{
1700 struct dahdi_pvt *p = pvt;
1701 struct analog_pvt *analog_p = p->sig_pvt;
1702
1703 ast_debug(2, "Starting cid spill\n");
1704
1705 if (p->cidspill) {
1706 ast_log(LOG_WARNING, "cidspill already exists??\n");
1707 ast_free(p->cidspill);
1708 }
1709
1711 int pres = ast_party_id_presentation(&caller->id);
1712 if (cwcid == 0) {
1713 /* Some CPE support additional parameters for on-hook Caller*ID,
1714 * such as redirecting reason and call qualifier, so send those
1715 * if available.
1716 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1717 * so don't send those for call waiting as that will just lengthen the CID spill
1718 * for no good reason.
1719 */
1721 caller->id.name.str,
1723 NULL,
1724 analog_p->redirecting_reason,
1725 pres,
1726 analog_p->call_qualifier,
1728 AST_LAW(p));
1729 } else {
1730 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1732 p->callwaitcas = 0;
1733 p->cidcwexpire = 0;
1735 caller->id.name.str,
1737 NULL,
1738 -1,
1739 pres,
1740 0,
1741 AST_LAW(p));
1742 p->cidlen += READ_SIZE * 4;
1743 }
1744 p->cidpos = 0;
1745 p->cid_suppress_expire = 0;
1746 send_callerid(p);
1747 }
1748 return 0;
1749}
1750
1752{
1753 struct dahdi_pvt *p = pvt;
1754 if (p->dsp)
1756
1757 return 0;
1758}
1759
1760static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
1761{
1762 struct dahdi_pvt *p = pvt;
1763
1764 if (p->channel == CHAN_PSEUDO)
1765 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1766
1767 if (mode == ANALOG_DIGITMODE_DTMF) {
1768 /* If we do hardware dtmf, no need for a DSP */
1769 if (p->hardwaredtmf) {
1770 if (p->dsp) {
1771 ast_dsp_free(p->dsp);
1772 p->dsp = NULL;
1773 }
1774 return 0;
1775 }
1776
1777 if (!p->dsp) {
1778 p->dsp = ast_dsp_new();
1779 if (!p->dsp) {
1780 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1781 return -1;
1782 }
1783 }
1784
1786 } else if (mode == ANALOG_DIGITMODE_MF) {
1787 if (!p->dsp) {
1788 p->dsp = ast_dsp_new();
1789 if (!p->dsp) {
1790 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1791 return -1;
1792 }
1793 }
1795 }
1796 return 0;
1797}
1798
1799static int dahdi_wink(struct dahdi_pvt *p, int index);
1800
1801static int my_wink(void *pvt, enum analog_sub sub)
1802{
1803 struct dahdi_pvt *p = pvt;
1804 int index = analogsub_to_dahdisub(sub);
1805 if (index != SUB_REAL) {
1806 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1807 }
1808 return dahdi_wink(p, index);
1809}
1810
1811static void wakeup_sub(struct dahdi_pvt *p, int a);
1812
1813static int reset_conf(struct dahdi_pvt *p);
1814
1815static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1816
1817static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
1818{
1819 struct ast_frame *f = *dest;
1820 struct dahdi_pvt *p = pvt;
1821 int idx = analogsub_to_dahdisub(analog_index);
1822
1823 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1824 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1825 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1826
1827 if (f->subclass.integer == 'f') {
1828 if (f->frametype == AST_FRAME_DTMF_END) {
1829 /* Fax tone -- Handle and return NULL */
1830 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1831 /* If faxbuffers are configured, use them for the fax transmission */
1832 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1833 struct dahdi_bufferinfo bi = {
1834 .txbufpolicy = p->faxbuf_policy,
1835 .bufsize = p->bufsize,
1836 .numbufs = p->faxbuf_no
1837 };
1838 int res;
1839
1840 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1841 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1842 } else {
1843 p->bufferoverrideinuse = 1;
1844 }
1845 }
1846 p->faxhandled = 1;
1847 if (p->dsp) {
1848 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1850 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1851 }
1852 if (strcmp(ast_channel_exten(ast), "fax")) {
1853 const char *target_context = ast_channel_context(ast);
1854
1855 /*
1856 * We need to unlock 'ast' here because ast_exists_extension has the
1857 * potential to start autoservice on the channel. Such action is prone
1858 * to deadlock if the channel is locked.
1859 *
1860 * ast_async_goto() has its own restriction on not holding the
1861 * channel lock.
1862 */
1864 ast_channel_unlock(ast);
1865 if (ast_exists_extension(ast, target_context, "fax", 1,
1866 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1867 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1868 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1869 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1870 if (ast_async_goto(ast, target_context, "fax", 1))
1871 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1872 } else {
1873 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1874 }
1875 ast_channel_lock(ast);
1876 ast_mutex_lock(&p->lock);
1877 } else {
1878 ast_debug(1, "Already in a fax extension, not redirecting\n");
1879 }
1880 } else {
1881 ast_debug(1, "Fax already handled\n");
1882 }
1883 dahdi_confmute(p, 0);
1884 }
1885 p->subs[idx].f.frametype = AST_FRAME_NULL;
1886 p->subs[idx].f.subclass.integer = 0;
1887 *dest = &p->subs[idx].f;
1888 }
1889}
1890
1891static void my_lock_private(void *pvt)
1892{
1893 struct dahdi_pvt *p = pvt;
1894 ast_mutex_lock(&p->lock);
1895}
1896
1897static void my_unlock_private(void *pvt)
1898{
1899 struct dahdi_pvt *p = pvt;
1901}
1902
1903static void my_deadlock_avoidance_private(void *pvt)
1904{
1905 struct dahdi_pvt *p = pvt;
1906
1908}
1909
1911{
1912 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1913 struct ast_channel_blob *obj = stasis_message_data(msg);
1914 struct ast_json *group, *span, *channel;
1915
1916 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1917 if (!channel_string) {
1918 return NULL;
1919 }
1920
1921 group = ast_json_object_get(obj->blob, "group");
1922 span = ast_json_object_get(obj->blob, "span");
1923 channel = ast_json_object_get(obj->blob, "channel");
1924
1925 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1926 "%s"
1927 "DAHDIGroup: %llu\r\n"
1928 "DAHDISpan: %u\r\n"
1929 "DAHDIChannel: %s\r\n",
1930 ast_str_buffer(channel_string),
1932 (unsigned int)ast_json_integer_get(span),
1933 ast_json_string_get(channel));
1934}
1935
1938 );
1939
1940/*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1941static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
1942{
1943 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1944
1945 ast_assert(dahdi_channel != NULL);
1946
1947 blob = ast_json_pack("{s: I, s: i, s: s}",
1948 "group", (ast_json_int_t)group,
1949 "span", span,
1950 "channel", dahdi_channel);
1951 if (!blob) {
1952 return;
1953 }
1954
1955 ast_channel_lock(chan);
1956 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1957 ast_channel_unlock(chan);
1958}
1959
1960/*!
1961 * \internal
1962 * \brief Post an AMI DAHDI channel association event.
1963 * \since 1.8
1964 *
1965 * \param p DAHDI private pointer
1966 * \param chan Channel associated with the private pointer
1967 */
1968static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
1969{
1970 char ch_name[23];
1971
1972 if (p->channel < CHAN_PSEUDO) {
1973 /* No B channel */
1974 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1975 } else if (p->channel == CHAN_PSEUDO) {
1976 /* Pseudo channel */
1977 strcpy(ch_name, "pseudo");
1978 } else {
1979 /* Real channel */
1980 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1981 }
1982 publish_dahdichannel(chan, p->group, p->span, ch_name);
1983}
1984
1985#ifdef HAVE_PRI
1986/*!
1987 * \internal
1988 * \brief Post an AMI DAHDI channel association event.
1989 * \since 1.8
1990 *
1991 * \param pvt DAHDI private pointer
1992 * \param chan Channel associated with the private pointer
1993 */
1994static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
1995{
1996 struct dahdi_pvt *p = pvt;
1997
1998 dahdi_ami_channel_event(p, chan);
1999}
2000#endif
2001
2002/* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
2003* returns the last value of the linear setting
2004*/
2005static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
2006{
2007 struct dahdi_pvt *p = pvt;
2008 int oldval;
2009 int idx = analogsub_to_dahdisub(sub);
2010
2011 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
2012 oldval = p->subs[idx].linear;
2013 p->subs[idx].linear = linear_mode ? 1 : 0;
2014 return oldval;
2015}
2016
2017static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
2018{
2019 struct dahdi_pvt *p = pvt;
2020 int idx = analogsub_to_dahdisub(sub);
2021
2022 p->subs[idx].inthreeway = inthreeway;
2023}
2024
2025static int get_alarms(struct dahdi_pvt *p);
2026static void handle_alarms(struct dahdi_pvt *p, int alms);
2027static void my_get_and_handle_alarms(void *pvt)
2028{
2029 int res;
2030 struct dahdi_pvt *p = pvt;
2031
2032 res = get_alarms(p);
2033 handle_alarms(p, res);
2034}
2035
2037{
2039
2040 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2041 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2042
2043 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2044 return p->sig_pvt;
2045 }
2046 }
2047 return NULL;
2048}
2049
2050static int my_get_sub_fd(void *pvt, enum analog_sub sub)
2051{
2052 struct dahdi_pvt *p = pvt;
2053 int dahdi_sub = analogsub_to_dahdisub(sub);
2054 return p->subs[dahdi_sub].dfd;
2055}
2056
2057static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
2058{
2059 struct dahdi_pvt *p = pvt;
2060
2061 /* Choose proper cadence */
2062 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2063 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2064 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2065 *cid_rings = cidrings[p->distinctivering - 1];
2066 } else {
2067 if (p->distinctivering > 0) {
2068 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2069 }
2070 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2071 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2072 *cid_rings = p->sendcalleridafter;
2073 }
2074}
2075
2076static void my_set_alarm(void *pvt, int in_alarm)
2077{
2078 struct dahdi_pvt *p = pvt;
2079
2080 p->inalarm = in_alarm;
2081}
2082
2083static void my_set_dialing(void *pvt, int is_dialing)
2084{
2085 struct dahdi_pvt *p = pvt;
2086
2087 p->dialing = is_dialing;
2088}
2089
2090static void my_set_outgoing(void *pvt, int is_outgoing)
2091{
2092 struct dahdi_pvt *p = pvt;
2093
2094 p->outgoing = is_outgoing;
2095}
2096
2097#if defined(HAVE_PRI) || defined(HAVE_SS7)
2098static void my_set_digital(void *pvt, int is_digital)
2099{
2100 struct dahdi_pvt *p = pvt;
2101
2102 p->digital = is_digital;
2103}
2104#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2105
2106#if defined(HAVE_SS7)
2107static void my_set_inservice(void *pvt, int is_inservice)
2108{
2109 struct dahdi_pvt *p = pvt;
2110
2111 p->inservice = is_inservice;
2112}
2113#endif /* defined(HAVE_SS7) */
2114
2115#if defined(HAVE_SS7)
2116static void my_set_locallyblocked(void *pvt, int is_blocked)
2117{
2118 struct dahdi_pvt *p = pvt;
2119
2120 p->locallyblocked = is_blocked;
2121}
2122#endif /* defined(HAVE_SS7) */
2123
2124#if defined(HAVE_SS7)
2125static void my_set_remotelyblocked(void *pvt, int is_blocked)
2126{
2127 struct dahdi_pvt *p = pvt;
2128
2129 p->remotelyblocked = is_blocked;
2130}
2131#endif /* defined(HAVE_SS7) */
2132
2133static void my_set_ringtimeout(void *pvt, int ringt)
2134{
2135 struct dahdi_pvt *p = pvt;
2136 p->ringt = ringt;
2137}
2138
2139static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
2140{
2141 struct dahdi_pvt *p = pvt;
2142
2143 /* We reset p->waitfordialtonetemp here, to prevent leaking to future calls,
2144 * but we also need to check against this value until we get dialtone
2145 * or the timer expires, since waitingfordt is when the timer started,
2146 * not when it should expire.
2147 *
2148 * Critically, we only set p->waitingfordt here if waitfordialtone or waitfordialtonetemp
2149 * has already been set, as waitingfordt is what is checked at runtime to determine
2150 * if we should be waiting for dial tone. This ensures that if a second call
2151 * is initiated concurrently, the first one "consumes" waitfordialtonetemp and resets it,
2152 * preventing leaking to other calls while remaining available to check on the first one while dialing.
2153 */
2155 p->waitfordialtonetemp = 0;
2156
2158 return;
2159 }
2160
2161 /* Because the DSP is allocated when the channel is created,
2162 * if we requested waitfordialtone later (in a predial handler),
2163 * we need to create it now */
2164 if (!p->dsp) {
2165 p->dsp = ast_dsp_new();
2166 if (!p->dsp) {
2167 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
2168 return;
2169 }
2170 }
2173
2174 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtoneduration);
2175 gettimeofday(&p->waitingfordt, NULL);
2177}
2178
2179static int my_check_waitingfordt(void *pvt)
2180{
2181 struct dahdi_pvt *p = pvt;
2182
2183 if (p->waitingfordt.tv_sec) {
2184 return 1;
2185 }
2186
2187 return 0;
2188}
2189
2190static void my_set_confirmanswer(void *pvt, int flag)
2191{
2192 struct dahdi_pvt *p = pvt;
2193 p->confirmanswer = flag;
2194}
2195
2196static int my_check_confirmanswer(void *pvt)
2197{
2198 struct dahdi_pvt *p = pvt;
2199 if (p->confirmanswer) {
2200 return 1;
2201 }
2202
2203 return 0;
2204}
2205
2206static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2207{
2208 struct dahdi_pvt *p = pvt;
2209
2210 p->callwaiting = callwaiting_enable;
2211}
2212
2213static void my_cancel_cidspill(void *pvt)
2214{
2215 struct dahdi_pvt *p = pvt;
2216
2217 ast_free(p->cidspill);
2218 p->cidspill = NULL;
2220}
2221
2222static int my_confmute(void *pvt, int mute)
2223{
2224 struct dahdi_pvt *p = pvt;
2225 return dahdi_confmute(p, mute);
2226}
2227
2228static void my_set_pulsedial(void *pvt, int flag)
2229{
2230 struct dahdi_pvt *p = pvt;
2231 p->pulsedial = flag;
2232}
2233
2234static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
2235{
2236 struct dahdi_pvt *p = pvt;
2237
2238 p->owner = new_owner;
2239}
2240
2241static const char *my_get_orig_dialstring(void *pvt)
2242{
2243 struct dahdi_pvt *p = pvt;
2244
2245 return p->dialstring;
2246}
2247
2248static void my_increase_ss_count(void)
2249{
2253}
2254
2255static void my_decrease_ss_count(void)
2256{
2261}
2262
2263static void my_all_subchannels_hungup(void *pvt)
2264{
2265 struct dahdi_pvt *p = pvt;
2266 int res, law;
2267
2268 p->faxhandled = 0;
2269 p->didtdd = 0;
2270
2271 if (p->dsp) {
2272 ast_dsp_free(p->dsp);
2273 p->dsp = NULL;
2274 }
2275
2276 p->law = p->law_default;
2277 law = p->law_default;
2278 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2279 if (res < 0)
2280 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2281
2283
2284#if 1
2285 {
2286 int i;
2287 p->owner = NULL;
2288 /* Cleanup owners here */
2289 for (i = 0; i < 3; i++) {
2290 p->subs[i].owner = NULL;
2291 }
2292 }
2293#endif
2294
2295 reset_conf(p);
2296 if (num_restart_pending == 0) {
2298 }
2299}
2300
2301static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2302
2303static int my_conf_del(void *pvt, enum analog_sub sub)
2304{
2305 struct dahdi_pvt *p = pvt;
2306 int x = analogsub_to_dahdisub(sub);
2307
2308 return conf_del(p, &p->subs[x], x);
2309}
2310
2311static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2312
2313static int my_conf_add(void *pvt, enum analog_sub sub)
2314{
2315 struct dahdi_pvt *p = pvt;
2316 int x = analogsub_to_dahdisub(sub);
2317
2318 return conf_add(p, &p->subs[x], x, 0);
2319}
2320
2321static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2322
2323static int my_complete_conference_update(void *pvt, int needconference)
2324{
2325 struct dahdi_pvt *p = pvt;
2326 int needconf = needconference;
2327 int x;
2328 int useslavenative;
2329 struct dahdi_pvt *slave = NULL;
2330
2331 useslavenative = isslavenative(p, &slave);
2332
2333 /* If we have a slave, add him to our conference now. or DAX
2334 if this is slave native */
2335 for (x = 0; x < MAX_SLAVES; x++) {
2336 if (p->slaves[x]) {
2337 if (useslavenative)
2338 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2339 else {
2340 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2341 needconf++;
2342 }
2343 }
2344 }
2345 /* If we're supposed to be in there, do so now */
2346 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2347 if (useslavenative)
2348 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2349 else {
2350 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2351 needconf++;
2352 }
2353 }
2354 /* If we have a master, add ourselves to his conference */
2355 if (p->master) {
2356 if (isslavenative(p->master, NULL)) {
2358 } else {
2359 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2360 }
2361 }
2362 if (!needconf) {
2363 /* Nobody is left (or should be left) in our conference.
2364 Kill it. */
2365 p->confno = -1;
2366 }
2367
2368 return 0;
2369}
2370
2371static int check_for_conference(struct dahdi_pvt *p);
2372
2373static int my_check_for_conference(void *pvt)
2374{
2375 struct dahdi_pvt *p = pvt;
2376 return check_for_conference(p);
2377}
2378
2379static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
2380{
2381 struct dahdi_pvt *p = pvt;
2382 int da, db;
2383 int tchan;
2384 int tinthreeway;
2385
2388
2389 tchan = p->subs[da].chan;
2390 p->subs[da].chan = p->subs[db].chan;
2391 p->subs[db].chan = tchan;
2392
2393 tinthreeway = p->subs[da].inthreeway;
2394 p->subs[da].inthreeway = p->subs[db].inthreeway;
2395 p->subs[db].inthreeway = tinthreeway;
2396
2397 p->subs[da].owner = ast_a;
2398 p->subs[db].owner = ast_b;
2399
2400 if (ast_a)
2401 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2402 if (ast_b)
2403 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2404
2405 wakeup_sub(p, a);
2406 wakeup_sub(p, b);
2407
2408 return;
2409}
2410
2411/*!
2412 * \internal
2413 * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
2414 * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
2415 *
2416 * \param callid_created value returned from ast_callid_threadstorage_auto()
2417 * \param i, state, startpbx, idx, law, assignedids, requestor, callid
2418 */
2419static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created);
2420
2421static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid);
2422
2423static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
2424{
2425 ast_callid callid = 0;
2426 int callid_created = ast_callid_threadstorage_auto(&callid);
2427 struct dahdi_pvt *p = pvt;
2428 int dsub = analogsub_to_dahdisub(sub);
2429
2430 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2431}
2432
2433#if defined(HAVE_PRI) || defined(HAVE_SS7)
2434static int dahdi_setlaw(int dfd, int law)
2435{
2436 int res;
2437 res = ioctl(dfd, DAHDI_SETLAW, &law);
2438 if (res)
2439 return res;
2440 return 0;
2441}
2442#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2443
2444#if defined(HAVE_PRI)
2445static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
2446 enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
2447 const struct ast_channel *requestor)
2448{
2449 struct dahdi_pvt *p = pvt;
2450 int audio;
2451 int newlaw = -1;
2452 ast_callid callid = 0;
2453 int callid_created = ast_callid_threadstorage_auto(&callid);
2454
2455 switch (p->sig) {
2457 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2458 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
2459 break;
2460 }
2461 /* Fall through */
2462 default:
2463 /* Set to audio mode at this point */
2464 audio = 1;
2465 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2466 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
2467 p->channel, audio, strerror(errno));
2468 }
2469 break;
2470 }
2471
2472 if (law != SIG_PRI_DEFLAW) {
2473 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2474 }
2475
2476 ast_copy_string(p->exten, exten, sizeof(p->exten));
2477
2478 switch (law) {
2479 case SIG_PRI_DEFLAW:
2480 newlaw = 0;
2481 break;
2482 case SIG_PRI_ALAW:
2483 newlaw = DAHDI_LAW_ALAW;
2484 break;
2485 case SIG_PRI_ULAW:
2486 newlaw = DAHDI_LAW_MULAW;
2487 break;
2488 }
2489
2490 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2491}
2492#endif /* defined(HAVE_PRI) */
2493
2494static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
2495
2496#if defined(HAVE_PRI) || defined(HAVE_SS7)
2497/*!
2498 * \internal
2499 * \brief Open the PRI/SS7 channel media path.
2500 * \since 1.8
2501 *
2502 * \param p Channel private control structure.
2503 */
2504static void my_pri_ss7_open_media(void *p)
2505{
2506 struct dahdi_pvt *pvt = p;
2507 int res;
2508 int dfd;
2509 int set_val;
2510
2511 dfd = pvt->subs[SUB_REAL].dfd;
2512
2513 /* Open the media path. */
2514 set_val = 1;
2515 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2516 if (res < 0) {
2517 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
2518 pvt->channel, strerror(errno));
2519 }
2520
2521 /* Set correct companding law for this call. */
2522 res = dahdi_setlaw(dfd, pvt->law);
2523 if (res < 0) {
2524 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
2525 }
2526
2527 /* Set correct gain for this call. */
2528 if (pvt->digital) {
2529 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
2530 } else {
2531 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
2532 pvt->law);
2533 }
2534 if (res < 0) {
2535 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
2536 }
2537
2538 if (pvt->dsp_features && pvt->dsp) {
2540 }
2541}
2542#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2543
2544#if defined(HAVE_PRI)
2545/*!
2546 * \internal
2547 * \brief Ask DAHDI to dial the given dial string.
2548 * \since 1.8.11
2549 *
2550 * \param p Channel private control structure.
2551 * \param dial_string String to pass to DAHDI to dial.
2552 *
2553 * \note The channel private lock needs to be held when calling.
2554 */
2555static void my_pri_dial_digits(void *p, const char *dial_string)
2556{
2557 char dial_str[DAHDI_MAX_DTMF_BUF];
2558 struct dahdi_pvt *pvt = p;
2559 int res;
2560
2561 snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
2562 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2563 if (!res) {
2564 pvt->dialing = 1;
2565 }
2566}
2567#endif /* defined(HAVE_PRI) */
2568
2569static int unalloc_sub(struct dahdi_pvt *p, int x);
2570
2571static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
2572{
2573 struct dahdi_pvt *p = pvt;
2574
2575 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2576}
2577
2578static int alloc_sub(struct dahdi_pvt *p, int x);
2579
2580static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
2581{
2582 struct dahdi_pvt *p = pvt;
2583
2584 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2585}
2586
2587static int has_voicemail(struct dahdi_pvt *p);
2588
2589static int my_has_voicemail(void *pvt)
2590{
2591 struct dahdi_pvt *p = pvt;
2592
2593 return has_voicemail(p);
2594}
2595
2596static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
2597{
2598 struct dahdi_pvt *p = pvt;
2599 int index;
2600
2601 index = analogsub_to_dahdisub(sub);
2602
2603 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2604}
2605
2607{
2608 enum analog_event res;
2609
2610 switch (event) {
2611 case DAHDI_EVENT_ONHOOK:
2612 res = ANALOG_EVENT_ONHOOK;
2613 break;
2614 case DAHDI_EVENT_RINGOFFHOOK:
2616 break;
2617 case DAHDI_EVENT_WINKFLASH:
2619 break;
2620 case DAHDI_EVENT_ALARM:
2621 res = ANALOG_EVENT_ALARM;
2622 break;
2623 case DAHDI_EVENT_NOALARM:
2625 break;
2626 case DAHDI_EVENT_DIALCOMPLETE:
2628 break;
2629 case DAHDI_EVENT_RINGERON:
2631 break;
2632 case DAHDI_EVENT_RINGEROFF:
2634 break;
2635 case DAHDI_EVENT_HOOKCOMPLETE:
2637 break;
2638 case DAHDI_EVENT_PULSE_START:
2640 break;
2641 case DAHDI_EVENT_POLARITY:
2643 break;
2644 case DAHDI_EVENT_RINGBEGIN:
2646 break;
2647 case DAHDI_EVENT_EC_DISABLED:
2649 break;
2650 case DAHDI_EVENT_REMOVED:
2652 break;
2653 case DAHDI_EVENT_NEONMWI_ACTIVE:
2655 break;
2656 case DAHDI_EVENT_NEONMWI_INACTIVE:
2658 break;
2659#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2660 case DAHDI_EVENT_TX_CED_DETECTED:
2662 break;
2663 case DAHDI_EVENT_RX_CED_DETECTED:
2665 break;
2666 case DAHDI_EVENT_EC_NLP_DISABLED:
2668 break;
2669 case DAHDI_EVENT_EC_NLP_ENABLED:
2671 break;
2672#endif
2673 case DAHDI_EVENT_PULSEDIGIT:
2675 break;
2676 case DAHDI_EVENT_DTMFDOWN:
2678 break;
2679 case DAHDI_EVENT_DTMFUP:
2680 res = ANALOG_EVENT_DTMFUP;
2681 break;
2682 default:
2683 switch(event & 0xFFFF0000) {
2684 case DAHDI_EVENT_PULSEDIGIT:
2685 case DAHDI_EVENT_DTMFDOWN:
2686 case DAHDI_EVENT_DTMFUP:
2687 /* The event includes a digit number in the low word.
2688 * Converting it to a 'enum analog_event' would remove
2689 * that information. Thus it is returned as-is.
2690 */
2691 return event;
2692 }
2693
2694 res = ANALOG_EVENT_ERROR;
2695 break;
2696 }
2697
2698 return res;
2699}
2700
2701static inline int dahdi_wait_event(int fd);
2702
2703static int my_wait_event(void *pvt)
2704{
2705 struct dahdi_pvt *p = pvt;
2706
2707 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2708}
2709
2710static int my_get_event(void *pvt)
2711{
2712 struct dahdi_pvt *p = pvt;
2713 int res;
2714
2715 if (p->fake_event) {
2716 res = p->fake_event;
2717 p->fake_event = 0;
2718 } else
2719 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2720
2721 return dahdievent_to_analogevent(res);
2722}
2723
2724static int my_is_off_hook(void *pvt)
2725{
2726 struct dahdi_pvt *p = pvt;
2727 int res;
2728 struct dahdi_params par;
2729
2730 memset(&par, 0, sizeof(par));
2731
2732 if (p->subs[SUB_REAL].dfd > -1)
2733 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2734 else {
2735 /* Assume not off hook on CVRS */
2736 res = 0;
2737 par.rxisoffhook = 0;
2738 }
2739 if (res) {
2740 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2741 }
2742
2743 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2744 /* When "onhook" that means no battery on the line, and thus
2745 it is out of service..., if it's on a TDM card... If it's a channel
2746 bank, there is no telling... */
2747 return (par.rxbits > -1) || par.rxisoffhook;
2748 }
2749
2750 return par.rxisoffhook;
2751}
2752
2753static int my_set_echocanceller(void *pvt, int enable)
2754{
2755 struct dahdi_pvt *p = pvt;
2756
2757 if (enable)
2758 dahdi_ec_enable(p);
2759 else
2761
2762 return 0;
2763}
2764
2765static int dahdi_ring_phone(struct dahdi_pvt *p);
2766
2767static int my_ring(void *pvt)
2768{
2769 struct dahdi_pvt *p = pvt;
2770
2771 return dahdi_ring_phone(p);
2772}
2773
2774static int my_flash(void *pvt)
2775{
2776 struct dahdi_pvt *p = pvt;
2777 int func = DAHDI_FLASH;
2778 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2779}
2780
2781static inline int dahdi_set_hook(int fd, int hs);
2782
2783static int my_off_hook(void *pvt)
2784{
2785 struct dahdi_pvt *p = pvt;
2786 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2787}
2788
2789static void my_set_needringing(void *pvt, int value)
2790{
2791 struct dahdi_pvt *p = pvt;
2793}
2794
2795static void my_set_polarity(void *pvt, int value)
2796{
2797 struct dahdi_pvt *p = pvt;
2798
2799 if (p->channel == CHAN_PSEUDO) {
2800 return;
2801 }
2802 p->polarity = value;
2803 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2804}
2805
2806static void my_start_polarityswitch(void *pvt)
2807{
2808 struct dahdi_pvt *p = pvt;
2809
2811 my_set_polarity(pvt, 0);
2812 }
2813}
2814
2815static void my_answer_polarityswitch(void *pvt)
2816{
2817 struct dahdi_pvt *p = pvt;
2818
2819 if (!p->answeronpolarityswitch) {
2820 return;
2821 }
2822
2823 my_set_polarity(pvt, 1);
2824}
2825
2826static void my_hangup_polarityswitch(void *pvt)
2827{
2828 struct dahdi_pvt *p = pvt;
2829
2830 if (!p->hanguponpolarityswitch) {
2831 return;
2832 }
2833
2834 if (p->answeronpolarityswitch) {
2835 my_set_polarity(pvt, 0);
2836 } else {
2837 my_set_polarity(pvt, 1);
2838 }
2839}
2840
2841/*! \brief Return DAHDI pivot if channel is FXO signalled */
2842static struct dahdi_pvt *fxo_pvt(struct ast_channel *chan)
2843{
2844 int res;
2845 struct dahdi_params dahdip;
2846 struct dahdi_pvt *pvt = NULL;
2847
2848 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2849 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2850 return NULL;
2851 }
2852
2853 memset(&dahdip, 0, sizeof(dahdip));
2854 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2855
2856 if (res) {
2857 ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2858 return NULL;
2859 }
2860 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2861 ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2862 return NULL;
2863 }
2864
2865 pvt = ast_channel_tech_pvt(chan);
2866 if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2867 ast_log(LOG_WARNING, "Channel signalling is not analog");
2868 return NULL;
2869 }
2870
2871 return pvt;
2872}
2873
2874static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
2875{
2876 struct dahdi_pvt *pvt;
2877
2878 pvt = fxo_pvt(chan);
2879 if (!pvt) {
2880 return -1;
2881 }
2882
2883 snprintf(buffer, buflen, "%d", pvt->polarity);
2884
2885 return 0;
2886}
2887
2888static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2889{
2890 struct dahdi_pvt *pvt;
2891 int polarity;
2892
2893 pvt = fxo_pvt(chan);
2894 if (!pvt) {
2895 return -1;
2896 }
2897
2898 if (!strcasecmp(value, "idle")) {
2900 } else if (!strcasecmp(value, "reverse")) {
2902 } else {
2903 polarity = atoi(value);
2904 }
2905
2907 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2908 return -1;
2909 }
2910
2912 return 0;
2913}
2914
2916 .name = "POLARITY",
2917 .write = polarity_write,
2918 .read = polarity_read,
2919};
2920
2921static int my_start(void *pvt)
2922{
2923 struct dahdi_pvt *p = pvt;
2924 int x = DAHDI_START;
2925
2926 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2927}
2928
2929static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
2930{
2931 struct dahdi_pvt *p = pvt;
2932
2933 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2934 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2935 return -1;
2936 }
2937
2938 if (sub != ANALOG_SUB_REAL) {
2939 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2940 dop->dialstr, p->channel, sub);
2941 return -1;
2942 }
2943
2944 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2945}
2946
2947static void dahdi_train_ec(struct dahdi_pvt *p);
2948
2949static int my_train_echocanceller(void *pvt)
2950{
2951 struct dahdi_pvt *p = pvt;
2952
2953 dahdi_train_ec(p);
2954
2955 return 0;
2956}
2957
2958static int my_is_dialing(void *pvt, enum analog_sub sub)
2959{
2960 struct dahdi_pvt *p = pvt;
2961 int index;
2962 int x;
2963
2964 index = analogsub_to_dahdisub(sub);
2965
2966 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2967 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2968 return -1;
2969 }
2970
2971 return x;
2972}
2973
2974static int my_on_hook(void *pvt)
2975{
2976 struct dahdi_pvt *p = pvt;
2977 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2978}
2979
2980#if defined(HAVE_PRI)
2981static void my_pri_fixup_chans(void *chan_old, void *chan_new)
2982{
2983 struct dahdi_pvt *old_chan = chan_old;
2984 struct dahdi_pvt *new_chan = chan_new;
2985
2986 new_chan->owner = old_chan->owner;
2987 old_chan->owner = NULL;
2988 if (new_chan->owner) {
2989 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
2990 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
2991 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
2992 old_chan->subs[SUB_REAL].owner = NULL;
2993 }
2994 /* Copy any DSP that may be present */
2995 new_chan->dsp = old_chan->dsp;
2996 new_chan->dsp_features = old_chan->dsp_features;
2997 old_chan->dsp = NULL;
2998 old_chan->dsp_features = 0;
2999
3000 /* Transfer flags from the old channel. */
3001 new_chan->dialing = old_chan->dialing;
3002 new_chan->digital = old_chan->digital;
3003 new_chan->outgoing = old_chan->outgoing;
3004 old_chan->dialing = 0;
3005 old_chan->digital = 0;
3006 old_chan->outgoing = 0;
3007
3008 /* More stuff to transfer to the new channel. */
3009 new_chan->law = old_chan->law;
3010 strcpy(new_chan->dialstring, old_chan->dialstring);
3011}
3012#endif /* defined(HAVE_PRI) */
3013
3014#if defined(HAVE_PRI)
3015static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
3016{
3017 switch (tone) {
3019 return DAHDI_TONE_RINGTONE;
3021 return DAHDI_TONE_STUTTER;
3023 return DAHDI_TONE_CONGESTION;
3025 return DAHDI_TONE_DIALTONE;
3027 return DAHDI_TONE_DIALRECALL;
3028 case SIG_PRI_TONE_INFO:
3029 return DAHDI_TONE_INFO;
3030 case SIG_PRI_TONE_BUSY:
3031 return DAHDI_TONE_BUSY;
3032 default:
3033 return -1;
3034 }
3035}
3036#endif /* defined(HAVE_PRI) */
3037
3038#if defined(HAVE_PRI)
3039static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
3040{
3041 int x;
3042
3043 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
3044 switch (x) {
3045 case DAHDI_EVENT_NONE:
3046 break;
3047 case DAHDI_EVENT_ALARM:
3048 case DAHDI_EVENT_NOALARM:
3049 if (sig_pri_is_alarm_ignored(pri)) {
3050 break;
3051 }
3052 /* Fall through */
3053 default:
3054 ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
3055 event2str(x), x, pri->span);
3056 break;
3057 }
3058 /* Keep track of alarm state */
3059 switch (x) {
3060 case DAHDI_EVENT_ALARM:
3061 pri_event_alarm(pri, index, 0);
3062 break;
3063 case DAHDI_EVENT_NOALARM:
3064 pri_event_noalarm(pri, index, 0);
3065 break;
3066 case DAHDI_EVENT_REMOVED:
3067 pri_queue_for_destruction(pri);
3068 break;
3069 default:
3070 break;
3071 }
3072}
3073#endif /* defined(HAVE_PRI) */
3074
3075#if defined(HAVE_PRI)
3076static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
3077{
3078 struct dahdi_pvt *p = pvt;
3079
3080 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
3081}
3082#endif /* defined(HAVE_PRI) */
3083
3084#if defined(HAVE_PRI) || defined(HAVE_SS7)
3085/*!
3086 * \internal
3087 * \brief Set the caller id information.
3088 * \since 1.8
3089 *
3090 * \param pvt DAHDI private structure
3091 * \param caller Caller-id information to set.
3092 */
3093static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
3094{
3095 struct dahdi_pvt *p = pvt;
3096
3098 S_COR(caller->id.number.valid, caller->id.number.str, ""),
3099 sizeof(p->cid_num));
3101 S_COR(caller->id.name.valid, caller->id.name.str, ""),
3102 sizeof(p->cid_name));
3104 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
3105 sizeof(p->cid_subaddr));
3106 p->cid_ton = caller->id.number.plan;
3108 if (caller->id.tag) {
3109 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
3110 }
3111 ast_copy_string(p->cid_ani,
3112 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
3113 sizeof(p->cid_ani));
3114 p->cid_ani2 = caller->ani2;
3115}
3116#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3117
3118#if defined(HAVE_PRI) || defined(HAVE_SS7)
3119/*!
3120 * \internal
3121 * \brief Set the Dialed Number Identifier.
3122 * \since 1.8
3123 *
3124 * \param pvt DAHDI private structure
3125 * \param dnid Dialed Number Identifier string.
3126 */
3127static void my_set_dnid(void *pvt, const char *dnid)
3128{
3129 struct dahdi_pvt *p = pvt;
3130
3131 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
3132}
3133#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3134
3135#if defined(HAVE_PRI)
3136/*!
3137 * \internal
3138 * \brief Set the Redirecting Directory Number Information Service (RDNIS).
3139 * \since 1.8
3140 *
3141 * \param pvt DAHDI private structure
3142 * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
3143 */
3144static void my_set_rdnis(void *pvt, const char *rdnis)
3145{
3146 struct dahdi_pvt *p = pvt;
3147
3148 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
3149}
3150#endif /* defined(HAVE_PRI) */
3151
3152#if defined(HAVE_PRI)
3153/*!
3154 * \internal
3155 * \brief Make a dialstring for native ISDN CC to recall properly.
3156 * \since 1.8
3157 *
3158 * \param priv Channel private control structure.
3159 * \param buf Where to put the modified dialstring.
3160 * \param buf_size Size of modified dialstring buffer.
3161 *
3162 * \details
3163 * original dialstring:
3164 * \verbatim
3165 DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3166 \endverbatim
3167 *
3168 * The modified dialstring will have prefixed the channel-group section
3169 * with the ISDN channel restriction.
3170 *
3171 * buf:
3172 * \verbatim
3173 DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3174 \endverbatim
3175 *
3176 * The routine will check to see if the ISDN channel restriction is already
3177 * in the original dialstring.
3178 */
3179static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
3180{
3181 char *dial;
3182 struct dahdi_pvt *pvt;
3184 AST_APP_ARG(tech); /* channel technology token */
3185 AST_APP_ARG(group); /* channel/group token */
3186 //AST_APP_ARG(ext); /* extension token */
3187 //AST_APP_ARG(opts); /* options token */
3188 //AST_APP_ARG(other); /* Any remining unused arguments */
3189 );
3190
3191 pvt = priv;
3192 dial = ast_strdupa(pvt->dialstring);
3193 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
3194 if (!args.tech) {
3195 ast_copy_string(buf, pvt->dialstring, buf_size);
3196 return;
3197 }
3198 if (!args.group) {
3199 /* Append the ISDN span channel restriction to the dialstring. */
3200 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
3201 return;
3202 }
3203 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
3204 /* The ISDN span channel restriction is not needed or already
3205 * in the dialstring. */
3206 ast_copy_string(buf, pvt->dialstring, buf_size);
3207 return;
3208 }
3209 /* Insert the ISDN span channel restriction into the dialstring. */
3210 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
3211}
3212#endif /* defined(HAVE_PRI) */
3213
3214#if defined(HAVE_PRI)
3215/*!
3216 * \internal
3217 * \brief Reevaluate the PRI span device state.
3218 * \since 1.8
3219 *
3220 * \param pri Asterisk D channel control structure.
3221 *
3222 * \note Assumes the pri->lock is already obtained.
3223 */
3224static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
3225{
3226 unsigned idx;
3227 unsigned num_b_chans; /* Number of B channels provisioned on the span. */
3228 unsigned in_use; /* Number of B channels in use on the span. */
3229 unsigned in_alarm; /* TRUE if the span is in alarm condition. */
3230 enum ast_device_state new_state;
3231
3232 /* Count the number of B channels and the number of B channels in use. */
3233 num_b_chans = 0;
3234 in_use = 0;
3235 in_alarm = 1;
3236 for (idx = pri->numchans; idx--;) {
3237 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
3238 /* This is a B channel interface. */
3239 ++num_b_chans;
3240 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
3241 ++in_use;
3242 }
3243 if (!pri->pvts[idx]->inalarm) {
3244 /* There is a channel that is not in alarm. */
3245 in_alarm = 0;
3246 }
3247 }
3248 }
3249
3250 /* Update the span congestion device state and report any change. */
3251 if (in_alarm) {
3252 new_state = AST_DEVICE_UNAVAILABLE;
3253 } else {
3254 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
3255 }
3256 if (pri->congestion_devstate != new_state) {
3257 pri->congestion_devstate = new_state;
3259 }
3260#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
3261 /* Update the span threshold device state and report any change. */
3262 if (in_alarm) {
3263 new_state = AST_DEVICE_UNAVAILABLE;
3264 } else if (!in_use) {
3265 new_state = AST_DEVICE_NOT_INUSE;
3266 } else if (!pri->user_busy_threshold) {
3267 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
3268 } else {
3269 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
3271 }
3272 if (pri->threshold_devstate != new_state) {
3273 pri->threshold_devstate = new_state;
3275 }
3276#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
3277}
3278#endif /* defined(HAVE_PRI) */
3279
3280#if defined(HAVE_PRI)
3281/*!
3282 * \internal
3283 * \brief Reference this module.
3284 * \since 1.8
3285 */
3286static void my_module_ref(void)
3287{
3289}
3290#endif /* defined(HAVE_PRI) */
3291
3292#if defined(HAVE_PRI)
3293/*!
3294 * \internal
3295 * \brief Unreference this module.
3296 * \since 1.8
3297 */
3298static void my_module_unref(void)
3299{
3301}
3302#endif /* defined(HAVE_PRI) */
3303
3304#if defined(HAVE_PRI)
3305#if defined(HAVE_PRI_CALL_WAITING)
3306static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3307#endif /* defined(HAVE_PRI_CALL_WAITING) */
3308static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
3309
3311{
3312 .handle_dchan_exception = my_handle_dchan_exception,
3313 .play_tone = my_pri_play_tone,
3314 .set_echocanceller = my_set_echocanceller,
3315 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3316 .lock_private = my_lock_private,
3317 .unlock_private = my_unlock_private,
3318 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3319 .new_ast_channel = my_new_pri_ast_channel,
3320 .fixup_chans = my_pri_fixup_chans,
3321 .set_alarm = my_set_alarm,
3322 .set_dialing = my_set_dialing,
3323 .set_outgoing = my_set_outgoing,
3324 .set_digital = my_set_digital,
3325 .set_callerid = my_set_callerid,
3326 .set_dnid = my_set_dnid,
3327 .set_rdnis = my_set_rdnis,
3328 .new_nobch_intf = dahdi_new_pri_nobch_channel,
3329#if defined(HAVE_PRI_CALL_WAITING)
3330 .init_config = my_pri_init_config,
3331#endif /* defined(HAVE_PRI_CALL_WAITING) */
3332 .get_orig_dialstring = my_get_orig_dialstring,
3333 .make_cc_dialstring = my_pri_make_cc_dialstring,
3334 .update_span_devstate = dahdi_pri_update_span_devstate,
3335 .module_ref = my_module_ref,
3336 .module_unref = my_module_unref,
3337 .dial_digits = my_pri_dial_digits,
3338 .open_media = my_pri_ss7_open_media,
3339 .ami_channel_event = my_ami_channel_event,
3340 .destroy_later = pri_queue_for_destruction,
3341};
3342#endif /* defined(HAVE_PRI) */
3343
3344#if defined(HAVE_SS7)
3345/*!
3346 * \internal
3347 * \brief Handle the SS7 link exception.
3348 * \since 1.8
3349 *
3350 * \param linkset Controlling linkset for the channel.
3351 * \param which Link index of the signaling channel.
3352 */
3353static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
3354{
3355 int event;
3356
3357 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3358 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
3359 linkset->span, which);
3360 return;
3361 }
3362 switch (event) {
3363 case DAHDI_EVENT_NONE:
3364 break;
3365 case DAHDI_EVENT_ALARM:
3366 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3367 event2str(event), event, linkset->span, which);
3368 sig_ss7_link_alarm(linkset, which);
3369 break;
3370 case DAHDI_EVENT_NOALARM:
3371 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3372 event2str(event), event, linkset->span, which);
3373 sig_ss7_link_noalarm(linkset, which);
3374 break;
3375 default:
3376 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
3377 event2str(event), event, linkset->span, which);
3378 break;
3379 }
3380}
3381#endif /* defined(HAVE_SS7) */
3382
3383#if defined(HAVE_SS7)
3384static void my_ss7_set_loopback(void *pvt, int enable)
3385{
3386 struct dahdi_pvt *p = pvt;
3387
3388 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3389 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
3390 strerror(errno));
3391 }
3392}
3393#endif /* defined(HAVE_SS7) */
3394
3395#if defined(HAVE_SS7)
3396/*!
3397 * \internal
3398 * \brief Find the linkset to which SS7 belongs.
3399 * \since 11.0
3400 *
3401 * \param ss7 structure to match on.
3402 *
3403 * \retval linkset if found.
3404 * \retval NULL if not found.
3405 */
3406static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
3407{
3408 int idx;
3409
3410 if (!ss7) {
3411 return NULL;
3412 }
3413
3414 for (idx = 0; idx < NUM_SPANS; ++idx) {
3415 if (linksets[idx].ss7.ss7 == ss7) {
3416 return &linksets[idx].ss7;
3417 }
3418 }
3419 return NULL;
3420}
3421#endif /* defined(HAVE_SS7) */
3422
3423#if defined(HAVE_SS7)
3424/*!
3425 * \internal
3426 * \brief Create a new asterisk channel structure for SS7.
3427 * \since 1.8
3428 *
3429 * \param pvt Private channel structure.
3430 * \param state Initial state of new channel.
3431 * \param law Companding law to use.
3432 * \param exten Dialplan extension for incoming call.
3433 * \param requestor Channel requesting this new channel.
3434 * \param assignedids
3435 *
3436 * \retval ast_channel on success.
3437 * \retval NULL on error.
3438 */
3439static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
3440{
3441 struct dahdi_pvt *p = pvt;
3442 int audio;
3443 int newlaw;
3444 ast_callid callid = 0;
3445 int callid_created = ast_callid_threadstorage_auto(&callid);
3446
3447 /* Set to audio mode at this point */
3448 audio = 1;
3449 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3450 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
3451 p->channel, audio, strerror(errno));
3452
3453 if (law != SIG_SS7_DEFLAW) {
3454 dahdi_setlaw(p->subs[SUB_REAL].dfd,
3455 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3456 }
3457
3458 ast_copy_string(p->exten, exten, sizeof(p->exten));
3459
3460 newlaw = -1;
3461 switch (law) {
3462 case SIG_SS7_DEFLAW:
3463 newlaw = 0;
3464 break;
3465 case SIG_SS7_ALAW:
3466 newlaw = DAHDI_LAW_ALAW;
3467 break;
3468 case SIG_SS7_ULAW:
3469 newlaw = DAHDI_LAW_MULAW;
3470 break;
3471 }
3472 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3473}
3474#endif /* defined(HAVE_SS7) */
3475
3476#if defined(HAVE_SS7)
3477static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3478{
3479 switch (tone) {
3481 return DAHDI_TONE_RINGTONE;
3483 return DAHDI_TONE_STUTTER;
3485 return DAHDI_TONE_CONGESTION;
3487 return DAHDI_TONE_DIALTONE;
3489 return DAHDI_TONE_DIALRECALL;
3490 case SIG_SS7_TONE_INFO:
3491 return DAHDI_TONE_INFO;
3492 case SIG_SS7_TONE_BUSY:
3493 return DAHDI_TONE_BUSY;
3494 default:
3495 return -1;
3496 }
3497}
3498#endif /* defined(HAVE_SS7) */
3499
3500#if defined(HAVE_SS7)
3501static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
3502{
3503 struct dahdi_pvt *p = pvt;
3504
3505 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3506}
3507#endif /* defined(HAVE_SS7) */
3508
3509#if defined(HAVE_SS7)
3511{
3513 .unlock_private = my_unlock_private,
3514 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3515
3516 .set_echocanceller = my_set_echocanceller,
3517 .set_loopback = my_ss7_set_loopback,
3518
3519 .new_ast_channel = my_new_ss7_ast_channel,
3520 .play_tone = my_ss7_play_tone,
3521
3522 .handle_link_exception = my_handle_link_exception,
3523 .set_alarm = my_set_alarm,
3524 .set_dialing = my_set_dialing,
3525 .set_outgoing = my_set_outgoing,
3526 .set_digital = my_set_digital,
3527 .set_inservice = my_set_inservice,
3528 .set_locallyblocked = my_set_locallyblocked,
3529 .set_remotelyblocked = my_set_remotelyblocked,
3530 .set_callerid = my_set_callerid,
3531 .set_dnid = my_set_dnid,
3532 .open_media = my_pri_ss7_open_media,
3533 .find_linkset = my_ss7_find_linkset,
3534};
3535#endif /* defined(HAVE_SS7) */
3536
3537/*!
3538 * \brief Send MWI state change
3539 *
3540 * \param mailbox This is the mailbox associated with the FXO line that the
3541 * MWI state has changed on.
3542 * \param thereornot This argument should simply be set to 1 or 0, to indicate
3543 * whether there are messages waiting or not.
3544 *
3545 * This function does two things:
3546 *
3547 * 1) It generates an internal Asterisk event notifying any other module that
3548 * cares about MWI that the state of a mailbox has changed.
3549 *
3550 * 2) It runs the script specified by the mwimonitornotify option to allow
3551 * some custom handling of the state change.
3552 */
3553static void notify_message(char *mailbox, int thereornot)
3554{
3555 char s[sizeof(mwimonitornotify) + 164];
3556
3557 if (ast_strlen_zero(mailbox)) {
3558 return;
3559 }
3560
3561 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3563 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3564 ast_safe_system(s);
3565 }
3566}
3567
3568static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
3569{
3570 struct dahdi_pvt *p = pvt;
3571
3572 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3573 return;
3574
3575 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3576 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3577 notify_message(p->mailbox, 1);
3578 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3579 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3580 notify_message(p->mailbox, 0);
3581 }
3582 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3583 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3584 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3585 ast_hangup(chan);
3586 return;
3587 }
3588}
3589
3590static int my_have_progressdetect(void *pvt)
3591{
3592 struct dahdi_pvt *p = pvt;
3593
3595 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3596 return 1;
3597 } else {
3598 /* Don't have progress detection. */
3599 return 0;
3600 }
3601}
3602
3603#define gen_pvt_field_callback(type, field) \
3604 static type my_get_##field(void *pvt) \
3605 { \
3606 struct dahdi_pvt *p = pvt; \
3607 return p->field; \
3608 }
3609
3613
3614#undef gen_pvt_field_callback
3615
3617{
3619 .get_event = my_get_event,
3620 .wait_event = my_wait_event,
3621 .is_off_hook = my_is_off_hook,
3622 .set_echocanceller = my_set_echocanceller,
3623 .ring = my_ring,
3624 .flash = my_flash,
3625 .off_hook = my_off_hook,
3626 .dial_digits = my_dial_digits,
3627 .train_echocanceller = my_train_echocanceller,
3628 .on_hook = my_on_hook,
3629 .is_dialing = my_is_dialing,
3630 .allocate_sub = my_allocate_sub,
3631 .unallocate_sub = my_unallocate_sub,
3632 .swap_subs = my_swap_subchannels,
3633 .has_voicemail = my_has_voicemail,
3634 .check_for_conference = my_check_for_conference,
3635 .conf_add = my_conf_add,
3636 .conf_del = my_conf_del,
3637 .complete_conference_update = my_complete_conference_update,
3638 .start = my_start,
3639 .all_subchannels_hungup = my_all_subchannels_hungup,
3640 .lock_private = my_lock_private,
3641 .unlock_private = my_unlock_private,
3642 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3643 .handle_dtmf = my_handle_dtmf,
3644 .wink = my_wink,
3645 .new_ast_channel = my_new_analog_ast_channel,
3646 .dsp_set_digitmode = my_dsp_set_digitmode,
3647 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3648 .send_callerid = my_send_callerid,
3649 .callwait = my_callwait,
3650 .stop_callwait = my_stop_callwait,
3651 .get_callerid = my_get_callerid,
3652 .start_cid_detect = my_start_cid_detect,
3653 .stop_cid_detect = my_stop_cid_detect,
3654 .handle_notify_message = my_handle_notify_message,
3655 .increase_ss_count = my_increase_ss_count,
3656 .decrease_ss_count = my_decrease_ss_count,
3657 .distinctive_ring = my_distinctive_ring,
3658 .set_linear_mode = my_set_linear_mode,
3659 .set_inthreeway = my_set_inthreeway,
3660 .get_and_handle_alarms = my_get_and_handle_alarms,
3661 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3662 .get_sub_fd = my_get_sub_fd,
3663 .set_cadence = my_set_cadence,
3664 .set_alarm = my_set_alarm,
3665 .set_dialing = my_set_dialing,
3666 .set_outgoing = my_set_outgoing,
3667 .set_ringtimeout = my_set_ringtimeout,
3668 .set_waitingfordt = my_set_waitingfordt,
3669 .check_waitingfordt = my_check_waitingfordt,
3670 .set_confirmanswer = my_set_confirmanswer,
3671 .check_confirmanswer = my_check_confirmanswer,
3672 .set_callwaiting = my_set_callwaiting,
3673 .cancel_cidspill = my_cancel_cidspill,
3674 .confmute = my_confmute,
3675 .set_pulsedial = my_set_pulsedial,
3676 .set_new_owner = my_set_new_owner,
3677 .get_orig_dialstring = my_get_orig_dialstring,
3678 .set_needringing = my_set_needringing,
3679 .set_polarity = my_set_polarity,
3680 .start_polarityswitch = my_start_polarityswitch,
3681 .answer_polarityswitch = my_answer_polarityswitch,
3682 .hangup_polarityswitch = my_hangup_polarityswitch,
3683 .have_progressdetect = my_have_progressdetect,
3684 .get_firstdigit_timeout = my_get_firstdigit_timeout,
3685 .get_matchdigit_timeout = my_get_matchdigit_timeout,
3686 .get_interdigit_timeout = my_get_interdigit_timeout,
3687};
3688
3689/*! Round robin search locations. */
3690static struct dahdi_pvt *round_robin[64]; /* groups can range from 0-63 */
3691
3692int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
3693{
3694 int res;
3695 if (p->subs[SUB_REAL].owner == ast)
3696 res = 0;
3697 else if (p->subs[SUB_CALLWAIT].owner == ast)
3698 res = 1;
3699 else if (p->subs[SUB_THREEWAY].owner == ast)
3700 res = 2;
3701 else {
3702 res = -1;
3703 if (!nullok)
3705 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3706 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3707 }
3708 return res;
3709}
3710
3711/*!
3712 * \internal
3713 * \brief Obtain the specified subchannel owner lock if the owner exists.
3714 *
3715 * \param pvt Channel private struct.
3716 * \param sub_idx Subchannel owner to lock.
3717 *
3718 * \note Assumes the pvt->lock is already obtained.
3719 *
3720 * \note
3721 * Because deadlock avoidance may have been necessary, you need to confirm
3722 * the state of things before continuing.
3723 */
3724static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
3725{
3726 for (;;) {
3727 if (!pvt->subs[sub_idx].owner) {
3728 /* No subchannel owner pointer */
3729 break;
3730 }
3731 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3732 /* Got subchannel owner lock */
3733 break;
3734 }
3735 /* We must unlock the private to avoid the possibility of a deadlock */
3736 DEADLOCK_AVOIDANCE(&pvt->lock);
3737 }
3738}
3739
3740static void wakeup_sub(struct dahdi_pvt *p, int a)
3741{
3743 if (p->subs[a].owner) {
3746 }
3747}
3748
3749static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
3750{
3751 for (;;) {
3752 if (p->owner) {
3753 if (ast_channel_trylock(p->owner)) {
3755 } else {
3756 ast_queue_frame(p->owner, f);
3758 break;
3759 }
3760 } else
3761 break;
3762 }
3763}
3764
3766{
3767 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3768 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3769 if (!dahdi_chan) {
3770 return;
3771 }
3772
3773 ast_str_set(&dahdi_chan, 0, "%d", channel);
3774 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3775 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3776 if (!body) {
3777 return;
3778 }
3779
3780 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3781}
3782
3784{
3785 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3786
3787 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3788 body = ast_json_pack("{s: i}", "Span", span);
3789 if (!body) {
3790 return;
3791 }
3792
3793 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3794}
3795
3796static void handle_clear_alarms(struct dahdi_pvt *p)
3797{
3798#if defined(HAVE_PRI)
3800 return;
3801 }
3802#endif /* defined(HAVE_PRI) */
3803
3806 }
3809 }
3810}
3811
3812#ifdef HAVE_OPENR2
3813static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)
3814{
3815 const struct dahdi_mfcr2 *r2link = p->mfcr2;
3816 struct r2link_entry *cur;
3817 AST_LIST_LOCK(&r2links);
3818 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
3819 if (r2link == &cur->mfcr2) {
3820 ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);
3821 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
3822 break;
3823 }
3824 }
3826 AST_LIST_UNLOCK(&r2links);
3827}
3828
3829static int dahdi_r2_answer(struct dahdi_pvt *p)
3830{
3831 int res = 0;
3832 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
3833 * and does not has support for openr2_chan_answer_call_with_mode
3834 * */
3835#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3836 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
3837 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
3838 if (!double_answer) {
3839 /* this still can result in double answer if the channel context
3840 * was configured that way */
3841 res = openr2_chan_answer_call(p->r2chan);
3842 } else if (wants_double_answer) {
3843 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3844 } else {
3845 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3846 }
3847#else
3848 res = openr2_chan_answer_call(p->r2chan);
3849#endif
3850 return res;
3851}
3852
3853
3854
3855/* should be called with the ast_channel locked */
3856static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
3857{
3858 openr2_calling_party_category_t cat;
3859 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
3860 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3861 if (ast_strlen_zero(catstr)) {
3862 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
3863 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3864 return p->mfcr2_category;
3865 }
3866 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3867 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
3868 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3869 return p->mfcr2_category;
3870 }
3871 ast_debug(1, "Using category %s\n", catstr);
3872 return cat;
3873}
3874
3875static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3876{
3877 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3878 ast_mutex_lock(&p->lock);
3879 if (p->mfcr2call) {
3881 /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
3882 interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
3883 can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
3884 the other end will see our seize as a forced release and drop the call, we will see an invalid
3885 pattern that will be seen and treated as protocol error. */
3886 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3887 return;
3888 }
3889 p->mfcr2call = 1;
3890 /* better safe than sorry ... */
3891 p->cid_name[0] = '\0';
3892 p->cid_num[0] = '\0';
3893 p->cid_subaddr[0] = '\0';
3894 p->rdnis[0] = '\0';
3895 p->exten[0] = '\0';
3896 p->mfcr2_ani_index = '\0';
3897 p->mfcr2_dnis_index = '\0';
3898 p->mfcr2_dnis_matched = 0;
3899 p->mfcr2_answer_pending = 0;
3900 p->mfcr2_call_accepted = 0;
3902 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3903}
3904
3905static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
3906{
3907 int res;
3908 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3909 ast_mutex_lock(&p->lock);
3910 p->inalarm = alarm ? 1 : 0;
3911 if (p->inalarm) {
3912 res = get_alarms(p);
3913 if (res == DAHDI_ALARM_NOTOPEN) {
3914 mfcr2_queue_for_destruction(p);
3915 }
3916 handle_alarms(p, res);
3917 } else {
3919 }
3921}
3922
3923static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
3924{
3925 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3926
3927 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3928 ast_mutex_lock(&p->lock);
3929 /* Disconnected? */
3930 if (errorcode == ENODEV) {
3931 struct dahdi_mfcr2 *r2link = p->mfcr2;
3932 p->mfcr2call = 0;
3933 if (r2link) {
3934 r2link->nodev = 1;
3935 }
3936 }
3938}
3939
3940static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3941{
3942 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3943 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3944 if (p->owner) {
3947 }
3948 ast_mutex_lock(&p->lock);
3949 p->mfcr2call = 0;
3951}
3952
3953static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3954{
3955 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3956 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3957 p->channel, openr2_proto_get_disconnect_string(cause));
3958 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
3959 openr2_chan_set_idle(p->r2chan);
3960 ast_mutex_lock(&p->lock);
3961 p->mfcr2call = 0;
3963 }
3964}
3965
3966static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
3967{
3968 struct dahdi_pvt *p;
3969 struct ast_channel *c;
3970 ast_callid callid = 0;
3971 int callid_created = ast_callid_threadstorage_auto(&callid);
3972 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3973 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
3974 openr2_proto_get_category_string(category));
3975 p = openr2_chan_get_client_data(r2chan);
3976 /* if collect calls are not allowed and this is a collect call, reject it! */
3977 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3978 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
3979 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3980 goto dahdi_r2_on_call_offered_cleanup;
3981 }
3982 ast_mutex_lock(&p->lock);
3983 p->mfcr2_recvd_category = category;
3984 /* if we're not supposed to use CID, clear whatever we have */
3985 if (!p->use_callerid) {
3986 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
3987 p->cid_num[0] = 0;
3988 p->cid_name[0] = 0;
3989 }
3990 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
3991 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3992 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
3993 p->exten[0] = 's';
3994 p->exten[1] = 0;
3995 }
3997 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3998 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
3999 p->channel, p->exten, p->context);
4000 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
4001 goto dahdi_r2_on_call_offered_cleanup;
4002 }
4003 if (!p->mfcr2_accept_on_offer) {
4004 /* The user wants us to start the PBX thread right away without accepting the call first */
4005 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
4006 if (c) {
4007 /* Done here, don't disable reading now since we still need to generate MF tones to accept
4008 the call or reject it and detect the tone off condition of the other end, all of this
4009 will be done in the PBX thread now */
4010 goto dahdi_r2_on_call_offered_cleanup;
4011 }
4012 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4013 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4014 } else if (p->mfcr2_charge_calls) {
4015 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
4016 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
4017 } else {
4018 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
4019 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
4020 }
4021
4022dahdi_r2_on_call_offered_cleanup:
4024}
4025
4026static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
4027{
4028 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4029 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
4030 ast_mutex_lock(&p->lock);
4031 p->mfcr2call = 0;
4033}
4034
4035static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
4036{
4037 struct dahdi_pvt *p = NULL;
4038 struct ast_channel *c = NULL;
4039 ast_callid callid = 0;
4040 int callid_created = ast_callid_threadstorage_auto(&callid);
4041 p = openr2_chan_get_client_data(r2chan);
4042 dahdi_ec_enable(p);
4043 p->mfcr2_call_accepted = 1;
4044 /* if it's an incoming call ... */
4045 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
4046 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
4047 /* If accept on offer is not set, it means at this point the PBX thread is already
4048 launched (was launched in the 'on call offered' handler) and therefore this callback
4049 is being executed already in the PBX thread rather than the monitor thread, don't launch
4050 any other thread, just disable the openr2 reading and answer the call if needed */
4051 if (!p->mfcr2_accept_on_offer) {
4052 openr2_chan_disable_read(r2chan);
4053 if (p->mfcr2_answer_pending) {
4054 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
4055 dahdi_r2_answer(p);
4056 }
4057 goto dahdi_r2_on_call_accepted_cleanup;
4058 }
4059 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
4060 if (c) {
4061 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
4062 library to forget about it */
4063 openr2_chan_disable_read(r2chan);
4064 goto dahdi_r2_on_call_accepted_cleanup;
4065 }
4066 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4067 /* failed to create the channel, bail out and report it as an out of order line */
4068 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4069 goto dahdi_r2_on_call_accepted_cleanup;
4070 }
4071 /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
4072 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
4073 p->subs[SUB_REAL].needringing = 1;
4074 p->dialing = 0;
4075 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
4076 openr2_chan_disable_read(r2chan);
4077
4078dahdi_r2_on_call_accepted_cleanup:
4080}
4081
4082static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
4083{
4084 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4085 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
4086 p->subs[SUB_REAL].needanswer = 1;
4087}
4088
4089static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
4090{
4091 /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
4092}
4093
4094static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
4095{
4096 switch (cause) {
4097 case OR2_CAUSE_BUSY_NUMBER:
4098 return AST_CAUSE_BUSY;
4099 case OR2_CAUSE_NETWORK_CONGESTION:
4100 return AST_CAUSE_CONGESTION;
4101 case OR2_CAUSE_OUT_OF_ORDER:
4103 case OR2_CAUSE_UNALLOCATED_NUMBER:
4105 case OR2_CAUSE_NO_ANSWER:
4106 return AST_CAUSE_NO_ANSWER;
4107 case OR2_CAUSE_NORMAL_CLEARING:
4109 case OR2_CAUSE_UNSPECIFIED:
4110 default:
4111 return AST_CAUSE_NOTDEFINED;
4112 }
4113}
4114
4115static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
4116{
4117 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4118 char cause_str[50];
4119 struct ast_control_pvt_cause_code *cause_code;
4120 int datalen = sizeof(*cause_code);
4121
4122 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
4123 ast_mutex_lock(&p->lock);
4124 if (!p->owner) {
4126 /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
4127 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
4128 return;
4129 }
4130
4131 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
4132 datalen += strlen(cause_str);
4133 cause_code = ast_alloca(datalen);
4134 memset(cause_code, 0, datalen);
4135 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
4137 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
4139 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
4141
4142 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
4143 be done in dahdi_hangup */
4147 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
4148 /* being the forward side we must report what happened to the call to whoever requested it */
4149 switch (cause) {
4150 case OR2_CAUSE_BUSY_NUMBER:
4151 p->subs[SUB_REAL].needbusy = 1;
4152 break;
4153 case OR2_CAUSE_NETWORK_CONGESTION:
4154 case OR2_CAUSE_OUT_OF_ORDER:
4155 case OR2_CAUSE_UNALLOCATED_NUMBER:
4156 case OR2_CAUSE_NO_ANSWER:
4157 case OR2_CAUSE_UNSPECIFIED:
4158 case OR2_CAUSE_NORMAL_CLEARING:
4160 break;
4161 default:
4163 }
4165 } else {
4167 /* being the backward side and not UP yet, we only need to request hangup */
4168 /* TODO: what about doing this same thing when were AST_STATE_UP? */
4169 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
4170 }
4171}
4172
4173static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
4174{
4175 switch (level) {
4176 case OR2_LOG_NOTICE:
4177 ast_verbose("%s", logmessage);
4178 break;
4179 case OR2_LOG_WARNING:
4180 ast_log(LOG_WARNING, "%s", logmessage);
4181 break;
4182 case OR2_LOG_ERROR:
4183 ast_log(LOG_ERROR, "%s", logmessage);
4184 break;
4185 case OR2_LOG_STACK_TRACE:
4186 case OR2_LOG_MF_TRACE:
4187 case OR2_LOG_CAS_TRACE:
4188 case OR2_LOG_DEBUG:
4189 case OR2_LOG_EX_DEBUG:
4190 ast_debug(1, "%s", logmessage);
4191 break;
4192 default:
4193 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
4194 ast_debug(1, "%s", logmessage);
4195 break;
4196 }
4197}
4198
4199static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
4200{
4201 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4202 ast_mutex_lock(&p->lock);
4203 p->remotelyblocked = 1;
4205 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4206}
4207
4208static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
4209{
4210 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4211 ast_mutex_lock(&p->lock);
4212 p->remotelyblocked = 0;
4214 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4215}
4216
4217static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4218 __attribute__((format (printf, 3, 0)));
4219static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4220{
4221#define CONTEXT_TAG "Context - "
4222 char logmsg[256];
4223 char completemsg[sizeof(logmsg) * 2];
4224 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4225 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
4226 dahdi_r2_write_log(level, completemsg);
4227#undef CONTEXT_TAG
4228}
4229
4230static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4231 __attribute__((format (printf, 3, 0)));
4232static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4233{
4234#define CHAN_TAG "Chan "
4235 char logmsg[256];
4236 char completemsg[sizeof(logmsg) * 2];
4237 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4238 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
4239 dahdi_r2_write_log(level, completemsg);
4240#undef CHAN_TAG
4241}
4242
4243static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
4244{
4245 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4246 /* if 'immediate' is set, let's stop requesting DNIS */
4247 if (p->immediate) {
4248 return 0;
4249 }
4250 p->exten[p->mfcr2_dnis_index] = digit;
4251 p->rdnis[p->mfcr2_dnis_index] = digit;
4252 p->mfcr2_dnis_index++;
4253 p->exten[p->mfcr2_dnis_index] = 0;
4254 p->rdnis[p->mfcr2_dnis_index] = 0;
4255 /* if the DNIS is a match and cannot match more, stop requesting DNIS */
4256 if ((p->mfcr2_dnis_matched ||
4257 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
4259 return 0;
4260 }
4261 /* otherwise keep going */
4262 return 1;
4263}
4264
4265static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
4266{
4267 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4268 p->cid_num[p->mfcr2_ani_index] = digit;
4269 p->cid_name[p->mfcr2_ani_index] = digit;
4270 p->mfcr2_ani_index++;
4271 p->cid_num[p->mfcr2_ani_index] = 0;
4272 p->cid_name[p->mfcr2_ani_index] = 0;
4273}
4274
4275static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4276{
4277 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4278}
4279
4280static openr2_event_interface_t dahdi_r2_event_iface = {
4281 .on_call_init = dahdi_r2_on_call_init,
4282 .on_call_offered = dahdi_r2_on_call_offered,
4283 .on_call_accepted = dahdi_r2_on_call_accepted,
4284 .on_call_answered = dahdi_r2_on_call_answered,
4285 .on_call_disconnect = dahdi_r2_on_call_disconnect,
4286 .on_call_end = dahdi_r2_on_call_end,
4287 .on_call_read = dahdi_r2_on_call_read,
4288 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4289 .on_os_error = dahdi_r2_on_os_error,
4290 .on_protocol_error = dahdi_r2_on_protocol_error,
4291 .on_line_blocked = dahdi_r2_on_line_blocked,
4292 .on_line_idle = dahdi_r2_on_line_idle,
4293 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
4294 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4295 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4296 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4297 /* so far we do nothing with billing pulses */
4298 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4299};
4300
4301static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4302{
4303 return AST_ALAW(sample);
4304}
4305
4306static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4307{
4308 return AST_LIN2A(sample);
4309}
4310
4311static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4312 dahdi_r2_alaw_to_linear,
4313 dahdi_r2_linear_to_alaw
4314};
4315
4316#endif /* HAVE_OPENR2 */
4317
4318static void swap_subs(struct dahdi_pvt *p, int a, int b)
4319{
4320 int tchan;
4321 int tinthreeway;
4322 struct ast_channel *towner;
4323
4324 ast_debug(1, "Swapping %d and %d\n", a, b);
4325
4326 tchan = p->subs[a].chan;
4327 towner = p->subs[a].owner;
4328 tinthreeway = p->subs[a].inthreeway;
4329
4330 p->subs[a].chan = p->subs[b].chan;
4331 p->subs[a].owner = p->subs[b].owner;
4332 p->subs[a].inthreeway = p->subs[b].inthreeway;
4333
4334 p->subs[b].chan = tchan;
4335 p->subs[b].owner = towner;
4336 p->subs[b].inthreeway = tinthreeway;
4337
4338 if (p->subs[a].owner)
4339 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4340 if (p->subs[b].owner)
4341 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4342 wakeup_sub(p, a);
4343 wakeup_sub(p, b);
4344}
4345
4346static int dahdi_open(char *fn)
4347{
4348 int fd;
4349 int isnum;
4350 int chan = 0;
4351 int bs;
4352 int x;
4353 isnum = 1;
4354 for (x = 0; x < strlen(fn); x++) {
4355 if (!isdigit(fn[x])) {
4356 isnum = 0;
4357 break;
4358 }
4359 }
4360 if (isnum) {
4361 chan = atoi(fn);
4362 if (chan < 1) {
4363 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4364 return -1;
4365 }
4366 fn = "/dev/dahdi/channel";
4367 }
4368 fd = open(fn, O_RDWR | O_NONBLOCK);
4369 if (fd < 0) {
4370 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4371 return -1;
4372 }
4373 if (chan) {
4374 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4375 x = errno;
4376 close(fd);
4377 errno = x;
4378 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4379 return -1;
4380 }
4381 }
4382 bs = READ_SIZE;
4383 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4384 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4385 x = errno;
4386 close(fd);
4387 errno = x;
4388 return -1;
4389 }
4390 return fd;
4391}
4392
4393static void dahdi_close(int fd)
4394{
4395 if (fd > 0)
4396 close(fd);
4397}
4398
4399static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
4400{
4401 dahdi_close(chan_pvt->subs[sub_num].dfd);
4402 chan_pvt->subs[sub_num].dfd = -1;
4403}
4404
4405#if defined(HAVE_PRI)
4406static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
4407{
4408 dahdi_close(pri->pri.fds[fd_num]);
4409 pri->pri.fds[fd_num] = -1;
4410}
4411#endif /* defined(HAVE_PRI) */
4412
4413#if defined(HAVE_SS7)
4414static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
4415{
4416 dahdi_close(ss7->ss7.fds[fd_num]);
4417 ss7->ss7.fds[fd_num] = -1;
4418}
4419#endif /* defined(HAVE_SS7) */
4420
4421static int dahdi_setlinear(int dfd, int linear)
4422{
4423 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4424}
4425
4426
4427static int alloc_sub(struct dahdi_pvt *p, int x)
4428{
4429 struct dahdi_bufferinfo bi;
4430 int res;
4431 if (p->subs[x].dfd >= 0) {
4432 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4433 return -1;
4434 }
4435
4436 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4437 if (p->subs[x].dfd <= -1) {
4438 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4439 return -1;
4440 }
4441
4442 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4443 if (!res) {
4444 bi.txbufpolicy = p->buf_policy;
4445 bi.rxbufpolicy = p->buf_policy;
4446 bi.numbufs = p->buf_no;
4447 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4448 if (res < 0) {
4449 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4450 }
4451 } else
4452 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4453
4454 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4455 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4456 dahdi_close_sub(p, x);
4457 p->subs[x].dfd = -1;
4458 return -1;
4459 }
4460 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4461 return 0;
4462}
4463
4464static int unalloc_sub(struct dahdi_pvt *p, int x)
4465{
4466 if (!x) {
4467 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4468 return -1;
4469 }
4470 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4471 dahdi_close_sub(p, x);
4472 p->subs[x].linear = 0;
4473 p->subs[x].chan = 0;
4474 p->subs[x].owner = NULL;
4475 p->subs[x].inthreeway = 0;
4477 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4478 return 0;
4479}
4480
4482{
4483 if (isdigit(digit))
4484 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4485 else if (digit >= 'A' && digit <= 'D')
4486 return DAHDI_TONE_DTMF_A + (digit - 'A');
4487 else if (digit >= 'a' && digit <= 'd')
4488 return DAHDI_TONE_DTMF_A + (digit - 'a');
4489 else if (digit == '*')
4490 return DAHDI_TONE_DTMF_s;
4491 else if (digit == '#')
4492 return DAHDI_TONE_DTMF_p;
4493 else
4494 return -1;
4495}
4496
4497static int dahdi_digit_begin(struct ast_channel *chan, char digit)
4498{
4499 struct dahdi_pvt *pvt;
4500 int idx;
4501 int dtmf;
4502 int res;
4503
4504 pvt = ast_channel_tech_pvt(chan);
4505
4506 ast_mutex_lock(&pvt->lock);
4507
4508 idx = dahdi_get_index(chan, pvt, 0);
4509
4510 if ((idx != SUB_REAL) || !pvt->owner)
4511 goto out;
4512
4513#ifdef HAVE_PRI
4514 switch (pvt->sig) {
4516 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4517 if (!res)
4518 goto out;
4519 break;
4520 default:
4521 break;
4522 }
4523#endif
4524 dtmf = digit_to_dtmfindex(digit);
4525 if (dtmf == -1) {
4526 /* Not a valid DTMF digit */
4527 goto out;
4528 }
4529
4530 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4531 char dial_str[] = { 'T', digit, '\0' };
4532
4533 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4534 if (!res) {
4535 pvt->dialing = 1;
4536 }
4537 } else {
4538 pvt->dialing = 1;
4539 pvt->begindigit = digit;
4540
4541 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4542 dtmf = DAHDI_FLUSH_WRITE;
4543 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4544 if (res) {
4545 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4546 pvt->channel, strerror(errno));
4547 }
4548
4549 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4550 ast_channel_name(chan), digit);
4551 }
4552
4553out:
4554 ast_mutex_unlock(&pvt->lock);
4555
4556 return 0;
4557}
4558
4559static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
4560{
4561 struct dahdi_pvt *pvt;
4562 int res = 0;
4563 int idx;
4564 int x;
4565
4566 pvt = ast_channel_tech_pvt(chan);
4567
4568 ast_mutex_lock(&pvt->lock);
4569
4570 idx = dahdi_get_index(chan, pvt, 0);
4571
4572 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4573 goto out;
4574
4575#ifdef HAVE_PRI
4576 /* This means that the digit was already sent via PRI signalling */
4577 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4578 goto out;
4579 }
4580#endif
4581
4582 if (pvt->begindigit) {
4583 x = -1;
4584 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4585 ast_channel_name(chan), digit);
4586 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4587 pvt->dialing = 0;
4588 pvt->begindigit = 0;
4589 }
4590
4591out:
4592 ast_mutex_unlock(&pvt->lock);
4593
4594 return res;
4595}
4596
4597static const char * const events[] = {
4598 "No event",
4599 "On hook",
4600 "Ring/Answered",
4601 "Wink/Flash",
4602 "Alarm",
4603 "No more alarm",
4604 "HDLC Abort",
4605 "HDLC Overrun",
4606 "HDLC Bad FCS",
4607 "Dial Complete",
4608 "Ringer On",
4609 "Ringer Off",
4610 "Hook Transition Complete",
4611 "Bits Changed",
4612 "Pulse Start",
4613 "Timer Expired",
4614 "Timer Ping",
4615 "Polarity Reversal",
4616 "Ring Begin",
4617};
4618
4619static struct {
4621 char *name;
4622} alarms[] = {
4623 { DAHDI_ALARM_RED, "Red Alarm" },
4624 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
4625 { DAHDI_ALARM_BLUE, "Blue Alarm" },
4626 { DAHDI_ALARM_RECOVER, "Recovering" },
4627 { DAHDI_ALARM_LOOPBACK, "Loopback" },
4628 { DAHDI_ALARM_NOTOPEN, "Not Open" },
4629 { DAHDI_ALARM_NONE, "None" },
4631
4632static char *alarm2str(int alm)
4633{
4634 int x;
4635 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4636 if (alarms[x].alarm & alm)
4637 return alarms[x].name;
4638 }
4639 return alm ? "Unknown Alarm" : "No Alarm";
4640}
4641
4642static const char *event2str(int event)
4643{
4644 static char buf[256];
4645 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4646 return events[event];
4647 sprintf(buf, "Event %d", event); /* safe */
4648 return buf;
4649}
4650
4651static char *dahdi_sig2str(int sig)
4652{
4653 static char buf[256];
4654 switch (sig) {
4655 case SIG_EM:
4656 return "E & M Immediate";
4657 case SIG_EMWINK:
4658 return "E & M Wink";
4659 case SIG_EM_E1:
4660 return "E & M E1";
4661 case SIG_FEATD:
4662 return "Feature Group D (DTMF)";
4663 case SIG_FEATDMF:
4664 return "Feature Group D (MF)";
4665 case SIG_FEATDMF_TA:
4666 return "Feature Group D (MF) Tandem Access";
4667 case SIG_FEATB:
4668 return "Feature Group B (MF)";
4669 case SIG_E911:
4670 return "E911 (MF)";
4671 case SIG_FGC_CAMA:
4672 return "FGC/CAMA (Dialpulse)";
4673 case SIG_FGC_CAMAMF:
4674 return "FGC/CAMA (MF)";
4675 case SIG_FXSLS:
4676 return "FXS Loopstart";
4677 case SIG_FXSGS:
4678 return "FXS Groundstart";
4679 case SIG_FXSKS:
4680 return "FXS Kewlstart";
4681 case SIG_FXOLS:
4682 return "FXO Loopstart";
4683 case SIG_FXOGS:
4684 return "FXO Groundstart";
4685 case SIG_FXOKS:
4686 return "FXO Kewlstart";
4687 case SIG_PRI:
4688 return "ISDN PRI";
4689 case SIG_BRI:
4690 return "ISDN BRI Point to Point";
4691 case SIG_BRI_PTMP:
4692 return "ISDN BRI Point to MultiPoint";
4693 case SIG_SS7:
4694 return "SS7";
4695 case SIG_MFCR2:
4696 return "MFC/R2";
4697 case SIG_SF:
4698 return "SF (Tone) Immediate";
4699 case SIG_SFWINK:
4700 return "SF (Tone) Wink";
4701 case SIG_SF_FEATD:
4702 return "SF (Tone) with Feature Group D (DTMF)";
4703 case SIG_SF_FEATDMF:
4704 return "SF (Tone) with Feature Group D (MF)";
4705 case SIG_SF_FEATB:
4706 return "SF (Tone) with Feature Group B (MF)";
4707 case 0:
4708 return "Pseudo";
4709 default:
4710 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4711 return buf;
4712 }
4713}
4714
4715#define sig2str dahdi_sig2str
4716
4717static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
4718{
4719 /* If the conference already exists, and we're already in it
4720 don't bother doing anything */
4721 struct dahdi_confinfo zi;
4722
4723 memset(&zi, 0, sizeof(zi));
4724 zi.chan = 0;
4725
4726 if (slavechannel > 0) {
4727 /* If we have only one slave, do a digital mon */
4728 zi.confmode = DAHDI_CONF_DIGITALMON;
4729 zi.confno = slavechannel;
4730 } else {
4731 if (!idx) {
4732 /* Real-side and pseudo-side both participate in conference */
4733 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4734 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4735 } else
4736 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4737 zi.confno = p->confno;
4738 }
4739 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4740 return 0;
4741 if (c->dfd < 0)
4742 return 0;
4743 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4744 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4745 return -1;
4746 }
4747 if (slavechannel < 1) {
4748 p->confno = zi.confno;
4749 }
4750 c->curconf = zi;
4751 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4752 return 0;
4753}
4754
4755static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
4756{
4757 /* If they're listening to our channel, they're ours */
4758 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4759 return 1;
4760 /* If they're a talker on our (allocated) conference, they're ours */
4761 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4762 return 1;
4763 return 0;
4764}
4765
4766static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
4767{
4768 struct dahdi_confinfo zi;
4769 if (/* Can't delete if there's no dfd */
4770 (c->dfd < 0) ||
4771 /* Don't delete from the conference if it's not our conference */
4772 !isourconf(p, c)
4773 /* Don't delete if we don't think it's conferenced at all (implied) */
4774 ) return 0;
4775 memset(&zi, 0, sizeof(zi));
4776 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4777 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4778 return -1;
4779 }
4780 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4781 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4782 return 0;
4783}
4784
4785static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
4786{
4787 int x;
4788 int useslavenative;
4789 struct dahdi_pvt *slave = NULL;
4790 /* Start out optimistic */
4791 useslavenative = 1;
4792 /* Update conference state in a stateless fashion */
4793 for (x = 0; x < 3; x++) {
4794 /* Any three-way calling makes slave native mode *definitely* out
4795 of the question */
4796 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4797 useslavenative = 0;
4798 }
4799 /* If we don't have any 3-way calls, check to see if we have
4800 precisely one slave */
4801 if (useslavenative) {
4802 for (x = 0; x < MAX_SLAVES; x++) {
4803 if (p->slaves[x]) {
4804 if (slave) {
4805 /* Whoops already have a slave! No
4806 slave native and stop right away */
4807 slave = NULL;
4808 useslavenative = 0;
4809 break;
4810 } else {
4811 /* We have one slave so far */
4812 slave = p->slaves[x];
4813 }
4814 }
4815 }
4816 }
4817 /* If no slave, slave native definitely out */
4818 if (!slave)
4819 useslavenative = 0;
4820 else if (slave->law != p->law) {
4821 useslavenative = 0;
4822 slave = NULL;
4823 }
4824 if (out)
4825 *out = slave;
4826 return useslavenative;
4827}
4828
4829static int reset_conf(struct dahdi_pvt *p)
4830{
4831 p->confno = -1;
4832 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4833 if (p->subs[SUB_REAL].dfd > -1) {
4834 struct dahdi_confinfo zi;
4835
4836 memset(&zi, 0, sizeof(zi));
4837 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4838 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4839 }
4840 return 0;
4841}
4842
4844{
4845 int needconf = 0;
4846 int x;
4847 int useslavenative;
4848 struct dahdi_pvt *slave = NULL;
4849
4850 useslavenative = isslavenative(p, &slave);
4851 /* Start with the obvious, general stuff */
4852 for (x = 0; x < 3; x++) {
4853 /* Look for three way calls */
4854 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4855 conf_add(p, &p->subs[x], x, 0);
4856 needconf++;
4857 } else {
4858 conf_del(p, &p->subs[x], x);
4859 }
4860 }
4861 /* If we have a slave, add him to our conference now. or DAX
4862 if this is slave native */
4863 for (x = 0; x < MAX_SLAVES; x++) {
4864 if (p->slaves[x]) {
4865 if (useslavenative)
4866 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4867 else {
4868 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4869 needconf++;
4870 }
4871 }
4872 }
4873 /* If we're supposed to be in there, do so now */
4874 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4875 if (useslavenative)
4876 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4877 else {
4878 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4879 needconf++;
4880 }
4881 }
4882 /* If we have a master, add ourselves to his conference */
4883 if (p->master) {
4884 if (isslavenative(p->master, NULL)) {
4886 } else {
4887 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4888 }
4889 }
4890 if (!needconf) {
4891 /* Nobody is left (or should be left) in our conference.
4892 Kill it. */
4893 p->confno = -1;
4894 }
4895 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4896}
4897
4899{
4900 int res;
4901 if (!p)
4902 return;
4903 if (p->echocanon) {
4904 ast_debug(1, "Echo cancellation already on\n");
4905 return;
4906 }
4907 if (p->digital) {
4908 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4909 return;
4910 }
4911 if (p->echocancel.head.tap_length) {
4912#if defined(HAVE_PRI) || defined(HAVE_SS7)
4913 switch (p->sig) {
4914#if defined(HAVE_PRI)
4916 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4917 /*
4918 * PRI nobch pseudo channel. Does not need ec anyway.
4919 * Does not handle ioctl(DAHDI_AUDIOMODE)
4920 */
4921 return;
4922 }
4923 /* Fall through */
4924#endif /* defined(HAVE_PRI) */
4925#if defined(HAVE_SS7)
4926 case SIG_SS7:
4927#endif /* defined(HAVE_SS7) */
4928 {
4929 int x = 1;
4930
4931 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4932 if (res)
4934 "Unable to enable audio mode on channel %d (%s)\n",
4935 p->channel, strerror(errno));
4936 }
4937 break;
4938 default:
4939 break;
4940 }
4941#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4942 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4943 if (res) {
4944 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4945 } else {
4946 p->echocanon = 1;
4947 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4948 }
4949 } else
4950 ast_debug(1, "No echo cancellation requested\n");
4951}
4952
4953static void dahdi_train_ec(struct dahdi_pvt *p)
4954{
4955 int x;
4956 int res;
4957
4958 if (p && p->echocanon && p->echotraining) {
4959 x = p->echotraining;
4960 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4961 if (res)
4962 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4963 else
4964 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4965 } else {
4966 ast_debug(1, "No echo training requested\n");
4967 }
4968}
4969
4971{
4972 int res;
4973
4974 if (p->echocanon) {
4975 struct dahdi_echocanparams ecp = { .tap_length = 0 };
4976
4977 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4978
4979 if (res)
4980 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4981 else
4982 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4983 }
4984
4985 p->echocanon = 0;
4986}
4987
4988static int set_hwgain(int fd, float gain, int tx_direction)
4989{
4990 struct dahdi_hwgain hwgain;
4991
4992 hwgain.newgain = gain * 10.0;
4993 hwgain.tx = tx_direction;
4994 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4995}
4996
4997/* perform a dynamic range compression transform on the given sample */
4998static int drc_sample(int sample, float drc)
4999{
5000 float neg;
5001 float shallow, steep;
5002 float max = SHRT_MAX;
5003
5004 neg = (sample < 0 ? -1 : 1);
5005 steep = drc*sample;
5006 shallow = neg*(max-max/drc)+(float)sample/drc;
5007 if (fabsf(steep) < fabsf(shallow)) {
5008 sample = steep;
5009 }
5010 else {
5011 sample = shallow;
5012 }
5013
5014 return sample;
5015}
5016
5017
5018static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
5019{
5020 int j;
5021 int k;
5022
5023 float linear_gain = pow(10.0, gain / 20.0);
5024
5025 switch (law) {
5026 case DAHDI_LAW_ALAW:
5027 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5028 if (gain || drc) {
5029 k = AST_ALAW(j);
5030 if (drc) {
5031 k = drc_sample(k, drc);
5032 }
5033 k = (float)k * linear_gain;
5034 if (k > 32767) {
5035 k = 32767;
5036 } else if (k < -32768) {
5037 k = -32768;
5038 }
5039 g->txgain[j] = AST_LIN2A(k);
5040 } else {
5041 g->txgain[j] = j;
5042 }
5043 }
5044 break;
5045 case DAHDI_LAW_MULAW:
5046 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5047 if (gain || drc) {
5048 k = AST_MULAW(j);
5049 if (drc) {
5050 k = drc_sample(k, drc);
5051 }
5052 k = (float)k * linear_gain;
5053 if (k > 32767) {
5054 k = 32767;
5055 } else if (k < -32768) {
5056 k = -32768;
5057 }
5058 g->txgain[j] = AST_LIN2MU(k);
5059
5060 } else {
5061 g->txgain[j] = j;
5062 }
5063 }
5064 break;
5065 }
5066}
5067
5068static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
5069{
5070 int j;
5071 int k;
5072 float linear_gain = pow(10.0, gain / 20.0);
5073
5074 switch (law) {
5075 case DAHDI_LAW_ALAW:
5076 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5077 if (gain || drc) {
5078 k = AST_ALAW(j);
5079 if (drc) {
5080 k = drc_sample(k, drc);
5081 }
5082 k = (float)k * linear_gain;
5083 if (k > 32767) {
5084 k = 32767;
5085 } else if (k < -32768) {
5086 k = -32768;
5087 }
5088 g->rxgain[j] = AST_LIN2A(k);
5089 } else {
5090 g->rxgain[j] = j;
5091 }
5092 }
5093 break;
5094 case DAHDI_LAW_MULAW:
5095 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5096 if (gain || drc) {
5097 k = AST_MULAW(j);
5098 if (drc) {
5099 k = drc_sample(k, drc);
5100 }
5101 k = (float)k * linear_gain;
5102 if (k > 32767) {
5103 k = 32767;
5104 } else if (k < -32768) {
5105 k = -32768;
5106 }
5107 g->rxgain[j] = AST_LIN2MU(k);
5108 } else {
5109 g->rxgain[j] = j;
5110 }
5111 }
5112 break;
5113 }
5114}
5115
5116static int set_actual_txgain(int fd, float gain, float drc, int law)
5117{
5118 struct dahdi_gains g;
5119 int res;
5120
5121 memset(&g, 0, sizeof(g));
5122 res = ioctl(fd, DAHDI_GETGAINS, &g);
5123 if (res) {
5124 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5125 return res;
5126 }
5127
5128 fill_txgain(&g, gain, drc, law);
5129
5130 return ioctl(fd, DAHDI_SETGAINS, &g);
5131}
5132
5133static int set_actual_rxgain(int fd, float gain, float drc, int law)
5134{
5135 struct dahdi_gains g;
5136 int res;
5137
5138 memset(&g, 0, sizeof(g));
5139 res = ioctl(fd, DAHDI_GETGAINS, &g);
5140 if (res) {
5141 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5142 return res;
5143 }
5144
5145 fill_rxgain(&g, gain, drc, law);
5146
5147 return ioctl(fd, DAHDI_SETGAINS, &g);
5148}
5149
5150static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
5151{
5152 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5153}
5154
5155static int bump_gains(struct dahdi_pvt *p)
5156{
5157 int res;
5158
5159 /* Bump receive gain by value stored in cid_rxgain */
5160 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5161 if (res) {
5162 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5163 return -1;
5164 }
5165
5166 return 0;
5167}
5168
5169static int restore_gains(struct dahdi_pvt *p)
5170{
5171 int res;
5172
5173 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5174 if (res) {
5175 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5176 return -1;
5177 }
5178
5179 return 0;
5180}
5181
5182static inline int dahdi_set_hook(int fd, int hs)
5183{
5184 int x, res;
5185
5186 x = hs;
5187 res = ioctl(fd, DAHDI_HOOK, &x);
5188
5189 if (res < 0) {
5190 if (errno == EINPROGRESS)
5191 return 0;
5192 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5193 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5194 }
5195
5196 return res;
5197}
5198
5199static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
5200{
5201 int x, res;
5202
5203 x = muted;
5204#if defined(HAVE_PRI) || defined(HAVE_SS7)
5205 switch (p->sig) {
5206#if defined(HAVE_PRI)
5208 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5209 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5210 break;
5211 }
5212 /* Fall through */
5213#endif /* defined(HAVE_PRI) */
5214#if defined(HAVE_SS7)
5215 case SIG_SS7:
5216#endif /* defined(HAVE_SS7) */
5217 {
5218 int y = 1;
5219
5220 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5221 if (res)
5222 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5223 p->channel, strerror(errno));
5224 }
5225 break;
5226 default:
5227 break;
5228 }
5229#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5231 if (res < 0)
5232 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5233 return res;
5234}
5235
5236static int save_conference(struct dahdi_pvt *p)
5237{
5238 struct dahdi_confinfo c;
5239 int res;
5240 if (p->saveconf.confmode) {
5241 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5242 return -1;
5243 }
5244 p->saveconf.chan = 0;
5245 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5246 if (res) {
5247 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5248 p->saveconf.confmode = 0;
5249 return -1;
5250 }
5251 memset(&c, 0, sizeof(c));
5252 c.confmode = DAHDI_CONF_NORMAL;
5253 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5254 if (res) {
5255 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5256 return -1;
5257 }
5258 ast_debug(1, "Disabled conferencing\n");
5259 return 0;
5260}
5261
5262static int restore_conference(struct dahdi_pvt *p)
5263{
5264 int res;
5265 if (p->saveconf.confmode) {
5266 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5267 p->saveconf.confmode = 0;
5268 if (res) {
5269 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5270 return -1;
5271 }
5272 ast_debug(1, "Restored conferencing\n");
5273 }
5274 return 0;
5275}
5276
5277static int send_cwcidspill(struct dahdi_pvt *p)
5278{
5279 p->callwaitcas = 0;
5280 p->cidcwexpire = 0;
5281 p->cid_suppress_expire = 0;
5283 return -1;
5285 /* Make sure we account for the end */
5286 p->cidlen += READ_SIZE * 4;
5287 p->cidpos = 0;
5288 send_callerid(p);
5289 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5290 return 0;
5291}
5292
5293static int has_voicemail(struct dahdi_pvt *p)
5294{
5295 int new_msgs;
5296 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5297
5298 /* A manual MWI disposition has been requested, use that instead
5299 * if this is for sending the new MWI indication. */
5300 if (p->mwioverride_active) {
5301 /* We don't clear p->mwioverride_active automatically,
5302 * because otherwise do_monitor would just change it back to the way it was.
5303 * We need to keep the override active until explicitly disabled by the user,
5304 * so that we can keep returning the correct answer in subsequent calls to do_monitor. */
5305 ast_debug(6, "MWI manual override active on channel %d: pretending that it should be %s\n",
5306 p->channel, p->mwioverride_disposition ? "active" : "inactive");
5307 return p->mwioverride_disposition;
5308 }
5309
5311 if (mwi_message) {
5312 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5313 new_msgs = mwi_state->new_msgs;
5314 } else {
5316 }
5317
5318 return new_msgs;
5319}
5320
5321
5322
5323static int send_callerid(struct dahdi_pvt *p)
5324{
5325 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5326 int res;
5327 /* Take out of linear mode if necessary */
5328 if (p->subs[SUB_REAL].linear) {
5329 p->subs[SUB_REAL].linear = 0;
5331 }
5332 while (p->cidpos < p->cidlen) {
5333 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5334 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5335 if (res < 0) {
5336 if (errno == EAGAIN)
5337 return 0;
5338 else {
5339 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5340 return -1;
5341 }
5342 }
5343 if (!res)
5344 return 0;
5345 p->cidpos += res;
5346 }
5348 ast_free(p->cidspill);
5349 p->cidspill = NULL;
5350 if (p->callwaitcas) {
5351 /* Wait for CID/CW to expire */
5354 } else
5356 return 0;
5357}
5358
5359static int dahdi_callwait(struct ast_channel *ast)
5360{
5361 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5362
5364 if (p->cidspill) {
5365 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5366 ast_free(p->cidspill);
5367 }
5368
5369 /*
5370 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5371 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5372 */
5373 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5374 return -1;
5375 save_conference(p);
5376 /* Silence */
5377 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5378 if (!p->callwaitrings && p->callwaitingcallerid) {
5379 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5380 p->callwaitcas = 1;
5381 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5382 } else {
5383 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5384 p->callwaitcas = 0;
5385 p->cidlen = 2400 + READ_SIZE * 4;
5386 }
5387 p->cidpos = 0;
5388 send_callerid(p);
5389
5390 return 0;
5391}
5392
5393static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
5394{
5395 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5396 int x, res, mysig;
5397 char *dest;
5399 AST_APP_ARG(group); /* channel/group token */
5400 AST_APP_ARG(ext); /* extension token */
5401 //AST_APP_ARG(opts); /* options token */
5402 AST_APP_ARG(other); /* Any remining unused arguments */
5403 );
5404
5405 ast_mutex_lock(&p->lock);
5406 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5407
5408 /* Split the dialstring */
5409 dest = ast_strdupa(rdest);
5410 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5411 if (!args.ext) {
5412 args.ext = "";
5413 }
5414
5415#if defined(HAVE_PRI)
5417 char *subaddr;
5418
5419 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5420
5421 /* Remove any subaddress for uniformity with incoming calls. */
5422 subaddr = strchr(p->exten, ':');
5423 if (subaddr) {
5424 *subaddr = '\0';
5425 }
5426 } else
5427#endif /* defined(HAVE_PRI) */
5428 {
5429 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5430 }
5431
5432 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5433 p->subs[SUB_REAL].needbusy = 1;
5435 return 0;
5436 }
5438 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5440 return -1;
5441 }
5442 p->waitingfordt.tv_sec = 0;
5443 p->dialednone = 0;
5444 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5445 {
5446 /* Special pseudo -- automatically up */
5449 return 0;
5450 }
5451 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5452 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5453 if (res)
5454 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5455 p->outgoing = 1;
5456
5458 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5459 } else {
5460 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5461 }
5462
5463#ifdef HAVE_PRI
5465 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5466 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5468 return res;
5469 }
5470#endif
5471
5472#if defined(HAVE_SS7)
5473 if (p->sig == SIG_SS7) {
5474 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5476 return res;
5477 }
5478#endif /* defined(HAVE_SS7) */
5479
5480 /* If this is analog signalling we can exit here */
5481 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5482 p->callwaitrings = 0;
5483 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5485 return res;
5486 }
5487
5488 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5489 switch (mysig) {
5490 case 0:
5491 /* Special pseudo -- automatically up*/
5493 break;
5494 case SIG_MFCR2:
5495 break;
5496 default:
5497 ast_debug(1, "not yet implemented\n");
5499 return -1;
5500 }
5501
5502#ifdef HAVE_OPENR2
5503 if (p->mfcr2) {
5504 openr2_calling_party_category_t chancat;
5505 int callres = 0;
5506 char *c, *l;
5507
5508 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5509 p->dialdest[0] = '\0';
5510
5511 c = args.ext;
5512 if (!p->hidecallerid) {
5514 } else {
5515 l = NULL;
5516 }
5517 if (strlen(c) < p->stripmsd) {
5518 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5520 return -1;
5521 }
5522 p->dialing = 1;
5523 chancat = dahdi_r2_get_channel_category(ast);
5524 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5525 if (-1 == callres) {
5527 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5528 return -1;
5529 }
5530 p->mfcr2_call_accepted = 0;
5531 p->mfcr2_progress_sent = 0;
5533 }
5534#endif /* HAVE_OPENR2 */
5536 return 0;
5537}
5538
5539/*!
5540 * \internal
5541 * \brief Insert the given chan_dahdi interface structure into the interface list.
5542 * \since 1.8
5543 *
5544 * \param pvt chan_dahdi private interface structure to insert.
5545 *
5546 * \details
5547 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5548 * Any duplicates are inserted after the existing entries.
5549 *
5550 * \note The new interface must not already be in the list.
5551 */
5552static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
5553{
5554 struct dahdi_pvt *cur;
5555
5557
5558 /* Find place in middle of list for the new interface. */
5559 for (cur = iflist; cur; cur = cur->next) {
5560 if (pvt->channel < cur->channel) {
5561 /* New interface goes before the current interface. */
5562 pvt->prev = cur->prev;
5563 pvt->next = cur;
5564 if (cur->prev) {
5565 /* Insert into the middle of the list. */
5566 cur->prev->next = pvt;
5567 } else {
5568 /* Insert at head of list. */
5569 iflist = pvt;
5570 }
5571 cur->prev = pvt;
5572 return;
5573 }
5574 }
5575
5576 /* New interface goes onto the end of the list */
5577 pvt->prev = ifend;
5578 pvt->next = NULL;
5579 if (ifend) {
5580 ifend->next = pvt;
5581 }
5582 ifend = pvt;
5583 if (!iflist) {
5584 /* List was empty */
5585 iflist = pvt;
5586 }
5587}
5588
5589/*!
5590 * \internal
5591 * \brief Extract the given chan_dahdi interface structure from the interface list.
5592 * \since 1.8
5593 *
5594 * \param pvt chan_dahdi private interface structure to extract.
5595 *
5596 * \note
5597 * The given interface structure can be either in the interface list or a stand alone
5598 * structure that has not been put in the list if the next and prev pointers are NULL.
5599 */
5600static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
5601{
5602 /* Extract from the forward chain. */
5603 if (pvt->prev) {
5604 pvt->prev->next = pvt->next;
5605 } else if (iflist == pvt) {
5606 /* Node is at the head of the list. */
5607 iflist = pvt->next;
5608 }
5609
5610 /* Extract from the reverse chain. */
5611 if (pvt->next) {
5612 pvt->next->prev = pvt->prev;
5613 } else if (ifend == pvt) {
5614 /* Node is at the end of the list. */
5615 ifend = pvt->prev;
5616 }
5617
5618 /* Node is no longer in the list. */
5620 pvt->prev = NULL;
5621 pvt->next = NULL;
5622}
5623
5624#if defined(HAVE_PRI)
5625/*!
5626 * \internal
5627 * \brief Insert the given chan_dahdi interface structure into the no B channel list.
5628 * \since 1.8
5629 *
5630 * \param pri sig_pri span control structure holding no B channel list.
5631 * \param pvt chan_dahdi private interface structure to insert.
5632 *
5633 * \details
5634 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5635 * Any duplicates are inserted after the existing entries.
5636 *
5637 * \note The new interface must not already be in the list.
5638 */
5639static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5640{
5641 struct dahdi_pvt *cur;
5642
5643 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
5644
5645 /* Find place in middle of list for the new interface. */
5646 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
5647 if (pvt->channel < cur->channel) {
5648 /* New interface goes before the current interface. */
5649 pvt->prev = cur->prev;
5650 pvt->next = cur;
5651 if (cur->prev) {
5652 /* Insert into the middle of the list. */
5653 cur->prev->next = pvt;
5654 } else {
5655 /* Insert at head of list. */
5656 pri->no_b_chan_iflist = pvt;
5657 }
5658 cur->prev = pvt;
5659 return;
5660 }
5661 }
5662
5663 /* New interface goes onto the end of the list */
5664 pvt->prev = pri->no_b_chan_end;
5665 pvt->next = NULL;
5666 if (pri->no_b_chan_end) {
5667 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
5668 }
5669 pri->no_b_chan_end = pvt;
5670 if (!pri->no_b_chan_iflist) {
5671 /* List was empty */
5672 pri->no_b_chan_iflist = pvt;
5673 }
5674}
5675#endif /* defined(HAVE_PRI) */
5676
5677#if defined(HAVE_PRI)
5678/*!
5679 * \internal
5680 * \brief Extract the given chan_dahdi interface structure from the no B channel list.
5681 * \since 1.8
5682 *
5683 * \param pri sig_pri span control structure holding no B channel list.
5684 * \param pvt chan_dahdi private interface structure to extract.
5685 *
5686 * \note
5687 * The given interface structure can be either in the interface list or a stand alone
5688 * structure that has not been put in the list if the next and prev pointers are NULL.
5689 */
5690static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5691{
5692 /* Extract from the forward chain. */
5693 if (pvt->prev) {
5694 pvt->prev->next = pvt->next;
5695 } else if (pri->no_b_chan_iflist == pvt) {
5696 /* Node is at the head of the list. */
5697 pri->no_b_chan_iflist = pvt->next;
5698 }
5699
5700 /* Extract from the reverse chain. */
5701 if (pvt->next) {
5702 pvt->next->prev = pvt->prev;
5703 } else if (pri->no_b_chan_end == pvt) {
5704 /* Node is at the end of the list. */
5705 pri->no_b_chan_end = pvt->prev;
5706 }
5707
5708 /* Node is no longer in the list. */
5710 pvt->prev = NULL;
5711 pvt->next = NULL;
5712}
5713#endif /* defined(HAVE_PRI) */
5714
5715#if defined(HAVE_PRI)
5716/*!
5717 * \internal
5718 * \brief Unlink the channel interface from the PRI private pointer array.
5719 * \since 1.8
5720 *
5721 * \param pvt chan_dahdi private interface structure to unlink.
5722 */
5723static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
5724{
5725 unsigned idx;
5726 struct sig_pri_span *pri;
5727
5728 pri = pvt->pri;
5729 if (!pri) {
5730 /* Not PRI signaling so cannot be in a PRI private pointer array. */
5731 return;
5732 }
5733 ast_mutex_lock(&pri->lock);
5734 for (idx = 0; idx < pri->numchans; ++idx) {
5735 if (pri->pvts[idx] == pvt->sig_pvt) {
5736 pri->pvts[idx] = NULL;
5737 ast_mutex_unlock(&pri->lock);
5738 return;
5739 }
5740 }
5741 ast_mutex_unlock(&pri->lock);
5742}
5743#endif /* defined(HAVE_PRI) */
5744
5745#if defined(HAVE_SS7)
5746/*!
5747 * \internal
5748 * \brief Unlink the channel interface from the SS7 private pointer array.
5749 * \since 1.8
5750 *
5751 * \param pvt chan_dahdi private interface structure to unlink.
5752 */
5753static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
5754{
5755 unsigned idx;
5756 struct sig_ss7_linkset *ss7;
5757
5758 ss7 = pvt->ss7;
5759 if (!ss7) {
5760 /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
5761 return;
5762 }
5763 ast_mutex_lock(&ss7->lock);
5764 for (idx = 0; idx < ss7->numchans; ++idx) {
5765 if (ss7->pvts[idx] == pvt->sig_pvt) {
5766 ss7->pvts[idx] = NULL;
5767 ast_mutex_unlock(&ss7->lock);
5768 return;
5769 }
5770 }
5771 ast_mutex_unlock(&ss7->lock);
5772}
5773#endif /* defined(HAVE_SS7) */
5774
5775#if defined(HAVE_OPENR2)
5776/*!
5777 * \internal
5778 * \brief Unlink the channel interface from the MFC/R2 private pointer array.
5779 *
5780 * \param pvt chan_dahdi private interface structure to unlink.
5781 */
5782static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)
5783{
5784 unsigned idx;
5785 struct dahdi_mfcr2 *mfcr2;
5786 int should_destroy_link = 0;
5787
5788 ast_mutex_lock(&pvt->lock);
5789 if (pvt->r2chan) {
5790 ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);
5791 openr2_chan_disable_read(pvt->r2chan);
5792 }
5793 mfcr2 = pvt->mfcr2;
5794 if (mfcr2) {
5795 for (idx = 0; idx < mfcr2->numchans; ++idx) {
5796 if (mfcr2->pvts[idx] == pvt) {
5797 ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);
5798 mfcr2->pvts[idx] = NULL;
5799 mfcr2->live_chans--;
5800 break;
5801 }
5802 }
5803 if (!mfcr2->live_chans) {
5804 ast_debug(1, "MFC/R2 link is now empty\n");
5805 should_destroy_link = 1;
5806 }
5807 }
5808 ast_mutex_unlock(&pvt->lock);
5809 if (should_destroy_link) {
5810 ast_debug(1, "MFC/R2 link is now empty\n");
5811 mfcr2_queue_for_destruction(pvt);
5812 }
5813}
5814#endif /* defined(HAVE_OPENR2) */
5815
5817{
5818 if (cur->next && cur->next->span == cur->span) {
5819 return cur->next;
5820 } else if (cur->prev && cur->prev->span == cur->span) {
5821 return cur->prev;
5822 }
5823
5824 return NULL;
5825}
5826
5827static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5828{
5829 struct dahdi_pvt *p = pvt;
5830
5831 if (p->manages_span_alarms) {
5833 if (next) {
5835 }
5836 }
5837
5838 /* Remove channel from the list */
5839#if defined(HAVE_PRI)
5840 dahdi_unlink_pri_pvt(p);
5841#endif /* defined(HAVE_PRI) */
5842#if defined(HAVE_SS7)
5843 dahdi_unlink_ss7_pvt(p);
5844#endif /* defined(HAVE_SS7) */
5845#if defined(HAVE_OPENR2)
5846 dahdi_unlink_mfcr2_pvt(p);
5847#endif /* defined(HAVE_SS7) */
5848 switch (pvt->which_iflist) {
5849 case DAHDI_IFLIST_NONE:
5850 break;
5851 case DAHDI_IFLIST_MAIN:
5853 break;
5854#if defined(HAVE_PRI)
5855 case DAHDI_IFLIST_NO_B_CHAN:
5856 if (p->pri) {
5857 dahdi_nobch_extract(p->pri, p);
5858 }
5859 break;
5860#endif /* defined(HAVE_PRI) */
5861 }
5862
5863 if (p->sig_pvt) {
5864 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5866 }
5867 switch (p->sig) {
5868#if defined(HAVE_PRI)
5871 break;
5872#endif /* defined(HAVE_PRI) */
5873#if defined(HAVE_SS7)
5874 case SIG_SS7:
5876 break;
5877#endif /* defined(HAVE_SS7) */
5878 default:
5879 break;
5880 }
5881 }
5882 ast_free(p->cidspill);
5883 if (p->use_smdi) {
5885 }
5886 if (p->mwi_event_sub) {
5888 }
5889 if (p->vars) {
5891 }
5892 if (p->cc_params) {
5894 }
5895
5898
5901 if (p->owner) {
5903 }
5904 ast_free(p);
5905}
5906
5907static void destroy_channel(struct dahdi_pvt *cur, int now)
5908{
5909 int i;
5910
5911 if (!now) {
5912 /* Do not destroy the channel now if it is owned by someone. */
5913 if (cur->owner) {
5914 return;
5915 }
5916 for (i = 0; i < 3; i++) {
5917 if (cur->subs[i].owner) {
5918 return;
5919 }
5920 }
5921 }
5922 destroy_dahdi_pvt(cur);
5923}
5924
5925static void destroy_all_channels(void)
5926{
5927 int chan;
5928#if defined(HAVE_PRI)
5929 unsigned span;
5930 struct sig_pri_span *pri;
5931#endif /* defined(HAVE_PRI) */
5932 struct dahdi_pvt *p;
5933
5934 while (num_restart_pending) {
5935 usleep(1);
5936 }
5937
5939 /* Destroy all the interfaces and free their memory */
5940 while (iflist) {
5941 p = iflist;
5942
5943 chan = p->channel;
5944#if defined(HAVE_PRI_SERVICE_MESSAGES)
5945 {
5946 char db_chan_name[20];
5947 char db_answer[5];
5948 char state;
5949 int why = -1;
5950
5951 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5952 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5953 sscanf(db_answer, "%1c:%30d", &state, &why);
5954 }
5955 if (!why) {
5956 /* SRVST persistence is not required */
5957 ast_db_del(db_chan_name, SRVST_DBKEY);
5958 }
5959 }
5960#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5961 /* Free associated memory */
5963 ast_verb(3, "Unregistered channel %d\n", chan);
5964 }
5965 ifcount = 0;
5967
5968#if defined(HAVE_PRI)
5969 /* Destroy all of the no B channel interface lists */
5970 for (span = 0; span < NUM_SPANS; ++span) {
5971 if (!pris[span].dchannels[0]) {
5972 break;
5973 }
5974 pri = &pris[span].pri;
5975 ast_mutex_lock(&pri->lock);
5976 while (pri->no_b_chan_iflist) {
5977 p = pri->no_b_chan_iflist;
5978
5979 /* Free associated memory */
5981 }
5982 ast_mutex_unlock(&pri->lock);
5983 }
5984#endif /* defined(HAVE_PRI) */
5985}
5986
5987#if defined(HAVE_PRI)
5988static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5989
5990static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
5991{
5992 /* Data will be our digit string */
5993 struct dahdi_pvt *p;
5994
5995 if (ast_strlen_zero(digits)) {
5996 ast_debug(1, "No digit string sent to application!\n");
5997 return -1;
5998 }
5999
6000 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6001
6002 if (!p) {
6003 ast_debug(1, "Unable to find technology private\n");
6004 return -1;
6005 }
6006
6008
6009 return 0;
6010}
6011#endif /* defined(HAVE_PRI) */
6012
6013#if defined(HAVE_PRI)
6014#if defined(HAVE_PRI_PROG_W_CAUSE)
6015static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
6016
6017static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
6018{
6019 /* Data will be our digit string */
6020 struct dahdi_pvt *pvt;
6021 char *parse;
6022 int res;
6024 AST_APP_ARG(destination);
6025 AST_APP_ARG(original);
6026 AST_APP_ARG(reason);
6027 );
6028
6029 if (ast_strlen_zero(data)) {
6030 ast_debug(1, "No data sent to application!\n");
6031 return -1;
6032 }
6033 if (ast_channel_tech(chan) != &dahdi_tech) {
6034 ast_debug(1, "Only DAHDI technology accepted!\n");
6035 return -1;
6036 }
6037 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
6038 if (!pvt) {
6039 ast_debug(1, "Unable to find technology private\n");
6040 return -1;
6041 }
6042 switch (pvt->sig) {
6044 break;
6045 default:
6046 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
6047 ast_channel_name(chan));
6048 return -1;
6049 }
6050
6051 parse = ast_strdupa(data);
6053
6054 if (ast_strlen_zero(args.destination)) {
6055 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
6056 return -1;
6057 }
6058
6059 if (ast_strlen_zero(args.original)) {
6060 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
6061 args.original = NULL;
6062 }
6063
6064 if (ast_strlen_zero(args.reason)) {
6065 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
6066 args.reason = NULL;
6067 }
6068
6070 args.destination, args.original, args.reason);
6071 if (!res) {
6072 /*
6073 * Wait up to 5 seconds for a reply before hanging up this call
6074 * leg if the peer does not disconnect first.
6075 */
6076 ast_safe_sleep(chan, 5000);
6077 }
6078
6079 return -1;
6080}
6081#endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
6082#endif /* defined(HAVE_PRI) */
6083
6084#if defined(HAVE_OPENR2)
6085static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
6086
6087static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
6088{
6089 /* data is whether to accept with charge or no charge */
6090 openr2_call_mode_t accept_mode;
6091 int res, timeout, maxloops;
6092 struct ast_frame *f;
6093 struct dahdi_pvt *p;
6094 char *parse;
6096 AST_APP_ARG(charge);
6097 );
6098
6099 if (ast_strlen_zero(data)) {
6100 ast_debug(1, "No data sent to application!\n");
6101 return -1;
6102 }
6103
6104 if (ast_channel_tech(chan) != &dahdi_tech) {
6105 ast_debug(1, "Only DAHDI technology accepted!\n");
6106 return -1;
6107 }
6108
6109 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6110 if (!p) {
6111 ast_debug(1, "Unable to find technology private!\n");
6112 return -1;
6113 }
6114
6115 parse = ast_strdupa(data);
6117
6118 if (ast_strlen_zero(args.charge)) {
6119 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
6120 return -1;
6121 }
6122
6123 ast_mutex_lock(&p->lock);
6124 if (!p->mfcr2 || !p->mfcr2call) {
6126 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
6127 return -1;
6128 }
6129
6130 if (p->mfcr2_call_accepted) {
6132 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
6133 return 0;
6134 }
6135 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
6136 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
6138 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6139 return -1;
6140 }
6142
6143 res = 0;
6144 timeout = 100;
6145 maxloops = 50; /* wait up to 5 seconds */
6146 /* we need to read() until the call is accepted */
6147 while (maxloops > 0) {
6148 maxloops--;
6149 if (ast_check_hangup(chan)) {
6150 break;
6151 }
6152 res = ast_waitfor(chan, timeout);
6153 if (res < 0) {
6154 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
6155 res = -1;
6156 break;
6157 }
6158 if (res == 0) {
6159 continue;
6160 }
6161 res = 0;
6162 f = ast_read(chan);
6163 if (!f) {
6164 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
6165 res = -1;
6166 break;
6167 }
6169 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
6170 ast_frfree(f);
6171 res = -1;
6172 break;
6173 }
6174 ast_frfree(f);
6175 ast_mutex_lock(&p->lock);
6176 if (p->mfcr2_call_accepted) {
6178 ast_debug(1, "Accepted MFC/R2 call!\n");
6179 break;
6180 }
6182 }
6183 if (res == -1) {
6184 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6185 }
6186 return res;
6187}
6188
6189static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
6190{
6191 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
6192 switch (cause) {
6195 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
6196 r2cause = OR2_CAUSE_BUSY_NUMBER;
6197 break;
6198
6201 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6202 break;
6203
6205 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6206 break;
6207
6210 r2cause = OR2_CAUSE_OUT_OF_ORDER;
6211 break;
6212
6215 r2cause = OR2_CAUSE_NO_ANSWER;
6216 break;
6217
6218 default:
6219 r2cause = OR2_CAUSE_NORMAL_CLEARING;
6220 break;
6221 }
6222 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
6223 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
6224 return r2cause;
6225}
6226#endif
6227
6228static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
6229{
6230 if (p->bufferoverrideinuse) {
6231 /* faxbuffers are in use, revert them */
6232 struct dahdi_bufferinfo bi = {
6233 .txbufpolicy = p->buf_policy,
6234 .rxbufpolicy = p->buf_policy,
6235 .bufsize = p->bufsize,
6236 .numbufs = p->buf_no
6237 };
6238 int bpres;
6239
6240 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6241 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6242 }
6243 p->bufferoverrideinuse = 0;
6244 return bpres;
6245 }
6246
6247 return -1;
6248}
6249
6250static int dahdi_hangup(struct ast_channel *ast)
6251{
6252 int res = 0;
6253 int idx,x;
6254 int law;
6255 /*static int restore_gains(struct dahdi_pvt *p);*/
6256 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6257 struct dahdi_params par;
6258
6259 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6260 if (!ast_channel_tech_pvt(ast)) {
6261 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6262 return 0;
6263 }
6264
6265 ast_mutex_lock(&p->lock);
6266 p->exten[0] = '\0';
6267 /* Always use sig_analog hangup handling for operator mode */
6268 if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6269 p->oprmode = 0;
6270 dahdi_confmute(p, 0);
6271 restore_gains(p);
6272 p->ignoredtmf = 0;
6273 p->waitingfordt.tv_sec = 0;
6274
6275 res = analog_hangup(p->sig_pvt, ast);
6276 revert_fax_buffers(p, ast);
6277
6278 goto hangup_out;
6279 } else {
6280 p->cid_num[0] = '\0';
6281 p->cid_name[0] = '\0';
6282 p->cid_subaddr[0] = '\0';
6283 }
6284
6285#if defined(HAVE_PRI)
6287 x = 1;
6288 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6289
6290 dahdi_confmute(p, 0);
6291 p->muting = 0;
6292 restore_gains(p);
6293 if (p->dsp) {
6294 ast_dsp_free(p->dsp);
6295 p->dsp = NULL;
6296 }
6297 p->ignoredtmf = 0;
6298
6299 /* Real channel, do some fixup */
6300 p->subs[SUB_REAL].owner = NULL;
6301 p->subs[SUB_REAL].needbusy = 0;
6303
6304 p->owner = NULL;
6305 p->cid_tag[0] = '\0';
6306 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6307 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6308 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6309 p->outgoing = 0;
6310 p->digital = 0;
6311 p->faxhandled = 0;
6312 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6313
6314 revert_fax_buffers(p, ast);
6315
6316 p->law = p->law_default;
6317 law = p->law_default;
6318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6319 if (res < 0) {
6320 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6321 p->channel, strerror(errno));
6322 }
6323
6324 sig_pri_hangup(p->sig_pvt, ast);
6325
6326 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6328
6329 x = 0;
6330 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6331 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6332
6333 p->rdnis[0] = '\0';
6335 reset_conf(p);
6336
6337 /* Restore data mode */
6338 x = 0;
6339 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6340
6341 if (num_restart_pending == 0) {
6343 }
6344 goto hangup_out;
6345 }
6346#endif /* defined(HAVE_PRI) */
6347
6348#if defined(HAVE_SS7)
6349 if (p->sig == SIG_SS7) {
6350 x = 1;
6351 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6352
6353 dahdi_confmute(p, 0);
6354 p->muting = 0;
6355 restore_gains(p);
6356 if (p->dsp) {
6357 ast_dsp_free(p->dsp);
6358 p->dsp = NULL;
6359 }
6360 p->ignoredtmf = 0;
6361
6362 /* Real channel, do some fixup */
6363 p->subs[SUB_REAL].owner = NULL;
6364 p->subs[SUB_REAL].needbusy = 0;
6366
6367 p->owner = NULL;
6368 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6369 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6370 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6371 p->outgoing = 0;
6372 p->digital = 0;
6373 p->faxhandled = 0;
6374 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6375
6376 revert_fax_buffers(p, ast);
6377
6378 p->law = p->law_default;
6379 law = p->law_default;
6380 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6381 if (res < 0) {
6382 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6383 p->channel, strerror(errno));
6384 }
6385
6386 sig_ss7_hangup(p->sig_pvt, ast);
6387
6388 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6390
6391 x = 0;
6392 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6393 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6394
6396 reset_conf(p);
6397
6398 /* Restore data mode */
6399 x = 0;
6400 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6401
6402 if (num_restart_pending == 0) {
6404 }
6405 goto hangup_out;
6406 }
6407#endif /* defined(HAVE_SS7) */
6408
6409 idx = dahdi_get_index(ast, p, 1);
6410
6411 dahdi_confmute(p, 0);
6412 p->muting = 0;
6413 restore_gains(p);
6414 if (p->origcid_num) {
6415 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6417 p->origcid_num = NULL;
6418 }
6419 if (p->origcid_name) {
6420 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6422 p->origcid_name = NULL;
6423 }
6424 if (p->dsp)
6426
6427 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6428 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6429 p->ignoredtmf = 0;
6430
6431 if (idx > -1) {
6432 /* Real channel, do some fixup */
6433 p->subs[idx].owner = NULL;
6434 p->subs[idx].needanswer = 0;
6435 p->subs[idx].needflash = 0;
6436 p->subs[idx].needringing = 0;
6437 p->subs[idx].needbusy = 0;
6438 p->subs[idx].needcongestion = 0;
6439 p->subs[idx].linear = 0;
6441 dahdi_setlinear(p->subs[idx].dfd, 0);
6442 if (idx == SUB_REAL) {
6443 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6444 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6445 if (p->subs[SUB_CALLWAIT].inthreeway) {
6446 /* We had flipped over to answer a callwait and now it's gone */
6447 ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6448 /* Move to the call-wait, but un-own us until they flip back. */
6451 p->owner = NULL;
6452 } else {
6453 /* The three way hung up, but we still have a call wait */
6454 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6457 if (p->subs[SUB_REAL].inthreeway) {
6458 /* This was part of a three way call. Immediately make way for
6459 another call */
6460 ast_debug(1, "Call was complete, setting owner to former third call\n");
6461 p->owner = p->subs[SUB_REAL].owner;
6462 } else {
6463 /* This call hasn't been completed yet... Set owner to NULL */
6464 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6465 p->owner = NULL;
6466 }
6467 p->subs[SUB_REAL].inthreeway = 0;
6468 }
6469 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6470 /* Move to the call-wait and switch back to them. */
6473 p->owner = p->subs[SUB_REAL].owner;
6475 p->subs[SUB_REAL].needanswer = 1;
6477 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6480 if (p->subs[SUB_REAL].inthreeway) {
6481 /* This was part of a three way call. Immediately make way for
6482 another call */
6483 ast_debug(1, "Call was complete, setting owner to former third call\n");
6484 p->owner = p->subs[SUB_REAL].owner;
6485 } else {
6486 /* This call hasn't been completed yet... Set owner to NULL */
6487 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6488 p->owner = NULL;
6489 }
6490 p->subs[SUB_REAL].inthreeway = 0;
6491 }
6492 } else if (idx == SUB_CALLWAIT) {
6493 /* Ditch the holding callwait call, and immediately make it availabe */
6494 if (p->subs[SUB_CALLWAIT].inthreeway) {
6495 /* This is actually part of a three way, placed on hold. Place the third part
6496 on music on hold now */
6497 if (p->subs[SUB_THREEWAY].owner) {
6499 }
6501 /* Make it the call wait now */
6504 } else
6506 } else if (idx == SUB_THREEWAY) {
6507 if (p->subs[SUB_CALLWAIT].inthreeway) {
6508 /* The other party of the three way call is currently in a call-wait state.
6509 Start music on hold for them, and take the main guy out of the third call */
6510 if (p->subs[SUB_CALLWAIT].owner) {
6512 }
6514 }
6515 p->subs[SUB_REAL].inthreeway = 0;
6516 /* If this was part of a three way call index, let us make
6517 another three way call */
6519 } else {
6520 /* This wasn't any sort of call, but how are we an index? */
6521 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6522 }
6523 }
6524
6525 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6526 p->owner = NULL;
6527 p->ringt = 0;
6528 p->distinctivering = 0;
6529 p->confirmanswer = 0;
6530 p->outgoing = 0;
6531 p->digital = 0;
6532 p->faxhandled = 0;
6533 p->pulsedial = 0;
6534 if (p->dsp) {
6535 ast_dsp_free(p->dsp);
6536 p->dsp = NULL;
6537 }
6538
6539 revert_fax_buffers(p, ast);
6540
6541 p->law = p->law_default;
6542 law = p->law_default;
6543 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6544 if (res < 0)
6545 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6546 /* Perform low level hangup if no owner left */
6547#ifdef HAVE_OPENR2
6548 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6549 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6550 /* If it's an incoming call, check the mfcr2_forced_release setting */
6551 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6552 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6553 } else {
6554 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6555 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6556 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6557 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6558 dahdi_r2_disconnect_call(p, r2cause);
6559 }
6560 } else if (p->mfcr2call) {
6561 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6562 /* since ast_request() was called but not ast_call() we have not yet dialed
6563 and the openr2 stack will not call on_call_end callback, we need to unset
6564 the mfcr2call flag and bump the monitor count so the monitor thread can take
6565 care of this channel events from now on */
6566 p->mfcr2call = 0;
6567 }
6568#endif
6569 switch (p->sig) {
6570 case SIG_SS7:
6571 case SIG_MFCR2:
6573 case 0:
6574 break;
6575 default:
6576 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6577 break;
6578 }
6579 if (res < 0) {
6580 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6581 }
6582 switch (p->sig) {
6583 case SIG_FXOGS:
6584 case SIG_FXOLS:
6585 case SIG_FXOKS:
6586 memset(&par, 0, sizeof(par));
6587 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6588 if (!res) {
6589 struct analog_pvt *analog_p = p->sig_pvt;
6590#if 0
6591 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6592#endif
6593 /* If they're off hook, try playing congestion */
6594 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6595 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6596 else
6597 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6598 analog_p->fxsoffhookstate = par.rxisoffhook;
6599 }
6600 break;
6601 case SIG_FXSGS:
6602 case SIG_FXSLS:
6603 case SIG_FXSKS:
6604 /* Make sure we're not made available for at least two seconds assuming
6605 we were actually used for an inbound or outbound call. */
6607 time(&p->guardtime);
6608 p->guardtime += 2;
6609 }
6610 break;
6611 default:
6612 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6613 break;
6614 }
6615 if (p->sig)
6617 x = 0;
6618 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6619 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6620 p->didtdd = 0;
6621 p->callwaitcas = 0;
6624 p->waitingfordt.tv_sec = 0;
6625 p->dialing = 0;
6626 p->rdnis[0] = '\0';
6628 reset_conf(p);
6629 /* Restore data mode */
6630 switch (p->sig) {
6632 case SIG_SS7:
6633 x = 0;
6634 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6635 break;
6636 default:
6637 break;
6638 }
6639 if (num_restart_pending == 0)
6641 }
6642
6643 p->callwaitingrepeat = 0;
6644 p->cidcwexpire = 0;
6645 p->cid_suppress_expire = 0;
6646 p->oprmode = 0;
6647hangup_out:
6649 ast_free(p->cidspill);
6650 p->cidspill = NULL;
6651
6652 if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6653 /* Automatic reorigination: if all calls towards a user have hung up,
6654 * give dial tone again, so user doesn't need to cycle the hook state manually. */
6655 if (my_is_off_hook(p) && !p->owner) {
6656 /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6657 ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6658 my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6659 /* Must wait for the loop disconnect to end.
6660 * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6661 * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6662 */
6663 usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6664 /* If the line is still off-hook and ownerless, actually queue the reorigination.
6665 * do_monitor will actually go ahead and do it. */
6666 if (!p->owner && my_is_off_hook(p)) {
6667 p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6668 /* Note, my_off_hook will fail if called before the loop disconnect has finished
6669 * (important for FXOKS signaled channels). This is because DAHDI will reject
6670 * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6671 * so we have to wait for that to finish (see comment above).
6672 * do_monitor itself cannot block, so make the blocking usleep call
6673 * here in the channel thread instead.
6674 */
6675 my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6676 } else {
6677 ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6678 }
6679 }
6680 }
6681
6683 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6684
6686 if (p->restartpending) {
6688 }
6689
6690 if (p->destroy) {
6691 destroy_channel(p, 0);
6692 }
6694
6696 return 0;
6697}
6698
6699static int dahdi_answer(struct ast_channel *ast)
6700{
6701 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6702 int res = 0;
6703 int idx;
6704 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6705 ast_mutex_lock(&p->lock);
6706 idx = dahdi_get_index(ast, p, 0);
6707 if (idx < 0)
6708 idx = SUB_REAL;
6709 /* nothing to do if a radio channel */
6710 if ((p->radio || (p->oprmode < 0))) {
6712 return 0;
6713 }
6714
6715 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6716 res = analog_answer(p->sig_pvt, ast);
6718 return res;
6719 }
6720
6721 switch (p->sig) {
6722#if defined(HAVE_PRI)
6724 res = sig_pri_answer(p->sig_pvt, ast);
6725 break;
6726#endif /* defined(HAVE_PRI) */
6727#if defined(HAVE_SS7)
6728 case SIG_SS7:
6729 res = sig_ss7_answer(p->sig_pvt, ast);
6730 break;
6731#endif /* defined(HAVE_SS7) */
6732#ifdef HAVE_OPENR2
6733 case SIG_MFCR2:
6734 if (!p->mfcr2_call_accepted) {
6735 /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6736 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6737 p->mfcr2_answer_pending = 1;
6738 if (p->mfcr2_charge_calls) {
6739 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6740 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6741 } else {
6742 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6743 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6744 }
6745 } else {
6746 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6747 dahdi_r2_answer(p);
6748 }
6749 break;
6750#endif
6751 case 0:
6753 return 0;
6754 default:
6755 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6756 res = -1;
6757 break;
6758 }
6760 return res;
6761}
6762
6764{
6765 int val = 0;
6766
6767 p->ignoredtmf = 1;
6768
6769 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6770
6771 if (!p->hardwaredtmf && p->dsp) {
6772 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6774 }
6775}
6776
6778{
6779 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6780
6781 if (p->channel == CHAN_PSEUDO)
6782 return;
6783
6784 p->ignoredtmf = 0;
6785
6786 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6787
6788 if (!p->hardwaredtmf && p->dsp) {
6791 }
6792}
6793
6794static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
6795{
6796 char *cp;
6797 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6798
6799 /* all supported options require data */
6800 if (!p || !data || (*datalen < 1)) {
6801 errno = EINVAL;
6802 return -1;
6803 }
6804
6805 switch (option) {
6806 case AST_OPTION_TDD:
6807 cp = (char *) data;
6808 if (p->mate) {
6809 *cp = 2;
6810 } else {
6811 *cp = p->tdd ? 1 : 0;
6812 }
6813 break;
6815 cp = (char *) data;
6816 *cp = p->ignoredtmf ? 0 : 1;
6817 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6818 break;
6820 cp = (char *) data;
6821 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6822 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6823 break;
6825#if defined(HAVE_PRI)
6826#if defined(HAVE_PRI_CCSS)
6828 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6829 break;
6830 }
6831#endif /* defined(HAVE_PRI_CCSS) */
6832#endif /* defined(HAVE_PRI) */
6833 return -1;
6834 default:
6835 return -1;
6836 }
6837
6838 errno = 0;
6839
6840 return 0;
6841}
6842
6843static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
6844{
6845 char *cp;
6846 signed char *scp;
6847 int x;
6848 int idx;
6849 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6850 struct oprmode *oprmode;
6851
6852
6853 /* all supported options require data */
6854 if (!p || !data || (datalen < 1)) {
6855 errno = EINVAL;
6856 return -1;
6857 }
6858
6859 switch (option) {
6860 case AST_OPTION_TXGAIN:
6861 scp = (signed char *) data;
6862 idx = dahdi_get_index(chan, p, 0);
6863 if (idx < 0) {
6864 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6865 return -1;
6866 }
6867 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6868 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6869 case AST_OPTION_RXGAIN:
6870 scp = (signed char *) data;
6871 idx = dahdi_get_index(chan, p, 0);
6872 if (idx < 0) {
6873 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6874 return -1;
6875 }
6876 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6877 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6879 if (!p->dsp)
6880 break;
6881 cp = (char *) data;
6882 switch (*cp) {
6883 case 1:
6884 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6885 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6886 break;
6887 case 2:
6888 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6889 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6890 break;
6891 default:
6892 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6893 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6894 break;
6895 }
6896 break;
6897 case AST_OPTION_TDD:
6898 /* turn on or off TDD */
6899 cp = (char *) data;
6900 p->mate = 0;
6901 if (!*cp) { /* turn it off */
6902 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6903 if (p->tdd)
6904 tdd_free(p->tdd);
6905 p->tdd = 0;
6906 break;
6907 }
6908 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6909 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6911 /* otherwise, turn it on */
6912 if (!p->didtdd) { /* if havent done it yet */
6913 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6914 unsigned char *buf;
6915 int size, res, fd, len;
6916 struct pollfd fds[1];
6917
6918 buf = mybuf;
6919 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6920 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6921 len = 40000;
6922 idx = dahdi_get_index(chan, p, 0);
6923 if (idx < 0) {
6924 ast_log(LOG_WARNING, "No index in TDD?\n");
6925 return -1;
6926 }
6927 fd = p->subs[idx].dfd;
6928 while (len) {
6929 if (ast_check_hangup(chan))
6930 return -1;
6931 size = len;
6932 if (size > READ_SIZE)
6933 size = READ_SIZE;
6934 fds[0].fd = fd;
6935 fds[0].events = POLLPRI | POLLOUT;
6936 fds[0].revents = 0;
6937 res = poll(fds, 1, -1);
6938 if (!res) {
6939 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6940 continue;
6941 }
6942 /* if got exception */
6943 if (fds[0].revents & POLLPRI)
6944 return -1;
6945 if (!(fds[0].revents & POLLOUT)) {
6946 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6947 continue;
6948 }
6949 res = write(fd, buf, size);
6950 if (res != size) {
6951 if (res == -1) return -1;
6952 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6953 break;
6954 }
6955 len -= size;
6956 buf += size;
6957 }
6958 p->didtdd = 1; /* set to have done it now */
6959 }
6960 if (*cp == 2) { /* Mate mode */
6961 if (p->tdd)
6962 tdd_free(p->tdd);
6963 p->tdd = 0;
6964 p->mate = 1;
6965 break;
6966 }
6967 if (!p->tdd) { /* if we don't have one yet */
6968 p->tdd = tdd_new(); /* allocate one */
6969 }
6970 break;
6971 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6972 if (!p->dsp)
6973 break;
6974 cp = (char *) data;
6975 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6976 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6978 break;
6979 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6980#if defined(HAVE_PRI)
6982 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6983 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6984 break;
6985 }
6986#endif /* defined(HAVE_PRI) */
6987
6988 cp = (char *) data;
6989 if (!*cp) {
6990 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6991 x = 0;
6993 } else {
6994 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6995 x = 1;
6996 }
6997 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6998 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6999 break;
7000 case AST_OPTION_OPRMODE: /* Operator services mode */
7001 oprmode = (struct oprmode *) data;
7002 /* We don't support operator mode across technologies */
7003 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
7004 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
7006 errno = EINVAL;
7007 return -1;
7008 }
7010 p->oprmode = pp->oprmode = 0;
7011 /* setup peers */
7012 p->oprpeer = pp;
7013 pp->oprpeer = p;
7014 /* setup modes, if any */
7015 if (oprmode->mode)
7016 {
7017 pp->oprmode = oprmode->mode;
7018 p->oprmode = -oprmode->mode;
7019 }
7020 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
7022 break;
7023 case AST_OPTION_ECHOCAN:
7024 cp = (char *) data;
7025 if (*cp) {
7026 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
7027 dahdi_ec_enable(p);
7028 } else {
7029 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
7031 }
7032 break;
7034 cp = (char *) data;
7035 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7036 if (*cp) {
7038 } else {
7040 }
7041 break;
7043 cp = (char *) data;
7044 if (p->dsp) {
7045 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
7046 if (*cp) {
7048 } else {
7049 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7050 }
7052 }
7053 break;
7054 default:
7055 return -1;
7056 }
7057 errno = 0;
7058
7059 return 0;
7060}
7061
7062static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
7063{
7064 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7065 int res = 0;
7066
7067 if (!p) {
7068 /* No private structure! */
7069 *buf = '\0';
7070 return -1;
7071 }
7072
7073 if (!strcasecmp(data, "rxgain")) {
7074 ast_mutex_lock(&p->lock);
7075 snprintf(buf, len, "%f", p->rxgain);
7077 } else if (!strcasecmp(data, "txgain")) {
7078 ast_mutex_lock(&p->lock);
7079 snprintf(buf, len, "%f", p->txgain);
7081 } else if (!strcasecmp(data, "dahdi_channel")) {
7082 ast_mutex_lock(&p->lock);
7083 snprintf(buf, len, "%d", p->channel);
7085 } else if (!strcasecmp(data, "dahdi_span")) {
7086 ast_mutex_lock(&p->lock);
7087 snprintf(buf, len, "%d", p->span);
7089 } else if (!strcasecmp(data, "dahdi_group")) {
7090 ast_mutex_lock(&p->lock);
7091 snprintf(buf, len, "%llu", p->group);
7093 } else if (!strcasecmp(data, "dahdi_type")) {
7094 ast_mutex_lock(&p->lock);
7095 switch (p->sig) {
7096#if defined(HAVE_OPENR2)
7097 case SIG_MFCR2:
7098 ast_copy_string(buf, "mfc/r2", len);
7099 break;
7100#endif /* defined(HAVE_OPENR2) */
7101#if defined(HAVE_PRI)
7103 ast_copy_string(buf, "pri", len);
7104 break;
7105#endif /* defined(HAVE_PRI) */
7106 case 0:
7107 ast_copy_string(buf, "pseudo", len);
7108 break;
7109#if defined(HAVE_SS7)
7110 case SIG_SS7:
7111 ast_copy_string(buf, "ss7", len);
7112 break;
7113#endif /* defined(HAVE_SS7) */
7114 default:
7115 /* The only thing left is analog ports. */
7116 ast_copy_string(buf, "analog", len);
7117 break;
7118 }
7120#if defined(HAVE_PRI)
7121#if defined(HAVE_PRI_REVERSE_CHARGE)
7122 } else if (!strcasecmp(data, "reversecharge")) {
7123 ast_mutex_lock(&p->lock);
7124 switch (p->sig) {
7126 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7127 break;
7128 default:
7129 *buf = '\0';
7130 res = -1;
7131 break;
7132 }
7134#endif
7135#if defined(HAVE_PRI_SETUP_KEYPAD)
7136 } else if (!strcasecmp(data, "keypad_digits")) {
7137 ast_mutex_lock(&p->lock);
7138 switch (p->sig) {
7140 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7141 len);
7142 break;
7143 default:
7144 *buf = '\0';
7145 res = -1;
7146 break;
7147 }
7149#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7150 } else if (!strcasecmp(data, "no_media_path")) {
7151 ast_mutex_lock(&p->lock);
7152 switch (p->sig) {
7154 /*
7155 * TRUE if the call is on hold or is call waiting because
7156 * there is no media path available.
7157 */
7158 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7159 break;
7160 default:
7161 *buf = '\0';
7162 res = -1;
7163 break;
7164 }
7166#endif /* defined(HAVE_PRI) */
7167 } else if (!strcasecmp(data, "dialmode")) {
7168 struct analog_pvt *analog_p;
7169 ast_mutex_lock(&p->lock);
7170 analog_p = p->sig_pvt;
7171 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7172 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7173 switch (analog_p->dialmode) {
7175 ast_copy_string(buf, "both", len);
7176 break;
7178 ast_copy_string(buf, "pulse", len);
7179 break;
7181 ast_copy_string(buf, "dtmf", len);
7182 break;
7184 ast_copy_string(buf, "none", len);
7185 break;
7186 }
7187 } else {
7188 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7189 *buf = '\0';
7190 res = -1;
7191 }
7193 } else {
7194 *buf = '\0';
7195 res = -1;
7196 }
7197
7198 return res;
7199}
7200
7201
7202static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
7203{
7204 int res;
7205 char policy_str[21] = "";
7206
7207 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7208 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7209 return 1;
7210 }
7211 if (*num_buffers < 0) {
7212 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7213 return -1;
7214 }
7215 if (!strcasecmp(policy_str, "full")) {
7216 *policy = DAHDI_POLICY_WHEN_FULL;
7217 } else if (!strcasecmp(policy_str, "immediate")) {
7218 *policy = DAHDI_POLICY_IMMEDIATE;
7219#if defined(HAVE_DAHDI_HALF_FULL)
7220 } else if (!strcasecmp(policy_str, "half")) {
7221 *policy = DAHDI_POLICY_HALF_FULL;
7222#endif
7223 } else {
7224 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7225 return -1;
7226 }
7227
7228 return 0;
7229}
7230
7231static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
7232{
7233 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7234 int res = 0;
7235
7236 if (!p) {
7237 /* No private structure! */
7238 return -1;
7239 }
7240
7241 if (!strcasecmp(data, "buffers")) {
7242 int num_bufs, policy;
7243
7244 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7245 struct dahdi_bufferinfo bi = {
7246 .txbufpolicy = policy,
7247 .rxbufpolicy = policy,
7248 .bufsize = p->bufsize,
7249 .numbufs = num_bufs,
7250 };
7251 int bpres;
7252
7253 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7254 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7255 } else {
7256 p->bufferoverrideinuse = 1;
7257 }
7258 } else {
7259 res = -1;
7260 }
7261 } else if (!strcasecmp(data, "echocan_mode")) {
7262 if (!strcasecmp(value, "on")) {
7263 ast_mutex_lock(&p->lock);
7264 dahdi_ec_enable(p);
7266 } else if (!strcasecmp(value, "off")) {
7267 ast_mutex_lock(&p->lock);
7270#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7271 } else if (!strcasecmp(value, "fax")) {
7272 int blah = 1;
7273
7274 ast_mutex_lock(&p->lock);
7275 if (!p->echocanon) {
7276 dahdi_ec_enable(p);
7277 }
7278 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7279 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7280 }
7282 } else if (!strcasecmp(value, "voice")) {
7283 int blah = 0;
7284
7285 ast_mutex_lock(&p->lock);
7286 if (!p->echocanon) {
7287 dahdi_ec_enable(p);
7288 }
7289 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7290 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7291 }
7293#endif
7294 } else {
7295 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7296 res = -1;
7297 }
7298 } else if (!strcasecmp(data, "dialmode")) {
7299 struct analog_pvt *analog_p;
7300
7301 ast_mutex_lock(&p->lock);
7302 analog_p = p->sig_pvt;
7303 if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7304 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7306 return -1;
7307 }
7308 /* analog pvt is used for pulse dialing, so update both */
7309 if (!strcasecmp(value, "pulse")) {
7310 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7311 } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7312 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7313 } else if (!strcasecmp(value, "none")) {
7314 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7315 } else if (!strcasecmp(value, "both")) {
7316 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7317 } else {
7318 ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7319 res = -1;
7320 }
7322 } else if (!strcasecmp(data, "waitfordialtone")) {
7323 if (ast_strlen_zero(value)) {
7324 ast_log(LOG_WARNING, "waitfordialtone requires a duration in ms\n");
7325 return -1;
7326 }
7327
7328 ast_mutex_lock(&p->lock);
7329 if (!CANPROGRESSDETECT(p)) {
7330 ast_log(LOG_WARNING, "%s only supported on analog trunks\n", data);
7332 return -1;
7333 }
7334 /* Only set the temp waitfordialtone setting, not the permanent one. */
7335 p->waitfordialtonetemp = atoi(value);
7337 } else {
7338 res = -1;
7339 }
7340
7341 return res;
7342}
7343
7344void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
7345{
7346 /* Unlink a specific slave or all slaves/masters from a given master */
7347 int x;
7348 int hasslaves;
7349 if (!master)
7350 return;
7351 if (needlock) {
7352 ast_mutex_lock(&master->lock);
7353 if (slave) {
7354 while (ast_mutex_trylock(&slave->lock)) {
7355 DEADLOCK_AVOIDANCE(&master->lock);
7356 }
7357 }
7358 }
7359 hasslaves = 0;
7360 for (x = 0; x < MAX_SLAVES; x++) {
7361 if (master->slaves[x]) {
7362 if (!slave || (master->slaves[x] == slave)) {
7363 /* Take slave out of the conference */
7364 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7365 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7366 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7367 master->slaves[x]->master = NULL;
7368 master->slaves[x] = NULL;
7369 } else
7370 hasslaves = 1;
7371 }
7372 if (!hasslaves)
7373 master->inconference = 0;
7374 }
7375 if (!slave) {
7376 if (master->master) {
7377 /* Take master out of the conference */
7378 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7379 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7380 hasslaves = 0;
7381 for (x = 0; x < MAX_SLAVES; x++) {
7382 if (master->master->slaves[x] == master)
7383 master->master->slaves[x] = NULL;
7384 else if (master->master->slaves[x])
7385 hasslaves = 1;
7386 }
7387 if (!hasslaves)
7388 master->master->inconference = 0;
7389 }
7390 master->master = NULL;
7391 }
7392 dahdi_conf_update(master);
7393 if (needlock) {
7394 if (slave)
7395 ast_mutex_unlock(&slave->lock);
7396 ast_mutex_unlock(&master->lock);
7397 }
7398}
7399
7400void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
7401{
7402 int x;
7403 if (!slave || !master) {
7404 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7405 return;
7406 }
7407 for (x = 0; x < MAX_SLAVES; x++) {
7408 if (!master->slaves[x]) {
7409 master->slaves[x] = slave;
7410 break;
7411 }
7412 }
7413 if (x >= MAX_SLAVES) {
7414 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7415 master->slaves[MAX_SLAVES - 1] = slave;
7416 }
7417 if (slave->master)
7418 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7419 slave->master = master;
7420
7421 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7422}
7423
7424static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
7425{
7426 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7427 int x;
7428
7429 ast_mutex_lock(&p->lock);
7430
7431 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7432 if (p->owner == oldchan) {
7433 p->owner = newchan;
7434 }
7435 for (x = 0; x < 3; x++) {
7436 if (p->subs[x].owner == oldchan) {
7437 if (!x) {
7439 }
7440 p->subs[x].owner = newchan;
7441 }
7442 }
7443 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7444 analog_fixup(oldchan, newchan, p->sig_pvt);
7445#if defined(HAVE_PRI)
7446 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7447 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7448#endif /* defined(HAVE_PRI) */
7449#if defined(HAVE_SS7)
7450 } else if (p->sig == SIG_SS7) {
7451 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7452#endif /* defined(HAVE_SS7) */
7453 }
7455
7457
7458 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7460 }
7461 return 0;
7462}
7463
7464static int dahdi_ring_phone(struct dahdi_pvt *p)
7465{
7466 int x;
7467 int res;
7468 /* Make sure our transmit state is on hook */
7469 x = 0;
7470 x = DAHDI_ONHOOK;
7471 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7472 do {
7473 x = DAHDI_RING;
7474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7475 if (res) {
7476 switch (errno) {
7477 case EBUSY:
7478 case EINTR:
7479 /* Wait just in case */
7480 usleep(10000);
7481 continue;
7482 case EINPROGRESS:
7483 res = 0;
7484 break;
7485 default:
7486 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7487 res = 0;
7488 }
7489 }
7490 } while (res);
7491 return res;
7492}
7493
7494static void *analog_ss_thread(void *data);
7495
7496/*!
7497 * \internal
7498 * \brief Attempt to transfer 3-way call.
7499 *
7500 * \param p DAHDI private structure.
7501 *
7502 * \note On entry these locks are held: real-call, private, 3-way call.
7503 * \note On exit these locks are held: real-call, private.
7504 *
7505 * \retval 0 on success.
7506 * \retval -1 on error.
7507 */
7508static int attempt_transfer(struct dahdi_pvt *p)
7509{
7510 struct ast_channel *owner_real;
7511 struct ast_channel *owner_3way;
7512 enum ast_transfer_result xfer_res;
7513 int res = 0;
7514
7515 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7516 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7517
7518 ast_verb(3, "TRANSFERRING %s to %s\n",
7519 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7520
7521 ast_channel_unlock(owner_real);
7522 ast_channel_unlock(owner_3way);
7524
7525 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7526 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7528 res = -1;
7529 }
7530
7531 /* Must leave with these locked. */
7532 ast_channel_lock(owner_real);
7533 ast_mutex_lock(&p->lock);
7534
7535 ast_channel_unref(owner_real);
7536 ast_channel_unref(owner_3way);
7537
7538 return res;
7539}
7540
7541static int check_for_conference(struct dahdi_pvt *p)
7542{
7543 struct dahdi_confinfo ci;
7544 /* Fine if we already have a master, etc */
7545 if (p->master || (p->confno > -1))
7546 return 0;
7547 memset(&ci, 0, sizeof(ci));
7548 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7549 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7550 return 0;
7551 }
7552 /* If we have no master and don't have a confno, then
7553 if we're in a conference, it's probably a MeetMe room or
7554 some such, so don't let us 3-way out! */
7555 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7556 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7557 return 1;
7558 }
7559 return 0;
7560}
7561
7562/*! Checks channel for alarms
7563 * \param p a channel to check for alarms.
7564 * \returns the alarms on the span to which the channel belongs, or alarms on
7565 * the channel if no span alarms.
7566 */
7567static int get_alarms(struct dahdi_pvt *p)
7568{
7569 int res;
7570 struct dahdi_spaninfo zi;
7571 struct dahdi_params params;
7572
7573 memset(&zi, 0, sizeof(zi));
7574 zi.spanno = p->span;
7575
7576 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7577 if (zi.alarms != DAHDI_ALARM_NONE)
7578 return zi.alarms;
7579 } else {
7580 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7581 return 0;
7582 }
7583
7584 /* No alarms on the span. Check for channel alarms. */
7585 memset(&params, 0, sizeof(params));
7586 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7587 return params.chan_alarms;
7588
7589 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7590
7591 return DAHDI_ALARM_NONE;
7592}
7593
7594static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
7595{
7596 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7597 struct ast_frame *f = *dest;
7598
7599 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7600 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7601 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7602
7603 if (p->confirmanswer) {
7604 if (f->frametype == AST_FRAME_DTMF_END) {
7605 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7606 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7607 of a DTMF digit */
7610 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7611 p->confirmanswer = 0;
7612 } else {
7613 p->subs[idx].f.frametype = AST_FRAME_NULL;
7614 p->subs[idx].f.subclass.integer = 0;
7615 }
7616 *dest = &p->subs[idx].f;
7617 } else if (p->callwaitcas) {
7618 if (f->frametype == AST_FRAME_DTMF_END) {
7619 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7620 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7621 ast_free(p->cidspill);
7622 p->cidspill = NULL;
7623 send_cwcidspill(p);
7624 }
7625 p->callwaitcas = 0;
7626 }
7627 p->subs[idx].f.frametype = AST_FRAME_NULL;
7628 p->subs[idx].f.subclass.integer = 0;
7629 *dest = &p->subs[idx].f;
7630 } else if (f->subclass.integer == 'f') {
7631 if (f->frametype == AST_FRAME_DTMF_END) {
7632 /* Fax tone -- Handle and return NULL */
7633 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7634 /* If faxbuffers are configured, use them for the fax transmission */
7635 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7636 struct dahdi_bufferinfo bi = {
7637 .txbufpolicy = p->faxbuf_policy,
7638 .bufsize = p->bufsize,
7639 .numbufs = p->faxbuf_no
7640 };
7641 int res;
7642
7643 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7644 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7645 } else {
7646 p->bufferoverrideinuse = 1;
7647 }
7648 }
7649 p->faxhandled = 1;
7650 if (p->dsp) {
7651 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7653 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7654 }
7655 if (strcmp(ast_channel_exten(ast), "fax")) {
7656 const char *target_context = ast_channel_context(ast);
7657
7658 /*
7659 * We need to unlock 'ast' here because ast_exists_extension has the
7660 * potential to start autoservice on the channel. Such action is prone
7661 * to deadlock if the channel is locked.
7662 *
7663 * ast_async_goto() has its own restriction on not holding the
7664 * channel lock.
7665 */
7667 ast_channel_unlock(ast);
7668 if (ast_exists_extension(ast, target_context, "fax", 1,
7669 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7670 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7671 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7672 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7673 if (ast_async_goto(ast, target_context, "fax", 1))
7674 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7675 } else {
7676 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7677 }
7678 ast_channel_lock(ast);
7679 ast_mutex_lock(&p->lock);
7680 } else {
7681 ast_debug(1, "Already in a fax extension, not redirecting\n");
7682 }
7683 } else {
7684 ast_debug(1, "Fax already handled\n");
7685 }
7686 dahdi_confmute(p, 0);
7687 }
7688 p->subs[idx].f.frametype = AST_FRAME_NULL;
7689 p->subs[idx].f.subclass.integer = 0;
7690 *dest = &p->subs[idx].f;
7691 }
7692}
7693
7694static void publish_span_alarm(int span, const char *alarm_txt)
7695{
7696 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7697
7698 body = ast_json_pack("{s: i, s: s}",
7699 "Span", span,
7700 "Alarm", alarm_txt);
7701 if (!body) {
7702 return;
7703 }
7704
7705 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7706}
7707
7708static void publish_channel_alarm(int channel, const char *alarm_txt)
7709{
7710 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7711 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7712 if (!dahdi_chan) {
7713 return;
7714 }
7715
7716 ast_str_set(&dahdi_chan, 0, "%d", channel);
7717 body = ast_json_pack("{s: s, s: s}",
7718 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7719 "Alarm", alarm_txt);
7720 if (!body) {
7721 return;
7722 }
7723
7725}
7726
7727static void handle_alarms(struct dahdi_pvt *p, int alms)
7728{
7729 const char *alarm_str;
7730
7731#if defined(HAVE_PRI)
7733 return;
7734 }
7735#endif /* defined(HAVE_PRI) */
7736
7737 alarm_str = alarm2str(alms);
7739 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7740 publish_channel_alarm(p->channel, alarm_str);
7741 }
7742
7744 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7745 publish_span_alarm(p->span, alarm_str);
7746 }
7747}
7748
7749static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
7750{
7751 int res, x;
7752 int idx, mysig;
7753 char *c;
7754 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7755 pthread_t threadid;
7756 struct ast_channel *chan;
7757 struct ast_frame *f;
7758
7759 idx = dahdi_get_index(ast, p, 0);
7760 if (idx < 0) {
7761 return &ast_null_frame;
7762 }
7763 mysig = p->sig;
7764 if (p->outsigmod > -1)
7765 mysig = p->outsigmod;
7766 p->subs[idx].f.frametype = AST_FRAME_NULL;
7767 p->subs[idx].f.subclass.integer = 0;
7768 p->subs[idx].f.datalen = 0;
7769 p->subs[idx].f.samples = 0;
7770 p->subs[idx].f.mallocd = 0;
7771 p->subs[idx].f.offset = 0;
7772 p->subs[idx].f.src = "dahdi_handle_event";
7773 p->subs[idx].f.data.ptr = NULL;
7774 f = &p->subs[idx].f;
7775
7776 if (p->fake_event) {
7777 res = p->fake_event;
7778 p->fake_event = 0;
7779 } else
7780 res = dahdi_get_event(p->subs[idx].dfd);
7781
7782 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7783
7784 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7785 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7786 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7787#if defined(HAVE_PRI)
7789 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7790 && p->pri
7791 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7792 /* absorb event */
7793 } else
7794#endif /* defined(HAVE_PRI) */
7795 {
7796 /* Unmute conference */
7797 dahdi_confmute(p, 0);
7799 p->subs[idx].f.subclass.integer = res & 0xff;
7800 dahdi_handle_dtmf(ast, idx, &f);
7801 }
7802 return f;
7803 }
7804
7805 if (res & DAHDI_EVENT_DTMFDOWN) {
7806 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7807#if defined(HAVE_PRI)
7809 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7810 && p->pri
7811 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7812 /* absorb event */
7813 } else
7814#endif /* defined(HAVE_PRI) */
7815 {
7816 /* Mute conference */
7817 dahdi_confmute(p, 1);
7819 p->subs[idx].f.subclass.integer = res & 0xff;
7820 dahdi_handle_dtmf(ast, idx, &f);
7821 }
7822 return &p->subs[idx].f;
7823 }
7824
7825 switch (res) {
7826 case DAHDI_EVENT_EC_DISABLED:
7827 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7828 p->echocanon = 0;
7829 break;
7830#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7831 case DAHDI_EVENT_TX_CED_DETECTED:
7832 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7833 break;
7834 case DAHDI_EVENT_RX_CED_DETECTED:
7835 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7836 break;
7837 case DAHDI_EVENT_EC_NLP_DISABLED:
7838 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7839 break;
7840 case DAHDI_EVENT_EC_NLP_ENABLED:
7841 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7842 break;
7843#endif
7844 case DAHDI_EVENT_BITSCHANGED:
7845#ifdef HAVE_OPENR2
7846 if (p->sig != SIG_MFCR2) {
7847 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7848 } else {
7849 ast_debug(1, "bits changed in chan %d\n", p->channel);
7850 openr2_chan_handle_cas(p->r2chan);
7851 }
7852#else
7853 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7854#endif
7855 break;
7856 case DAHDI_EVENT_PULSE_START:
7857 /* Stop tone if there's a pulse start and the PBX isn't started */
7858 if (!ast_channel_pbx(ast))
7859 tone_zone_play_tone(p->subs[idx].dfd, -1);
7860 break;
7861 case DAHDI_EVENT_DIALCOMPLETE:
7862 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7863#if defined(HAVE_PRI)
7865 if (p->inalarm) {
7866 break;
7867 }
7868 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7869 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7870 ast_channel_name(ast), strerror(errno));
7871 return NULL;
7872 }
7873 if (x) {
7874 /* Still dialing in DAHDI driver */
7875 break;
7876 }
7877 /*
7878 * The ast channel is locked and the private may be locked more
7879 * than once.
7880 */
7882 break;
7883 }
7884#endif /* defined(HAVE_PRI) */
7885#ifdef HAVE_OPENR2
7886 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7887 /* we don't need to do anything for this event for R2 signaling
7888 if the call is being setup */
7889 break;
7890 }
7891#endif
7892 if (p->inalarm) break;
7893 if ((p->radio || (p->oprmode < 0))) break;
7894 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7895 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7896 return NULL;
7897 }
7898 if (!x) { /* if not still dialing in driver */
7899 dahdi_ec_enable(p);
7900 if (p->echobreak) {
7901 dahdi_train_ec(p);
7902 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7903 p->dop.op = DAHDI_DIAL_OP_REPLACE;
7904 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7905 p->echobreak = 0;
7906 } else {
7907 p->dialing = 0;
7908 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7909 /* if thru with dialing after offhook */
7914 break;
7915 } else { /* if to state wait for offhook to dial rest */
7916 /* we now wait for off hook */
7918 }
7919 }
7921 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7922 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7923 } else if (p->confirmanswer || (!p->dialednone
7924 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7925 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7926 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7927 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7928 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7929 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7930 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7931 || (mysig == SIG_SF_FEATB)))) {
7933 } else if (!p->answeronpolarityswitch) {
7937 /* If aops=0 and hops=1, this is necessary */
7939 } else {
7940 /* Start clean, so we can catch the change to REV polarity when party answers */
7942 }
7943 }
7944 }
7945 }
7946 break;
7947 case DAHDI_EVENT_ALARM:
7948 switch (p->sig) {
7949#if defined(HAVE_PRI)
7952 break;
7953#endif /* defined(HAVE_PRI) */
7954#if defined(HAVE_SS7)
7955 case SIG_SS7:
7957 break;
7958#endif /* defined(HAVE_SS7) */
7959 default:
7960 p->inalarm = 1;
7961 break;
7962 }
7963 res = get_alarms(p);
7964 handle_alarms(p, res);
7965#ifdef HAVE_PRI
7966 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7967 /* fall through intentionally */
7968 } else {
7969 break;
7970 }
7971#endif
7972#if defined(HAVE_SS7)
7973 if (p->sig == SIG_SS7)
7974 break;
7975#endif /* defined(HAVE_SS7) */
7976#ifdef HAVE_OPENR2
7977 if (p->sig == SIG_MFCR2)
7978 break;
7979#endif
7980 case DAHDI_EVENT_ONHOOK:
7981 if (p->radio) {
7984 break;
7985 }
7986 if (p->oprmode < 0)
7987 {
7988 if (p->oprmode != -1) { /* Operator flash recall */
7989 ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
7990 break;
7991 }
7992 /* Otherwise, immediate recall */
7993 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7994 {
7995 /* Make sure it starts ringing */
7996 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7997 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7999 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8000 ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8001 }
8002 break;
8003 }
8004 switch (p->sig) {
8005 case SIG_FXOLS:
8006 case SIG_FXOGS:
8007 case SIG_FXOKS:
8008 /* Check for some special conditions regarding call waiting */
8009 if (idx == SUB_REAL) {
8010 /* The normal line was hung up */
8011 if (p->subs[SUB_CALLWAIT].owner) {
8012 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
8014 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
8016#if 0
8017 p->subs[idx].needanswer = 0;
8018 p->subs[idx].needringing = 0;
8019#endif
8020 p->callwaitingrepeat = 0;
8021 p->cidcwexpire = 0;
8022 p->cid_suppress_expire = 0;
8023 p->owner = NULL;
8024 /* Don't start streaming audio yet if the incoming call isn't up yet */
8026 p->dialing = 1;
8028 } else if (p->subs[SUB_THREEWAY].owner) {
8029 unsigned int mssinceflash;
8030 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
8031 the private structure -- not especially easy or clean */
8033 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
8034 DLA_UNLOCK(&p->lock);
8036 /* We can grab ast and p in that order, without worry. We should make sure
8037 nothing seriously bad has happened though like some sort of bizarre double
8038 masquerade! */
8039 DLA_LOCK(&p->lock);
8040 if (p->owner != ast) {
8041 ast_log(LOG_WARNING, "This isn't good...\n");
8042 return NULL;
8043 }
8044 }
8045 if (!p->subs[SUB_THREEWAY].owner) {
8046 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
8047 return NULL;
8048 }
8049 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
8050 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
8051 if (mssinceflash < MIN_MS_SINCE_FLASH) {
8052 /* It hasn't been long enough since the last flashook. This is probably a bounce on
8053 hanging up. Hangup both channels now */
8054 if (p->subs[SUB_THREEWAY].owner)
8057 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
8059 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
8060 if (p->transfer) {
8061 /* In any case this isn't a threeway call anymore */
8062 p->subs[SUB_REAL].inthreeway = 0;
8064 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
8065 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
8067 /* Swap subs and dis-own channel */
8069 p->owner = NULL;
8070 /* Ring the phone */
8072 } else if (!attempt_transfer(p)) {
8073 /*
8074 * Transfer successful. Don't actually hang up at this point.
8075 * Let our channel legs of the calls die off as the transfer
8076 * percolates through the core.
8077 */
8078 break;
8079 }
8080 } else {
8082 if (p->subs[SUB_THREEWAY].owner)
8084 }
8085 } else {
8087 /* Swap subs and dis-own channel */
8089 p->owner = NULL;
8090 /* Ring the phone */
8092 }
8093 }
8094 } else {
8095 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8096 }
8097 /* Fall through */
8098 default:
8100 return NULL;
8101 }
8102 break;
8103 case DAHDI_EVENT_RINGOFFHOOK:
8104 if (p->inalarm) break;
8105 if (p->oprmode < 0)
8106 {
8107 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8108 {
8109 /* Make sure it stops ringing */
8110 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8111 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8113 ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8114 }
8115 break;
8116 }
8117 if (p->radio)
8118 {
8121 break;
8122 }
8123 /* for E911, its supposed to wait for offhook then dial
8124 the second half of the dial string */
8125 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8126 c = strchr(p->dialdest, '/');
8127 if (c)
8128 c++;
8129 else
8130 c = p->dialdest;
8131
8132 if (*c) {
8133 int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8134 if (numchars >= sizeof(p->dop.dialstr)) {
8135 ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8136 }
8137 } else {
8138 ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8139 }
8140
8141 if (strlen(p->dop.dialstr) > 4) {
8142 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8143 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8144 p->echorest[sizeof(p->echorest) - 1] = '\0';
8145 p->echobreak = 1;
8146 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8147 } else
8148 p->echobreak = 0;
8149 if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8150 x = DAHDI_ONHOOK;
8151 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8152 return NULL;
8153 }
8154 p->dialing = 1;
8155 return &p->subs[idx].f;
8156 }
8157 switch (p->sig) {
8158 case SIG_FXOLS:
8159 case SIG_FXOGS:
8160 case SIG_FXOKS:
8161 switch (ast_channel_state(ast)) {
8162 case AST_STATE_RINGING:
8163 dahdi_ec_enable(p);
8164 dahdi_train_ec(p);
8167 /* Make sure it stops ringing */
8168 p->subs[SUB_REAL].needringing = 0;
8169 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8170 ast_debug(1, "channel %d answered\n", p->channel);
8171
8172 /* Cancel any running CallerID spill */
8173 ast_free(p->cidspill);
8174 p->cidspill = NULL;
8176
8177 p->dialing = 0;
8178 p->callwaitcas = 0;
8179 if (p->confirmanswer) {
8180 /* Ignore answer if "confirm answer" is enabled */
8181 p->subs[idx].f.frametype = AST_FRAME_NULL;
8182 p->subs[idx].f.subclass.integer = 0;
8183 } else if (!ast_strlen_zero(p->dop.dialstr)) {
8184 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8185 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8186 if (res) {
8187 p->dop.dialstr[0] = '\0';
8188 return NULL;
8189 } else {
8190 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8191 p->subs[idx].f.frametype = AST_FRAME_NULL;
8192 p->subs[idx].f.subclass.integer = 0;
8193 p->dialing = 1;
8194 }
8195 p->dop.dialstr[0] = '\0';
8197 } else
8199 return &p->subs[idx].f;
8200 case AST_STATE_DOWN:
8202 ast_channel_rings_set(ast, 1);
8205 ast_debug(1, "channel %d picked up\n", p->channel);
8206 return &p->subs[idx].f;
8207 case AST_STATE_UP:
8208 /* Make sure it stops ringing */
8209 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8210 /* Okay -- probably call waiting*/
8212 p->subs[idx].needunhold = 1;
8213 break;
8214 case AST_STATE_RESERVED:
8215 /* Start up dialtone */
8216 if (has_voicemail(p))
8217 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8218 else
8219 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8220 break;
8221 default:
8222 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8223 }
8224 break;
8225 case SIG_FXSLS:
8226 case SIG_FXSGS:
8227 case SIG_FXSKS:
8228 if (ast_channel_state(ast) == AST_STATE_RING) {
8229 p->ringt = p->ringt_base;
8230 }
8231
8232 /* If we get a ring then we cannot be in
8233 * reversed polarity. So we reset to idle */
8234 ast_debug(1, "Setting IDLE polarity due "
8235 "to ring. Old polarity was %d\n",
8236 p->polarity);
8238
8239 /* Fall through */
8240 case SIG_EM:
8241 case SIG_EM_E1:
8242 case SIG_EMWINK:
8243 case SIG_FEATD:
8244 case SIG_FEATDMF:
8245 case SIG_FEATDMF_TA:
8246 case SIG_E911:
8247 case SIG_FGC_CAMA:
8248 case SIG_FGC_CAMAMF:
8249 case SIG_FEATB:
8250 case SIG_SF:
8251 case SIG_SFWINK:
8252 case SIG_SF_FEATD:
8253 case SIG_SF_FEATDMF:
8254 case SIG_SF_FEATB:
8258 ast_debug(1, "Ring detected\n");
8261 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8262 ast_debug(1, "Line answered\n");
8263 if (p->confirmanswer) {
8264 p->subs[idx].f.frametype = AST_FRAME_NULL;
8265 p->subs[idx].f.subclass.integer = 0;
8266 } else {
8270 }
8271 } else if (ast_channel_state(ast) != AST_STATE_RING)
8272 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8273 break;
8274 default:
8275 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8276 }
8277 break;
8278 case DAHDI_EVENT_RINGBEGIN:
8279 switch (p->sig) {
8280 case SIG_FXSLS:
8281 case SIG_FXSGS:
8282 case SIG_FXSKS:
8283 if (ast_channel_state(ast) == AST_STATE_RING) {
8284 p->ringt = p->ringt_base;
8285 }
8286 break;
8287 }
8288 break;
8289 case DAHDI_EVENT_RINGERON:
8290 break;
8291 case DAHDI_EVENT_NOALARM:
8292 switch (p->sig) {
8293#if defined(HAVE_PRI)
8296 break;
8297#endif /* defined(HAVE_PRI) */
8298#if defined(HAVE_SS7)
8299 case SIG_SS7:
8301 break;
8302#endif /* defined(HAVE_SS7) */
8303 default:
8304 p->inalarm = 0;
8305 break;
8306 }
8308 break;
8309 case DAHDI_EVENT_WINKFLASH:
8310 if (p->inalarm) break;
8311 if (p->radio) break;
8312 if (p->oprmode < 0) break;
8313 if (p->oprmode > 1)
8314 {
8315 struct dahdi_params par;
8316
8317 memset(&par, 0, sizeof(par));
8318 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8319 {
8320 if (!par.rxisoffhook)
8321 {
8322 /* Make sure it stops ringing */
8323 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8324 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8325 save_conference(p);
8326 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8327 ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8328 }
8329 }
8330 break;
8331 }
8332 /* Remember last time we got a flash-hook */
8333 p->flashtime = ast_tvnow();
8334 switch (mysig) {
8335 case SIG_FXOLS:
8336 case SIG_FXOGS:
8337 case SIG_FXOKS:
8338 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8340
8341 /* Cancel any running CallerID spill */
8342 ast_free(p->cidspill);
8343 p->cidspill = NULL;
8345 p->callwaitcas = 0;
8346
8347 if (idx != SUB_REAL) {
8348 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8349 goto winkflashdone;
8350 }
8351
8352 if (p->subs[SUB_CALLWAIT].owner) {
8353 /* Swap to call-wait */
8355 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8356 p->owner = p->subs[SUB_REAL].owner;
8357 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8360 p->subs[SUB_REAL].needanswer = 1;
8361 }
8362 p->callwaitingrepeat = 0;
8363 p->cidcwexpire = 0;
8364 p->cid_suppress_expire = 0;
8365 /* Start music on hold if appropriate */
8366 if (!p->subs[SUB_CALLWAIT].inthreeway) {
8368 }
8369 p->subs[SUB_CALLWAIT].needhold = 1;
8371 p->subs[SUB_REAL].needunhold = 1;
8372 } else if (!p->subs[SUB_THREEWAY].owner) {
8373 if (!p->threewaycalling) {
8374 /* Just send a flash if no 3-way calling */
8375 p->subs[SUB_REAL].needflash = 1;
8376 goto winkflashdone;
8377 } else if (!check_for_conference(p)) {
8378 ast_callid callid = 0;
8379 int callid_created;
8380 char cid_num[256];
8381 char cid_name[256];
8382
8383 cid_num[0] = 0;
8384 cid_name[0] = 0;
8385 if (p->dahditrcallerid && p->owner) {
8389 sizeof(cid_num));
8390 }
8394 sizeof(cid_name));
8395 }
8396 }
8397 /* XXX This section needs much more error checking!!! XXX */
8398 /* Start a 3-way call if feasible */
8399 if (!((ast_channel_pbx(ast)) ||
8400 (ast_channel_state(ast) == AST_STATE_UP) ||
8401 (ast_channel_state(ast) == AST_STATE_RING))) {
8402 ast_debug(1, "Flash when call not up or ringing\n");
8403 goto winkflashdone;
8404 }
8405 if (alloc_sub(p, SUB_THREEWAY)) {
8406 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8407 goto winkflashdone;
8408 }
8409 callid_created = ast_callid_threadstorage_auto(&callid);
8410 /*
8411 * Make new channel
8412 *
8413 * We cannot hold the p or ast locks while creating a new
8414 * channel.
8415 */
8417 ast_channel_unlock(ast);
8418 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8419 ast_channel_lock(ast);
8420 ast_mutex_lock(&p->lock);
8421 if (p->dahditrcallerid) {
8422 if (!p->origcid_num)
8424 if (!p->origcid_name)
8426 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8427 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8428 }
8429 /* Swap things around between the three-way and real call */
8431 /* Disable echo canceller for better dialing */
8433 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8434 if (res)
8435 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8436 p->owner = chan;
8437 if (!chan) {
8438 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8439 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8440 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8441 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8442 dahdi_ec_enable(p);
8443 ast_hangup(chan);
8444 } else {
8445 ast_verb(3, "Started three way call on channel %d\n", p->channel);
8446
8447 /* Start music on hold */
8449 p->subs[SUB_THREEWAY].needhold = 1;
8450 }
8451 ast_callid_threadstorage_auto_clean(callid, callid_created);
8452 }
8453 } else {
8454 /* Already have a 3 way call */
8455 if (p->subs[SUB_THREEWAY].inthreeway) {
8456 /* Call is already up, drop the last person */
8457 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8458 /* If the primary call isn't answered yet, use it */
8460 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8462 p->owner = p->subs[SUB_REAL].owner;
8463 }
8464 /* Drop the last call and stop the conference */
8465 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8467 p->subs[SUB_REAL].inthreeway = 0;
8469 } else {
8470 /* Lets see what we're up to */
8471 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8473 int otherindex = SUB_THREEWAY;
8474
8475 ast_verb(3, "Building conference call with %s and %s\n",
8478 /* Put them in the threeway, and flip */
8480 p->subs[SUB_REAL].inthreeway = 1;
8481 if (ast_channel_state(ast) == AST_STATE_UP) {
8483 otherindex = SUB_REAL;
8484 }
8485 if (p->subs[otherindex].owner) {
8486 ast_queue_unhold(p->subs[otherindex].owner);
8487 }
8488 p->subs[otherindex].needunhold = 1;
8489 p->owner = p->subs[SUB_REAL].owner;
8490 } else {
8491 ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8494 p->owner = p->subs[SUB_REAL].owner;
8495 if (p->subs[SUB_REAL].owner) {
8497 }
8498 p->subs[SUB_REAL].needunhold = 1;
8499 dahdi_ec_enable(p);
8500 }
8501 }
8502 }
8503winkflashdone:
8505 break;
8506 case SIG_EM:
8507 case SIG_EM_E1:
8508 case SIG_FEATD:
8509 case SIG_SF:
8510 case SIG_SFWINK:
8511 case SIG_SF_FEATD:
8512 case SIG_FXSLS:
8513 case SIG_FXSGS:
8514 if (p->dialing)
8515 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8516 else
8517 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8518 break;
8519 case SIG_FEATDMF_TA:
8520 switch (p->whichwink) {
8521 case 0:
8522 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8525 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8529 break;
8530 case 1:
8531 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8532 break;
8533 case 2:
8534 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8535 return NULL;
8536 }
8537 p->whichwink++;
8538 /* Fall through */
8539 case SIG_FEATDMF:
8540 case SIG_E911:
8541 case SIG_FGC_CAMAMF:
8542 case SIG_FGC_CAMA:
8543 case SIG_FEATB:
8544 case SIG_SF_FEATDMF:
8545 case SIG_SF_FEATB:
8546 case SIG_EMWINK:
8547 /* FGD MF and EMWINK *Must* wait for wink */
8548 if (!ast_strlen_zero(p->dop.dialstr)) {
8549 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8550 if (res) {
8551 p->dop.dialstr[0] = '\0';
8552 return NULL;
8553 } else
8554 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8555 }
8556 p->dop.dialstr[0] = '\0';
8557 break;
8558 default:
8559 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8560 }
8561 break;
8562 case DAHDI_EVENT_HOOKCOMPLETE:
8563 if (p->inalarm) break;
8564 if ((p->radio || (p->oprmode < 0))) break;
8565 if (p->waitingfordt.tv_sec) break;
8566 switch (mysig) {
8567 case SIG_FXSLS: /* only interesting for FXS */
8568 case SIG_FXSGS:
8569 case SIG_FXSKS:
8570 case SIG_EM:
8571 case SIG_EM_E1:
8572 case SIG_EMWINK:
8573 case SIG_FEATD:
8574 case SIG_SF:
8575 case SIG_SFWINK:
8576 case SIG_SF_FEATD:
8577 if (!ast_strlen_zero(p->dop.dialstr)) {
8578 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8579 if (res) {
8580 p->dop.dialstr[0] = '\0';
8581 return NULL;
8582 } else
8583 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8584 }
8585 p->dop.dialstr[0] = '\0';
8586 p->dop.op = DAHDI_DIAL_OP_REPLACE;
8587 break;
8588 case SIG_FEATDMF:
8589 case SIG_FEATDMF_TA:
8590 case SIG_E911:
8591 case SIG_FGC_CAMA:
8592 case SIG_FGC_CAMAMF:
8593 case SIG_FEATB:
8594 case SIG_SF_FEATDMF:
8595 case SIG_SF_FEATB:
8596 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8597 break;
8598 default:
8599 break;
8600 }
8601 break;
8602 case DAHDI_EVENT_POLARITY:
8603 /*
8604 * If we get a Polarity Switch event, check to see
8605 * if we should change the polarity state and
8606 * mark the channel as UP or if this is an indication
8607 * of remote end disconnect.
8608 */
8609 if (p->polarity == POLARITY_IDLE) {
8611 if (p->answeronpolarityswitch &&
8614 ast_debug(1, "Answering on polarity switch!\n");
8616 if (p->hanguponpolarityswitch) {
8618 }
8619 } else
8620 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8621 }
8622 /* Removed else statement from here as it was preventing hangups from ever happening*/
8623 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8624 if (p->hanguponpolarityswitch &&
8625 (p->polarityonanswerdelay > 0) &&
8626 (p->polarity == POLARITY_REV) &&
8628 /* Added log_debug information below to provide a better indication of what is going on */
8629 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8630
8632 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8635 } else
8636 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8637
8638 } else {
8640 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8641 }
8642 /* Added more log_debug information below to provide a better indication of what is going on */
8643 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8644 break;
8645 default:
8646 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8647 }
8648 return &p->subs[idx].f;
8649}
8650
8651static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
8652{
8653 int res;
8654 int idx;
8655 struct ast_frame *f;
8656 int usedindex = -1;
8657 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8658
8659 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8660 idx = SUB_REAL;
8661 }
8662
8663 p->subs[idx].f.frametype = AST_FRAME_NULL;
8664 p->subs[idx].f.datalen = 0;
8665 p->subs[idx].f.samples = 0;
8666 p->subs[idx].f.mallocd = 0;
8667 p->subs[idx].f.offset = 0;
8668 p->subs[idx].f.subclass.integer = 0;
8669 p->subs[idx].f.delivery = ast_tv(0,0);
8670 p->subs[idx].f.src = "dahdi_exception";
8671 p->subs[idx].f.data.ptr = NULL;
8672
8673
8674 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8675 /* If nobody owns us, absorb the event appropriately, otherwise
8676 we loop indefinitely. This occurs when, during call waiting, the
8677 other end hangs up our channel so that it no longer exists, but we
8678 have neither FLASH'd nor ONHOOK'd to signify our desire to
8679 change to the other channel. */
8680 if (p->fake_event) {
8681 res = p->fake_event;
8682 p->fake_event = 0;
8683 } else
8684 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8685 /* Switch to real if there is one and this isn't something really silly... */
8686 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8687 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8688 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8689 p->owner = p->subs[SUB_REAL].owner;
8690 if (p->owner) {
8692 }
8693 p->subs[SUB_REAL].needunhold = 1;
8694 }
8695 switch (res) {
8696 case DAHDI_EVENT_ONHOOK:
8698 if (p->owner) {
8699 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8701 p->callwaitingrepeat = 0;
8702 p->cidcwexpire = 0;
8703 p->cid_suppress_expire = 0;
8704 } else
8705 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8707 break;
8708 case DAHDI_EVENT_RINGOFFHOOK:
8709 dahdi_ec_enable(p);
8710 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8711 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8712 p->subs[SUB_REAL].needanswer = 1;
8713 p->dialing = 0;
8714 }
8715 break;
8716 case DAHDI_EVENT_HOOKCOMPLETE:
8717 case DAHDI_EVENT_RINGERON:
8718 case DAHDI_EVENT_RINGEROFF:
8719 /* Do nothing */
8720 break;
8721 case DAHDI_EVENT_WINKFLASH:
8722 p->flashtime = ast_tvnow();
8723 if (p->owner) {
8724 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8726 /* Answer if necessary */
8727 usedindex = dahdi_get_index(p->owner, p, 0);
8728 if (usedindex > -1) {
8729 p->subs[usedindex].needanswer = 1;
8730 }
8732 }
8733 p->callwaitingrepeat = 0;
8734 p->cidcwexpire = 0;
8735 p->cid_suppress_expire = 0;
8737 p->subs[SUB_REAL].needunhold = 1;
8738 } else
8739 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8741 break;
8742 default:
8743 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8744 }
8745 f = &p->subs[idx].f;
8746 return f;
8747 }
8748 if (!(p->radio || (p->oprmode < 0)))
8749 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8750 /* If it's not us, return NULL immediately */
8751 if (ast != p->owner) {
8752 if (p->owner) {
8753 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8754 }
8755 f = &p->subs[idx].f;
8756 return f;
8757 }
8758
8759 f = dahdi_handle_event(ast);
8760 if (!f) {
8761 const char *name = ast_strdupa(ast_channel_name(ast));
8762
8763 /* Tell the CDR this DAHDI device hung up */
8765 ast_channel_unlock(ast);
8766 ast_set_hangupsource(ast, name, 0);
8767 ast_channel_lock(ast);
8768 ast_mutex_lock(&p->lock);
8769 }
8770 return f;
8771}
8772
8773static struct ast_frame *dahdi_exception(struct ast_channel *ast)
8774{
8775 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8776 struct ast_frame *f;
8777 ast_mutex_lock(&p->lock);
8778 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8779 struct analog_pvt *analog_p = p->sig_pvt;
8780 f = analog_exception(analog_p, ast);
8781 } else {
8782 f = __dahdi_exception(ast);
8783 }
8785 return f;
8786}
8787
8788static struct ast_frame *dahdi_read(struct ast_channel *ast)
8789{
8790 struct dahdi_pvt *p;
8791 int res;
8792 int idx;
8793 void *readbuf;
8794 struct ast_frame *f;
8795
8796 /*
8797 * For analog channels, we must do deadlock avoidance because
8798 * analog ports can have more than one Asterisk channel using
8799 * the same private structure.
8800 */
8801 p = ast_channel_tech_pvt(ast);
8802 while (ast_mutex_trylock(&p->lock)) {
8804
8805 /*
8806 * Check to see if the channel is still associated with the same
8807 * private structure. While the Asterisk channel was unlocked
8808 * the following events may have occured:
8809 *
8810 * 1) A masquerade may have associated the channel with another
8811 * technology or private structure.
8812 *
8813 * 2) For PRI calls, call signaling could change the channel
8814 * association to another B channel (private structure).
8815 */
8816 if (ast_channel_tech_pvt(ast) != p) {
8817 /* The channel is no longer associated. Quit gracefully. */
8818 return &ast_null_frame;
8819 }
8820 }
8821
8822 idx = dahdi_get_index(ast, p, 0);
8823
8824 /* Hang up if we don't really exist */
8825 if (idx < 0) {
8826 ast_log(LOG_WARNING, "We don't exist?\n");
8828 return NULL;
8829 }
8830
8831 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8833 return NULL;
8834 }
8835
8836 p->subs[idx].f.frametype = AST_FRAME_NULL;
8837 p->subs[idx].f.datalen = 0;
8838 p->subs[idx].f.samples = 0;
8839 p->subs[idx].f.mallocd = 0;
8840 p->subs[idx].f.offset = 0;
8841 p->subs[idx].f.subclass.integer = 0;
8842 p->subs[idx].f.delivery = ast_tv(0,0);
8843 p->subs[idx].f.src = "dahdi_read";
8844 p->subs[idx].f.data.ptr = NULL;
8845
8846 /* make sure it sends initial key state as first frame */
8847 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8848 {
8849 struct dahdi_params ps;
8850
8851 memset(&ps, 0, sizeof(ps));
8852 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8854 return NULL;
8855 }
8856 p->firstradio = 1;
8858 if (ps.rxisoffhook)
8859 {
8861 }
8862 else
8863 {
8865 }
8867 return &p->subs[idx].f;
8868 }
8869 if (p->ringt > 0) {
8870 if (!(--p->ringt)) {
8872 return NULL;
8873 }
8874 }
8875
8876#ifdef HAVE_OPENR2
8877 if (p->mfcr2) {
8878 openr2_chan_process_event(p->r2chan);
8879 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8881 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8882 * now enqueue a progress frame to bridge the media up */
8883 if (p->mfcr2_call_accepted &&
8884 !p->mfcr2_progress_sent &&
8886 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8887 ast_queue_frame(p->owner, &fr);
8888 p->mfcr2_progress_sent = 1;
8889 }
8890 }
8891 }
8892#endif
8893
8894 if (p->subs[idx].needringing) {
8895 /* Send ringing frame if requested */
8896 p->subs[idx].needringing = 0;
8901 return &p->subs[idx].f;
8902 }
8903
8904 if (p->subs[idx].needbusy) {
8905 /* Send busy frame if requested */
8906 p->subs[idx].needbusy = 0;
8910 return &p->subs[idx].f;
8911 }
8912
8913 if (p->subs[idx].needcongestion) {
8914 /* Send congestion frame if requested */
8915 p->subs[idx].needcongestion = 0;
8919 return &p->subs[idx].f;
8920 }
8921
8922 if (p->subs[idx].needanswer) {
8923 /* Send answer frame if requested */
8924 p->subs[idx].needanswer = 0;
8928 return &p->subs[idx].f;
8929 }
8930#ifdef HAVE_OPENR2
8931 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8932 /* openr2 took care of reading and handling any event
8933 (needanswer, needbusy etc), if we continue we will read()
8934 twice, lets just return a null frame. This should only
8935 happen when openr2 is dialing out */
8937 return &ast_null_frame;
8938 }
8939#endif
8940
8941 if (p->subs[idx].needflash) {
8942 /* Send answer frame if requested */
8943 p->subs[idx].needflash = 0;
8947 return &p->subs[idx].f;
8948 }
8949
8950 if (p->subs[idx].needhold) {
8951 /* Send answer frame if requested */
8952 p->subs[idx].needhold = 0;
8956 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8957 return &p->subs[idx].f;
8958 }
8959
8960 if (p->subs[idx].needunhold) {
8961 /* Send answer frame if requested */
8962 p->subs[idx].needunhold = 0;
8966 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8967 return &p->subs[idx].f;
8968 }
8969
8970 /*
8971 * If we have a fake_event, fake an exception to handle it only
8972 * if this channel owns the private.
8973 */
8974 if (p->fake_event && p->owner == ast) {
8975 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8976 struct analog_pvt *analog_p = p->sig_pvt;
8977
8978 f = analog_exception(analog_p, ast);
8979 } else {
8980 f = __dahdi_exception(ast);
8981 }
8983 return f;
8984 }
8985
8987 if (!p->subs[idx].linear) {
8988 p->subs[idx].linear = 1;
8989 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8990 if (res)
8991 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8992 }
8993 } else {
8994 if (p->subs[idx].linear) {
8995 p->subs[idx].linear = 0;
8996 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8997 if (res)
8998 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8999 }
9000 }
9001 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
9002 CHECK_BLOCKING(ast);
9003 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9005 /* Check for hangup */
9006 if (res < 0) {
9007 f = NULL;
9008 if (res == -1) {
9009 if (errno == EAGAIN) {
9010 /* Return "NULL" frame if there is nobody there */
9012 return &p->subs[idx].f;
9013 } else if (errno == ELAST) {
9014 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9015 struct analog_pvt *analog_p = p->sig_pvt;
9016 f = analog_exception(analog_p, ast);
9017 } else {
9018 f = __dahdi_exception(ast);
9019 }
9020 } else
9021 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
9022 }
9024 return f;
9025 }
9026 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
9027 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9028 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9029 struct analog_pvt *analog_p = p->sig_pvt;
9030 f = analog_exception(analog_p, ast);
9031 } else {
9032 f = __dahdi_exception(ast);
9033 }
9035 return f;
9036 }
9037 if (p->tdd) { /* if in TDD mode, see if we receive that */
9038 int c;
9039
9040 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
9041 if (c < 0) {
9042 ast_debug(1,"tdd_feed failed\n");
9044 return NULL;
9045 }
9046 if (c) { /* if a char to return */
9047 p->subs[idx].f.subclass.integer = 0;
9048 p->subs[idx].f.frametype = AST_FRAME_TEXT;
9049 p->subs[idx].f.mallocd = 0;
9050 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9051 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
9052 p->subs[idx].f.datalen = 1;
9053 *((char *) p->subs[idx].f.data.ptr) = c;
9055 return &p->subs[idx].f;
9056 }
9057 }
9058 if (idx == SUB_REAL) {
9059 /* Ensure the CW timers decrement only on a single subchannel */
9060 if (p->cidcwexpire) {
9061 if (!--p->cidcwexpire) {
9062 /* Expired CID/CW */
9063 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
9065 }
9066 }
9067 if (p->cid_suppress_expire) {
9069 }
9070 if (p->callwaitingrepeat) {
9071 if (!--p->callwaitingrepeat) {
9072 /* Expired, Repeat callwaiting tone */
9073 ++p->callwaitrings;
9074 dahdi_callwait(ast);
9075 }
9076 }
9077 }
9078 if (p->subs[idx].linear) {
9079 p->subs[idx].f.datalen = READ_SIZE * 2;
9080 } else
9081 p->subs[idx].f.datalen = READ_SIZE;
9082
9083 /* Handle CallerID Transmission */
9084 if ((p->owner == ast) && p->cidspill) {
9085 send_callerid(p);
9086 }
9087
9088 p->subs[idx].f.frametype = AST_FRAME_VOICE;
9090 p->subs[idx].f.samples = READ_SIZE;
9091 p->subs[idx].f.mallocd = 0;
9092 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9093 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9094#if 0
9095 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9096#endif
9097 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9098 (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9099 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9100 ) {
9101 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9102 don't send anything */
9103 p->subs[idx].f.frametype = AST_FRAME_NULL;
9104 p->subs[idx].f.subclass.integer = 0;
9105 p->subs[idx].f.samples = 0;
9106 p->subs[idx].f.mallocd = 0;
9107 p->subs[idx].f.offset = 0;
9108 p->subs[idx].f.data.ptr = NULL;
9109 p->subs[idx].f.datalen= 0;
9110 }
9111 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9112 /* Perform busy detection etc on the dahdi line */
9113 int mute;
9114
9116 && p->faxdetect_timeout
9118 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9120 ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9121 ast_channel_name(ast));
9122 }
9123
9124 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9125
9126 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9127 mute = ast_dsp_was_muted(p->dsp);
9128 if (p->muting != mute) {
9129 p->muting = mute;
9130 dahdi_confmute(p, mute);
9131 }
9132
9133 if (f) {
9135 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9137 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9139 }
9140 }
9142 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9143 /*
9144 * Treat this as a "hangup" instead of a "busy" on the
9145 * assumption that a busy means the incoming call went away.
9146 */
9147 ast_frfree(f);
9148 f = NULL;
9149 }
9150 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9152 /* Dialtone detected on inbound call; hangup the channel */
9153 ast_frfree(f);
9154 f = NULL;
9155 }
9156 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9157 || f->frametype == AST_FRAME_DTMF_END) {
9158#ifdef HAVE_PRI
9160 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9161 && p->pri
9162 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9163 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9164 /* Don't accept in-band DTMF when in overlap dial mode */
9165 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9166 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9167 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9168
9170 f->subclass.integer = 0;
9171 }
9172#endif
9173 /* DSP clears us of being pulse */
9174 p->pulsedial = 0;
9175 } else if (p->waitingfordt.tv_sec) {
9177 p->waitingfordt.tv_sec = 0;
9178 ast_log(LOG_NOTICE, "Never saw dialtone on channel %d\n", p->channel);
9179 ast_frfree(f);
9180 f = NULL;
9181 } else if (f->frametype == AST_FRAME_VOICE) {
9183 f->subclass.integer = 0;
9185 p->waitingfordt.tv_sec = 0;
9186 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9188 ast_debug(1, "Got 10 samples of dialtone!\n");
9189 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9190 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9191 if (res) {
9192 p->dop.dialstr[0] = '\0';
9194 ast_frfree(f);
9195 return NULL;
9196 } else {
9197 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9198 p->dialing = 1;
9199 p->dop.dialstr[0] = '\0';
9200 p->dop.op = DAHDI_DIAL_OP_REPLACE;
9202 }
9203 }
9204 }
9205 }
9206 }
9207 }
9208 } else
9209 f = &p->subs[idx].f;
9210
9211 if (f) {
9212 switch (f->frametype) {
9214 case AST_FRAME_DTMF_END:
9215 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9216 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9217 } else {
9218 dahdi_handle_dtmf(ast, idx, &f);
9219 }
9221 if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9222 ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9223 }
9225 f->subclass.integer = 0;
9226 }
9227 break;
9228 case AST_FRAME_VOICE:
9229 if (p->cidspill || p->cid_suppress_expire) {
9230 /* We are/were sending a caller id spill. Suppress any echo. */
9231 p->subs[idx].f.frametype = AST_FRAME_NULL;
9232 p->subs[idx].f.subclass.integer = 0;
9233 p->subs[idx].f.samples = 0;
9234 p->subs[idx].f.mallocd = 0;
9235 p->subs[idx].f.offset = 0;
9236 p->subs[idx].f.data.ptr = NULL;
9237 p->subs[idx].f.datalen= 0;
9238 }
9239 break;
9240 default:
9241 break;
9242 }
9243 }
9244
9246 return f;
9247}
9248
9249static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
9250{
9251 int sent=0;
9252 int size;
9253 int res;
9254 int fd;
9255 fd = p->subs[idx].dfd;
9256 while (len) {
9257 size = len;
9258 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9259 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9260 res = write(fd, buf, size);
9261 if (res != size) {
9262 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9263 return sent;
9264 }
9265 len -= size;
9266 buf += size;
9267 }
9268 return sent;
9269}
9270
9271static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
9272{
9273 struct dahdi_pvt *p;
9274 int res;
9275 int idx;
9276
9277 /* Write a frame of (presumably voice) data */
9278 if (frame->frametype != AST_FRAME_VOICE) {
9279 if (frame->frametype != AST_FRAME_IMAGE) {
9280 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9281 frame->frametype);
9282 }
9283 return 0;
9284 }
9285
9286 /* Return if it's not valid data */
9287 if (!frame->data.ptr || !frame->datalen) {
9288 return 0;
9289 }
9290
9291 p = ast_channel_tech_pvt(ast);
9292 ast_mutex_lock(&p->lock);
9293
9294 idx = dahdi_get_index(ast, p, 0);
9295 if (idx < 0) {
9297 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9298 return -1;
9299 }
9300
9301 if (p->dialing) {
9303 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9304 ast_channel_name(ast));
9305 return 0;
9306 }
9307 if (!p->owner) {
9309 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9310 ast_channel_name(ast));
9311 return 0;
9312 }
9313 if (p->cidspill) {
9315 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9316 ast_channel_name(ast));
9317 return 0;
9318 }
9319
9321 if (!p->subs[idx].linear) {
9322 p->subs[idx].linear = 1;
9323 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9324 if (res)
9325 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9326 }
9327 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9330 /* x-law already */
9331 if (p->subs[idx].linear) {
9332 p->subs[idx].linear = 0;
9333 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9334 if (res)
9335 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9336 }
9337 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9338 } else {
9340 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9342 return -1;
9343 }
9345 if (res < 0) {
9346 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9347 return -1;
9348 }
9349 return 0;
9350}
9351
9352static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
9353{
9354 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9355 int res=-1;
9356 int idx;
9357 int func = DAHDI_FLASH;
9358
9359 ast_mutex_lock(&p->lock);
9360 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9361 switch (p->sig) {
9362#if defined(HAVE_PRI)
9364 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9366 return res;
9367#endif /* defined(HAVE_PRI) */
9368#if defined(HAVE_SS7)
9369 case SIG_SS7:
9370 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9372 return res;
9373#endif /* defined(HAVE_SS7) */
9374 default:
9375 break;
9376 }
9377#ifdef HAVE_OPENR2
9378 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9380 /* if this is an R2 call and the call is not yet accepted, we don't want the
9381 tone indications to mess up with the MF tones */
9382 return 0;
9383 }
9384#endif
9385 idx = dahdi_get_index(chan, p, 0);
9386 if (idx == SUB_REAL) {
9387 switch (condition) {
9388 case AST_CONTROL_BUSY:
9389 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9390 break;
9392 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9393
9394 if (ast_channel_state(chan) != AST_STATE_UP) {
9395 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9396 ((p->sig != SIG_FXSKS) &&
9397 (p->sig != SIG_FXSLS) &&
9398 (p->sig != SIG_FXSGS)))
9400 }
9401 break;
9403 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9404 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9405 res = 0;
9406 break;
9408 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9409 /* don't continue in ast_indicate */
9410 res = 0;
9411 break;
9413 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9414 /* don't continue in ast_indicate */
9415 res = 0;
9416 break;
9418 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9419 switch (ast_channel_hangupcause(chan)) {
9422 case 0:/* Cause has not been set. */
9423 /* Supply a more appropriate cause. */
9425 break;
9426 default:
9427 break;
9428 }
9429 break;
9430 case AST_CONTROL_HOLD:
9431 ast_moh_start(chan, data, p->mohinterpret);
9432 break;
9433 case AST_CONTROL_UNHOLD:
9434 ast_moh_stop(chan);
9435 break;
9437 if (p->radio)
9438 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9439 res = 0;
9440 break;
9442 if (p->radio)
9443 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9444 res = 0;
9445 break;
9446 case AST_CONTROL_FLASH:
9447 /* flash hookswitch */
9448 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9449 /* Clear out the dial buffer */
9450 p->dop.dialstr[0] = '\0';
9451 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9452 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9453 ast_channel_name(chan), strerror(errno));
9454 } else
9455 res = 0;
9456 } else
9457 res = 0;
9458 break;
9460 res = 0;
9461 break;
9462 case -1:
9463 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9464 break;
9465 }
9466 } else {
9467 res = 0;
9468 }
9470 return res;
9471}
9472
9473#if defined(HAVE_PRI)
9474static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9475#else
9476static struct ast_str *create_channel_name(struct dahdi_pvt *i)
9477#endif /* defined(HAVE_PRI) */
9478{
9479 struct ast_str *chan_name;
9480 int x, y;
9481
9482 /* Create the new channel name tail. */
9483 if (!(chan_name = ast_str_create(32))) {
9484 return NULL;
9485 }
9486 if (i->channel == CHAN_PSEUDO) {
9487 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9488#if defined(HAVE_PRI)
9489 } else if (i->pri) {
9490 ast_mutex_lock(&i->pri->lock);
9491 y = ++i->pri->new_chan_seq;
9492 if (is_outgoing) {
9493 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9494 address[0] = '\0';
9495 } else if (ast_strlen_zero(i->cid_subaddr)) {
9496 /* Put in caller-id number only since there is no subaddress. */
9497 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9498 } else {
9499 /* Put in caller-id number and subaddress. */
9500 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9501 i->cid_subaddr, (unsigned)y);
9502 }
9503 ast_mutex_unlock(&i->pri->lock);
9504#endif /* defined(HAVE_PRI) */
9505 } else {
9506 y = 1;
9507 do {
9508 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9509 for (x = 0; x < 3; ++x) {
9510 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9511 ast_channel_name(i->subs[x].owner) + 6)) {
9512 break;
9513 }
9514 }
9515 ++y;
9516 } while (x < 3);
9517 }
9518 return chan_name;
9519}
9520
9521static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
9522{
9523 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9524
9526
9527 return new_channel;
9528}
9529
9530static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
9531{
9532 struct ast_channel *tmp;
9533 struct ast_format_cap *caps;
9534 struct ast_format *deflaw;
9535 int x;
9536 int features;
9537 struct ast_str *chan_name;
9538 struct ast_variable *v;
9539 char *dashptr;
9540 char device_name[AST_CHANNEL_NAME];
9541
9542 if (i->subs[idx].owner) {
9543 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9544 return NULL;
9545 }
9546
9547#if defined(HAVE_PRI)
9548 /*
9549 * The dnid has been stuffed with the called-number[:subaddress]
9550 * by dahdi_request() for outgoing calls.
9551 */
9552 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9553#else
9554 chan_name = create_channel_name(i);
9555#endif /* defined(HAVE_PRI) */
9556 if (!chan_name) {
9557 return NULL;
9558 }
9559
9561 if (!caps) {
9562 ast_free(chan_name);
9563 return NULL;
9564 }
9565
9566 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
9567 ast_free(chan_name);
9568 if (!tmp) {
9569 ao2_ref(caps, -1);
9570 return NULL;
9571 }
9572
9574
9575 if (callid) {
9576 ast_channel_callid_set(tmp, callid);
9577 }
9578
9580#if defined(HAVE_PRI)
9581 if (i->pri) {
9583 }
9584#endif /* defined(HAVE_PRI) */
9586 if (law) {
9587 i->law = law;
9588 if (law == DAHDI_LAW_ALAW) {
9589 deflaw = ast_format_alaw;
9590 } else {
9591 deflaw = ast_format_ulaw;
9592 }
9593 } else {
9594 switch (i->sig) {
9596 /* Make sure companding law is known. */
9597 i->law = (i->law_default == DAHDI_LAW_ALAW)
9598 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9599 break;
9600 default:
9601 i->law = i->law_default;
9602 break;
9603 }
9604 if (i->law_default == DAHDI_LAW_ALAW) {
9605 deflaw = ast_format_alaw;
9606 } else {
9607 deflaw = ast_format_ulaw;
9608 }
9609 }
9610 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9611 ast_format_cap_append(caps, deflaw, 0);
9613 ao2_ref(caps, -1);
9614 /* Start out assuming ulaw since it's smaller :) */
9619 i->subs[idx].linear = 0;
9620 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9621 features = 0;
9622 if (idx == SUB_REAL) {
9623 if (i->busydetect && CANBUSYDETECT(i))
9624 features |= DSP_FEATURE_BUSY_DETECT;
9626 features |= DSP_FEATURE_CALL_PROGRESS;
9628 features |= DSP_FEATURE_WAITDIALTONE;
9629 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9631 features |= DSP_FEATURE_FAX_DETECT;
9632 }
9633 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9634 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9635 i->hardwaredtmf = 0;
9636 features |= DSP_FEATURE_DIGIT_DETECT;
9637 } else if (NEED_MFDETECT(i)) {
9638 i->hardwaredtmf = 1;
9639 features |= DSP_FEATURE_DIGIT_DETECT;
9640 }
9641 }
9642 if (features) {
9643 if (i->dsp) {
9644 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9645 } else {
9646 if (i->channel != CHAN_PSEUDO)
9647 i->dsp = ast_dsp_new();
9648 else
9649 i->dsp = NULL;
9650 if (i->dsp) {
9651 i->dsp_features = features;
9652#if defined(HAVE_PRI) || defined(HAVE_SS7)
9653 /* We cannot do progress detection until receive PROGRESS message */
9654 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9655 /* Remember requested DSP features, don't treat
9656 talking as ANSWER */
9657 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9658 features = 0;
9659 }
9660#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9661 ast_dsp_set_features(i->dsp, features);
9665 if (i->busydetect && CANBUSYDETECT(i)) {
9668 }
9669 }
9670 }
9671 }
9672
9674
9675 if (state == AST_STATE_RING)
9678 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9679 /* Only FXO signalled stuff can be picked up */
9684 }
9685 if (!ast_strlen_zero(i->parkinglot))
9686 ast_channel_parkinglot_set(tmp, i->parkinglot);
9687 if (!ast_strlen_zero(i->language))
9688 ast_channel_language_set(tmp, i->language);
9689 if (!i->owner)
9690 i->owner = tmp;
9692 ast_channel_accountcode_set(tmp, i->accountcode);
9693 if (i->amaflags)
9695 i->subs[idx].owner = tmp;
9697 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9698 ast_channel_call_forward_set(tmp, i->call_forward);
9699 }
9700 /* If we've been told "no ADSI" then enforce it */
9701 if (!i->adsi)
9703 if (!ast_strlen_zero(i->exten))
9705 if (!ast_strlen_zero(i->rdnis)) {
9708 }
9709 if (!ast_strlen_zero(i->dnid)) {
9711 }
9712
9713 /* Don't use ast_set_callerid() here because it will
9714 * generate a needless NewCallerID event */
9715#if defined(HAVE_PRI) || defined(HAVE_SS7)
9716 if (!ast_strlen_zero(i->cid_ani)) {
9719 } else if (!ast_strlen_zero(i->cid_num)) {
9722 }
9723#else
9724 if (!ast_strlen_zero(i->cid_num)) {
9727 }
9728#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9734 /* clear the fake event in case we posted one before we had ast_channel */
9735 i->fake_event = 0;
9736 /* Assure there is no confmute on this channel */
9737 dahdi_confmute(i, 0);
9738 i->muting = 0;
9739 /* Configure the new channel jb */
9741
9742 /* Set initial device state */
9743 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9744 dashptr = strrchr(device_name, '-');
9745 if (dashptr) {
9746 *dashptr = '\0';
9747 }
9750
9751 for (v = i->vars ; v ; v = v->next)
9753
9755
9757
9759
9761 if (startpbx) {
9762#ifdef HAVE_OPENR2
9763 if (i->mfcr2call) {
9764 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9765 }
9766#endif
9767 if (ast_pbx_start(tmp)) {
9768 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9769 ast_hangup(tmp);
9770 return NULL;
9771 }
9772 }
9773 return tmp;
9774}
9775
9776
9777static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
9778{
9779 char c;
9780
9781 *str = 0; /* start with empty output buffer */
9782 for (;;)
9783 {
9784 /* Wait for the first digit (up to specified ms). */
9785 c = ast_waitfordigit(chan, ms);
9786 /* if timeout, hangup or error, return as such */
9787 if (c < 1)
9788 return c;
9789 *str++ = c;
9790 *str = 0;
9791 if (strchr(term, c))
9792 return 1;
9793 }
9794}
9795
9796static int dahdi_wink(struct dahdi_pvt *p, int idx)
9797{
9798 int j;
9799 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9800 for (;;)
9801 {
9802 /* set bits of interest */
9803 j = DAHDI_IOMUX_SIGEVENT;
9804 /* wait for some happening */
9805 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9806 /* exit loop if we have it */
9807 if (j & DAHDI_IOMUX_SIGEVENT) break;
9808 }
9809 /* get the event info */
9810 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9811 return 0;
9812}
9813
9814static void publish_dnd_state(int channel, const char *status)
9815{
9816 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9817 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9818 if (!dahdichan) {
9819 return;
9820 }
9821
9822 ast_str_set(&dahdichan, 0, "%d", channel);
9823
9824 body = ast_json_pack("{s: s, s: s}",
9825 "DAHDIChannel", ast_str_buffer(dahdichan),
9826 "Status", status);
9827 if (!body) {
9828 return;
9829 }
9830
9832}
9833
9834/*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
9835 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
9836 * \param flag on 1 to enable, 0 to disable, -1 return dnd value
9837 *
9838 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
9839 * DAHDI channel). Use this to enable or disable it.
9840 *
9841 * \bug the use of the word "channel" for those dahdichans is really confusing.
9842 */
9843static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
9844{
9845 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9846 return analog_dnd(dahdichan->sig_pvt, flag);
9847 }
9848
9849 if (flag == -1) {
9850 return dahdichan->dnd;
9851 }
9852
9853 /* Do not disturb */
9854 dahdichan->dnd = flag;
9855 ast_verb(3, "%s DND on channel %d\n",
9856 flag? "Enabled" : "Disabled",
9857 dahdichan->channel);
9858 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9859 return 0;
9860}
9861
9862static int canmatch_featurecode(const char *pickupexten, const char *exten)
9863{
9864 int extlen = strlen(exten);
9865
9866 if (!extlen) {
9867 return 1;
9868 }
9869
9870 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9871 return 1;
9872 }
9873 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9874 if (exten[0] == '*' && extlen < 3) {
9875 if (extlen == 1) {
9876 return 1;
9877 }
9878 /* "*0" should be processed before it gets here */
9879 switch (exten[1]) {
9880 case '6':
9881 case '7':
9882 case '8':
9883 return 1;
9884 }
9885 }
9886 return 0;
9887}
9888
9889static void *analog_ss_thread(void *data)
9890{
9891 struct ast_channel *chan = data;
9892 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9893 char exten[AST_MAX_EXTENSION] = "";
9894 char exten2[AST_MAX_EXTENSION] = "";
9895 unsigned char buf[256];
9896 char dtmfcid[300];
9897 char dtmfbuf[300];
9898 struct callerid_state *cs = NULL;
9899 char *name = NULL, *number = NULL;
9900 int distMatches;
9901 int curRingData[3];
9902 int receivedRingT;
9903 int counter1;
9904 int counter;
9905 int samples = 0;
9906 struct ast_smdi_md_message *smdi_msg = NULL;
9907 int flags = 0;
9908 int i;
9909 int timeout;
9910 int getforward = 0;
9911 char *s1, *s2;
9912 int len = 0;
9913 int res;
9914 int idx;
9915 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9916 const char *pickupexten;
9917
9921 /* in the bizarre case where the channel has become a zombie before we
9922 even get started here, abort safely
9923 */
9924 if (!p) {
9925 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9926 ast_hangup(chan);
9927 goto quit;
9928 }
9929 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9930 idx = dahdi_get_index(chan, p, 1);
9931 if (idx < 0) {
9932 ast_log(LOG_WARNING, "Huh?\n");
9933 ast_hangup(chan);
9934 goto quit;
9935 }
9936
9937 ast_channel_lock(chan);
9938 pickup_cfg = ast_get_chan_features_pickup_config(chan);
9939 if (!pickup_cfg) {
9940 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9941 pickupexten = "";
9942 } else {
9943 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9944 }
9945 ast_channel_unlock(chan);
9946
9947 if (p->dsp)
9949 switch (p->sig) {
9950 case SIG_FEATD:
9951 case SIG_FEATDMF:
9952 case SIG_FEATDMF_TA:
9953 case SIG_E911:
9954 case SIG_FGC_CAMAMF:
9955 case SIG_FEATB:
9956 case SIG_EMWINK:
9957 case SIG_SF_FEATD:
9958 case SIG_SF_FEATDMF:
9959 case SIG_SF_FEATB:
9960 case SIG_SFWINK:
9961 if (dahdi_wink(p, idx))
9962 goto quit;
9963 /* Fall through */
9964 case SIG_EM:
9965 case SIG_EM_E1:
9966 case SIG_SF:
9967 case SIG_FGC_CAMA:
9968 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9969 if (p->dsp)
9971 /* set digit mode appropriately */
9972 if (p->dsp) {
9973 if (NEED_MFDETECT(p))
9975 else
9977 }
9978 memset(dtmfbuf, 0, sizeof(dtmfbuf));
9979 /* Wait for the first digit only if immediate=no */
9980 if (!p->immediate)
9981 /* Wait for the first digit (up to 5 seconds). */
9982 res = ast_waitfordigit(chan, 5000);
9983 else
9984 res = 0;
9985 if (res > 0) {
9986 /* save first char */
9987 dtmfbuf[0] = res;
9988 switch (p->sig) {
9989 case SIG_FEATD:
9990 case SIG_SF_FEATD:
9991 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9992 if (res > 0)
9993 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9994 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9995 break;
9996 case SIG_FEATDMF_TA:
9997 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9998 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9999 if (dahdi_wink(p, idx)) goto quit;
10000 dtmfbuf[0] = 0;
10001 /* Wait for the first digit (up to 5 seconds). */
10002 res = ast_waitfordigit(chan, 5000);
10003 if (res <= 0) break;
10004 dtmfbuf[0] = res;
10005 /* fall through intentionally */
10006 case SIG_FEATDMF:
10007 case SIG_E911:
10008 case SIG_FGC_CAMAMF:
10009 case SIG_SF_FEATDMF:
10010 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10011 /* if international caca, do it again to get real ANO */
10012 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10013 {
10014 if (dahdi_wink(p, idx)) goto quit;
10015 dtmfbuf[0] = 0;
10016 /* Wait for the first digit (up to 5 seconds). */
10017 res = ast_waitfordigit(chan, 5000);
10018 if (res <= 0) break;
10019 dtmfbuf[0] = res;
10020 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10021 }
10022 if (res > 0) {
10023 /* if E911, take off hook */
10024 if (p->sig == SIG_E911)
10025 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10026 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10027 }
10028 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10029 break;
10030 case SIG_FEATB:
10031 case SIG_SF_FEATB:
10032 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10033 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10034 break;
10035 case SIG_EMWINK:
10036 /* if we received a '*', we are actually receiving Feature Group D
10037 dial syntax, so use that mode; otherwise, fall through to normal
10038 mode
10039 */
10040 if (res == '*') {
10041 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10042 if (res > 0)
10043 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10044 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10045 break;
10046 }
10047 default:
10048 /* If we got the first digit, get the rest */
10049 len = 1;
10050 dtmfbuf[len] = '\0';
10051 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10052 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10053 timeout = p->matchdigit_timeout;
10054 } else {
10055 timeout = p->interdigit_timeout;
10056 }
10057 res = ast_waitfordigit(chan, timeout);
10058 if (res < 0) {
10059 ast_debug(1, "waitfordigit returned < 0...\n");
10060 ast_hangup(chan);
10061 goto quit;
10062 } else if (res) {
10063 dtmfbuf[len++] = res;
10064 dtmfbuf[len] = '\0';
10065 } else {
10066 break;
10067 }
10068 }
10069 break;
10070 }
10071 }
10072 if (res == -1) {
10073 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10074 ast_hangup(chan);
10075 goto quit;
10076 } else if (res < 0) {
10077 ast_debug(1, "Got hung up before digits finished\n");
10078 ast_hangup(chan);
10079 goto quit;
10080 }
10081
10082 if (p->sig == SIG_FGC_CAMA) {
10083 char anibuf[100];
10084
10085 if (ast_safe_sleep(chan,1000) == -1) {
10086 ast_hangup(chan);
10087 goto quit;
10088 }
10089 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10091 res = my_getsigstr(chan, anibuf, "#", 10000);
10092 if ((res > 0) && (strlen(anibuf) > 2)) {
10093 if (anibuf[strlen(anibuf) - 1] == '#')
10094 anibuf[strlen(anibuf) - 1] = 0;
10095 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10096 }
10098 }
10099
10100 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10101 if (ast_strlen_zero(exten))
10102 ast_copy_string(exten, "s", sizeof(exten));
10103 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10104 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10105 if (exten[0] == '*') {
10106 char *stringp=NULL;
10107 ast_copy_string(exten2, exten, sizeof(exten2));
10108 /* Parse out extension and callerid */
10109 stringp=exten2 +1;
10110 s1 = strsep(&stringp, "*");
10111 s2 = strsep(&stringp, "*");
10112 if (s2) {
10113 if (!ast_strlen_zero(p->cid_num))
10114 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10115 else
10116 ast_set_callerid(chan, s1, NULL, s1);
10117 ast_copy_string(exten, s2, sizeof(exten));
10118 } else
10119 ast_copy_string(exten, s1, sizeof(exten));
10120 } else if (p->sig == SIG_FEATD)
10121 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10122 }
10123 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10124 if (exten[0] == '*') {
10125 char *stringp=NULL;
10126 ast_copy_string(exten2, exten, sizeof(exten2));
10127 /* Parse out extension and callerid */
10128 stringp=exten2 +1;
10129 s1 = strsep(&stringp, "#");
10130 s2 = strsep(&stringp, "#");
10131 if (s2) {
10132 if (!ast_strlen_zero(p->cid_num))
10133 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10134 else
10135 if (*(s1 + 2))
10136 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10137 ast_copy_string(exten, s2 + 1, sizeof(exten));
10138 } else
10139 ast_copy_string(exten, s1 + 2, sizeof(exten));
10140 } else
10141 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10142 }
10143 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10144 if (exten[0] == '*') {
10145 char *stringp=NULL;
10146 ast_copy_string(exten2, exten, sizeof(exten2));
10147 /* Parse out extension and callerid */
10148 stringp=exten2 +1;
10149 s1 = strsep(&stringp, "#");
10150 s2 = strsep(&stringp, "#");
10151 if (s2 && (*(s2 + 1) == '0')) {
10152 if (*(s2 + 2))
10153 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10154 }
10155 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10156 else ast_copy_string(exten, "911", sizeof(exten));
10157 } else
10158 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10159 }
10160 if (p->sig == SIG_FEATB) {
10161 if (exten[0] == '*') {
10162 char *stringp=NULL;
10163 ast_copy_string(exten2, exten, sizeof(exten2));
10164 /* Parse out extension and callerid */
10165 stringp=exten2 +1;
10166 s1 = strsep(&stringp, "#");
10167 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10168 } else
10169 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10170 }
10171 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10172 dahdi_wink(p, idx);
10173 /* some switches require a minimum guard time between
10174 the last FGD wink and something that answers
10175 immediately. This ensures it */
10176 if (ast_safe_sleep(chan, 100)) {
10177 ast_hangup(chan);
10178 goto quit;
10179 }
10180 }
10181 dahdi_ec_enable(p);
10182 if (NEED_MFDETECT(p)) {
10183 if (p->dsp) {
10184 if (!p->hardwaredtmf)
10186 else {
10187 ast_dsp_free(p->dsp);
10188 p->dsp = NULL;
10189 }
10190 }
10191 }
10192
10193 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10194 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10195 ast_channel_exten_set(chan, exten);
10196 if (p->dsp) ast_dsp_digitreset(p->dsp);
10197 res = ast_pbx_run(chan);
10198 if (res) {
10199 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10200 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10201 }
10202 goto quit;
10203 } else {
10204 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10205 sleep(2);
10206 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10207 if (res < 0)
10208 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10209 else
10210 sleep(1);
10211 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10212 if (res >= 0)
10213 ast_waitstream(chan, "");
10214 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10215 ast_hangup(chan);
10216 goto quit;
10217 }
10218 break;
10219 case SIG_FXOLS:
10220 case SIG_FXOGS:
10221 case SIG_FXOKS:
10222 /* Read the first digit */
10223 timeout = p->firstdigit_timeout;
10224 /* If starting a threeway call, never timeout on the first digit so someone
10225 can use flash-hook as a "hold" feature */
10226 if (p->subs[SUB_THREEWAY].owner)
10227 timeout = INT_MAX;
10228 while (len < AST_MAX_EXTENSION-1) {
10229 int is_exten_parking = 0;
10230
10231 /* Read digit unless it's supposed to be immediate, in which case the
10232 only answer is 's' */
10233 if (p->immediate)
10234 res = 's';
10235 else
10236 res = ast_waitfordigit(chan, timeout);
10237 timeout = 0;
10238 if (res < 0) {
10239 ast_debug(1, "waitfordigit returned < 0...\n");
10240 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10241 ast_hangup(chan);
10242 goto quit;
10243 } else if (res) {
10244 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10245 exten[len++]=res;
10246 exten[len] = '\0';
10247 }
10248 if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10249 tone_zone_play_tone(p->subs[idx].dfd, -1);
10250 } else {
10251 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10252 }
10254 is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10255 }
10256 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10257 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10258 if (getforward) {
10259 /* Record this as the forwarding extension */
10260 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10261 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10262 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10263 if (res)
10264 break;
10265 usleep(500000);
10266 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10267 sleep(1);
10268 memset(exten, 0, sizeof(exten));
10269 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10270 len = 0;
10271 getforward = 0;
10272 } else {
10273 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10274 ast_channel_lock(chan);
10275 ast_channel_exten_set(chan, exten);
10276 if (!ast_strlen_zero(p->cid_num)) {
10277 if (!p->hidecallerid)
10278 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10279 else
10280 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10281 }
10282 if (!ast_strlen_zero(p->cid_name)) {
10283 if (!p->hidecallerid)
10284 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10285 }
10287 ast_channel_unlock(chan);
10288 dahdi_ec_enable(p);
10289 res = ast_pbx_run(chan);
10290 if (res) {
10291 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10292 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10293 }
10294 goto quit;
10295 }
10296 } else {
10297 /* It's a match, but they just typed a digit, and there is an ambiguous match,
10298 so just set the timeout to matchdigit_timeout and wait some more */
10299 timeout = p->matchdigit_timeout;
10300 }
10301 } else if (res == 0) {
10302 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10303 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10304 dahdi_wait_event(p->subs[idx].dfd);
10305 ast_hangup(chan);
10306 goto quit;
10307 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10308 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10309 /* Disable call waiting if enabled */
10310 p->callwaiting = 0;
10311 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10312 if (res) {
10313 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10314 ast_channel_name(chan), strerror(errno));
10315 }
10316 len = 0;
10317 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10318 memset(exten, 0, sizeof(exten));
10319 timeout = p->firstdigit_timeout;
10320
10321 } else if (!strcmp(exten, pickupexten)) {
10322 /* Scan all channels and see if there are any
10323 * ringing channels that have call groups
10324 * that equal this channels pickup group
10325 */
10326 if (idx == SUB_REAL) {
10327 /* Switch us from Third call to Call Wait */
10328 if (p->subs[SUB_THREEWAY].owner) {
10329 /* If you make a threeway call and the *8# a call, it should actually
10330 look like a callwait */
10334 }
10335 dahdi_ec_enable(p);
10336 if (ast_pickup_call(chan)) {
10337 ast_debug(1, "No call pickup possible...\n");
10338 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10339 dahdi_wait_event(p->subs[idx].dfd);
10340 }
10341 ast_hangup(chan);
10342 goto quit;
10343 } else {
10344 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10345 ast_hangup(chan);
10346 goto quit;
10347 }
10348
10349 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10350 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10351 /* Disable Caller*ID if enabled */
10352 p->hidecallerid = 1;
10357 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10358 if (res) {
10359 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10360 ast_channel_name(chan), strerror(errno));
10361 }
10362 len = 0;
10363 memset(exten, 0, sizeof(exten));
10364 timeout = p->firstdigit_timeout;
10365 } else if (p->callreturn && !strcmp(exten, "*69")) {
10366 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10367 break;
10368 } else if (!strcmp(exten, "*78")) {
10369 dahdi_dnd(p, 1);
10370 /* Do not disturb */
10371 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372 getforward = 0;
10373 memset(exten, 0, sizeof(exten));
10374 len = 0;
10375 } else if (!strcmp(exten, "*79")) {
10376 dahdi_dnd(p, 0);
10377 /* Do not disturb */
10378 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10379 getforward = 0;
10380 memset(exten, 0, sizeof(exten));
10381 len = 0;
10382 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10383 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384 getforward = 1;
10385 memset(exten, 0, sizeof(exten));
10386 len = 0;
10387 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10388 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10389 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10390 memset(p->call_forward, 0, sizeof(p->call_forward));
10391 getforward = 0;
10392 memset(exten, 0, sizeof(exten));
10393 len = 0;
10394 } else if ((p->transfer || p->canpark) && is_exten_parking
10395 && p->subs[SUB_THREEWAY].owner) {
10396 struct ast_bridge_channel *bridge_channel;
10397
10398 /*
10399 * This is a three way call, the main call being a real channel,
10400 * and we're parking the first call.
10401 */
10405 if (bridge_channel) {
10406 if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10407 /*
10408 * Swap things around between the three-way and real call so we
10409 * can hear where the channel got parked.
10410 */
10411 ast_mutex_lock(&p->lock);
10412 p->owner = p->subs[SUB_THREEWAY].owner;
10415
10416 ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10418 ao2_ref(bridge_channel, -1);
10419 goto quit;
10420 }
10421 ao2_ref(bridge_channel, -1);
10422 }
10423 break;
10424 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10425 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10426 /* Enable Caller*ID if enabled */
10427 p->hidecallerid = 0;
10429 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10430 if (res) {
10431 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10432 ast_channel_name(chan), strerror(errno));
10433 }
10434 len = 0;
10435 memset(exten, 0, sizeof(exten));
10436 timeout = p->firstdigit_timeout;
10437 } else if (!strcmp(exten, "*0")) {
10438 struct ast_channel *nbridge =
10440 struct dahdi_pvt *pbridge = NULL;
10441 RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10442
10443 /* set up the private struct of the bridged one, if any */
10444 if (nbridge && bridged) {
10445 pbridge = ast_channel_tech_pvt(bridged);
10446 }
10447 if (nbridge && pbridge &&
10448 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10449 (ast_channel_tech(bridged) == &dahdi_tech) &&
10450 ISTRUNK(pbridge)) {
10451 int func = DAHDI_FLASH;
10452 /* Clear out the dial buffer */
10453 p->dop.dialstr[0] = '\0';
10454 /* flash hookswitch */
10455 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10456 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10457 ast_channel_name(nbridge), strerror(errno));
10458 }
10461 p->owner = p->subs[SUB_REAL].owner;
10463 ast_hangup(chan);
10464 goto quit;
10465 } else {
10466 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10467 dahdi_wait_event(p->subs[idx].dfd);
10468 tone_zone_play_tone(p->subs[idx].dfd, -1);
10471 p->owner = p->subs[SUB_REAL].owner;
10472 ast_hangup(chan);
10473 goto quit;
10474 }
10475 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10476 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10477 && !canmatch_featurecode(pickupexten, exten)) {
10478 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10479 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10480 ast_channel_context(chan));
10481 break;
10482 }
10483 if (!timeout)
10484 timeout = p->interdigit_timeout;
10486 tone_zone_play_tone(p->subs[idx].dfd, -1);
10487 }
10488 break;
10489 case SIG_FXSLS:
10490 case SIG_FXSGS:
10491 case SIG_FXSKS:
10492 /* check for SMDI messages */
10493 if (p->use_smdi && p->smdi_iface) {
10495
10496 if (smdi_msg != NULL) {
10497 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10498
10499 if (smdi_msg->type == 'B')
10500 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10501 else if (smdi_msg->type == 'N')
10502 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10503
10504 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10505 } else {
10506 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10507 }
10508 }
10509
10510 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10511 number = smdi_msg->calling_st;
10512
10513 /* If we want caller id, we're in a prering state due to a polarity reversal
10514 * and we're set to use a polarity reversal to trigger the start of caller id,
10515 * grab the caller id and wait for ringing to start... */
10516 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10518 /* If set to use DTMF CID signalling, listen for DTMF */
10519 if (p->cid_signalling == CID_SIG_DTMF) {
10520 int k = 0;
10521 int off_ms;
10522 struct timeval start = ast_tvnow();
10523 int ms;
10524 cs = NULL;
10525 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10526 dahdi_setlinear(p->subs[idx].dfd, 0);
10527 /*
10528 * We are the only party interested in the Rx stream since
10529 * we have not answered yet. We don't need or even want DTMF
10530 * emulation. The DTMF digits can come so fast that emulation
10531 * can drop some of them.
10532 */
10533 ast_channel_lock(chan);
10535 ast_channel_unlock(chan);
10536 off_ms = 4000;/* This is a typical OFF time between rings. */
10537 for (;;) {
10538 struct ast_frame *f;
10539
10540 ms = ast_remaining_ms(start, off_ms);
10541 res = ast_waitfor(chan, ms);
10542 if (res <= 0) {
10543 /*
10544 * We do not need to restore the dahdi_setlinear()
10545 * or AST_FLAG_END_DTMF_ONLY flag settings since we
10546 * are hanging up the channel.
10547 */
10548 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10549 "Exiting simple switch\n");
10550 ast_hangup(chan);
10551 goto quit;
10552 }
10553 f = ast_read(chan);
10554 if (!f)
10555 break;
10556 if (f->frametype == AST_FRAME_DTMF) {
10557 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10558 dtmfbuf[k++] = f->subclass.integer;
10559 }
10560 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10561 start = ast_tvnow();
10562 }
10563 ast_frfree(f);
10564 if (ast_channel_state(chan) == AST_STATE_RING ||
10566 break; /* Got ring */
10567 }
10568 ast_channel_lock(chan);
10570 ast_channel_unlock(chan);
10571 dtmfbuf[k] = '\0';
10572 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10573 /* Got cid and ring. */
10574 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10575 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10576 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10577 /* If first byte is NULL, we have no cid */
10578 if (!ast_strlen_zero(dtmfcid))
10579 number = dtmfcid;
10580 else
10581 number = NULL;
10582 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10583 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10585 if (cs) {
10586 int off_ms;
10587 struct timeval start;
10588 int ms;
10589 samples = 0;
10590#if 1
10591 bump_gains(p);
10592#endif
10593 /* Take out of linear mode for Caller*ID processing */
10594 dahdi_setlinear(p->subs[idx].dfd, 0);
10595
10596 /* First we wait and listen for the Caller*ID */
10597 for (;;) {
10598 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10599 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10600 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10601 callerid_free(cs);
10602 ast_hangup(chan);
10603 goto quit;
10604 }
10605 if (i & DAHDI_IOMUX_SIGEVENT) {
10606 res = dahdi_get_event(p->subs[idx].dfd);
10607 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10608 if (res == DAHDI_EVENT_NOALARM) {
10609 p->inalarm = 0;
10610 }
10611
10612 if (p->cid_signalling == CID_SIG_V23_JP) {
10613 if (res == DAHDI_EVENT_RINGBEGIN) {
10614 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10615 usleep(1);
10616 }
10617 } else {
10618 res = 0;
10619 break;
10620 }
10621 } else if (i & DAHDI_IOMUX_READ) {
10622 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10623 if (res < 0) {
10624 if (errno != ELAST) {
10625 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10626 callerid_free(cs);
10627 ast_hangup(chan);
10628 goto quit;
10629 }
10630 break;
10631 }
10632 samples += res;
10633
10634 if (p->cid_signalling == CID_SIG_V23_JP) {
10635 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10636 } else {
10637 res = callerid_feed(cs, buf, res, AST_LAW(p));
10638 }
10639 if (res < 0) {
10640 /*
10641 * The previous diagnostic message output likely
10642 * explains why it failed.
10643 */
10645 "Failed to decode CallerID on channel '%s'\n",
10646 ast_channel_name(chan));
10647 break;
10648 } else if (res)
10649 break;
10650 else if (samples > (8000 * 10))
10651 break;
10652 }
10653 }
10654 if (res == 1) {
10655 callerid_get(cs, &name, &number, &flags);
10656 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10657 }
10658
10659 if (p->cid_signalling == CID_SIG_V23_JP) {
10660 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10661 usleep(1);
10662 }
10663
10664 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10665 start = ast_tvnow();
10666 off_ms = 4000;/* This is a typical OFF time between rings. */
10667 for (;;) {
10668 struct ast_frame *f;
10669
10670 ms = ast_remaining_ms(start, off_ms);
10671 res = ast_waitfor(chan, ms);
10672 if (res <= 0) {
10673 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10674 "Exiting simple switch\n");
10675 ast_hangup(chan);
10676 goto quit;
10677 }
10678 if (!(f = ast_read(chan))) {
10679 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10680 ast_hangup(chan);
10681 goto quit;
10682 }
10683 ast_frfree(f);
10684 if (ast_channel_state(chan) == AST_STATE_RING ||
10686 break; /* Got ring */
10687 }
10688
10689 /* We must have a ring by now, so, if configured, lets try to listen for
10690 * distinctive ringing */
10692 len = 0;
10693 distMatches = 0;
10694 /* Clear the current ring data array so we don't have old data in it. */
10695 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10696 curRingData[receivedRingT] = 0;
10697 receivedRingT = 0;
10698 counter = 0;
10699 counter1 = 0;
10700 /* Check to see if context is what it should be, if not set to be. */
10701 if (strcmp(p->context,p->defcontext) != 0) {
10702 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10704 }
10705
10706 for (;;) {
10707 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10708 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10709 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10710 callerid_free(cs);
10711 ast_hangup(chan);
10712 goto quit;
10713 }
10714 if (i & DAHDI_IOMUX_SIGEVENT) {
10715 res = dahdi_get_event(p->subs[idx].dfd);
10716 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10717 if (res == DAHDI_EVENT_NOALARM) {
10718 p->inalarm = 0;
10719 }
10720 res = 0;
10721 /* Let us detect distinctive ring */
10722
10723 curRingData[receivedRingT] = p->ringt;
10724
10725 if (p->ringt < p->ringt_base/2)
10726 break;
10727 /* Increment the ringT counter so we can match it against
10728 values in chan_dahdi.conf for distinctive ring */
10729 if (++receivedRingT == ARRAY_LEN(curRingData))
10730 break;
10731 } else if (i & DAHDI_IOMUX_READ) {
10732 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10733 if (res < 0) {
10734 if (errno != ELAST) {
10735 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10736 callerid_free(cs);
10737 ast_hangup(chan);
10738 goto quit;
10739 }
10740 break;
10741 }
10742 if (p->ringt > 0) {
10743 if (!(--p->ringt)) {
10744 res = -1;
10745 break;
10746 }
10747 }
10748 }
10749 }
10750 /* this only shows up if you have n of the dring patterns filled in */
10751 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10752 for (counter = 0; counter < 3; counter++) {
10753 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10754 channel */
10755 distMatches = 0;
10756 for (counter1 = 0; counter1 < 3; counter1++) {
10757 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10758 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10759 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10760 curRingData[counter1]);
10761 distMatches++;
10762 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10763 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10764 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10765 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10766 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10767 distMatches++;
10768 }
10769 }
10770
10771 if (distMatches == 3) {
10772 /* The ring matches, set the context to whatever is for distinctive ring.. */
10773 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10775 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10776 break;
10777 }
10778 }
10779 }
10780 /* Restore linear mode (if appropriate) for Caller*ID processing */
10781 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10782#if 1
10783 restore_gains(p);
10784#endif
10785 } else
10786 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10787 } else {
10788 ast_log(LOG_WARNING, "Channel %s in prering "
10789 "state, but I have nothing to do. "
10790 "Terminating simple switch, should be "
10791 "restarted by the actual ring.\n",
10792 ast_channel_name(chan));
10793 ast_hangup(chan);
10794 goto quit;
10795 }
10796 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10797 if (p->cid_signalling == CID_SIG_DTMF) {
10798 int k = 0;
10799 int off_ms;
10800 struct timeval start;
10801 int ms;
10802 cs = NULL;
10803 dahdi_setlinear(p->subs[idx].dfd, 0);
10804 off_ms = 2000;
10805 start = ast_tvnow();
10806 for (;;) {
10807 struct ast_frame *f;
10808
10809 ms = ast_remaining_ms(start, off_ms);
10810 res = ast_waitfor(chan, ms);
10811 if (res <= 0) {
10812 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10813 "Exiting simple switch\n");
10814 ast_hangup(chan);
10815 goto quit;
10816 }
10817 f = ast_read(chan);
10818 if (!f) {
10819 /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10820 ast_hangup(chan);
10821 goto quit;
10822 }
10823 if (f->frametype == AST_FRAME_DTMF) {
10824 dtmfbuf[k++] = f->subclass.integer;
10825 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10826 start = ast_tvnow();
10827 }
10828 ast_frfree(f);
10829
10830 if (p->ringt_base == p->ringt)
10831 break;
10832 }
10833 dtmfbuf[k] = '\0';
10834 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10835 /* Got cid and ring. */
10836 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10837 ast_debug(1, "CID is '%s', flags %d\n",
10838 dtmfcid, flags);
10839 /* If first byte is NULL, we have no cid */
10840 if (!ast_strlen_zero(dtmfcid))
10841 number = dtmfcid;
10842 else
10843 number = NULL;
10844 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10845 } else {
10846 /* FSK Bell202 callerID */
10848 if (cs) {
10849#if 1
10850 bump_gains(p);
10851#endif
10852 samples = 0;
10853 len = 0;
10854 distMatches = 0;
10855 /* Clear the current ring data array so we don't have old data in it. */
10856 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10857 curRingData[receivedRingT] = 0;
10858 receivedRingT = 0;
10859 counter = 0;
10860 counter1 = 0;
10861 /* Check to see if context is what it should be, if not set to be. */
10862 if (strcmp(p->context,p->defcontext) != 0) {
10863 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10865 }
10866
10867 /* Take out of linear mode for Caller*ID processing */
10868 dahdi_setlinear(p->subs[idx].dfd, 0);
10869 for (;;) {
10870 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10871 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10872 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10873 callerid_free(cs);
10874 ast_hangup(chan);
10875 goto quit;
10876 }
10877 if (i & DAHDI_IOMUX_SIGEVENT) {
10878 res = dahdi_get_event(p->subs[idx].dfd);
10879 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10880 if (res == DAHDI_EVENT_NOALARM) {
10881 p->inalarm = 0;
10882 }
10883 /* If we get a PR event, they hung up while processing calerid */
10884 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10885 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10887 callerid_free(cs);
10888 ast_hangup(chan);
10889 goto quit;
10890 }
10891 res = 0;
10892 /* Let us detect callerid when the telco uses distinctive ring */
10893
10894 curRingData[receivedRingT] = p->ringt;
10895
10896 if (p->ringt < p->ringt_base/2)
10897 break;
10898 /* Increment the ringT counter so we can match it against
10899 values in chan_dahdi.conf for distinctive ring */
10900 if (++receivedRingT == ARRAY_LEN(curRingData))
10901 break;
10902 } else if (i & DAHDI_IOMUX_READ) {
10903 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10904 if (res < 0) {
10905 if (errno != ELAST) {
10906 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10907 callerid_free(cs);
10908 ast_hangup(chan);
10909 goto quit;
10910 }
10911 break;
10912 }
10913 if (p->ringt > 0) {
10914 if (!(--p->ringt)) {
10915 res = -1;
10916 break;
10917 }
10918 }
10919 samples += res;
10920 res = callerid_feed(cs, buf, res, AST_LAW(p));
10921 if (res < 0) {
10922 /*
10923 * The previous diagnostic message output likely
10924 * explains why it failed.
10925 */
10927 "Failed to decode CallerID on channel '%s'\n",
10928 ast_channel_name(chan));
10929 break;
10930 } else if (res)
10931 break;
10932 else if (samples > (8000 * 10))
10933 break;
10934 }
10935 }
10936 if (res == 1) {
10937 callerid_get(cs, &name, &number, &flags);
10938 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10939 }
10940 if (distinctiveringaftercid == 1) {
10941 /* Clear the current ring data array so we don't have old data in it. */
10942 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10943 curRingData[receivedRingT] = 0;
10944 }
10945 receivedRingT = 0;
10946 ast_verb(3, "Detecting post-CID distinctive ring\n");
10947 for (;;) {
10948 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10949 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10950 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10951 callerid_free(cs);
10952 ast_hangup(chan);
10953 goto quit;
10954 }
10955 if (i & DAHDI_IOMUX_SIGEVENT) {
10956 res = dahdi_get_event(p->subs[idx].dfd);
10957 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10958 if (res == DAHDI_EVENT_NOALARM) {
10959 p->inalarm = 0;
10960 }
10961 res = 0;
10962 /* Let us detect callerid when the telco uses distinctive ring */
10963
10964 curRingData[receivedRingT] = p->ringt;
10965
10966 if (p->ringt < p->ringt_base/2)
10967 break;
10968 /* Increment the ringT counter so we can match it against
10969 values in chan_dahdi.conf for distinctive ring */
10970 if (++receivedRingT == ARRAY_LEN(curRingData))
10971 break;
10972 } else if (i & DAHDI_IOMUX_READ) {
10973 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10974 if (res < 0) {
10975 if (errno != ELAST) {
10976 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10977 callerid_free(cs);
10978 ast_hangup(chan);
10979 goto quit;
10980 }
10981 break;
10982 }
10983 if (p->ringt > 0) {
10984 if (!(--p->ringt)) {
10985 res = -1;
10986 break;
10987 }
10988 }
10989 }
10990 }
10991 }
10993 /* this only shows up if you have n of the dring patterns filled in */
10994 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10995
10996 for (counter = 0; counter < 3; counter++) {
10997 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10998 channel */
10999 /* this only shows up if you have n of the dring patterns filled in */
11000 ast_verb(3, "Checking %d,%d,%d\n",
11001 p->drings.ringnum[counter].ring[0],
11002 p->drings.ringnum[counter].ring[1],
11003 p->drings.ringnum[counter].ring[2]);
11004 distMatches = 0;
11005 for (counter1 = 0; counter1 < 3; counter1++) {
11006 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11007 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11008 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11009 curRingData[counter1]);
11010 distMatches++;
11011 }
11012 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11013 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11014 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11015 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11016 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11017 distMatches++;
11018 }
11019 }
11020 if (distMatches == 3) {
11021 /* The ring matches, set the context to whatever is for distinctive ring.. */
11022 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11024 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11025 break;
11026 }
11027 }
11028 }
11029 /* Restore linear mode (if appropriate) for Caller*ID processing */
11030 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11031#if 1
11032 restore_gains(p);
11033#endif
11034 if (res < 0) {
11035 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11036 }
11037 } else
11038 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11039 }
11040 } else
11041 cs = NULL;
11042
11043 if (number)
11046
11047 ao2_cleanup(smdi_msg);
11048
11049 if (cs)
11050 callerid_free(cs);
11051
11052 my_handle_notify_message(chan, p, flags, -1);
11053
11054 ast_channel_lock(chan);
11056 ast_channel_rings_set(chan, 1);
11057 ast_channel_unlock(chan);
11058 p->ringt = p->ringt_base;
11059 res = ast_pbx_run(chan);
11060 if (res) {
11061 ast_hangup(chan);
11062 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11063 }
11064 goto quit;
11065 default:
11066 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11067 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11068 if (res < 0)
11069 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11070 }
11071 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11072 if (res < 0)
11073 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11074 ast_hangup(chan);
11075quit:
11080 return NULL;
11081}
11082
11085 unsigned char buf[READ_SIZE];
11086 size_t len;
11087};
11088
11089static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
11090{
11091 int x;
11092 int sum = 0;
11093
11094 if (!len)
11095 return 0;
11096
11097 for (x = 0; x < len; x++)
11098 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11099
11100 return sum / len;
11101}
11102
11103static void *mwi_thread(void *data)
11104{
11105 struct mwi_thread_data *mtd = data;
11106 struct callerid_state *cs;
11107 pthread_t threadid;
11108 int samples = 0;
11109 char *name, *number;
11110 int flags;
11111 int i, res;
11112 unsigned int spill_done = 0;
11113 int spill_result = -1;
11114
11115 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11116 goto quit_no_clean;
11117 }
11118
11119 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11120
11121 bump_gains(mtd->pvt);
11122
11123 for (;;) {
11124 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11125 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11126 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11127 goto quit;
11128 }
11129
11130 if (i & DAHDI_IOMUX_SIGEVENT) {
11131 struct ast_channel *chan;
11132 ast_callid callid = 0;
11133 int callid_created;
11134
11135 /* If we get an event, screen out events that we do not act on.
11136 * Otherwise, cancel and go to the simple switch to let it deal with it.
11137 */
11138 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11139
11140 switch (res) {
11141 case DAHDI_EVENT_NEONMWI_ACTIVE:
11142 case DAHDI_EVENT_NEONMWI_INACTIVE:
11143 case DAHDI_EVENT_NONE:
11144 case DAHDI_EVENT_BITSCHANGED:
11145 break;
11146 case DAHDI_EVENT_NOALARM:
11147 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11148 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11149
11150 analog_p->inalarm = 0;
11151 }
11152 mtd->pvt->inalarm = 0;
11154 break;
11155 case DAHDI_EVENT_ALARM:
11156 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11157 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11158
11159 analog_p->inalarm = 1;
11160 }
11161 mtd->pvt->inalarm = 1;
11162 res = get_alarms(mtd->pvt);
11163 handle_alarms(mtd->pvt, res);
11164 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11165 default:
11166 callid_created = ast_callid_threadstorage_auto(&callid);
11167 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11168 callerid_free(cs);
11169
11170 restore_gains(mtd->pvt);
11171 mtd->pvt->ringt = mtd->pvt->ringt_base;
11172
11173 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
11174 int result;
11175
11176 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11178 } else {
11180 }
11181 if (result) {
11182 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11183 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11184 if (res < 0)
11185 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11186 ast_hangup(chan);
11187 }
11188 } else {
11189 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11190 }
11191
11192 ast_callid_threadstorage_auto_clean(callid, callid_created);
11193 goto quit_no_clean;
11194 }
11195 } else if (i & DAHDI_IOMUX_READ) {
11196 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11197 if (errno != ELAST) {
11198 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11199 goto quit;
11200 }
11201 break;
11202 }
11203 samples += res;
11204 if (!spill_done) {
11205 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11206 /*
11207 * The previous diagnostic message output likely
11208 * explains why it failed.
11209 */
11210 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11211 break;
11212 } else if (spill_result) {
11213 spill_done = 1;
11214 }
11215 } else {
11216 /* keep reading data until the energy level drops below the threshold
11217 so we don't get another 'trigger' on the remaining carrier signal
11218 */
11219 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11220 break;
11221 }
11222 if (samples > (8000 * 4)) /*Termination case - time to give up*/
11223 break;
11224 }
11225 }
11226
11227 if (spill_result == 1) {
11228 callerid_get(cs, &name, &number, &flags);
11229 if (flags & CID_MSGWAITING) {
11230 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11231 notify_message(mtd->pvt->mailbox, 1);
11232 } else if (flags & CID_NOMSGWAITING) {
11233 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11234 notify_message(mtd->pvt->mailbox, 0);
11235 } else {
11236 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11237 }
11238 }
11239
11240
11241quit:
11242 callerid_free(cs);
11243
11244 restore_gains(mtd->pvt);
11245
11246quit_no_clean:
11247 mtd->pvt->mwimonitoractive = 0;
11248 ast_free(mtd);
11249
11250 return NULL;
11251}
11252
11253/*
11254* The following three functions (mwi_send_init, mwi_send_process_buffer,
11255* mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11256* that are sent out via FXS port on voicemail state change. The execution of
11257* the mwi send is state driven and can either generate a ring pulse prior to
11258* sending the fsk spill or simply send an fsk spill.
11259*/
11260static int mwi_send_init(struct dahdi_pvt * pvt)
11261{
11262 int x;
11263
11264#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11265 /* Determine how this spill is to be sent */
11266 if (pvt->mwisend_rpas) {
11268 pvt->mwisendactive = 1;
11269 } else if (pvt->mwisend_fsk) {
11271 pvt->mwisendactive = 1;
11272 } else {
11273 pvt->mwisendactive = 0;
11274 return 0;
11275 }
11276#else
11277 if (mwisend_rpas) {
11279 } else {
11281 }
11282 pvt->mwisendactive = 1;
11283#endif
11284
11285 if (pvt->cidspill) {
11286 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11287 ast_free(pvt->cidspill);
11288 pvt->cidspill = NULL;
11289 pvt->cidpos = 0;
11290 pvt->cidlen = 0;
11291 }
11293 if (!pvt->cidspill) {
11294 pvt->mwisendactive = 0;
11295 return -1;
11296 }
11297 x = DAHDI_FLUSH_BOTH;
11298 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11299 x = 3000;
11300 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11301#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11302 if (pvt->mwisend_fsk) {
11303#endif
11305 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11306 pvt->cidpos = 0;
11307#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11308 }
11309#endif
11310 return 0;
11311}
11312
11313static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11314{
11315 struct timeval now;
11316 int res;
11317
11318 /* sanity check to catch if this had been interrupted previously
11319 * i.e. state says there is more to do but there is no spill allocated
11320 */
11321 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11323 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11324 /* Normal processing -- Perform mwi send action */
11325 switch ( pvt->mwisend_data.mwisend_current) {
11326 case MWI_SEND_SA:
11327 /* Send the Ring Pulse Signal Alert */
11328 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11329 if (res) {
11330 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11331 goto quit;
11332 }
11333 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11335 break;
11336 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
11337 break;
11338 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
11339#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11340 if (pvt->mwisend_fsk) {
11341#endif
11342 gettimeofday(&now, NULL);
11343 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11345 }
11346#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11347 } else { /* support for mwisendtype=nofsk */
11349 }
11350#endif
11351 break;
11352 case MWI_SEND_SPILL:
11353 /* We read some number of bytes. Write an equal amount of data */
11354 if (0 < num_read) {
11355 if (num_read > pvt->cidlen - pvt->cidpos) {
11356 num_read = pvt->cidlen - pvt->cidpos;
11357 }
11358 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11359 if (res > 0) {
11360 pvt->cidpos += res;
11361 if (pvt->cidpos >= pvt->cidlen) {
11363 }
11364 } else {
11365 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11366 goto quit;
11367 }
11368 }
11369 break;
11370 case MWI_SEND_CLEANUP:
11371 /* For now, do nothing */
11373 break;
11374 default:
11375 /* Should not get here, punt*/
11376 goto quit;
11377 }
11378 }
11379
11381 if (pvt->cidspill) {
11382 ast_free(pvt->cidspill);
11383 pvt->cidspill = NULL;
11384 pvt->cidpos = 0;
11385 pvt->cidlen = 0;
11386 }
11387 pvt->mwisendactive = 0;
11388 }
11389 return 0;
11390quit:
11391 if (pvt->cidspill) {
11392 ast_free(pvt->cidspill);
11393 pvt->cidspill = NULL;
11394 pvt->cidpos = 0;
11395 pvt->cidlen = 0;
11396 }
11397 pvt->mwisendactive = 0;
11398 return -1;
11399}
11400
11401static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11402{
11403 int handled = 0;
11404
11406 switch (event) {
11407 case DAHDI_EVENT_RINGEROFF:
11409 handled = 1;
11410
11411 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11412 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11413 ast_free(pvt->cidspill);
11414 pvt->cidspill = NULL;
11416 pvt->mwisendactive = 0;
11417 } else {
11419 gettimeofday(&pvt->mwisend_data.pause, NULL);
11420 }
11421 }
11422 break;
11423 /* Going off hook, I need to punt this spill */
11424 case DAHDI_EVENT_RINGOFFHOOK:
11425 if (pvt->cidspill) {
11426 ast_free(pvt->cidspill);
11427 pvt->cidspill = NULL;
11428 pvt->cidpos = 0;
11429 pvt->cidlen = 0;
11430 }
11432 pvt->mwisendactive = 0;
11433 break;
11434 case DAHDI_EVENT_RINGERON:
11435 case DAHDI_EVENT_HOOKCOMPLETE:
11436 break;
11437 default:
11438 break;
11439 }
11440 }
11441 return handled;
11442}
11443
11444/* destroy a range DAHDI channels, identified by their number */
11445static void dahdi_destroy_channel_range(int start, int end)
11446{
11447 struct dahdi_pvt *cur;
11448 struct dahdi_pvt *next;
11449 int destroyed_first = 0;
11450 int destroyed_last = 0;
11451
11453 ast_debug(1, "range: %d-%d\n", start, end);
11454 for (cur = iflist; cur; cur = next) {
11455 next = cur->next;
11456 if (cur->channel >= start && cur->channel <= end) {
11457 int x = DAHDI_FLASH;
11458
11459 if (cur->channel > destroyed_last) {
11460 destroyed_last = cur->channel;
11461 }
11462 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11463 destroyed_first = cur->channel;
11464 }
11465 ast_debug(3, "Destroying %d\n", cur->channel);
11466 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11467 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11468
11469 destroy_channel(cur, 1);
11471 }
11472 }
11474 if (destroyed_first > start || destroyed_last < end) {
11475 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11476 start, end, destroyed_first, destroyed_last);
11477 }
11478}
11479
11480#ifdef HAVE_OPENR2
11481static void dahdi_r2_destroy_nodev(void)
11482{
11483 struct r2link_entry *cur;
11484 AST_LIST_LOCK(&nodev_r2links);
11485 AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {
11486 int i;
11487 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11488 ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11489 for (i = 0; i < r2->numchans; i++) {
11490 int channel;
11491 struct dahdi_pvt *pvt = r2->pvts[i];
11492 if (!pvt) {
11493 continue;
11494 }
11495 channel = pvt->channel;
11496 ast_debug(3, "About to destroy B-channel %d.\n", channel);
11498 }
11499 ast_debug(3, "Destroying R2 link\n");
11500 AST_LIST_REMOVE(&nodev_r2links, cur, list);
11501 if (r2->r2master != AST_PTHREADT_NULL) {
11502 pthread_cancel(r2->r2master);
11503 pthread_join(r2->r2master, NULL);
11504 r2->r2master = AST_PTHREADT_NULL;
11505 openr2_context_delete(r2->protocol_context);
11506 }
11507 ast_free(cur);
11508 }
11510 AST_LIST_UNLOCK(&nodev_r2links);
11511}
11512#endif
11513
11514static int setup_dahdi(int reload);
11515static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
11516
11517/*!
11518 * \internal
11519 * \brief create a range of new DAHDI channels
11520 *
11521 * \param start first channel in the range
11522 * \param end last channel in the range
11523 *
11524 * \retval RESULT_SUCCESS on success.
11525 * \retval RESULT_FAILURE on error.
11526 */
11527static int dahdi_create_channel_range(int start, int end)
11528{
11529 struct dahdi_pvt *cur;
11530 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11531 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11533 int ret = RESULT_FAILURE; /* be pessimistic */
11534
11535 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11537 for (cur = iflist; cur; cur = cur->next) {
11538 if (cur->channel >= start && cur->channel <= end) {
11540 "channel range %d-%d is occupied\n",
11541 start, end);
11542 goto out;
11543 }
11544 }
11545#ifdef HAVE_PRI
11546 {
11547 int i, x;
11548 for (x = 0; x < NUM_SPANS; x++) {
11549 struct dahdi_pri *pri = pris + x;
11550
11551 if (!pris[x].pri.pvts[0]) {
11552 break;
11553 }
11554 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11555 int channo = pri->dchannels[i];
11556
11557 if (!channo) {
11558 break;
11559 }
11560 if (!pri->pri.fds[i]) {
11561 break;
11562 }
11563 if (channo >= start && channo <= end) {
11565 "channel range %d-%d is occupied by span %d\n",
11566 start, end, x + 1);
11567 goto out;
11568 }
11569 }
11570 }
11571 }
11572#endif
11573 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11574 !conf.chan.cc_params) {
11575 goto out;
11576 }
11577 default_conf.wanted_channels_start = start;
11578 base_conf.wanted_channels_start = start;
11579 conf.wanted_channels_start = start;
11580 default_conf.wanted_channels_end = end;
11581 base_conf.wanted_channels_end = end;
11582 conf.wanted_channels_end = end;
11583 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11584 ret = RESULT_SUCCESS;
11585 }
11586out:
11589 ast_cc_config_params_destroy(conf.chan.cc_params);
11591 return ret;
11592}
11593
11594
11595static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11596{
11597 int res;
11598 pthread_t threadid;
11599 struct ast_channel *chan;
11600 ast_callid callid = 0;
11601 int callid_created;
11602
11603 /* Handle an event on a given channel for the monitor thread. */
11604
11605 switch (event) {
11606 case DAHDI_EVENT_NONE:
11607 case DAHDI_EVENT_BITSCHANGED:
11608 break;
11609 case DAHDI_EVENT_WINKFLASH:
11610 case DAHDI_EVENT_RINGOFFHOOK:
11611 if (i->inalarm) break;
11612 if (i->radio) break;
11613 /* Got a ring/answer. What kind of channel are we? */
11614 switch (i->sig) {
11615 case SIG_FXOLS:
11616 case SIG_FXOGS:
11617 case SIG_FXOKS:
11618 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11619 if (res && (errno == EBUSY)) {
11620 break;
11621 }
11622
11623 callid_created = ast_callid_threadstorage_auto(&callid);
11624
11625 /* Cancel VMWI spill */
11626 ast_free(i->cidspill);
11627 i->cidspill = NULL;
11629
11630 if (i->immediate) {
11631 dahdi_ec_enable(i);
11632 /* The channel is immediately up. Start right away */
11633 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11634 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11635 if (!chan) {
11636 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11637 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11638 if (res < 0)
11639 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11640 }
11641 } else {
11642 /* Check for callerid, digits, etc */
11643 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11644 if (chan) {
11645 if (has_voicemail(i))
11646 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11647 else
11648 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11649 if (res < 0)
11650 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11651 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11652 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11653 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11654 if (res < 0)
11655 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11656 ast_hangup(chan);
11657 }
11658 } else
11659 ast_log(LOG_WARNING, "Unable to create channel\n");
11660 }
11661
11663 break;
11664 case SIG_FXSLS:
11665 case SIG_FXSGS:
11666 case SIG_FXSKS:
11667 i->ringt = i->ringt_base;
11668 /* Fall through */
11669 case SIG_EMWINK:
11670 case SIG_FEATD:
11671 case SIG_FEATDMF:
11672 case SIG_FEATDMF_TA:
11673 case SIG_E911:
11674 case SIG_FGC_CAMA:
11675 case SIG_FGC_CAMAMF:
11676 case SIG_FEATB:
11677 case SIG_EM:
11678 case SIG_EM_E1:
11679 case SIG_SFWINK:
11680 case SIG_SF_FEATD:
11681 case SIG_SF_FEATDMF:
11682 case SIG_SF_FEATB:
11683 case SIG_SF:
11684 /* Check for callerid, digits, etc */
11685 callid_created = ast_callid_threadstorage_auto(&callid);
11686 if (i->cid_start == CID_START_POLARITY_IN) {
11687 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11688 } else {
11689 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11690 }
11691
11692 if (!chan) {
11693 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11694 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11695 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11696 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11697 if (res < 0) {
11698 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11699 }
11700 ast_hangup(chan);
11701 }
11702
11704 break;
11705 default:
11706 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11707 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11708 if (res < 0)
11709 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11710 return NULL;
11711 }
11712 break;
11713 case DAHDI_EVENT_NOALARM:
11714 switch (i->sig) {
11715#if defined(HAVE_PRI)
11717 ast_mutex_lock(&i->lock);
11720 break;
11721#endif /* defined(HAVE_PRI) */
11722#if defined(HAVE_SS7)
11723 case SIG_SS7:
11725 break;
11726#endif /* defined(HAVE_SS7) */
11727 default:
11728 i->inalarm = 0;
11729 break;
11730 }
11732 break;
11733 case DAHDI_EVENT_ALARM:
11734 switch (i->sig) {
11735#if defined(HAVE_PRI)
11737 ast_mutex_lock(&i->lock);
11740 break;
11741#endif /* defined(HAVE_PRI) */
11742#if defined(HAVE_SS7)
11743 case SIG_SS7:
11745 break;
11746#endif /* defined(HAVE_SS7) */
11747 default:
11748 i->inalarm = 1;
11749 break;
11750 }
11751 res = get_alarms(i);
11752 handle_alarms(i, res);
11753 /* fall thru intentionally */
11754 case DAHDI_EVENT_ONHOOK:
11755 if (i->radio)
11756 break;
11757 /* Back on hook. Hang up. */
11758 switch (i->sig) {
11759 case SIG_FXOLS:
11760 case SIG_FXOGS:
11761 case SIG_FEATD:
11762 case SIG_FEATDMF:
11763 case SIG_FEATDMF_TA:
11764 case SIG_E911:
11765 case SIG_FGC_CAMA:
11766 case SIG_FGC_CAMAMF:
11767 case SIG_FEATB:
11768 case SIG_EM:
11769 case SIG_EM_E1:
11770 case SIG_EMWINK:
11771 case SIG_SF_FEATD:
11772 case SIG_SF_FEATDMF:
11773 case SIG_SF_FEATB:
11774 case SIG_SF:
11775 case SIG_SFWINK:
11776 case SIG_FXSLS:
11777 case SIG_FXSGS:
11778 case SIG_FXSKS:
11779 case SIG_FXOKS:
11781 /* Diddle the battery for the zhone */
11782#ifdef ZHONE_HACK
11783 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11784 usleep(1);
11785#endif
11786 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11787 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11788 break;
11789 case SIG_SS7:
11792 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11793 break;
11794 default:
11795 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11796 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11797 return NULL;
11798 }
11799 break;
11800 case DAHDI_EVENT_POLARITY:
11801 switch (i->sig) {
11802 case SIG_FXSLS:
11803 case SIG_FXSKS:
11804 case SIG_FXSGS:
11805 /* We have already got a PR before the channel was
11806 created, but it wasn't handled. We need polarity
11807 to be REV for remote hangup detection to work.
11808 At least in Spain */
11809 callid_created = ast_callid_threadstorage_auto(&callid);
11814 ast_verb(2, "Starting post polarity "
11815 "CID detection on channel %d\n",
11816 i->channel);
11817 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11818 if (!chan) {
11819 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11820 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11821 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11822 ast_hangup(chan);
11823 }
11824 }
11826 break;
11827 default:
11828 ast_log(LOG_WARNING, "handle_init_event detected "
11829 "polarity reversal on non-FXO (SIG_FXS) "
11830 "interface %d\n", i->channel);
11831 }
11832 break;
11833 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11835 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11836 i->channel);
11837 return i;
11838 case DAHDI_EVENT_NEONMWI_ACTIVE:
11839 if (i->mwimonitor_neon) {
11840 notify_message(i->mailbox, 1);
11841 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11842 }
11843 break;
11844 case DAHDI_EVENT_NEONMWI_INACTIVE:
11845 if (i->mwimonitor_neon) {
11846 notify_message(i->mailbox, 0);
11847 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11848 }
11849 break;
11850 }
11851 return NULL;
11852}
11853
11854static void monitor_pfds_clean(void *arg) {
11855 struct pollfd **pfds = arg;
11856 ast_free(*pfds);
11857}
11858
11859static void *do_monitor(void *data)
11860{
11861 int count, res, res2, spoint, pollres=0;
11862 struct dahdi_pvt *i;
11863 struct dahdi_pvt *last = NULL;
11864 struct dahdi_pvt *doomed;
11865 time_t thispass = 0, lastpass = 0;
11866 int found;
11867 char buf[1024];
11868 struct pollfd *pfds=NULL;
11869 int lastalloc = -1;
11870 /* This thread monitors all the frame relay interfaces which are not yet in use
11871 (and thus do not have a separate thread) indefinitely */
11872 /* From here on out, we die whenever asked */
11873#if 0
11874 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11875 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11876 return NULL;
11877 }
11878 ast_debug(1, "Monitor starting...\n");
11879#endif
11880 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11881
11882 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11883 for (;;) {
11884 /* Lock the interface list */
11886 if (!pfds || (lastalloc != ifcount)) {
11887 if (pfds) {
11888 ast_free(pfds);
11889 pfds = NULL;
11890 }
11891 if (ifcount) {
11892 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11894 return NULL;
11895 }
11896 }
11897 lastalloc = ifcount;
11898 }
11899 /* Build the stuff we're going to poll on, that is the socket of every
11900 dahdi_pvt that does not have an associated owner channel */
11901 count = 0;
11902 for (i = iflist; i; i = i->next) {
11903 ast_mutex_lock(&i->lock);
11904 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11905 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11906 struct analog_pvt *p = i->sig_pvt;
11907
11908 if (!p) {
11909 ast_log(LOG_ERROR, "No sig_pvt?\n");
11910 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11911 /* This needs to be watched, as it lacks an owner */
11912 pfds[count].fd = i->subs[SUB_REAL].dfd;
11913 pfds[count].events = POLLPRI;
11914 pfds[count].revents = 0;
11915 /* Message waiting or r2 channels also get watched for reading */
11916 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11917 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11918 pfds[count].events |= POLLIN;
11919 }
11920 count++;
11921 }
11922 } else {
11923 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11924 /* This needs to be watched, as it lacks an owner */
11925 pfds[count].fd = i->subs[SUB_REAL].dfd;
11926 pfds[count].events = POLLPRI;
11927 pfds[count].revents = 0;
11928 /* If we are monitoring for VMWI or sending CID, we need to
11929 read from the channel as well */
11930 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11931 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11932 pfds[count].events |= POLLIN;
11933 }
11934 count++;
11935 }
11936 }
11937 }
11939 }
11940 /* Okay, now that we know what to do, release the interface lock */
11942
11943 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11944 pthread_testcancel();
11945 /* Wait at least a second for something to happen */
11946 res = poll(pfds, count, 1000);
11947 pthread_testcancel();
11948 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11949
11950 /* Okay, poll has finished. Let's see what happened. */
11951 if (res < 0) {
11952 if ((errno != EAGAIN) && (errno != EINTR))
11953 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11954 continue;
11955 }
11956 /* Alright, lock the interface list again, and let's look and see what has
11957 happened */
11959 found = 0;
11960 spoint = 0;
11961 lastpass = thispass;
11962 thispass = time(NULL);
11963 doomed = NULL;
11964 for (i = iflist;; i = i->next) {
11965 if (doomed) {
11967 doomed = NULL;
11968 }
11969 if (!i) {
11970 break;
11971 }
11972
11973 if (thispass != lastpass) {
11974 if (!found && ((i == last) || ((i == iflist) && !last))) {
11975 last = i;
11976 if (last) {
11977 struct analog_pvt *analog_p = last->sig_pvt;
11978 /* Only allow MWI to be initiated on a quiescent fxs port */
11979 if (analog_p
11980 && !last->mwisendactive
11981 && (last->sig & __DAHDI_SIG_FXO)
11982 && !analog_p->fxsoffhookstate
11983 && !last->owner
11984 && (!ast_strlen_zero(last->mailbox) || last->mwioverride_active)
11985 && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
11986 && (thispass - analog_p->onhooktime > 3)
11987 /* In some cases, all of the above checks will pass even if the line is really off-hook.
11988 * This last check will give the right answer 100% of the time, but is relatively
11989 * "expensive" (it requires an ioctl), so it is last to avoid unnecessary system calls. */
11990 && !my_is_off_hook(last)) {
11991 res = has_voicemail(last);
11992 if (analog_p->msgstate != res) {
11993 /* Set driver resources for signalling VMWI */
11994 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11995 if (res2) {
11996 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11997 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11998 }
11999 /* If enabled for FSK spill then initiate it */
12000 ast_debug(5, "Initiating MWI FSK spill on channel %d\n", last->channel);
12001 if (mwi_send_init(last)) {
12002 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12003 }
12004 analog_p->msgstate = res;
12005 found ++;
12006 }
12007 }
12008 last = last->next;
12009 }
12010 }
12011 }
12012 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12013 if (i->radio && !i->owner)
12014 {
12015 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12016 if (res)
12017 {
12018 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12019 /* Don't hold iflock while handling init events */
12021 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12023 else
12024 doomed = handle_init_event(i, res);
12026 }
12027 continue;
12028 }
12029 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12030 if (pollres & POLLIN) {
12031 if (i->owner || i->subs[SUB_REAL].owner) {
12032#ifdef HAVE_PRI
12033 if (!i->pri)
12034#endif
12035 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12036 continue;
12037 }
12039 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12040 continue;
12041 }
12042 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12043 if (res > 0) {
12044 if (i->mwimonitor_fsk) {
12045 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12046 pthread_attr_t attr;
12047 pthread_t threadid;
12048 struct mwi_thread_data *mtd;
12049
12050 pthread_attr_init(&attr);
12051 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12052
12053 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12054 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12055 mtd->pvt = i;
12056 memcpy(mtd->buf, buf, res);
12057 mtd->len = res;
12058 i->mwimonitoractive = 1;
12059 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12060 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12061 i->mwimonitoractive = 0;
12062 ast_free(mtd);
12063 }
12064 }
12065 }
12066 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12067 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12068 int energy;
12069 struct timeval now;
12070 /* State machine dtmfcid_holdoff_state allows for the line to settle
12071 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
12072 */
12073 if (1 == i->dtmfcid_holdoff_state) {
12074 gettimeofday(&i->dtmfcid_delay, NULL);
12075 i->dtmfcid_holdoff_state = 2;
12076 } else if (2 == i->dtmfcid_holdoff_state) {
12077 gettimeofday(&now, NULL);
12078 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12079 i->dtmfcid_holdoff_state = 0;
12080 }
12081 } else {
12082 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12083 if (!i->mwisendactive && energy > dtmfcid_level) {
12084 pthread_t threadid;
12085 struct ast_channel *chan;
12087 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12088 /* just in case this event changes or somehow destroys a channel, set doomed here too */
12090 i->dtmfcid_holdoff_state = 1;
12091 } else {
12092 ast_callid callid = 0;
12093 int callid_created = ast_callid_threadstorage_auto(&callid);
12094 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
12095 if (!chan) {
12096 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12097 } else {
12098 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12099 if (res) {
12100 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12101 ast_hangup(chan);
12102 } else {
12103 i->dtmfcid_holdoff_state = 1;
12104 }
12105 }
12107 }
12109 }
12110 }
12111 }
12112 if (i->mwisendactive) {
12114 }
12115 } else {
12116 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12117 }
12118 }
12119 if (pollres & POLLPRI) {
12120 if (i->owner || i->subs[SUB_REAL].owner) {
12121#ifdef HAVE_PRI
12122 if (!i->pri)
12123#endif
12124 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12125 continue;
12126 }
12127 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12128 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12129 /* Don't hold iflock while handling init events */
12131 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12132 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12134 else
12135 doomed = handle_init_event(i, res);
12136 }
12137 if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12138 /* Actually automatically reoriginate this FXS line, if directed to.
12139 * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12140 * doing its thing (one reason why this is for FXOKS only: FXOLS
12141 * hangups don't give us any DAHDI events to piggyback off of)*/
12142 i->doreoriginate = 0;
12143 /* Double check the channel is still off-hook. There's only about a millisecond
12144 * between when doreoriginate is set high and we see that here, but just to be safe. */
12145 if (!my_is_off_hook(i)) {
12146 ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12147 } else {
12148 ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12149 res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12150 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12152 } else {
12153 doomed = handle_init_event(i, res);
12154 }
12155 }
12156 }
12158 }
12159 }
12160 }
12163#ifdef HAVE_OPENR2
12164 dahdi_r2_destroy_nodev();
12165#endif
12166 }
12167 /* Never reached */
12168 pthread_cleanup_pop(1);
12169 return NULL;
12170
12171}
12172
12173static int restart_monitor(void)
12174{
12175 /* If we're supposed to be stopped -- stay stopped */
12177 return 0;
12179 if (monitor_thread == pthread_self()) {
12181 ast_log(LOG_WARNING, "Cannot kill myself\n");
12182 return -1;
12183 }
12185 /* Wake up the thread */
12186 pthread_kill(monitor_thread, SIGURG);
12187 } else {
12188 /* Start a new monitor */
12191 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12192 return -1;
12193 }
12194 }
12196 return 0;
12197}
12198
12199#if defined(HAVE_PRI)
12200static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12201{
12202 int x;
12203 int trunkgroup;
12204 /* Get appropriate trunk group if there is one */
12205 trunkgroup = pris[*span].mastertrunkgroup;
12206 if (trunkgroup) {
12207 /* Select a specific trunk group */
12208 for (x = 0; x < NUM_SPANS; x++) {
12209 if (pris[x].pri.trunkgroup == trunkgroup) {
12210 *span = x;
12211 return 0;
12212 }
12213 }
12214 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12215 *span = -1;
12216 } else {
12217 if (pris[*span].pri.trunkgroup) {
12218 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
12219 *span = -1;
12220 } else if (pris[*span].mastertrunkgroup) {
12221 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12222 *span = -1;
12223 } else {
12224 if (si->totalchans == 31) {
12225 /* E1 */
12226 pris[*span].dchannels[0] = 16 + offset;
12227 } else if (si->totalchans == 24) {
12228 /* T1 or J1 */
12229 pris[*span].dchannels[0] = 24 + offset;
12230 } else if (si->totalchans == 3) {
12231 /* BRI */
12232 pris[*span].dchannels[0] = 3 + offset;
12233 } else {
12234 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);
12235 *span = -1;
12236 return 0;
12237 }
12238 pris[*span].pri.span = *span + 1;
12239 }
12240 }
12241 return 0;
12242}
12243#endif /* defined(HAVE_PRI) */
12244
12245#if defined(HAVE_PRI)
12246static int pri_create_trunkgroup(int trunkgroup, int *channels)
12247{
12248 struct dahdi_spaninfo si;
12249 struct dahdi_params p;
12250 int fd;
12251 int span;
12252 int ospan=0;
12253 int x,y;
12254 for (x = 0; x < NUM_SPANS; x++) {
12255 if (pris[x].pri.trunkgroup == trunkgroup) {
12256 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12257 return -1;
12258 }
12259 }
12260 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12261 if (!channels[y])
12262 break;
12263 memset(&si, 0, sizeof(si));
12264 memset(&p, 0, sizeof(p));
12265 fd = open("/dev/dahdi/channel", O_RDWR);
12266 if (fd < 0) {
12267 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12268 return -1;
12269 }
12270 x = channels[y];
12271 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12272 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12273 close(fd);
12274 return -1;
12275 }
12276 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12277 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12278 close(fd);
12279 return -1;
12280 }
12281 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12282 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12283 close(fd);
12284 return -1;
12285 }
12286 span = p.spanno - 1;
12287 if (pris[span].pri.trunkgroup) {
12288 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12289 close(fd);
12290 return -1;
12291 }
12292 if (pris[span].pri.pvts[0]) {
12293 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12294 close(fd);
12295 return -1;
12296 }
12297 if (!y) {
12298 pris[span].pri.trunkgroup = trunkgroup;
12299 ospan = span;
12300 }
12301 pris[ospan].dchannels[y] = channels[y];
12302 pris[span].pri.span = span + 1;
12303 close(fd);
12304 }
12305 return 0;
12306}
12307#endif /* defined(HAVE_PRI) */
12308
12309#if defined(HAVE_PRI)
12310static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12311{
12312 if (pris[span].mastertrunkgroup) {
12313 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);
12314 return -1;
12315 }
12316 pris[span].mastertrunkgroup = trunkgroup;
12317 pris[span].prilogicalspan = logicalspan;
12318 return 0;
12319}
12320#endif /* defined(HAVE_PRI) */
12321
12322#if defined(HAVE_SS7)
12323static unsigned int parse_pointcode(const char *pcstring)
12324{
12325 unsigned int code1, code2, code3;
12326 int numvals;
12327
12328 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12329 if (numvals == 1)
12330 return code1;
12331 if (numvals == 3)
12332 return (code1 << 16) | (code2 << 8) | code3;
12333
12334 return 0;
12335}
12336#endif /* defined(HAVE_SS7) */
12337
12338#if defined(HAVE_SS7)
12339static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12340{
12341 if ((linkset < 0) || (linkset >= NUM_SPANS))
12342 return NULL;
12343 else
12344 return &linksets[linkset - 1];
12345}
12346#endif /* defined(HAVE_SS7) */
12347
12348#ifdef HAVE_OPENR2
12349static void dahdi_r2_destroy_links(void)
12350{
12351 struct r2link_entry *cur;
12352
12353 /* Queue everything for removal */
12354 AST_LIST_LOCK(&r2links);
12355 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
12356 ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
12357 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
12358 }
12360 AST_LIST_UNLOCK(&r2links);
12361 /* Now destroy properly */
12362 dahdi_r2_destroy_nodev();
12363}
12364
12365/* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12366#define R2_LINK_CAPACITY 30
12367static struct r2link_entry *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12368{
12369 struct r2link_entry *cur = NULL;
12370 /* Only create a new R2 link if
12371 1. This is the first link requested
12372 2. Configuration changed
12373 3. We got more channels than supported per link */
12374 AST_LIST_LOCK(&r2links);
12375 if (! AST_LIST_EMPTY(&r2links)) {
12376 cur = AST_LIST_LAST(&r2links);
12377 if (memcmp(&conf->mfcr2, &cur->mfcr2.conf, sizeof(conf->mfcr2))) {
12378 ast_debug(3, "Need new R2 link because of: Configuration change\n");
12379 cur = NULL;
12380 } else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
12381 ast_debug(3, "Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
12382 cur = NULL;
12383 }
12384 }
12385 if (!cur) {
12386 struct r2link_entry *tmp = NULL;
12387 int new_idx = r2links_count + 1;
12388 int i;
12389 for (i = 1; i <= r2links_count; i++) {
12390 int i_unused = 1;
12391 AST_LIST_TRAVERSE(&r2links, tmp, list) {
12392 if (i == tmp->mfcr2.index) {
12393 i_unused = 0;
12394 break;
12395 }
12396 }
12397 if (i_unused) {
12398 new_idx = i;
12399 break;
12400 }
12401 }
12402 cur = ast_calloc(1, sizeof(*cur));
12403 if (!cur) {
12404 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12405 return NULL;
12406 }
12407 cur->mfcr2.index = new_idx;
12408 cur->mfcr2.r2master = AST_PTHREADT_NULL;
12409 r2links_count++;
12410 ast_debug(3, "Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12411 AST_LIST_INSERT_TAIL(&r2links, cur, list);
12412 }
12413 AST_LIST_UNLOCK(&r2links);
12414 return cur;
12415}
12416
12417static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12418{
12419 char tmplogdir[] = "/tmp";
12420 char logdir[OR2_MAX_PATH];
12421 int threshold = 0;
12422 int snres = 0;
12423 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12424 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12425 conf->mfcr2.max_dnis);
12426 if (!r2_link->protocol_context) {
12427 return -1;
12428 }
12429 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12430 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12431#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12432 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12433#endif
12434 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12435 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12436 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12437 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12438 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12439#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12440 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12441 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12442#endif
12443#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12444 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12445#endif
12446 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12447 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12448 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12449 }
12450 } else {
12451 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12452 if (snres >= sizeof(logdir)) {
12453 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12454 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12455 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12456 }
12457 } else {
12458 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12459 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12460 }
12461 }
12462 }
12463 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12464 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12465 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12466 }
12467 }
12468 /* Save the configuration used to setup this link */
12469 memcpy(&r2_link->conf, &conf->mfcr2, sizeof(r2_link->conf));
12470 return 0;
12471}
12472#endif
12473
12474/* converts a DAHDI sigtype to signalling as can be configured from
12475 * chan_dahdi.conf.
12476 * While both have basically the same values, this will later be the
12477 * place to add filters and sanity checks
12478 */
12480{
12481 return sigtype;
12482}
12483
12484/*!
12485 * \internal
12486 * \brief Initialize/create a channel interface.
12487 *
12488 * \param channel Channel interface number to initialize/create.
12489 * \param conf Configuration parameters to initialize interface with.
12490 * \param reloading What we are doing now:
12491 * 0 - initial module load,
12492 * 1 - module reload,
12493 * 2 - module restart
12494 *
12495 * \retval Interface-pointer initialized/created
12496 * \retval NULL if error
12497 */
12498static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12499{
12500 /* Make a dahdi_pvt structure for this interface */
12501 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12502 char fn[80];
12503 struct dahdi_bufferinfo bi;
12504
12505 int res;
12506#if defined(HAVE_PRI)
12507 int span = 0;
12508#endif /* defined(HAVE_PRI) */
12509 int here = 0;/*!< TRUE if the channel interface already exists. */
12510 int x;
12511 struct analog_pvt *analog_p = NULL;
12512 struct dahdi_params p;
12513#if defined(HAVE_PRI)
12514 struct dahdi_spaninfo si;
12515 struct sig_pri_chan *pri_chan = NULL;
12516#endif /* defined(HAVE_PRI) */
12517#if defined(HAVE_SS7)
12518 struct sig_ss7_chan *ss7_chan = NULL;
12519#endif /* defined(HAVE_SS7) */
12520
12521 /* Search channel interface list to see if it already exists. */
12522 for (tmp = iflist; tmp; tmp = tmp->next) {
12523 if (!tmp->destroy) {
12524 if (tmp->channel == channel) {
12525 /* The channel interface already exists. */
12526 here = 1;
12527 break;
12528 }
12529 if (tmp->channel > channel) {
12530 /* No way it can be in the sorted list. */
12531 tmp = NULL;
12532 break;
12533 }
12534 }
12535 }
12536
12537 if (!here && reloading != 1) {
12538 tmp = ast_calloc(1, sizeof(*tmp));
12539 if (!tmp) {
12540 return NULL;
12541 }
12542 tmp->cc_params = ast_cc_config_params_init();
12543 if (!tmp->cc_params) {
12544 ast_free(tmp);
12545 return NULL;
12546 }
12547 ast_mutex_init(&tmp->lock);
12548 ifcount++;
12549 for (x = 0; x < 3; x++)
12550 tmp->subs[x].dfd = -1;
12551 tmp->channel = channel;
12552 tmp->priindication_oob = conf->chan.priindication_oob;
12553 }
12554
12555 if (tmp) {
12556 int chan_sig = conf->chan.sig;
12557
12558 /* If there are variables in tmp before it is updated to match the new config, clear them */
12559 if (reloading && tmp->vars) {
12561 tmp->vars = NULL;
12562 }
12563
12564 if (!here) {
12565 /* Can only get here if this is a new channel interface being created. */
12566 if ((channel != CHAN_PSEUDO)) {
12567 int count = 0;
12568
12569 snprintf(fn, sizeof(fn), "%d", channel);
12570 /* Open non-blocking */
12571 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12572 /* Retry open on restarts, but don't keep retrying if the channel doesn't exist (e.g. not configured) */
12573 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000 && errno != ENXIO) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12574 usleep(1);
12575 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12576 count++;
12577 }
12578 /* Allocate a DAHDI structure */
12579 if (tmp->subs[SUB_REAL].dfd < 0) {
12580 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);
12582 return NULL;
12583 }
12584 memset(&p, 0, sizeof(p));
12585 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12586 if (res < 0) {
12587 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12589 return NULL;
12590 }
12591 if (conf->is_sig_auto)
12592 chan_sig = sigtype_to_signalling(p.sigtype);
12593 if (p.sigtype != (chan_sig & 0x3ffff)) {
12594 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));
12596 return NULL;
12597 }
12598 tmp->law_default = p.curlaw;
12599 tmp->law = p.curlaw;
12600 tmp->span = p.spanno;
12601#if defined(HAVE_PRI)
12602 span = p.spanno - 1;
12603#endif /* defined(HAVE_PRI) */
12604 } else {
12605 chan_sig = 0;
12606 }
12607 tmp->sig = chan_sig;
12608 tmp->outsigmod = conf->chan.outsigmod;
12609
12610 if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12611 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12612 if (!analog_p) {
12614 return NULL;
12615 }
12616 tmp->sig_pvt = analog_p;
12617 }
12618#if defined(HAVE_SS7)
12619 if (chan_sig == SIG_SS7) {
12620 struct dahdi_ss7 *ss7;
12621 int clear = 0;
12622
12623 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12624 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12626 return NULL;
12627 }
12628
12629 ss7 = ss7_resolve_linkset(cur_linkset);
12630 if (!ss7) {
12631 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12633 return NULL;
12634 }
12635 ss7->ss7.span = cur_linkset;
12636 if (cur_cicbeginswith < 0) {
12637 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12639 return NULL;
12640 }
12641 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12642 if (!ss7_chan) {
12644 return NULL;
12645 }
12646 tmp->sig_pvt = ss7_chan;
12647 tmp->ss7 = &ss7->ss7;
12648
12649 ss7_chan->channel = tmp->channel;
12650 ss7_chan->cic = cur_cicbeginswith++;
12651
12652 /* DB: Add CIC's DPC information */
12653 ss7_chan->dpc = cur_defaultdpc;
12654
12655 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12656
12657 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12658 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12659 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12660 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12661 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12662
12663 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12664 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12665 }
12666#endif /* defined(HAVE_SS7) */
12667#ifdef HAVE_OPENR2
12668 if (chan_sig == SIG_MFCR2) {
12669 struct dahdi_mfcr2 *r2_link;
12670 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12671 r2_link = &r2_le->mfcr2;
12672 if (!r2_link) {
12673 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12675 return NULL;
12676 }
12677 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12678 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12680 return NULL;
12681 }
12682 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12683 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12685 return NULL;
12686 }
12687 r2_link->pvts[r2_link->numchans++] = tmp;
12688 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12689 tmp->subs[SUB_REAL].dfd,
12690 NULL, NULL);
12691 if (!tmp->r2chan) {
12692 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12693 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12695 return NULL;
12696 }
12697 r2_link->live_chans++;
12698 tmp->mfcr2 = r2_link;
12699 if (conf->mfcr2.call_files) {
12700 openr2_chan_enable_call_files(tmp->r2chan);
12701 }
12702 openr2_chan_set_client_data(tmp->r2chan, tmp);
12703 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12704 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12705 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12706 tmp->mfcr2_category = conf->mfcr2.category;
12707 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12708 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12709 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12710 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12711 tmp->mfcr2call = 0;
12712 tmp->mfcr2_dnis_index = 0;
12713 tmp->mfcr2_ani_index = 0;
12714 }
12715#endif
12716#ifdef HAVE_PRI
12717 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12718 int offset;
12719 int matchesdchan;
12720 int x,y;
12721 int myswitchtype = 0;
12722
12723 offset = 0;
12724 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12725 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12727 return NULL;
12728 }
12729 if (span >= NUM_SPANS) {
12730 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12732 return NULL;
12733 } else {
12734 si.spanno = 0;
12735 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12736 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12738 return NULL;
12739 }
12740 /* Store the logical span first based upon the real span */
12741 tmp->logicalspan = pris[span].prilogicalspan;
12742 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12743 if (span < 0) {
12744 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12746 return NULL;
12747 }
12748 myswitchtype = conf->pri.pri.switchtype;
12749 /* Make sure this isn't a d-channel */
12750 matchesdchan=0;
12751 for (x = 0; x < NUM_SPANS; x++) {
12752 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12753 if (pris[x].dchannels[y] == tmp->channel) {
12754 matchesdchan = 1;
12755 break;
12756 }
12757 }
12758 }
12759 if (!matchesdchan) {
12760 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12761 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12763 return NULL;
12764 }
12765 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12766 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12768 return NULL;
12769 }
12770 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12771 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12773 return NULL;
12774 }
12775 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12776 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12778 return NULL;
12779 }
12780 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12781 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12783 return NULL;
12784 }
12785 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12786 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12788 return NULL;
12789 }
12790 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12791 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12793 return NULL;
12794 }
12795 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12796 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12797 pris[span].pri.trunkgroup);
12799 return NULL;
12800 }
12801
12802 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12803 if (!pri_chan) {
12805 return NULL;
12806 }
12807 tmp->sig_pvt = pri_chan;
12808 tmp->pri = &pris[span].pri;
12809
12810 tmp->priexclusive = conf->chan.priexclusive;
12811
12812 if (!tmp->pri->cc_params) {
12813 tmp->pri->cc_params = ast_cc_config_params_init();
12814 if (!tmp->pri->cc_params) {
12816 return NULL;
12817 }
12818 }
12819 ast_cc_copy_config_params(tmp->pri->cc_params,
12820 conf->chan.cc_params);
12821
12822 pris[span].pri.sig = chan_sig;
12823 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12824 pris[span].pri.switchtype = myswitchtype;
12825 pris[span].pri.nsf = conf->pri.pri.nsf;
12826 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12827 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12828 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12829 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12830 pris[span].pri.minunused = conf->pri.pri.minunused;
12831 pris[span].pri.minidle = conf->pri.pri.minidle;
12832 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12833 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12834 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12835#if defined(HAVE_PRI_SERVICE_MESSAGES)
12836 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12837#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12838#ifdef HAVE_PRI_INBANDDISCONNECT
12839 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12840#endif
12841#if defined(HAVE_PRI_CALL_HOLD)
12842 pris[span].pri.hold_disconnect_transfer =
12843 conf->pri.pri.hold_disconnect_transfer;
12844#endif /* defined(HAVE_PRI_CALL_HOLD) */
12845#if defined(HAVE_PRI_CCSS)
12846 pris[span].pri.cc_ptmp_recall_mode =
12847 conf->pri.pri.cc_ptmp_recall_mode;
12848 pris[span].pri.cc_qsig_signaling_link_req =
12849 conf->pri.pri.cc_qsig_signaling_link_req;
12850 pris[span].pri.cc_qsig_signaling_link_rsp =
12851 conf->pri.pri.cc_qsig_signaling_link_rsp;
12852#endif /* defined(HAVE_PRI_CCSS) */
12853#if defined(HAVE_PRI_CALL_WAITING)
12854 pris[span].pri.max_call_waiting_calls =
12855 conf->pri.pri.max_call_waiting_calls;
12856 pris[span].pri.allow_call_waiting_calls =
12857 conf->pri.pri.allow_call_waiting_calls;
12858#endif /* defined(HAVE_PRI_CALL_WAITING) */
12859 pris[span].pri.transfer = conf->chan.transfer;
12860 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12861#if defined(HAVE_PRI_L2_PERSISTENCE)
12862 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12863#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12864 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12865#if defined(HAVE_PRI_AOC_EVENTS)
12866 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12867 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12868#endif /* defined(HAVE_PRI_AOC_EVENTS) */
12869 if (chan_sig == SIG_BRI_PTMP) {
12870 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12871 } else {
12872 /* Option does not apply to this line type. */
12873 pris[span].pri.layer1_ignored = 0;
12874 }
12875 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12876 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12877 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12878 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12879 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12880#if defined(HAVE_PRI_MWI)
12881 ast_copy_string(pris[span].pri.mwi_mailboxes,
12882 conf->pri.pri.mwi_mailboxes,
12883 sizeof(pris[span].pri.mwi_mailboxes));
12884 ast_copy_string(pris[span].pri.mwi_vm_boxes,
12885 conf->pri.pri.mwi_vm_boxes,
12886 sizeof(pris[span].pri.mwi_vm_boxes));
12887 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12888 conf->pri.pri.mwi_vm_numbers,
12889 sizeof(pris[span].pri.mwi_vm_numbers));
12890#endif /* defined(HAVE_PRI_MWI) */
12891 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12892 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12893 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12894 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12895 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12896 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12897 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12898 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12899 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12900#if defined(HAVE_PRI_DISPLAY_TEXT)
12901 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12902 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12903#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12904#if defined(HAVE_PRI_MCID)
12905 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12906#endif /* defined(HAVE_PRI_MCID) */
12907 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
12908#if defined(HAVE_PRI_DATETIME_SEND)
12909 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12910#endif /* defined(HAVE_PRI_DATETIME_SEND) */
12911
12912 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12913 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12914 }
12915
12916#if defined(HAVE_PRI_CALL_WAITING)
12917 /* Channel initial config parameters. */
12918 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12919 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12920 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12921 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12922 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12923 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12924 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12925 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12926 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12927 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12928#endif /* defined(HAVE_PRI_CALL_WAITING) */
12929 } else {
12930 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12932 return NULL;
12933 }
12934 }
12935 }
12936#endif
12937 } else {
12938 /* already exists in interface list */
12939 ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12940 chan_sig = tmp->sig;
12941 if (tmp->subs[SUB_REAL].dfd > -1) {
12942 memset(&p, 0, sizeof(p));
12943 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12944 }
12945 }
12946 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12947 switch (chan_sig) {
12948 case SIG_FXSKS:
12949 case SIG_FXSLS:
12950 case SIG_EM:
12951 case SIG_EM_E1:
12952 case SIG_EMWINK:
12953 case SIG_FEATD:
12954 case SIG_FEATDMF:
12955 case SIG_FEATDMF_TA:
12956 case SIG_FEATB:
12957 case SIG_E911:
12958 case SIG_SF:
12959 case SIG_SFWINK:
12960 case SIG_FGC_CAMA:
12961 case SIG_FGC_CAMAMF:
12962 case SIG_SF_FEATD:
12963 case SIG_SF_FEATDMF:
12964 case SIG_SF_FEATB:
12965 p.starttime = 250;
12966 break;
12967 }
12968
12969 if (tmp->radio) {
12970 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12971 p.channo = channel;
12972 p.rxwinktime = 1;
12973 p.rxflashtime = 1;
12974 p.starttime = 1;
12975 p.debouncetime = 5;
12976 } else {
12977 p.channo = channel;
12978 /* Override timing settings based on config file */
12979 if (conf->timing.prewinktime >= 0)
12980 p.prewinktime = conf->timing.prewinktime;
12981 if (conf->timing.preflashtime >= 0)
12982 p.preflashtime = conf->timing.preflashtime;
12983 if (conf->timing.winktime >= 0)
12984 p.winktime = conf->timing.winktime;
12985 if (conf->timing.flashtime >= 0)
12986 p.flashtime = conf->timing.flashtime;
12987 if (conf->timing.starttime >= 0)
12988 p.starttime = conf->timing.starttime;
12989 if (conf->timing.rxwinktime >= 0)
12990 p.rxwinktime = conf->timing.rxwinktime;
12991 if (conf->timing.rxflashtime >= 0)
12992 p.rxflashtime = conf->timing.rxflashtime;
12993 if (conf->timing.debouncetime >= 0)
12994 p.debouncetime = conf->timing.debouncetime;
12995 }
12996
12997 /* don't set parms on a pseudo-channel */
12998 if (tmp->subs[SUB_REAL].dfd >= 0)
12999 {
13000 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13001 if (res < 0) {
13002 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13004 return NULL;
13005 }
13006 }
13007#if 1
13008 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13009 memset(&bi, 0, sizeof(bi));
13010 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13011 if (!res) {
13012 bi.txbufpolicy = conf->chan.buf_policy;
13013 bi.rxbufpolicy = conf->chan.buf_policy;
13014 bi.numbufs = conf->chan.buf_no;
13015 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13016 if (res < 0) {
13017 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13018 }
13019 } else {
13020 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13021 }
13022 tmp->buf_policy = conf->chan.buf_policy;
13023 tmp->buf_no = conf->chan.buf_no;
13024 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13025 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13026 tmp->faxbuf_no = conf->chan.faxbuf_no;
13027 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
13028 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13029 * The reason the ioctl call above failed should to be determined before worrying about the
13030 * faxbuffer-related ioctl calls */
13031 tmp->bufsize = bi.bufsize;
13032 }
13033#endif
13034 tmp->immediate = conf->chan.immediate;
13035 tmp->immediatering = conf->chan.immediatering;
13036 tmp->transfertobusy = conf->chan.transfertobusy;
13037 tmp->dialmode = conf->chan.dialmode;
13038 if (chan_sig & __DAHDI_SIG_FXS) {
13039 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13040 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13041 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13042 }
13043 tmp->ringt_base = ringt_base;
13044 tmp->firstradio = 0;
13045 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13046 tmp->permcallwaiting = conf->chan.callwaiting;
13047 else
13048 tmp->permcallwaiting = 0;
13049 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
13050 tmp->destroy = 0;
13051 tmp->drings = conf->chan.drings;
13052
13053 /* 10 is a nice default. */
13054 if (tmp->drings.ringnum[0].range == 0)
13055 tmp->drings.ringnum[0].range = 10;
13056 if (tmp->drings.ringnum[1].range == 0)
13057 tmp->drings.ringnum[1].range = 10;
13058 if (tmp->drings.ringnum[2].range == 0)
13059 tmp->drings.ringnum[2].range = 10;
13060
13061 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13062 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13063 tmp->threewaycalling = conf->chan.threewaycalling;
13064 tmp->threewaysilenthold = conf->chan.threewaysilenthold;
13065 tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
13066 tmp->adsi = conf->chan.adsi;
13067 tmp->use_smdi = conf->chan.use_smdi;
13068 tmp->permhidecallerid = conf->chan.hidecallerid;
13069 tmp->hidecalleridname = conf->chan.hidecalleridname;
13070 tmp->callreturn = conf->chan.callreturn;
13071 tmp->echocancel = conf->chan.echocancel;
13072 tmp->echotraining = conf->chan.echotraining;
13073 tmp->pulse = conf->chan.pulse;
13074 if (tmp->echocancel.head.tap_length) {
13075 tmp->echocanbridged = conf->chan.echocanbridged;
13076 } else {
13077 if (conf->chan.echocanbridged)
13078 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13079 tmp->echocanbridged = 0;
13080 }
13081 tmp->busydetect = conf->chan.busydetect;
13082 tmp->busycount = conf->chan.busycount;
13083 tmp->busy_cadence = conf->chan.busy_cadence;
13084 tmp->callprogress = conf->chan.callprogress;
13085 tmp->waitfordialtone = conf->chan.waitfordialtone;
13086 tmp->dialtone_detect = conf->chan.dialtone_detect;
13087 tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
13088 tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
13089 tmp->interdigit_timeout = conf->chan.interdigit_timeout;
13090 tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
13091 tmp->cancallforward = conf->chan.cancallforward;
13092 tmp->dtmfrelax = conf->chan.dtmfrelax;
13093 tmp->callwaiting = tmp->permcallwaiting;
13094 tmp->hidecallerid = tmp->permhidecallerid;
13095 tmp->channel = channel;
13096 tmp->stripmsd = conf->chan.stripmsd;
13097 tmp->use_callerid = conf->chan.use_callerid;
13098 tmp->cid_signalling = conf->chan.cid_signalling;
13099 tmp->cid_start = conf->chan.cid_start;
13100 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13101 tmp->restrictcid = conf->chan.restrictcid;
13102 tmp->use_callingpres = conf->chan.use_callingpres;
13103 if (tmp->usedistinctiveringdetection) {
13104 if (!tmp->use_callerid) {
13105 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13106 tmp->use_callerid = 1;
13107 }
13108 }
13109
13110 if (tmp->cid_signalling == CID_SIG_SMDI) {
13111 if (!tmp->use_smdi) {
13112 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13113 tmp->use_smdi = 1;
13114 }
13115 }
13116 if (tmp->use_smdi) {
13117 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13118 if (!(tmp->smdi_iface)) {
13119 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13120 tmp->use_smdi = 0;
13121 }
13122 }
13123
13124 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13125 tmp->amaflags = conf->chan.amaflags;
13126 if (!here) {
13127 tmp->confno = -1;
13128 tmp->propconfno = -1;
13129 }
13130 tmp->canpark = conf->chan.canpark;
13131 tmp->transfer = conf->chan.transfer;
13132 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13133 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13134 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13135 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13136 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13137 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13138 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13139 tmp->cid_ton = 0;
13140 if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13141 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13142 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13143 } else {
13144 tmp->cid_num[0] = '\0';
13145 tmp->cid_name[0] = '\0';
13146 }
13147#if defined(HAVE_PRI)
13148 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13149 tmp->cid_tag[0] = '\0';
13150 } else
13151#endif /* defined(HAVE_PRI) */
13152 {
13153 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13154 }
13155 tmp->cid_subaddr[0] = '\0';
13156 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13157 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13158 /* This module does not handle MWI in an event-based manner. However, it
13159 * subscribes to MWI for each mailbox that is configured so that the core
13160 * knows that we care about it. Then, chan_dahdi will get the MWI from the
13161 * event cache instead of checking the mailbox directly. */
13162 tmp->mwi_event_sub = ast_mwi_subscribe_pool(tmp->mailbox, stasis_subscription_cb_noop, NULL);
13163 }
13164#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13165 tmp->mwisend_setting = conf->chan.mwisend_setting;
13166 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13167 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13168#endif
13169
13170 tmp->group = conf->chan.group;
13171 tmp->callgroup = conf->chan.callgroup;
13172 tmp->pickupgroup= conf->chan.pickupgroup;
13173 ast_unref_namedgroups(tmp->named_callgroups);
13174 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13175 ast_unref_namedgroups(tmp->named_pickupgroups);
13176 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13177 if (conf->chan.vars) {
13178 struct ast_variable *v, *tmpvar;
13179 for (v = conf->chan.vars ; v ; v = v->next) {
13180 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13181 if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13182 tmpvar->next = tmp->vars;
13183 tmp->vars = tmpvar;
13184 }
13185 }
13186 }
13187 }
13188 tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13189 tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13190 tmp->hwrxgain = conf->chan.hwrxgain;
13191 tmp->hwtxgain = conf->chan.hwtxgain;
13192 tmp->cid_rxgain = conf->chan.cid_rxgain;
13193 tmp->rxgain = conf->chan.rxgain;
13194 tmp->txgain = conf->chan.txgain;
13195 tmp->txdrc = conf->chan.txdrc;
13196 tmp->rxdrc = conf->chan.rxdrc;
13197 tmp->tonezone = conf->chan.tonezone;
13198 if (tmp->subs[SUB_REAL].dfd > -1) {
13199 if (tmp->hwrxgain_enabled) {
13200 tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13201 }
13202 if (tmp->hwtxgain_enabled) {
13203 tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13204 }
13205 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13206 if (tmp->dsp)
13207 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13209 if (!here) {
13210 switch (chan_sig) {
13212 case SIG_SS7:
13213 case SIG_MFCR2:
13214 break;
13215 default:
13216 /* Hang it up to be sure it's good */
13217 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13218 break;
13219 }
13220 }
13221 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13222 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13223 /* the dchannel is down so put the channel in alarm */
13224 switch (tmp->sig) {
13225#ifdef HAVE_PRI
13227 sig_pri_set_alarm(tmp->sig_pvt, 1);
13228 break;
13229#endif
13230#if defined(HAVE_SS7)
13231 case SIG_SS7:
13232 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13233 break;
13234#endif /* defined(HAVE_SS7) */
13235 default:
13236 /* The only sig submodule left should be sig_analog. */
13237 analog_p = tmp->sig_pvt;
13238 if (analog_p) {
13239 analog_p->inalarm = 1;
13240 }
13241 tmp->inalarm = 1;
13242 break;
13243 }
13244 handle_alarms(tmp, res);
13245 }
13246 }
13247
13248 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13249 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13250 tmp->ani_info_digits = conf->chan.ani_info_digits;
13251 tmp->ani_wink_time = conf->chan.ani_wink_time;
13252 tmp->ani_timeout = conf->chan.ani_timeout;
13253 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13254 tmp->reoriginate = conf->chan.reoriginate;
13255 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13256 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13257
13258 if (!here) {
13259 tmp->locallyblocked = 0;
13260 tmp->remotelyblocked = 0;
13261 switch (tmp->sig) {
13262#if defined(HAVE_PRI)
13264 tmp->inservice = 1;/* Inservice until actually implemented. */
13265#if defined(HAVE_PRI_SERVICE_MESSAGES)
13266 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13267 if (chan_sig == SIG_PRI) {
13268 char db_chan_name[20];
13269 char db_answer[5];
13270
13271 /*
13272 * Initialize the active out-of-service status
13273 * and delete any record if the feature is not enabled.
13274 */
13275 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13276 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13277 unsigned *why;
13278
13279 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13280 if (tmp->pri->enable_service_message_support) {
13281 char state;
13282
13283 sscanf(db_answer, "%1c:%30u", &state, why);
13284
13285 /* Ensure that only the implemented bits could be set.*/
13286 *why &= (SRVST_NEAREND | SRVST_FAREND);
13287 }
13288 if (!*why) {
13289 ast_db_del(db_chan_name, SRVST_DBKEY);
13290 }
13291 }
13292 }
13293#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13294 break;
13295#endif /* defined(HAVE_PRI) */
13296#if defined(HAVE_SS7)
13297 case SIG_SS7:
13298 tmp->inservice = 0;
13299 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13300 tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
13301 }
13302 break;
13303#endif /* defined(HAVE_SS7) */
13304 default:
13305 /* We default to in service on protocols that don't have a reset */
13306 tmp->inservice = 1;
13307 break;
13308 }
13309 }
13310
13311 switch (tmp->sig) {
13312#if defined(HAVE_PRI)
13314 if (pri_chan) {
13315 pri_chan->channel = tmp->channel;
13316 pri_chan->hidecallerid = tmp->hidecallerid;
13317 pri_chan->hidecalleridname = tmp->hidecalleridname;
13318 pri_chan->immediate = tmp->immediate;
13319 pri_chan->inalarm = tmp->inalarm;
13320 pri_chan->priexclusive = tmp->priexclusive;
13321 pri_chan->priindication_oob = tmp->priindication_oob;
13322 pri_chan->use_callerid = tmp->use_callerid;
13323 pri_chan->use_callingpres = tmp->use_callingpres;
13324 ast_copy_string(pri_chan->context, tmp->context,
13325 sizeof(pri_chan->context));
13326 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13327 sizeof(pri_chan->mohinterpret));
13328 pri_chan->stripmsd = tmp->stripmsd;
13329 }
13330 break;
13331#endif /* defined(HAVE_PRI) */
13332#if defined(HAVE_SS7)
13333 case SIG_SS7:
13334 if (ss7_chan) {
13335 ss7_chan->inalarm = tmp->inalarm;
13336 ss7_chan->inservice = tmp->inservice;
13337
13338 ss7_chan->stripmsd = tmp->stripmsd;
13339 ss7_chan->hidecallerid = tmp->hidecallerid;
13340 ss7_chan->use_callerid = tmp->use_callerid;
13341 ss7_chan->use_callingpres = tmp->use_callingpres;
13342 ss7_chan->immediate = tmp->immediate;
13343 ss7_chan->locallyblocked = tmp->locallyblocked;
13344 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13345 ast_copy_string(ss7_chan->context, tmp->context,
13346 sizeof(ss7_chan->context));
13347 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13348 sizeof(ss7_chan->mohinterpret));
13349 }
13350 break;
13351#endif /* defined(HAVE_SS7) */
13352 default:
13353 /* The only sig submodule left should be sig_analog. */
13354 analog_p = tmp->sig_pvt;
13355 if (analog_p) {
13356 analog_p->channel = tmp->channel;
13357 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13358 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13359 analog_p->ani_info_digits = conf->chan.ani_info_digits;
13360 analog_p->ani_timeout = conf->chan.ani_timeout;
13361 analog_p->ani_wink_time = conf->chan.ani_wink_time;
13362 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13363 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13364 analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13365 analog_p->callreturn = conf->chan.callreturn;
13366 analog_p->cancallforward = conf->chan.cancallforward;
13367 analog_p->canpark = conf->chan.canpark;
13368 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13369 analog_p->immediate = conf->chan.immediate;
13370 analog_p->immediatering = conf->chan.immediatering;
13371 analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13372 /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13373 analog_p->pulse = conf->chan.pulse;
13374 analog_p->threewaycalling = conf->chan.threewaycalling;
13375 analog_p->transfer = conf->chan.transfer;
13376 analog_p->transfertobusy = conf->chan.transfertobusy;
13377 analog_p->dialmode = conf->chan.dialmode;
13378 analog_p->use_callerid = tmp->use_callerid;
13379 analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
13380 analog_p->use_smdi = tmp->use_smdi;
13381 analog_p->smdi_iface = tmp->smdi_iface;
13382 analog_p->outsigmod = ANALOG_SIG_NONE;
13383 analog_p->echotraining = conf->chan.echotraining;
13384 analog_p->cid_signalling = conf->chan.cid_signalling;
13385 analog_p->stripmsd = conf->chan.stripmsd;
13386 switch (conf->chan.cid_start) {
13387 case CID_START_POLARITY:
13389 break;
13392 break;
13395 break;
13396 default:
13397 analog_p->cid_start = ANALOG_CID_START_RING;
13398 break;
13399 }
13400 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13401 analog_p->ringt = conf->chan.ringt;
13402 analog_p->ringt_base = ringt_base;
13403 analog_p->onhooktime = time(NULL);
13404 if (chan_sig & __DAHDI_SIG_FXO) {
13405 memset(&p, 0, sizeof(p));
13406 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13407 if (!res) {
13408 analog_p->fxsoffhookstate = p.rxisoffhook;
13409 }
13410#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13411 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13412#endif
13413 }
13414 analog_p->msgstate = -1;
13415
13416 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13417 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13418 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13419
13420 analog_config_complete(analog_p);
13421 }
13422 break;
13423 }
13424#if defined(HAVE_PRI)
13425 if (tmp->channel == CHAN_PSEUDO) {
13426 /*
13427 * Save off pseudo channel buffer policy values for dynamic creation of
13428 * no B channel interfaces.
13429 */
13430 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13431 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13432 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13433 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13434 }
13435#endif /* defined(HAVE_PRI) */
13436 }
13437 if (tmp && !here) {
13438 /* Add the new channel interface to the sorted channel interface list. */
13440 }
13441 return tmp;
13442}
13443
13444static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13445{
13446#if defined(HAVE_PRI)
13447 if (0 < span) {
13448 /* The channel must be on the specified PRI span. */
13449 if (!p->pri || p->pri->span != span) {
13450 return 0;
13451 }
13452 if (!groupmatch && channelmatch == -1) {
13453 /* Match any group since it only needs to be on the PRI span. */
13454 *groupmatched = 1;
13455 return 1;
13456 }
13457 }
13458#endif /* defined(HAVE_PRI) */
13459 /* check group matching */
13460 if (groupmatch) {
13461 if ((p->group & groupmatch) != groupmatch)
13462 /* Doesn't match the specified group, try the next one */
13463 return 0;
13464 *groupmatched = 1;
13465 }
13466 /* Check to see if we have a channel match */
13467 if (channelmatch != -1) {
13468 if (p->channel != channelmatch)
13469 /* Doesn't match the specified channel, try the next one */
13470 return 0;
13471 *channelmatched = 1;
13472 }
13473
13474 return 1;
13475}
13476
13477static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13478{
13479 struct dahdi_pvt *p = *pvt;
13480
13481 if (p->inalarm)
13482 return 0;
13483
13484 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13485 return analog_available(p->sig_pvt);
13486
13487 switch (p->sig) {
13488#if defined(HAVE_PRI)
13490 {
13491 struct sig_pri_chan *pvt_chan;
13492 int res;
13493
13494 pvt_chan = p->sig_pvt;
13495 res = sig_pri_available(&pvt_chan, is_specific_channel);
13496 *pvt = pvt_chan->chan_pvt;
13497 return res;
13498 }
13499#endif /* defined(HAVE_PRI) */
13500#if defined(HAVE_SS7)
13501 case SIG_SS7:
13502 return sig_ss7_available(p->sig_pvt);
13503#endif /* defined(HAVE_SS7) */
13504 default:
13505 break;
13506 }
13507
13508 if (p->locallyblocked || p->remotelyblocked) {
13509 return 0;
13510 }
13511
13512 /* If no owner definitely available */
13513 if (!p->owner) {
13514#ifdef HAVE_OPENR2
13515 /* Trust MFC/R2 */
13516 if (p->mfcr2) {
13517 if (p->mfcr2call) {
13518 return 0;
13519 } else {
13520 return 1;
13521 }
13522 }
13523#endif
13524 return 1;
13525 }
13526
13527 return 0;
13528}
13529
13530#if defined(HAVE_PRI)
13531#if defined(HAVE_PRI_CALL_WAITING)
13532/*!
13533 * \internal
13534 * \brief Init the private channel configuration using the span controller.
13535 * \since 1.8
13536 *
13537 * \param priv Channel to init the configuration.
13538 * \param pri sig_pri PRI control structure.
13539 *
13540 * \note Assumes the pri->lock is already obtained.
13541 */
13542static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13543{
13544 struct dahdi_pvt *pvt = priv;
13545
13546 pvt->stripmsd = pri->ch_cfg.stripmsd;
13547 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13548 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13549 pvt->immediate = pri->ch_cfg.immediate;
13550 pvt->priexclusive = pri->ch_cfg.priexclusive;
13551 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13552 pvt->use_callerid = pri->ch_cfg.use_callerid;
13553 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13554 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13555 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13556}
13557#endif /* defined(HAVE_PRI_CALL_WAITING) */
13558#endif /* defined(HAVE_PRI) */
13559
13560#if defined(HAVE_PRI)
13561/*!
13562 * \internal
13563 * \brief Create a no B channel interface.
13564 * \since 1.8
13565 *
13566 * \param pri sig_pri span controller to add interface.
13567 *
13568 * \note Assumes the pri->lock is already obtained.
13569 *
13570 * \retval array-index into private pointer array on success.
13571 * \retval -1 on error.
13572 */
13573static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13574{
13575 int pvt_idx;
13576 int res;
13577 unsigned idx;
13578 struct dahdi_pvt *pvt;
13579 struct sig_pri_chan *chan;
13580 struct dahdi_bufferinfo bi;
13581
13582 static int nobch_channel = CHAN_PSEUDO;
13583
13584 /* Find spot in the private pointer array for new interface. */
13585 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13586 if (!pri->pvts[pvt_idx]) {
13587 break;
13588 }
13589 }
13590 if (pri->numchans == pvt_idx) {
13591 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13592 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13593 return -1;
13594 }
13595
13596 /* Add new spot to the private pointer array. */
13597 pri->pvts[pvt_idx] = NULL;
13598 ++pri->numchans;
13599 }
13600
13601 pvt = ast_calloc(1, sizeof(*pvt));
13602 if (!pvt) {
13603 return -1;
13604 }
13606 if (!pvt->cc_params) {
13607 ast_free(pvt);
13608 return -1;
13609 }
13610 ast_mutex_init(&pvt->lock);
13611 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13612 pvt->subs[idx].dfd = -1;
13613 }
13614 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13615 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13616 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13617 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13618
13619 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13620 if (!chan) {
13621 destroy_dahdi_pvt(pvt);
13622 return -1;
13623 }
13624 chan->no_b_channel = 1;
13625
13626 /*
13627 * Pseudo channel companding law.
13628 * Needed for outgoing call waiting calls.
13629 * XXX May need to make this determined by switchtype or user option.
13630 */
13631 pvt->law_default = DAHDI_LAW_ALAW;
13632
13633 pvt->sig = pri->sig;
13634 pvt->outsigmod = -1;
13635 pvt->pri = pri;
13636 pvt->sig_pvt = chan;
13637 pri->pvts[pvt_idx] = chan;
13638
13639 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13640 if (pvt->subs[SUB_REAL].dfd < 0) {
13641 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13642 strerror(errno));
13643 destroy_dahdi_pvt(pvt);
13644 return -1;
13645 }
13646 memset(&bi, 0, sizeof(bi));
13647 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13648 if (!res) {
13649 pvt->bufsize = bi.bufsize;
13650 bi.txbufpolicy = pvt->buf_policy;
13651 bi.rxbufpolicy = pvt->buf_policy;
13652 bi.numbufs = pvt->buf_no;
13653 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13654 if (res < 0) {
13656 "Unable to set buffer policy on no B channel interface: %s\n",
13657 strerror(errno));
13658 }
13659 } else
13661 "Unable to check buffer policy on no B channel interface: %s\n",
13662 strerror(errno));
13663
13664 --nobch_channel;
13665 if (CHAN_PSEUDO < nobch_channel) {
13666 nobch_channel = CHAN_PSEUDO - 1;
13667 }
13668 pvt->channel = nobch_channel;
13669 pvt->span = pri->span;
13670 chan->channel = pvt->channel;
13671
13672 dahdi_nobch_insert(pri, pvt);
13673
13674 return pvt_idx;
13675}
13676#endif /* defined(HAVE_PRI) */
13677
13678/* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13679 structures; it makes no attempt to safely copy regular channel private
13680 structures that might contain reference-counted object pointers and other
13681 scary bits
13682*/
13683static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13684{
13685 struct dahdi_pvt *p;
13686 struct dahdi_bufferinfo bi;
13687 int res;
13688
13689 p = ast_malloc(sizeof(*p));
13690 if (!p) {
13691 return NULL;
13692 }
13693 *p = *src;
13694
13695 /* Must deep copy the cc_params. */
13697 if (!p->cc_params) {
13698 ast_free(p);
13699 return NULL;
13700 }
13702
13704 p->next = NULL;
13705 p->prev = NULL;
13706 ast_mutex_init(&p->lock);
13707 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13708 if (p->subs[SUB_REAL].dfd < 0) {
13709 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13711 return NULL;
13712 }
13713 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13714 if (!res) {
13715 bi.txbufpolicy = src->buf_policy;
13716 bi.rxbufpolicy = src->buf_policy;
13717 bi.numbufs = src->buf_no;
13718 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13719 if (res < 0) {
13720 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13721 }
13722 } else
13723 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13724 p->destroy = 1;
13726 return p;
13727}
13728
13730 /*! Group matching mask. Zero if not specified. */
13732 /*! DAHDI channel to match with. -1 if not specified. */
13734 /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13736 /*! ISDN span where channels can be picked (Zero if not specified) */
13737 int span;
13738 /*! Analog channel distinctive ring cadence index. */
13740 /*! Dialing option. c/r/d if present and valid. */
13741 char opt;
13742 /*! TRUE if to search the channel list backwards. */
13744 /*! TRUE if search is done with round robin sequence. */
13746};
13747static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13748{
13749 char *dest;
13750 char *s;
13751 int x;
13752 int res = 0;
13753 struct dahdi_pvt *p;
13754 char *subdir = NULL;
13756 AST_APP_ARG(group); /* channel/group token */
13757 //AST_APP_ARG(ext); /* extension token */
13758 //AST_APP_ARG(opts); /* options token */
13759 AST_APP_ARG(other); /* Any remining unused arguments */
13760 );
13761
13762 /*
13763 * data is ---v
13764 * Dial(DAHDI/pseudo[/extension[/options]])
13765 * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13766 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13767 * Dial(DAHDI/i<span>[/extension[/options]])
13768 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13769 *
13770 * i - ISDN span channel restriction.
13771 * Used by CC to ensure that the CC recall goes out the same span.
13772 * Also to make ISDN channel names dialable when the sequence number
13773 * is stripped off. (Used by DTMF attended transfer feature.)
13774 *
13775 * g - channel group allocation search forward
13776 * G - channel group allocation search backward
13777 * r - channel group allocation round robin search forward
13778 * R - channel group allocation round robin search backward
13779 *
13780 * c - Wait for DTMF digit to confirm answer
13781 * r<cadence#> - Set distinctive ring cadence number
13782 * d - Force bearer capability for ISDN/SS7 call to digital.
13783 */
13784
13785 if (data) {
13786 dest = ast_strdupa(data);
13787 } else {
13788 ast_log(LOG_WARNING, "Channel requested with no data\n");
13789 return NULL;
13790 }
13791 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13792 if (!args.argc || ast_strlen_zero(args.group)) {
13793 ast_log(LOG_WARNING, "No channel/group specified\n");
13794 return NULL;
13795 }
13796
13797 /* Initialize the output parameters */
13798 memset(param, 0, sizeof(*param));
13799 param->channelmatch = -1;
13800
13801 if (strchr(args.group, '!') != NULL) {
13802 char *prev = args.group;
13803 while ((s = strchr(prev, '!')) != NULL) {
13804 *s++ = '/';
13805 prev = s;
13806 }
13807 *(prev - 1) = '\0';
13808 subdir = args.group;
13809 args.group = prev;
13810 } else if (args.group[0] == 'i') {
13811 /* Extract the ISDN span channel restriction specifier. */
13812 res = sscanf(args.group + 1, "%30d", &x);
13813 if (res < 1) {
13814 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13815 return NULL;
13816 }
13817 param->span = x;
13818
13819 /* Remove the ISDN span channel restriction specifier. */
13820 s = strchr(args.group, '-');
13821 if (!s) {
13822 /* Search all groups since we are ISDN span restricted. */
13823 return iflist;
13824 }
13825 args.group = s + 1;
13826 res = 0;
13827 }
13828 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13829 /* Retrieve the group number */
13830 s = args.group + 1;
13831 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13832 if (res < 1) {
13833 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13834 return NULL;
13835 }
13836 param->groupmatch = ((ast_group_t) 1 << x);
13837
13838 if (toupper(args.group[0]) == 'G') {
13839 if (args.group[0] == 'G') {
13840 param->backwards = 1;
13841 p = ifend;
13842 } else
13843 p = iflist;
13844 } else {
13845 if (ARRAY_LEN(round_robin) <= x) {
13846 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13847 x, data);
13848 return NULL;
13849 }
13850 if (args.group[0] == 'R') {
13851 param->backwards = 1;
13852 p = round_robin[x] ? round_robin[x]->prev : ifend;
13853 if (!p)
13854 p = ifend;
13855 } else {
13856 p = round_robin[x] ? round_robin[x]->next : iflist;
13857 if (!p)
13858 p = iflist;
13859 }
13860 param->roundrobin = 1;
13861 param->rr_starting_point = x;
13862 }
13863 } else {
13864 s = args.group;
13865 if (!strcasecmp(s, "pseudo")) {
13866 /* Special case for pseudo */
13867 x = CHAN_PSEUDO;
13868 param->channelmatch = x;
13869 } else {
13870 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13871 if (res < 1) {
13872 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13873 return NULL;
13874 } else {
13875 param->channelmatch = x;
13876 }
13877 }
13878 if (subdir) {
13879 char path[PATH_MAX];
13880 struct stat stbuf;
13881
13882 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13883 subdir, param->channelmatch);
13884 if (stat(path, &stbuf) < 0) {
13885 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13886 path, strerror(errno));
13887 return NULL;
13888 }
13889 if (!S_ISCHR(stbuf.st_mode)) {
13890 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13891 path);
13892 return NULL;
13893 }
13894 param->channelmatch = minor(stbuf.st_rdev);
13895 }
13896
13897 p = iflist;
13898 }
13899
13900 if (param->opt == 'r' && res < 3) {
13901 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13902 param->opt = '\0';
13903 }
13904
13905 return p;
13906}
13907
13908static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
13909 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
13910 const char *data, int *cause)
13911{
13912 int callwait = 0;
13913 struct dahdi_pvt *p;
13914 struct ast_channel *tmp = NULL;
13915 struct dahdi_pvt *exitpvt;
13916 int channelmatched = 0;
13917 int foundowner = 0;
13918 int groupmatched = 0;
13919#if defined(HAVE_PRI) || defined(HAVE_SS7)
13920 int transcapdigital = 0;
13921#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13922 struct dahdi_starting_point start;
13923 ast_callid callid = 0;
13924 int callid_created = ast_callid_threadstorage_auto(&callid);
13925
13927 p = determine_starting_point(data, &start);
13928 if (!p) {
13929 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13931 ast_callid_threadstorage_auto_clean(callid, callid_created);
13932 return NULL;
13933 }
13934
13935 /* Search for an unowned channel */
13936 exitpvt = p;
13937 while (p && !tmp) {
13938 if (start.roundrobin)
13939 round_robin[start.rr_starting_point] = p;
13940
13941 if (p->owner) {
13942 foundowner++;
13943 }
13944
13945 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13946 && available(&p, channelmatched)) {
13947 ast_debug(1, "Using channel %d\n", p->channel);
13948
13949 callwait = (p->owner != NULL);
13950#ifdef HAVE_OPENR2
13951 if (p->mfcr2) {
13952 ast_mutex_lock(&p->lock);
13953 if (p->mfcr2call) {
13955 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13956 goto next;
13957 }
13958 p->mfcr2call = 1;
13960 }
13961#endif
13962 if (p->channel == CHAN_PSEUDO) {
13963 p = duplicate_pseudo(p);
13964 if (!p) {
13965 break;
13966 }
13967 }
13968
13969 p->distinctivering = 0;
13970 /* Make special notes */
13971 switch (start.opt) {
13972 case '\0':
13973 /* No option present. */
13974 break;
13975 case 'c':
13976 /* Confirm answer */
13977 p->confirmanswer = 1;
13978 break;
13979 case 'r':
13980 /* Distinctive ring */
13981 p->distinctivering = start.cadence;
13982 break;
13983 case 'd':
13984#if defined(HAVE_PRI) || defined(HAVE_SS7)
13985 /* If this is an ISDN call, make it digital */
13986 transcapdigital = AST_TRANS_CAP_DIGITAL;
13987#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13988 break;
13989 default:
13990 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13991 break;
13992 }
13993
13994 p->outgoing = 1;
13995 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13996 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13997#ifdef HAVE_PRI
13998 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13999 /*
14000 * We already have the B channel reserved for this call. We
14001 * just need to make sure that dahdi_hangup() has completed
14002 * cleaning up before continuing.
14003 */
14004 ast_mutex_lock(&p->lock);
14006
14008 sizeof(p->dnid));
14009 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
14010#endif
14011#if defined(HAVE_SS7)
14012 } else if (p->sig == SIG_SS7) {
14013 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
14014#endif /* defined(HAVE_SS7) */
14015 } else {
14016 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
14017 }
14018 if (!tmp) {
14019 p->outgoing = 0;
14020#if defined(HAVE_PRI)
14021 switch (p->sig) {
14023#if defined(HAVE_PRI_CALL_WAITING)
14024 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14025 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14026 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14027 }
14028#endif /* defined(HAVE_PRI_CALL_WAITING) */
14029 /*
14030 * This should be the last thing to clear when we are done with
14031 * the channel.
14032 */
14033 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14034 break;
14035 default:
14036 break;
14037 }
14038#endif /* defined(HAVE_PRI) */
14039 } else {
14040 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14041 }
14042 break;
14043 }
14044#ifdef HAVE_OPENR2
14045next:
14046#endif
14047 if (start.backwards) {
14048 p = p->prev;
14049 if (!p)
14050 p = ifend;
14051 } else {
14052 p = p->next;
14053 if (!p)
14054 p = iflist;
14055 }
14056 /* stop when you roll to the one that we started from */
14057 if (p == exitpvt)
14058 break;
14059 }
14062 if (cause && !tmp) {
14063 if (callwait || (channelmatched && foundowner)) {
14064 *cause = AST_CAUSE_BUSY;
14065 } else if (groupmatched) {
14066 *cause = AST_CAUSE_CONGESTION;
14067 } else {
14068 /*
14069 * We did not match any channel requested.
14070 * Dialplan error requesting non-existant channel?
14071 */
14072 }
14073 }
14074
14075 ast_callid_threadstorage_auto_clean(callid, callid_created);
14076 return tmp;
14077}
14078
14079/*!
14080 * \internal
14081 * \brief Determine the device state for a given DAHDI device if we can.
14082 * \since 1.8
14083 *
14084 * \param data DAHDI device name after "DAHDI/".
14085 *
14086 * \retval device_state enum ast_device_state value.
14087 * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
14088 */
14089static int dahdi_devicestate(const char *data)
14090{
14091#if defined(HAVE_PRI)
14092 const char *device;
14093 unsigned span;
14094 int res;
14095
14096 device = data;
14097
14098 if (*device != 'I') {
14099 /* The request is not for an ISDN span device. */
14100 return AST_DEVICE_UNKNOWN;
14101 }
14102 res = sscanf(device, "I%30u", &span);
14103 if (res != 1 || !span || NUM_SPANS < span) {
14104 /* Bad format for ISDN span device name. */
14105 return AST_DEVICE_UNKNOWN;
14106 }
14107 device = strchr(device, '/');
14108 if (!device) {
14109 /* Bad format for ISDN span device name. */
14110 return AST_DEVICE_UNKNOWN;
14111 }
14112
14113 /*
14114 * Since there are currently no other span devstate's defined,
14115 * it must be congestion.
14116 */
14117#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14118 ++device;
14119 if (!strcmp(device, "congestion"))
14120#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14121 {
14122 return pris[span - 1].pri.congestion_devstate;
14123 }
14124#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14125 else if (!strcmp(device, "threshold")) {
14126 return pris[span - 1].pri.threshold_devstate;
14127 }
14128 return AST_DEVICE_UNKNOWN;
14129#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14130#else
14131 return AST_DEVICE_UNKNOWN;
14132#endif /* defined(HAVE_PRI) */
14133}
14134
14135/*!
14136 * \brief Callback made when dial failed to get a channel out of dahdi_request().
14137 * \since 1.8
14138 *
14139 * \param inbound Incoming asterisk channel.
14140 * \param dest Same dial string passed to dahdi_request().
14141 * \param callback Callback into CC core to announce a busy channel available for CC.
14142 *
14143 * \details
14144 * This callback acts like a forked dial with all prongs of the fork busy.
14145 * Essentially, for each channel that could have taken the call, indicate that
14146 * it is busy.
14147 *
14148 * \retval 0 on success.
14149 * \retval -1 on error.
14150 */
14151static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14152{
14153 struct dahdi_pvt *p;
14154 struct dahdi_pvt *exitpvt;
14155 struct dahdi_starting_point start;
14156 int groupmatched = 0;
14157 int channelmatched = 0;
14158
14160 p = determine_starting_point(dest, &start);
14161 if (!p) {
14163 return -1;
14164 }
14165 exitpvt = p;
14166 for (;;) {
14167 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14168 /* We found a potential match. call the callback */
14169 struct ast_str *device_name;
14170 char *dash;
14171 const char *monitor_type;
14172 char dialstring[AST_CHANNEL_NAME];
14173 char full_device_name[AST_CHANNEL_NAME];
14174
14177 break;
14181#if defined(HAVE_PRI)
14183 /*
14184 * ISDN is in a trunk busy condition so we need to monitor
14185 * the span congestion device state.
14186 */
14187 snprintf(full_device_name, sizeof(full_device_name),
14188 "DAHDI/I%d/congestion", p->pri->span);
14189 } else
14190#endif /* defined(HAVE_PRI) */
14191 {
14192#if defined(HAVE_PRI)
14193 device_name = create_channel_name(p, 1, "");
14194#else
14195 device_name = create_channel_name(p);
14196#endif /* defined(HAVE_PRI) */
14197 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14198 device_name ? ast_str_buffer(device_name) : "");
14199 ast_free(device_name);
14200 /*
14201 * The portion after the '-' in the channel name is either a random
14202 * number, a sequence number, or a subchannel number. None are
14203 * necessary so strip them off.
14204 */
14205 dash = strrchr(full_device_name, '-');
14206 if (dash) {
14207 *dash = '\0';
14208 }
14209 }
14210 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14211
14212 /*
14213 * Analog can only do generic monitoring.
14214 * ISDN is in a trunk busy condition and any "device" is going
14215 * to be busy until a B channel becomes available. The generic
14216 * monitor can do this task.
14217 */
14218 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14219 callback(inbound,
14220#if defined(HAVE_PRI)
14221 p->pri ? p->pri->cc_params : p->cc_params,
14222#else
14223 p->cc_params,
14224#endif /* defined(HAVE_PRI) */
14225 monitor_type, full_device_name, dialstring, NULL);
14226 break;
14227 }
14228 }
14229 p = start.backwards ? p->prev : p->next;
14230 if (!p) {
14231 p = start.backwards ? ifend : iflist;
14232 }
14233 if (p == exitpvt) {
14234 break;
14235 }
14236 }
14238 return 0;
14239}
14240
14241#if defined(HAVE_SS7)
14242static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14243{
14244 int i;
14245
14246 if (ss7) {
14247 for (i = 0; i < NUM_SPANS; i++) {
14248 if (linksets[i].ss7.ss7 == ss7) {
14249 ast_verbose_callid(0, "[%d] %s", i + 1, s);
14250 return;
14251 }
14252 }
14253 }
14254 ast_verbose_callid(0, "%s", s);
14255}
14256#endif /* defined(HAVE_SS7) */
14257
14258#if defined(HAVE_SS7)
14259static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14260{
14261 int i;
14262
14263 if (ss7) {
14264 for (i = 0; i < NUM_SPANS; i++) {
14265 if (linksets[i].ss7.ss7 == ss7) {
14266 ast_log_callid(LOG_ERROR, 0, "[%d] %s", i + 1, s);
14267 return;
14268 }
14269 }
14270 }
14271 ast_log_callid(LOG_ERROR, 0, "%s", s);
14272}
14273#endif /* defined(HAVE_SS7) */
14274
14275#if defined(HAVE_OPENR2)
14276static void *mfcr2_monitor(void *data)
14277{
14278 struct dahdi_mfcr2 *mfcr2 = data;
14279 struct dahdi_pvt *pvt;
14280
14281 /* we should be using pthread_key_create
14282 and allocate pollers dynamically.
14283 I think do_monitor() could be leaking, since it
14284 could be cancelled at any time and is not
14285 using thread keys, why?, */
14286 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14287 int res = 0;
14288 int i = 0;
14289 int oldstate = 0;
14290 int quit_loop = 0;
14291 int maxsleep = 20;
14292 int was_idle = 0;
14293 int pollsize = 0;
14294 /* now that we're ready to get calls, unblock our side and
14295 get current line state */
14296 for (i = 0; i < mfcr2->numchans; i++) {
14297 pvt = mfcr2->pvts[i];
14298 if (!pvt) {
14299 continue;
14300 }
14301 openr2_chan_set_idle(pvt->r2chan);
14302 openr2_chan_handle_cas(pvt->r2chan);
14303 }
14304 while (1) {
14305 /* we trust here that the mfcr2 channel list will not ever change once
14306 the module is loaded */
14307 pollsize = 0;
14308 for (i = 0; i < mfcr2->numchans; i++) {
14309 pollers[i].revents = 0;
14310 pollers[i].events = 0;
14311 pvt = mfcr2->pvts[i];
14312 if (!pvt) {
14313 continue;
14314 }
14315 if (pvt->owner) {
14316 continue;
14317 }
14318 if (mfcr2->nodev) {
14319 continue;
14320 }
14321 if (!pvt->r2chan) {
14322 ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);
14323 quit_loop = 1;
14324 break;
14325 }
14326 openr2_chan_enable_read(pvt->r2chan);
14327 pollers[i].events = POLLIN | POLLPRI;
14328 pollers[i].fd = pvt->subs[SUB_REAL].dfd;
14329 pollsize++;
14330 }
14331 if (quit_loop) {
14332 break;
14333 }
14334 if (pollsize == 0) {
14335 if (!was_idle) {
14336 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14337 was_idle = 1;
14338 }
14339 poll(NULL, 0, maxsleep);
14340 continue;
14341 }
14342 was_idle = 0;
14343 /* probably poll() is a valid cancel point, lets just be on the safe side
14344 by calling pthread_testcancel */
14345 pthread_testcancel();
14346 res = poll(pollers, mfcr2->numchans, maxsleep);
14347 pthread_testcancel();
14348 if ((res < 0) && (errno != EINTR)) {
14349 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14350 break;
14351 }
14352 /* do we want to allow to cancel while processing events? */
14353 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14354 for (i = 0; i < mfcr2->numchans; i++) {
14355 pvt = mfcr2->pvts[i];
14356 if (!pvt) {
14357 continue;
14358 }
14359 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14360 openr2_chan_process_event(pvt->r2chan);
14361 }
14362 }
14363 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14364 }
14365 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14366 return 0;
14367}
14368#endif /* HAVE_OPENR2 */
14369
14370#if defined(HAVE_PRI)
14371static void dahdi_pri_message(struct pri *pri, char *s)
14372{
14373 int x;
14374 int y;
14375 int dchan = -1;
14376 int span = -1;
14377 int dchancount = 0;
14378
14379 if (pri) {
14380 for (x = 0; x < NUM_SPANS; x++) {
14381 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14382 if (pris[x].pri.dchans[y]) {
14383 dchancount++;
14384 }
14385
14386 if (pris[x].pri.dchans[y] == pri) {
14387 dchan = y;
14388 }
14389 }
14390 if (dchan >= 0) {
14391 span = x;
14392 break;
14393 }
14394 dchancount = 0;
14395 }
14396 if (-1 < span) {
14397 if (1 < dchancount) {
14398 ast_verbose_callid(0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14399 } else {
14400 ast_verbose_callid(0, "PRI Span: %d %s", span + 1, s);
14401 }
14402 } else {
14403 ast_verbose_callid(0, "PRI Span: ? %s", s);
14404 }
14405 } else {
14406 ast_verbose_callid(0, "PRI Span: ? %s", s);
14407 }
14408
14409 ast_mutex_lock(&pridebugfdlock);
14410
14411 if (pridebugfd >= 0) {
14412 if (write(pridebugfd, s, strlen(s)) < 0) {
14413 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14414 }
14415 }
14416
14417 ast_mutex_unlock(&pridebugfdlock);
14418}
14419#endif /* defined(HAVE_PRI) */
14420
14421#if defined(HAVE_PRI)
14422static void dahdi_pri_error(struct pri *pri, char *s)
14423{
14424 int x;
14425 int y;
14426 int dchan = -1;
14427 int span = -1;
14428 int dchancount = 0;
14429
14430 if (pri) {
14431 for (x = 0; x < NUM_SPANS; x++) {
14432 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14433 if (pris[x].pri.dchans[y]) {
14434 dchancount++;
14435 }
14436
14437 if (pris[x].pri.dchans[y] == pri) {
14438 dchan = y;
14439 }
14440 }
14441 if (dchan >= 0) {
14442 span = x;
14443 break;
14444 }
14445 dchancount = 0;
14446 }
14447 if (-1 < span) {
14448 if (1 < dchancount) {
14449 ast_log_callid(LOG_ERROR, 0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14450 } else {
14451 ast_log_callid(LOG_ERROR, 0, "PRI Span: %d %s", span + 1, s);
14452 }
14453 } else {
14454 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14455 }
14456 } else {
14457 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14458 }
14459
14460 ast_mutex_lock(&pridebugfdlock);
14461
14462 if (pridebugfd >= 0) {
14463 if (write(pridebugfd, s, strlen(s)) < 0) {
14464 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14465 }
14466 }
14467
14468 ast_mutex_unlock(&pridebugfdlock);
14469}
14470#endif /* defined(HAVE_PRI) */
14471
14472#if defined(HAVE_PRI)
14473static int prepare_pri(struct dahdi_pri *pri)
14474{
14475 int i, res, x;
14476 struct dahdi_params p;
14477 struct dahdi_bufferinfo bi;
14478 struct dahdi_spaninfo si;
14479
14480 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14481 if (!pri->dchannels[i])
14482 break;
14483 if (pri->pri.fds[i] >= 0) {
14484 /* A partial range addition. Not a complete setup. */
14485 break;
14486 }
14487 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14488 if ((pri->pri.fds[i] < 0)) {
14489 ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
14490 pri->pri.fds[i], strerror(errno));
14491 return -1;
14492 }
14493 x = pri->dchannels[i];
14494 res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
14495 if (res) {
14496 dahdi_close_pri_fd(pri, i);
14497 ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14498 return -1;
14499 }
14500 memset(&p, 0, sizeof(p));
14501 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14502 if (res) {
14503 dahdi_close_pri_fd(pri, i);
14504 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14505 return -1;
14506 }
14507 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14508 dahdi_close_pri_fd(pri, i);
14509 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14510 return -1;
14511 }
14512 memset(&si, 0, sizeof(si));
14513 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14514 if (res) {
14515 dahdi_close_pri_fd(pri, i);
14516 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14517 }
14518 if (!si.alarms) {
14519 pri_event_noalarm(&pri->pri, i, 1);
14520 } else {
14521 pri_event_alarm(&pri->pri, i, 1);
14522 }
14523 memset(&bi, 0, sizeof(bi));
14524 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14525 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14526 bi.numbufs = 32;
14527 bi.bufsize = 1024;
14528 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14529 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14530 dahdi_close_pri_fd(pri, i);
14531 return -1;
14532 }
14533 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14534 }
14535 return 0;
14536}
14537#endif /* defined(HAVE_PRI) */
14538
14539#if defined(HAVE_PRI)
14540static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14541{
14542 int which, span;
14543 char *ret = NULL;
14544
14545 if (pos != rpos)
14546 return ret;
14547
14548 for (which = span = 0; span < NUM_SPANS; span++) {
14549 if (pris[span].pri.pri && ++which > state) {
14550 if (ast_asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14551 ret = NULL;
14552 }
14553 break;
14554 }
14555 }
14556 return ret;
14557}
14558#endif /* defined(HAVE_PRI) */
14559
14560#if defined(HAVE_PRI)
14561static char *complete_span_4(const char *line, const char *word, int pos, int state)
14562{
14563 return complete_span_helper(line,word,pos,state,3);
14564}
14565#endif /* defined(HAVE_PRI) */
14566
14567#if defined(HAVE_PRI)
14568static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14569{
14570 int myfd;
14571 switch (cmd) {
14572 case CLI_INIT:
14573 e->command = "pri set debug file";
14574 e->usage = "Usage: pri set debug file [output-file]\n"
14575 " Sends PRI debug output to the specified output file\n";
14576 return NULL;
14577 case CLI_GENERATE:
14578 return NULL;
14579 }
14580 if (a->argc < 5)
14581 return CLI_SHOWUSAGE;
14582
14583 if (ast_strlen_zero(a->argv[4]))
14584 return CLI_SHOWUSAGE;
14585
14586 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14587 if (myfd < 0) {
14588 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14589 return CLI_SUCCESS;
14590 }
14591
14592 ast_mutex_lock(&pridebugfdlock);
14593
14594 if (pridebugfd >= 0)
14595 close(pridebugfd);
14596
14597 pridebugfd = myfd;
14598 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14599 ast_mutex_unlock(&pridebugfdlock);
14600 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14601 return CLI_SUCCESS;
14602}
14603#endif /* defined(HAVE_PRI) */
14604
14605#if defined(HAVE_PRI)
14606static int action_pri_debug_file_set(struct mansession *s, const struct message *m)
14607{
14608 const char *output_file = astman_get_header(m, "File");
14609 int myfd;
14610
14611 if (ast_strlen_zero(output_file)) {
14612 astman_send_error(s, m, "Action must define a 'File'");
14613 }
14614
14615 myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14616 if (myfd < 0) {
14617 astman_send_error(s, m, "Unable to open requested file for writing");
14618 return 0;
14619 }
14620
14621 ast_mutex_lock(&pridebugfdlock);
14622
14623 if (pridebugfd >= 0) {
14624 close(pridebugfd);
14625 }
14626
14627 pridebugfd = myfd;
14628 ast_copy_string(pridebugfilename, output_file, sizeof(pridebugfilename));
14629 ast_mutex_unlock(&pridebugfdlock);
14630 astman_send_ack(s, m, "PRI debug output will now be sent to requested file.");
14631
14632 return 0;
14633}
14634#endif /* defined(HAVE_PRI) */
14635
14636#if defined(HAVE_PRI)
14637static int action_pri_debug_file_unset(struct mansession *s, const struct message *m)
14638{
14639 ast_mutex_lock(&pridebugfdlock);
14640
14641 if (pridebugfd >= 0) {
14642 close(pridebugfd);
14643 }
14644
14645 pridebugfd = -1;
14646
14647 ast_mutex_unlock(&pridebugfdlock);
14648
14649 astman_send_ack(s, m, "PRI Debug output to file disabled");
14650 return 0;
14651}
14652#endif /* defined(HAVE_PRI) */
14653
14654#if defined(HAVE_PRI)
14655static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14656{
14657 int span;
14658 int x;
14659 int debugmask = 0;
14660 int level = 0;
14661 switch (cmd) {
14662 case CLI_INIT:
14663 e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14664 e->usage =
14665 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14666 " Enables debugging on a given PRI span\n"
14667 " Level is a bitmap of the following values:\n"
14668 " 1 General debugging incl. state changes\n"
14669 " 2 Decoded Q.931 messages\n"
14670 " 4 Decoded Q.921 messages\n"
14671 " 8 Raw hex dumps of Q.921 frames\n"
14672 " on - equivalent to 3\n"
14673 " hex - equivalent to 8\n"
14674 " intense - equivalent to 15\n";
14675 return NULL;
14676 case CLI_GENERATE:
14677 return complete_span_4(a->line, a->word, a->pos, a->n);
14678 }
14679 if (a->argc < 6) {
14680 return CLI_SHOWUSAGE;
14681 }
14682
14683 if (!strcasecmp(a->argv[3], "on")) {
14684 level = 3;
14685 } else if (!strcasecmp(a->argv[3], "off")) {
14686 level = 0;
14687 } else if (!strcasecmp(a->argv[3], "intense")) {
14688 level = 15;
14689 } else if (!strcasecmp(a->argv[3], "hex")) {
14690 level = 8;
14691 } else {
14692 level = atoi(a->argv[3]);
14693 }
14694 span = atoi(a->argv[5]);
14695 if ((span < 1) || (span > NUM_SPANS)) {
14696 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14697 return CLI_SUCCESS;
14698 }
14699 if (!pris[span-1].pri.pri) {
14700 ast_cli(a->fd, "No PRI running on span %d\n", span);
14701 return CLI_SUCCESS;
14702 }
14703
14704 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14705 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14706 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14707 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14708
14709 /* Set debug level in libpri */
14710 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14711 if (pris[span - 1].pri.dchans[x]) {
14712 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14713 }
14714 }
14715 if (level == 0) {
14716 /* Close the debugging file if it's set */
14717 ast_mutex_lock(&pridebugfdlock);
14718 if (0 <= pridebugfd) {
14719 close(pridebugfd);
14720 pridebugfd = -1;
14721 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14722 pridebugfilename);
14723 }
14724 ast_mutex_unlock(&pridebugfdlock);
14725 }
14726 pris[span - 1].pri.debug = (level) ? 1 : 0;
14727 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14728 return CLI_SUCCESS;
14729}
14730#endif /* defined(HAVE_PRI) */
14731
14732#if defined(HAVE_PRI)
14733static int action_pri_debug_set(struct mansession *s, const struct message *m)
14734{
14735 const char *level = astman_get_header(m, "Level");
14736 const char *span = astman_get_header(m, "Span");
14737 int level_val;
14738 int span_val;
14739 int x;
14740 int debugmask = 0;
14741
14742 if (ast_strlen_zero(level)) {
14743 astman_send_error(s, m, "'Level' was not specified");
14744 return 0;
14745 }
14746
14747 if (ast_strlen_zero(span)) {
14748 astman_send_error(s, m, "'Span' was not specified");
14749 return 0;
14750 }
14751
14752 if (!strcasecmp(level, "on")) {
14753 level_val = 3;
14754 } else if (!strcasecmp(level, "off")) {
14755 level_val = 0;
14756 } else if (!strcasecmp(level, "intense")) {
14757 level_val = 15;
14758 } else if (!strcasecmp(level, "hex")) {
14759 level_val = 8;
14760 } else {
14761 if (sscanf(level, "%30d", &level_val) != 1) {
14762 astman_send_error(s, m, "Invalid value for 'Level'");
14763 return 0;
14764 }
14765 }
14766
14767 if (sscanf(span, "%30d", &span_val) != 1) {
14768 astman_send_error(s, m, "Invalid value for 'Span'");
14769 }
14770
14771 if ((span_val < 1) || (span_val > NUM_SPANS)) {
14772 const char *id = astman_get_header(m, "ActionID");
14773 char id_text[256] = "";
14774
14775 if (!ast_strlen_zero(id)) {
14776 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
14777 }
14778
14779 astman_append(s, "Response: Error\r\n"
14780 "%s" /* id_text */
14781 "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14782 "\r\n",
14783 id_text,
14784 span, NUM_SPANS);
14785
14786 return 0;
14787 }
14788
14789 if (!pris[span_val-1].pri.pri) {
14790 astman_send_error(s, m, "No PRI running on requested span");
14791 return 0;
14792 }
14793
14794 if (level_val & 1) {
14795 debugmask |= SIG_PRI_DEBUG_NORMAL;
14796 }
14797 if (level_val & 2) {
14798 debugmask |= PRI_DEBUG_Q931_DUMP;
14799 }
14800 if (level_val & 4) {
14801 debugmask |= PRI_DEBUG_Q921_DUMP;
14802 }
14803 if (level_val & 8) {
14804 debugmask |= PRI_DEBUG_Q921_RAW;
14805 }
14806
14807 /* Set debug level in libpri */
14808 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14809 if (pris[span_val - 1].pri.dchans[x]) {
14810 pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14811 }
14812 }
14813
14814 pris[span_val - 1].pri.debug = (level_val) ? 1 : 0;
14815 astman_send_ack(s, m, "Debug level set for requested span");
14816
14817 return 0;
14818}
14819#endif /* defined(HAVE_PRI) */
14820
14821#if defined(HAVE_PRI)
14822#if defined(HAVE_PRI_SERVICE_MESSAGES)
14823static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14824{
14825 unsigned *why;
14826 int channel;
14827 int trunkgroup;
14828 int x, y, fd = a->fd;
14829 int interfaceid = 0;
14830 char db_chan_name[20], db_answer[15];
14831 struct dahdi_pvt *tmp;
14832 struct dahdi_pri *pri;
14833
14834 if (a->argc < 5 || a->argc > 6)
14835 return CLI_SHOWUSAGE;
14836 if (strchr(a->argv[4], ':')) {
14837 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14838 return CLI_SHOWUSAGE;
14839 if ((trunkgroup < 1) || (channel < 1))
14840 return CLI_SHOWUSAGE;
14841 pri = NULL;
14842 for (x=0;x<NUM_SPANS;x++) {
14843 if (pris[x].pri.trunkgroup == trunkgroup) {
14844 pri = pris + x;
14845 break;
14846 }
14847 }
14848 if (!pri) {
14849 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14850 return CLI_FAILURE;
14851 }
14852 } else
14853 channel = atoi(a->argv[4]);
14854
14855 if (a->argc == 6)
14856 interfaceid = atoi(a->argv[5]);
14857
14858 /* either servicing a D-Channel */
14859 for (x = 0; x < NUM_SPANS; x++) {
14860 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14861 if (pris[x].dchannels[y] == channel) {
14862 pri = pris + x;
14863 if (pri->pri.enable_service_message_support) {
14864 ast_mutex_lock(&pri->pri.lock);
14865 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14866 ast_mutex_unlock(&pri->pri.lock);
14867 } else {
14868 ast_cli(fd,
14869 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14870 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14871 }
14872 return CLI_SUCCESS;
14873 }
14874 }
14875 }
14876
14877 /* or servicing a B-Channel */
14879 for (tmp = iflist; tmp; tmp = tmp->next) {
14880 if (tmp->pri && tmp->channel == channel) {
14882 ast_mutex_lock(&tmp->pri->lock);
14883 if (!tmp->pri->enable_service_message_support) {
14884 ast_mutex_unlock(&tmp->pri->lock);
14885 ast_cli(fd,
14886 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14887 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14888 return CLI_SUCCESS;
14889 }
14890 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14891 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14892 switch(changestatus) {
14893 case 0: /* enable */
14894 /* Near end wants to be in service now. */
14895 ast_db_del(db_chan_name, SRVST_DBKEY);
14896 *why &= ~SRVST_NEAREND;
14897 if (*why) {
14898 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14899 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14900 } else {
14901 dahdi_pri_update_span_devstate(tmp->pri);
14902 }
14903 break;
14904 /* case 1: -- loop */
14905 case 2: /* disable */
14906 /* Near end wants to be out-of-service now. */
14907 ast_db_del(db_chan_name, SRVST_DBKEY);
14908 *why |= SRVST_NEAREND;
14909 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14910 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14911 dahdi_pri_update_span_devstate(tmp->pri);
14912 break;
14913 /* case 3: -- continuity */
14914 /* case 4: -- shutdown */
14915 default:
14916 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14917 break;
14918 }
14919 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14920 ast_mutex_unlock(&tmp->pri->lock);
14921 return CLI_SUCCESS;
14922 }
14923 }
14925
14926 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14927 return CLI_FAILURE;
14928}
14929
14930static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14931{
14932 switch (cmd) {
14933 case CLI_INIT:
14934 e->command = "pri service enable channel";
14935 e->usage =
14936 "Usage: pri service enable channel <channel> [<interface id>]\n"
14937 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14938 " to restore a channel to service, with optional interface id\n"
14939 " as agreed upon with remote switch operator\n";
14940 return NULL;
14941 case CLI_GENERATE:
14942 return NULL;
14943 }
14944 return handle_pri_service_generic(e, cmd, a, 0);
14945}
14946
14947static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14948{
14949 switch (cmd) {
14950 case CLI_INIT:
14951 e->command = "pri service disable channel";
14952 e->usage =
14953 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14954 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14955 " to remove a channel from service, with optional interface id\n"
14956 " as agreed upon with remote switch operator\n";
14957 return NULL;
14958 case CLI_GENERATE:
14959 return NULL;
14960 }
14961 return handle_pri_service_generic(e, cmd, a, 2);
14962}
14963#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14964#endif /* defined(HAVE_PRI) */
14965
14966#if defined(HAVE_PRI)
14967static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14968{
14969 int span;
14970
14971 switch (cmd) {
14972 case CLI_INIT:
14973 e->command = "pri show channels";
14974 e->usage =
14975 "Usage: pri show channels\n"
14976 " Displays PRI channel information such as the current mapping\n"
14977 " of DAHDI B channels to Asterisk channel names and which calls\n"
14978 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14979 " are not associated with any B channel.\n";
14980 return NULL;
14981 case CLI_GENERATE:
14982 return NULL;
14983 }
14984
14985 if (a->argc != 3)
14986 return CLI_SHOWUSAGE;
14987
14989 for (span = 0; span < NUM_SPANS; ++span) {
14990 if (pris[span].pri.pri) {
14991 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14992 }
14993 }
14994 return CLI_SUCCESS;
14995}
14996#endif /* defined(HAVE_PRI) */
14997
14998#if defined(HAVE_PRI)
14999static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15000{
15001 int span;
15002
15003 switch (cmd) {
15004 case CLI_INIT:
15005 e->command = "pri show spans";
15006 e->usage =
15007 "Usage: pri show spans\n"
15008 " Displays PRI span information\n";
15009 return NULL;
15010 case CLI_GENERATE:
15011 return NULL;
15012 }
15013
15014 if (a->argc != 3)
15015 return CLI_SHOWUSAGE;
15016
15017 for (span = 0; span < NUM_SPANS; span++) {
15018 if (pris[span].pri.pri) {
15019 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
15020 }
15021 }
15022 return CLI_SUCCESS;
15023}
15024#endif /* defined(HAVE_PRI) */
15025
15026#if defined(HAVE_PRI)
15027#define container_of(ptr, type, member) \
15028 ((type *)((char *)(ptr) - offsetof(type, member)))
15029/*!
15030 * \internal
15031 * \brief Destroy a D-Channel of a PRI span
15032 * \since 12
15033 *
15034 * \param pri the pri span
15035 *
15036 * Shuts down a span and destroys its D-Channel. Further destruction
15037 * of the B-channels using dahdi_destroy_channel() would probably be required
15038 * for the B-Channels.
15039 */
15040static void pri_destroy_span(struct sig_pri_span *pri)
15041{
15042 int i;
15043 int res;
15044 int cancel_code;
15045 struct dahdi_pri* dahdi_pri;
15046 pthread_t master = pri->master;
15047
15048 if (!master || (master == AST_PTHREADT_NULL)) {
15049 return;
15050 }
15051 ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
15052 for (i = 0; i < pri->numchans; i++) {
15053 int channel;
15054 struct sig_pri_chan *pvt = pri->pvts[i];
15055
15056 if (!pvt) {
15057 continue;
15058 }
15059 channel = pvt->channel;
15060 ast_debug(2, "About to destroy B-channel %d.\n", channel);
15062 }
15063
15064 cancel_code = pthread_cancel(master);
15065 pthread_kill(master, SIGURG);
15066 ast_debug(4,
15067 "Waiting to join thread of span %d "
15068 "with pid=%p cancel_code=%d\n",
15069 pri->span, (void *)master, cancel_code);
15070 res = pthread_join(master, NULL);
15071 if (res != 0) {
15072 ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
15073 }
15075
15076 /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
15077 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
15078 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
15079 ast_debug(4, "closing pri_fd %d\n", i);
15080 dahdi_close_pri_fd(dahdi_pri, i);
15081 dahdi_pri->dchannels[i] = 0;
15082 }
15084 ast_debug(1, "PRI span %d destroyed\n", pri->span);
15085}
15086
15087static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
15088 struct ast_cli_args *a)
15089{
15090 int span;
15091 int res;
15092 struct sig_pri_span *pri;
15093
15094 switch (cmd) {
15095 case CLI_INIT:
15096 e->command = "pri destroy span";
15097 e->usage =
15098 "Usage: pri destroy span <span>\n"
15099 " Destorys D-channel of span and its B-channels.\n"
15100 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15101 return NULL;
15102 case CLI_GENERATE:
15103 return complete_span_4(a->line, a->word, a->pos, a->n);
15104 }
15105
15106 if (a->argc < 4) {
15107 return CLI_SHOWUSAGE;
15108 }
15109 res = sscanf(a->argv[3], "%30d", &span);
15110 if ((res != 1) || span < 1 || span > NUM_SPANS) {
15111 ast_cli(a->fd,
15112 "Invalid span '%s'. Should be a number from %d to %d\n",
15113 a->argv[3], 1, NUM_SPANS);
15114 return CLI_SUCCESS;
15115 }
15116 pri = &pris[span - 1].pri;
15117 if (!pri->pri) {
15118 ast_cli(a->fd, "No PRI running on span %d\n", span);
15119 return CLI_SUCCESS;
15120 }
15121
15122 pri_destroy_span(pri);
15123 return CLI_SUCCESS;
15124}
15125
15126#endif /* defined(HAVE_PRI) */
15127
15128#if defined(HAVE_PRI)
15129static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15130{
15131 int span;
15132
15133 switch (cmd) {
15134 case CLI_INIT:
15135 e->command = "pri show span";
15136 e->usage =
15137 "Usage: pri show span <span>\n"
15138 " Displays PRI Information on a given PRI span\n";
15139 return NULL;
15140 case CLI_GENERATE:
15141 return complete_span_4(a->line, a->word, a->pos, a->n);
15142 }
15143
15144 if (a->argc < 4)
15145 return CLI_SHOWUSAGE;
15146 span = atoi(a->argv[3]);
15147 if ((span < 1) || (span > NUM_SPANS)) {
15148 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15149 return CLI_SUCCESS;
15150 }
15151 if (!pris[span-1].pri.pri) {
15152 ast_cli(a->fd, "No PRI running on span %d\n", span);
15153 return CLI_SUCCESS;
15154 }
15155
15156 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15157
15158 return CLI_SUCCESS;
15159}
15160#endif /* defined(HAVE_PRI) */
15161
15162#if defined(HAVE_PRI)
15163static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15164{
15165 int x;
15166 int span;
15167 int count=0;
15168 int debug;
15169
15170 switch (cmd) {
15171 case CLI_INIT:
15172 e->command = "pri show debug";
15173 e->usage =
15174 "Usage: pri show debug\n"
15175 " Show the debug state of pri spans\n";
15176 return NULL;
15177 case CLI_GENERATE:
15178 return NULL;
15179 }
15180
15181 for (span = 0; span < NUM_SPANS; span++) {
15182 if (pris[span].pri.pri) {
15183 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15184 if (pris[span].pri.dchans[x]) {
15185 debug = pri_get_debug(pris[span].pri.dchans[x]);
15186 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" );
15187 count++;
15188 }
15189 }
15190 }
15191
15192 }
15193 ast_mutex_lock(&pridebugfdlock);
15194 if (pridebugfd >= 0)
15195 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15196 ast_mutex_unlock(&pridebugfdlock);
15197
15198 if (!count)
15199 ast_cli(a->fd, "No PRI running\n");
15200 return CLI_SUCCESS;
15201}
15202#endif /* defined(HAVE_PRI) */
15203
15204#if defined(HAVE_PRI)
15205static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15206{
15207 switch (cmd) {
15208 case CLI_INIT:
15209 e->command = "pri show version";
15210 e->usage =
15211 "Usage: pri show version\n"
15212 "Show libpri version information\n";
15213 return NULL;
15214 case CLI_GENERATE:
15215 return NULL;
15216 }
15217
15218 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15219
15220 return CLI_SUCCESS;
15221}
15222#endif /* defined(HAVE_PRI) */
15223
15224#if defined(HAVE_PRI)
15225static struct ast_cli_entry dahdi_pri_cli[] = {
15226 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15227#if defined(HAVE_PRI_SERVICE_MESSAGES)
15228 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15229 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15230#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15231 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15232 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15233 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15234 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15235 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15236 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15237 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15238};
15239#endif /* defined(HAVE_PRI) */
15240
15241#ifdef HAVE_OPENR2
15242
15243static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15244{
15245 switch (cmd) {
15246 case CLI_INIT:
15247 e->command = "mfcr2 show version";
15248 e->usage =
15249 "Usage: mfcr2 show version\n"
15250 " Shows the version of the OpenR2 library being used.\n";
15251 return NULL;
15252 case CLI_GENERATE:
15253 return NULL;
15254 }
15255 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15256 return CLI_SUCCESS;
15257}
15258
15259static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15260{
15261#define FORMAT "%4s %40s\n"
15262 int i = 0;
15263 int numvariants = 0;
15264 const openr2_variant_entry_t *variants;
15265 switch (cmd) {
15266 case CLI_INIT:
15267 e->command = "mfcr2 show variants";
15268 e->usage =
15269 "Usage: mfcr2 show variants\n"
15270 " Shows the list of MFC/R2 variants supported.\n";
15271 return NULL;
15272 case CLI_GENERATE:
15273 return NULL;
15274 }
15275 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15276 ast_cli(a->fd, "Failed to get list of variants.\n");
15277 return CLI_FAILURE;
15278 }
15279 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15280 for (i = 0; i < numvariants; i++) {
15281 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15282 }
15283 return CLI_SUCCESS;
15284#undef FORMAT
15285}
15286
15287static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15288{
15289#define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15290 int filtertype = 0;
15291 int targetnum = 0;
15292 char channo[5];
15293 char linkno[5];
15294 char anino[5];
15295 char dnisno[5];
15296 struct dahdi_pvt *p;
15297 openr2_context_t *r2context;
15298 openr2_variant_t r2variant;
15299 switch (cmd) {
15300 case CLI_INIT:
15301 e->command = "mfcr2 show channels [group|context]";
15302 e->usage =
15303 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15304 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15305 return NULL;
15306 case CLI_GENERATE:
15307 return NULL;
15308 }
15309 if (!((a->argc == 3) || (a->argc == 5))) {
15310 return CLI_SHOWUSAGE;
15311 }
15312 if (a->argc == 5) {
15313 if (!strcasecmp(a->argv[3], "group")) {
15314 targetnum = atoi(a->argv[4]);
15315 if ((targetnum < 0) || (targetnum > 63))
15316 return CLI_SHOWUSAGE;
15317 targetnum = 1 << targetnum;
15318 filtertype = 1;
15319 } else if (!strcasecmp(a->argv[3], "context")) {
15320 filtertype = 2;
15321 } else {
15322 return CLI_SHOWUSAGE;
15323 }
15324 }
15325 ast_cli(a->fd, FORMAT, "Chan", "Link#", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15327 for (p = iflist; p; p = p->next) {
15328 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15329 continue;
15330 }
15331 if (filtertype) {
15332 switch(filtertype) {
15333 case 1: /* mfcr2 show channels group <group> */
15334 if (p->group != targetnum) {
15335 continue;
15336 }
15337 break;
15338 case 2: /* mfcr2 show channels context <context> */
15339 if (strcasecmp(p->context, a->argv[4])) {
15340 continue;
15341 }
15342 break;
15343 default:
15344 ;
15345 }
15346 }
15347 r2context = openr2_chan_get_context(p->r2chan);
15348 r2variant = openr2_context_get_variant(r2context);
15349 snprintf(channo, sizeof(channo), "%d", p->channel);
15350 snprintf(linkno, sizeof(linkno), "%d", p->mfcr2->index);
15351 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15352 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15353 ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
15354 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15355 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15356 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15357 }
15359 return CLI_SUCCESS;
15360#undef FORMAT
15361}
15362
15363static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15364{
15365 struct dahdi_pvt *p = NULL;
15366 int channo = 0;
15367 char *toklevel = NULL;
15368 char *saveptr = NULL;
15369 char *logval = NULL;
15370 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15371 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15372 switch (cmd) {
15373 case CLI_INIT:
15374 e->command = "mfcr2 set debug";
15375 e->usage =
15376 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15377 " Set a new logging level for the specified channel.\n"
15378 " If no channel is specified the logging level will be applied to all channels.\n";
15379 return NULL;
15380 case CLI_GENERATE:
15381 return NULL;
15382 }
15383 if (a->argc < 4) {
15384 return CLI_SHOWUSAGE;
15385 }
15386 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15387 logval = ast_strdupa(a->argv[3]);
15388 toklevel = strtok_r(logval, ",", &saveptr);
15389 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15390 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15391 return CLI_FAILURE;
15392 } else if (OR2_LOG_NOTHING == tmplevel) {
15393 loglevel = tmplevel;
15394 } else {
15395 loglevel |= tmplevel;
15396 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15397 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15398 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15399 continue;
15400 }
15401 loglevel |= tmplevel;
15402 }
15403 }
15405 for (p = iflist; p; p = p->next) {
15406 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15407 continue;
15408 }
15409 if ((channo != -1) && (p->channel != channo )) {
15410 continue;
15411 }
15412 openr2_chan_set_log_level(p->r2chan, loglevel);
15413 if (channo != -1) {
15414 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15415 break;
15416 }
15417 }
15418 if ((channo != -1) && !p) {
15419 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15420 }
15421 if (channo == -1) {
15422 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15423 }
15425 return CLI_SUCCESS;
15426}
15427
15428static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15429{
15430 struct dahdi_pvt *p = NULL;
15431 int channo = 0;
15432 switch (cmd) {
15433 case CLI_INIT:
15434 e->command = "mfcr2 call files [on|off]";
15435 e->usage =
15436 "Usage: mfcr2 call files [on|off] <channel>\n"
15437 " Enable call files creation on the specified channel.\n"
15438 " If no channel is specified call files creation policy will be applied to all channels.\n";
15439 return NULL;
15440 case CLI_GENERATE:
15441 return NULL;
15442 }
15443 if (a->argc < 4) {
15444 return CLI_SHOWUSAGE;
15445 }
15446 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15448 for (p = iflist; p; p = p->next) {
15449 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15450 continue;
15451 }
15452 if ((channo != -1) && (p->channel != channo )) {
15453 continue;
15454 }
15455 if (ast_true(a->argv[3])) {
15456 openr2_chan_enable_call_files(p->r2chan);
15457 } else {
15458 openr2_chan_disable_call_files(p->r2chan);
15459 }
15460 if (channo != -1) {
15461 if (ast_true(a->argv[3])) {
15462 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15463 } else {
15464 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15465 }
15466 break;
15467 }
15468 }
15469 if ((channo != -1) && !p) {
15470 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15471 }
15472 if (channo == -1) {
15473 if (ast_true(a->argv[3])) {
15474 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15475 } else {
15476 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15477 }
15478 }
15480 return CLI_SUCCESS;
15481}
15482
15483static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15484{
15485 struct dahdi_pvt *p = NULL;
15486 int channo = 0;
15487 switch (cmd) {
15488 case CLI_INIT:
15489 e->command = "mfcr2 set idle";
15490 e->usage =
15491 "Usage: mfcr2 set idle <channel>\n"
15492 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15493 " Force the given channel into IDLE state.\n"
15494 " If no channel is specified, all channels will be set to IDLE.\n";
15495 return NULL;
15496 case CLI_GENERATE:
15497 return NULL;
15498 }
15499 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15501 for (p = iflist; p; p = p->next) {
15502 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15503 continue;
15504 }
15505 if ((channo != -1) && (p->channel != channo )) {
15506 continue;
15507 }
15508 openr2_chan_set_idle(p->r2chan);
15509 ast_mutex_lock(&p->lock);
15510 p->locallyblocked = 0;
15511 p->mfcr2call = 0;
15513 if (channo != -1) {
15514 break;
15515 }
15516 }
15517 if ((channo != -1) && !p) {
15518 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15519 }
15521 return CLI_SUCCESS;
15522}
15523
15524static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15525{
15526 struct dahdi_pvt *p = NULL;
15527 int channo = 0;
15528 switch (cmd) {
15529 case CLI_INIT:
15530 e->command = "mfcr2 set blocked";
15531 e->usage =
15532 "Usage: mfcr2 set blocked <channel>\n"
15533 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15534 " Force the given channel into BLOCKED state.\n"
15535 " If no channel is specified, all channels will be set to BLOCKED.\n";
15536 return NULL;
15537 case CLI_GENERATE:
15538 return NULL;
15539 }
15540 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15542 for (p = iflist; p; p = p->next) {
15543 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15544 continue;
15545 }
15546 if ((channo != -1) && (p->channel != channo )) {
15547 continue;
15548 }
15549 openr2_chan_set_blocked(p->r2chan);
15550 ast_mutex_lock(&p->lock);
15551 p->locallyblocked = 1;
15553 if (channo != -1) {
15554 break;
15555 }
15556 }
15557 if ((channo != -1) && !p) {
15558 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15559 }
15561 return CLI_SUCCESS;
15562}
15563
15564static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_head, const char *title)
15565{
15566#define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15567 AST_LIST_LOCK(list_head);
15568 if (! AST_LIST_EMPTY(list_head)) {
15569 int x = 0;
15570 char index[5];
15571 char live_chans_str[5];
15572 char channel_list[R2_LINK_CAPACITY * 4];
15573 struct r2link_entry *cur;
15574 ast_cli(a->fd, "%s\n", title);
15575 ast_cli(a->fd, FORMAT, "Index", "Thread", "Dahdi-Device", "Channels", "Channel-List");
15576 AST_LIST_TRAVERSE(list_head, cur, list) {
15577 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15578 const char *thread_status = NULL;
15579 int i;
15580 int len;
15581 int inside_range;
15582 int channo;
15583 int prev_channo;
15584 x++;
15585 if (mfcr2->r2master == 0L) {
15586 thread_status = "zero";
15587 } else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15588 thread_status = "none";
15589 } else {
15590 thread_status = "created";
15591 }
15592 snprintf(index, sizeof(index), "%d", mfcr2->index);
15593 snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
15594 channo = 0;
15595 prev_channo = 0;
15596 inside_range = 0;
15597 len = 0;
15598 /* Prepare nice string in channel_list[] */
15599 for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
15600 struct dahdi_pvt *p = mfcr2->pvts[i];
15601 if (!p) {
15602 continue;
15603 }
15604 channo = p->channel;
15605 /* Don't show a range until we know the last channel number */
15606 if (prev_channo && prev_channo == channo - 1) {
15607 prev_channo = channo;
15608 inside_range = 1;
15609 continue;
15610 }
15611 if (inside_range) {
15612 /* Close range */
15613 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d,%d", prev_channo, channo);
15614 inside_range = 0;
15615 } else if (prev_channo) {
15616 /* Non-sequential channel numbers */
15617 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15618 } else {
15619 /* First channel number */
15620 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "%d", channo);
15621 }
15622 prev_channo = channo;
15623 }
15624 /* Handle leftover channels */
15625 if (inside_range) {
15626 /* Close range */
15627 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d", channo);
15628 inside_range = 0;
15629 } else if (prev_channo) {
15630 /* Non-sequential channel numbers */
15631 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15632 }
15633 // channel_list[len] = '\0';
15634 ast_cli(a->fd, FORMAT,
15635 index,
15636 thread_status,
15637 (mfcr2->nodev) ? "MISSING" : "OK",
15638 live_chans_str,
15639 channel_list);
15640 }
15641 }
15642 AST_LIST_UNLOCK(list_head);
15643#undef FORMAT
15644}
15645
15646static char *handle_mfcr2_show_links(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15647{
15648 switch (cmd) {
15649 case CLI_INIT:
15650 e->command = "mfcr2 show links";
15651 e->usage =
15652 "Usage: mfcr2 show links\n"
15653 " Shows the DAHDI MFC/R2 links.\n";
15654 return NULL;
15655 case CLI_GENERATE:
15656 return NULL;
15657 }
15658 if (a->argc != 3) {
15659 return CLI_SHOWUSAGE;
15660 }
15661 mfcr2_show_links_of(a, &r2links, "Live links\n");
15662 mfcr2_show_links_of(a, &nodev_r2links, "Links to be removed (device missing)\n");
15663 return CLI_SUCCESS;
15664}
15665
15666static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15667{
15668 int res;
15669 int wanted_link_index;
15670 int found_link = 0;
15671 struct r2link_entry *cur = NULL;
15672
15673 switch (cmd) {
15674 case CLI_INIT:
15675 e->command = "mfcr2 destroy link";
15676 e->usage =
15677 "Usage: mfcr2 destroy link <index-number>\n"
15678 " Destorys D-channel of link and its B-channels.\n"
15679 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15680 return NULL;
15681 case CLI_GENERATE:
15682 return NULL;
15683 }
15684 if (a->argc < 4) {
15685 return CLI_SHOWUSAGE;
15686 }
15687 res = sscanf(a->argv[3], "%30d", &wanted_link_index);
15688 if ((res != 1) || wanted_link_index < 1) {
15689 ast_cli(a->fd,
15690 "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15691 return CLI_SUCCESS;
15692 }
15693 AST_LIST_LOCK(&r2links);
15694 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
15695 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15696 if (wanted_link_index == mfcr2->index) {
15697 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
15698 r2links_count--;
15699 break;
15700 }
15701 }
15703 AST_LIST_UNLOCK(&r2links);
15704 if (! found_link) {
15705 ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);
15706 return CLI_FAILURE;
15707 }
15708 return CLI_SUCCESS;
15709}
15710
15711static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15712 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15713 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15714 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15715 AST_CLI_DEFINE(handle_mfcr2_show_links, "Show MFC/R2 links"),
15716 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15717 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15718 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15719 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15720 AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),
15721};
15722
15723#endif /* HAVE_OPENR2 */
15724
15725static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15726{
15727 int start;
15728 int end;
15729 switch (cmd) {
15730 case CLI_INIT:
15731 e->command = "dahdi destroy channels";
15732 e->usage =
15733 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15734 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15735 return NULL;
15736 case CLI_GENERATE:
15737 return NULL;
15738 }
15739 if ((a->argc < 4) || a->argc > 5) {
15740 return CLI_SHOWUSAGE;
15741 }
15742 start = atoi(a->argv[3]);
15743 if (start < 1) {
15744 ast_cli(a->fd, "Invalid starting channel number %s.\n",
15745 a->argv[4]);
15746 return CLI_FAILURE;
15747 }
15748 if (a->argc == 5) {
15749 end = atoi(a->argv[4]);
15750 if (end < 1) {
15751 ast_cli(a->fd, "Invalid ending channel number %s.\n",
15752 a->argv[4]);
15753 return CLI_FAILURE;
15754 }
15755 } else {
15756 end = start;
15757 }
15758
15759 if (end < start) {
15760 ast_cli(a->fd,
15761 "range end (%d) is smaller than range start (%d)\n",
15762 end, start);
15763 return CLI_FAILURE;
15764 }
15766 return CLI_SUCCESS;
15767}
15768
15769static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15770{
15771 int start;
15772 int end;
15773 int ret;
15774
15775 switch (cmd) {
15776 case CLI_INIT:
15777 e->command = "dahdi create channels";
15778 e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15779 " dahdi create channels new - add channels not yet created\n"
15780 "For ISDN and SS7 the range should include complete spans.\n";
15781 return NULL;
15782 case CLI_GENERATE:
15783 return NULL;
15784 }
15785 if ((a->argc < 4) || a->argc > 5) {
15786 return CLI_SHOWUSAGE;
15787 }
15788 if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15789 ret = dahdi_create_channel_range(0, 0);
15790 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15791 }
15792 start = atoi(a->argv[3]);
15793 if (start <= 0) {
15794 ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15795 a->argv[3]);
15796 return CLI_FAILURE;
15797 }
15798 if (a->argc == 5) {
15799 end = atoi(a->argv[4]);
15800 if (end <= 0) {
15801 ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15802 a->argv[4]);
15803 return CLI_FAILURE;
15804 }
15805 } else {
15806 end = start;
15807 }
15808 if (end < start) {
15809 ast_cli(a->fd,
15810 "range end (%d) is smaller than range start (%d)\n",
15811 end, start);
15812 return CLI_FAILURE;
15813 }
15814 ret = dahdi_create_channel_range(start, end);
15815 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15816}
15817
15818static void dahdi_softhangup_all(void)
15819{
15820 struct dahdi_pvt *p;
15821retry:
15823 for (p = iflist; p; p = p->next) {
15824 ast_mutex_lock(&p->lock);
15825 if (p->owner && !p->restartpending) {
15826 if (ast_channel_trylock(p->owner)) {
15827 if (DEBUG_ATLEAST(3))
15828 ast_verbose("Avoiding deadlock\n");
15829 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15832 goto retry;
15833 }
15834 if (DEBUG_ATLEAST(3))
15835 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15837 p->restartpending = 1;
15840 }
15842 }
15844}
15845
15846static int dahdi_restart(void)
15847{
15848#if defined(HAVE_PRI) || defined(HAVE_SS7)
15849 int i, j;
15850#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15851 int cancel_code;
15852 struct dahdi_pvt *p;
15853
15855 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15857 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15858#ifdef HAVE_OPENR2
15859 dahdi_r2_destroy_links();
15860#endif
15861
15862#if defined(HAVE_PRI)
15863 for (i = 0; i < NUM_SPANS; i++) {
15864 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15865 cancel_code = pthread_cancel(pris[i].pri.master);
15866 pthread_kill(pris[i].pri.master, SIGURG);
15867 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
15868 pthread_join(pris[i].pri.master, NULL);
15869 ast_debug(4, "Joined thread of span %d\n", i);
15870 }
15871 }
15872#endif
15873
15874#if defined(HAVE_SS7)
15875 for (i = 0; i < NUM_SPANS; i++) {
15876 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15877 cancel_code = pthread_cancel(linksets[i].ss7.master);
15878 pthread_kill(linksets[i].ss7.master, SIGURG);
15879 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
15880 pthread_join(linksets[i].ss7.master, NULL);
15881 ast_debug(4, "Joined thread of span %d\n", i);
15882 }
15883 }
15884#endif /* defined(HAVE_SS7) */
15885
15888 cancel_code = pthread_cancel(monitor_thread);
15889 pthread_kill(monitor_thread, SIGURG);
15890 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15891 pthread_join(monitor_thread, NULL);
15892 ast_debug(4, "Joined monitor thread\n");
15893 }
15894 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15895
15897 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15898 int x = DAHDI_FLASH;
15899 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15900
15902 for (p = iflist; p; p = p->next) {
15903 if (p->owner) {
15904 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15905 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15906 }
15907 }
15910 }
15911
15912 /* ensure any created channels before monitor threads were stopped are hungup */
15914 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15916 memset(round_robin, 0, sizeof(round_robin));
15917 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15918
15920
15921#ifdef HAVE_PRI
15922 for (i = 0; i < NUM_SPANS; i++) {
15923 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15924 dahdi_close_pri_fd(&(pris[i]), j);
15925 }
15926
15927 memset(pris, 0, sizeof(pris));
15928 for (i = 0; i < NUM_SPANS; i++) {
15929 sig_pri_init_pri(&pris[i].pri);
15930 }
15931 pri_set_error(dahdi_pri_error);
15932 pri_set_message(dahdi_pri_message);
15933#endif
15934#if defined(HAVE_SS7)
15935 for (i = 0; i < NUM_SPANS; i++) {
15936 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15937 dahdi_close_ss7_fd(&(linksets[i]), j);
15938 }
15939
15940 memset(linksets, 0, sizeof(linksets));
15941 for (i = 0; i < NUM_SPANS; i++) {
15942 sig_ss7_init_linkset(&linksets[i].ss7);
15943 }
15944 ss7_set_error(dahdi_ss7_error);
15945 ss7_set_message(dahdi_ss7_message);
15946 ss7_set_hangup(sig_ss7_cb_hangup);
15947 ss7_set_notinservice(sig_ss7_cb_notinservice);
15948 ss7_set_call_null(sig_ss7_cb_call_null);
15949#endif /* defined(HAVE_SS7) */
15950
15951 if (setup_dahdi(2) != 0) {
15952 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15954 return 1;
15955 }
15958 return 0;
15959}
15960
15961static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15962{
15963 switch (cmd) {
15964 case CLI_INIT:
15965 e->command = "dahdi restart";
15966 e->usage =
15967 "Usage: dahdi restart\n"
15968 " Restarts the DAHDI channels: destroys them all and then\n"
15969 " re-reads them from chan_dahdi.conf.\n"
15970 " Note that this will STOP any running CALL on DAHDI channels.\n"
15971 "";
15972 return NULL;
15973 case CLI_GENERATE:
15974 return NULL;
15975 }
15976 if (a->argc != 2)
15977 return CLI_SHOWUSAGE;
15978
15979 if (dahdi_restart() != 0)
15980 return CLI_FAILURE;
15981 return CLI_SUCCESS;
15982}
15983
15984static int action_dahdirestart(struct mansession *s, const struct message *m)
15985{
15986 if (dahdi_restart() != 0) {
15987 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15988 return 1;
15989 }
15990 astman_send_ack(s, m, "DAHDIRestart: Success");
15991 return 0;
15992}
15993
15994static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15995{
15996#define FORMAT "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15997#define FORMAT2 "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15998 ast_group_t targetnum = 0;
15999 int filtertype = 0;
16000 struct dahdi_pvt *tmp = NULL;
16001 char tmps[20];
16002 char blockstr[20];
16003
16004 switch (cmd) {
16005 case CLI_INIT:
16006 e->command = "dahdi show channels [group|context]";
16007 e->usage =
16008 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
16009 " Shows a list of available channels with optional filtering\n"
16010 " <group> must be a number between 0 and 63\n";
16011 return NULL;
16012 case CLI_GENERATE:
16013 return NULL;
16014 }
16015
16016 /* syntax: dahdi show channels [ group <group> | context <context> ] */
16017
16018 if (!((a->argc == 3) || (a->argc == 5))) {
16019 return CLI_SHOWUSAGE;
16020 }
16021
16022 if (a->argc == 5) {
16023 if (!strcasecmp(a->argv[3], "group")) {
16024 targetnum = atoi(a->argv[4]);
16025 if (63 < targetnum) {
16026 return CLI_SHOWUSAGE;
16027 }
16028 targetnum = ((ast_group_t) 1) << targetnum;
16029 filtertype = 1;
16030 } else if (!strcasecmp(a->argv[3], "context")) {
16031 filtertype = 2;
16032 }
16033 }
16034
16035 ast_cli(a->fd, FORMAT2, "Chan", "Span", "Signalling", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Alarms", "Description");
16037 for (tmp = iflist; tmp; tmp = tmp->next) {
16038 int alm = 0;
16039 if (filtertype) {
16040 switch(filtertype) {
16041 case 1: /* dahdi show channels group <group> */
16042 if (!(tmp->group & targetnum)) {
16043 continue;
16044 }
16045 break;
16046 case 2: /* dahdi show channels context <context> */
16047 if (strcasecmp(tmp->context, a->argv[4])) {
16048 continue;
16049 }
16050 break;
16051 default:
16052 break;
16053 }
16054 }
16055 if (tmp->channel > 0) {
16056 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
16057 alm = get_alarms(tmp);
16058 } else {
16059 ast_copy_string(tmps, "pseudo", sizeof(tmps));
16060 }
16061
16062 blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
16063 blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
16064 blockstr[2] = '\0';
16065
16066 ast_cli(a->fd, FORMAT, tmps, tmp->span, sig2str(tmp->sig), tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No",
16067 alarm2str(alm), tmp->description);
16068 }
16070 return CLI_SUCCESS;
16071#undef FORMAT
16072#undef FORMAT2
16073}
16074
16075static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16076{
16077 int channel;
16078 struct dahdi_pvt *tmp = NULL;
16079 struct dahdi_confinfo ci;
16080 struct dahdi_params ps;
16081 int x;
16082 char hwrxgain[15];
16083 char hwtxgain[15];
16084
16085 switch (cmd) {
16086 case CLI_INIT:
16087 e->command = "dahdi show channel";
16088 e->usage =
16089 "Usage: dahdi show channel <chan num>\n"
16090 " Detailed information about a given channel\n";
16091 return NULL;
16092 case CLI_GENERATE:
16093 return NULL;
16094 }
16095
16096 if (a->argc != 4)
16097 return CLI_SHOWUSAGE;
16098
16099 channel = atoi(a->argv[3]);
16100
16102 for (tmp = iflist; tmp; tmp = tmp->next) {
16103 if (tmp->channel == channel) {
16104 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16105 ast_cli(a->fd, "Description: %s\n", tmp->description);
16106 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16107 ast_cli(a->fd, "Span: %d\n", tmp->span);
16108 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16109 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16110 ast_cli(a->fd, "Context: %s\n", tmp->context);
16111 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16112 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16113#if defined(HAVE_PRI)
16114#if defined(HAVE_PRI_SUBADDR)
16115 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16116#endif /* defined(HAVE_PRI_SUBADDR) */
16117#endif /* defined(HAVE_PRI) */
16118 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16119 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16120 if (tmp->vars) {
16121 struct ast_variable *v;
16122 ast_cli(a->fd, "Variables:\n");
16123 for (v = tmp->vars ; v ; v = v->next)
16124 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16125 }
16126 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16127 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16128 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16129 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16130 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16131 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
16132 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
16133 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
16134 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16135 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16136 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16137 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16138 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16139 if (tmp->busydetect) {
16140#if defined(BUSYDETECT_TONEONLY)
16141 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16142#elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16143 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16144#endif
16145#ifdef BUSYDETECT_DEBUG
16146 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16147#endif
16148 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16149 ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
16150 }
16151 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16152 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16153 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16154 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16155 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16156 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16157 if (tmp->hwrxgain_enabled) {
16158 snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16159 } else {
16160 ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16161 }
16162 if (tmp->hwtxgain_enabled) {
16163 snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16164 } else {
16165 ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16166 }
16167 ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16168 ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16169 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16170 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16171 ast_cli(a->fd, "Echo Cancellation:\n");
16172
16173 if (tmp->echocancel.head.tap_length) {
16174 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16175 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16176 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16177 }
16178 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16179 } else {
16180 ast_cli(a->fd, "\tnone\n");
16181 }
16182 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16183 if (tmp->master)
16184 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16185 for (x = 0; x < MAX_SLAVES; x++) {
16186 if (tmp->slaves[x])
16187 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16188 }
16189#ifdef HAVE_OPENR2
16190 if (tmp->mfcr2) {
16191 char calldir[OR2_MAX_PATH];
16192 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16193 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16194 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16195 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16196 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16197 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16198 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16199 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16200 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16201 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16202#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16203 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16204 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16205#endif
16206 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16207#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16208 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16209#endif
16210 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16211 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16212 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16213 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16214 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16215 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16216 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16217 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16218 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16219 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16220 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16221 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16222 }
16223#endif
16224#if defined(HAVE_SS7)
16225 if (tmp->ss7) {
16226 struct sig_ss7_chan *chan = tmp->sig_pvt;
16227
16228 ast_cli(a->fd, "CIC: %d\n", chan->cic);
16229 }
16230#endif /* defined(HAVE_SS7) */
16231#ifdef HAVE_PRI
16232 if (tmp->pri) {
16233 struct sig_pri_chan *chan = tmp->sig_pvt;
16234
16235 ast_cli(a->fd, "PRI Flags: ");
16236 if (chan->resetting != SIG_PRI_RESET_IDLE) {
16237 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16238 }
16239 if (chan->call)
16240 ast_cli(a->fd, "Call ");
16241 if (chan->allocated) {
16242 ast_cli(a->fd, "Allocated ");
16243 }
16244 ast_cli(a->fd, "\n");
16245 if (tmp->logicalspan)
16246 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16247 else
16248 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16249 }
16250#endif
16251 memset(&ci, 0, sizeof(ci));
16252 ps.channo = tmp->channel;
16253 if (tmp->subs[SUB_REAL].dfd > -1) {
16254 memset(&ci, 0, sizeof(ci));
16255 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16256 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16257 }
16258 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16259 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16260 }
16261 memset(&ps, 0, sizeof(ps));
16262 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16263 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16264 } else {
16265 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16266 }
16267 }
16269 return CLI_SUCCESS;
16270 }
16271 }
16273
16274 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16275 return CLI_FAILURE;
16276}
16277
16278static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16279{
16280 int i, j;
16281 switch (cmd) {
16282 case CLI_INIT:
16283 e->command = "dahdi show cadences";
16284 e->usage =
16285 "Usage: dahdi show cadences\n"
16286 " Shows all cadences currently defined\n";
16287 return NULL;
16288 case CLI_GENERATE:
16289 return NULL;
16290 }
16291 for (i = 0; i < num_cadence; i++) {
16292 char output[1024];
16293 char tmp[16], tmp2[64];
16294 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16295 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16296
16297 for (j = 0; j < 16; j++) {
16298 if (cadences[i].ringcadence[j] == 0)
16299 break;
16300 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16301 if (cidrings[i] * 2 - 1 == j)
16302 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16303 else
16304 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16305 if (j != 0)
16306 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16307 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16308 }
16309 ast_cli(a->fd,"%s\n",output);
16310 }
16311 return CLI_SUCCESS;
16312}
16313
16314static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
16315{
16316 alarmstr[0] = '\0';
16317 if (spaninfo->alarms > 0) {
16318 if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16319 strcat(alarmstr, "BLU/");
16320 }
16321 if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16322 strcat(alarmstr, "YEL/");
16323 }
16324 if (spaninfo->alarms & DAHDI_ALARM_RED) {
16325 strcat(alarmstr, "RED/");
16326 }
16327 if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16328 strcat(alarmstr, "LB/");
16329 }
16330 if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16331 strcat(alarmstr, "REC/");
16332 }
16333 if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16334 strcat(alarmstr, "NOP/");
16335 }
16336 if (!strlen(alarmstr)) {
16337 strcat(alarmstr, "UUU/");
16338 }
16339 if (strlen(alarmstr)) {
16340 /* Strip trailing / */
16341 alarmstr[strlen(alarmstr) - 1] = '\0';
16342 }
16343 } else {
16344 if (spaninfo->numchans) {
16345 strcpy(alarmstr, "OK");
16346 } else {
16347 strcpy(alarmstr, "UNCONFIGURED");
16348 }
16349 }
16350}
16351
16352/* Based on irqmiss.c */
16353static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16354{
16355 #define FORMAT "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16356 #define FORMAT2 "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16357 int span;
16358 int res;
16359 char alarmstr[50];
16360
16361 int ctl;
16362 struct dahdi_spaninfo s;
16363
16364 switch (cmd) {
16365 case CLI_INIT:
16366 e->command = "dahdi show status";
16367 e->usage =
16368 "Usage: dahdi show status\n"
16369 " Shows a list of DAHDI cards with status\n";
16370 return NULL;
16371 case CLI_GENERATE:
16372 return NULL;
16373 }
16374 ctl = open("/dev/dahdi/ctl", O_RDWR);
16375 if (ctl < 0) {
16376 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16377 return CLI_FAILURE;
16378 }
16379 ast_cli(a->fd, FORMAT2, "Span", "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16380
16381 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16382 s.spanno = span;
16383 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16384 if (res) {
16385 continue;
16386 }
16387 build_alarm_info(alarmstr, &s);
16388 ast_cli(a->fd, FORMAT, span, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16389 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16390 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16391 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16392 "CAS",
16393 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16394 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16395 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16396 "Unknown",
16397 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16398 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16399 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16400 lbostr[s.lbo]
16401 );
16402 }
16403 close(ctl);
16404
16405 return CLI_SUCCESS;
16406#undef FORMAT
16407#undef FORMAT2
16408}
16409
16410static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16411{
16412 int pseudo_fd = -1;
16413 struct dahdi_versioninfo vi;
16414
16415 switch (cmd) {
16416 case CLI_INIT:
16417 e->command = "dahdi show version";
16418 e->usage =
16419 "Usage: dahdi show version\n"
16420 " Shows the DAHDI version in use\n";
16421 return NULL;
16422 case CLI_GENERATE:
16423 return NULL;
16424 }
16425 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16426 ast_cli(a->fd, "Failed to open control file to get version.\n");
16427 return CLI_SUCCESS;
16428 }
16429
16430 strcpy(vi.version, "Unknown");
16431 strcpy(vi.echo_canceller, "Unknown");
16432
16433 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16434 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16435 else
16436 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16437
16438 close(pseudo_fd);
16439
16440 return CLI_SUCCESS;
16441}
16442
16443static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16444{
16445 int channel;
16446 float gain;
16447 int tx;
16448 struct dahdi_pvt *tmp = NULL;
16449
16450 switch (cmd) {
16451 case CLI_INIT:
16452 e->command = "dahdi set hwgain {rx|tx}";
16453 e->usage =
16454 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16455 " Sets the hardware gain on a given channel and overrides the\n"
16456 " value provided at module loadtime. Changes take effect\n"
16457 " immediately whether the channel is in use or not.\n"
16458 "\n"
16459 " <rx|tx> which direction do you want to change (relative to our module)\n"
16460 " <chan num> is the channel number relative to the device\n"
16461 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16462 "\n"
16463 " Please note:\n"
16464 " * hwgain is only supportable by hardware with analog ports because\n"
16465 " hwgain works on the analog side of an analog-digital conversion.\n";
16466 return NULL;
16467 case CLI_GENERATE:
16468 return NULL;
16469 }
16470
16471 if (a->argc != 6)
16472 return CLI_SHOWUSAGE;
16473
16474 if (!strcasecmp("rx", a->argv[3]))
16475 tx = 0; /* rx */
16476 else if (!strcasecmp("tx", a->argv[3]))
16477 tx = 1; /* tx */
16478 else
16479 return CLI_SHOWUSAGE;
16480
16481 channel = atoi(a->argv[4]);
16482 gain = atof(a->argv[5]);
16483
16485
16486 for (tmp = iflist; tmp; tmp = tmp->next) {
16487
16488 if (tmp->channel != channel)
16489 continue;
16490
16491 if (tmp->subs[SUB_REAL].dfd == -1)
16492 break;
16493
16494 if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16495 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16497 return CLI_FAILURE;
16498 }
16499 ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16500 tx ? "tx" : "rx", gain, channel);
16501
16502 if (tx) {
16503 tmp->hwtxgain_enabled = 1;
16504 tmp->hwtxgain = gain;
16505 } else {
16506 tmp->hwrxgain_enabled = 1;
16507 tmp->hwrxgain = gain;
16508 }
16509 break;
16510 }
16511
16513
16514 if (tmp)
16515 return CLI_SUCCESS;
16516
16517 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16518 return CLI_FAILURE;
16519
16520}
16521
16522static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16523{
16524 int channel;
16525 float gain;
16526 int tx;
16527 int res;
16528 struct dahdi_pvt *tmp = NULL;
16529
16530 switch (cmd) {
16531 case CLI_INIT:
16532 e->command = "dahdi set swgain {rx|tx}";
16533 e->usage =
16534 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16535 " Sets the software gain on a given channel and overrides the\n"
16536 " value provided at module loadtime. Changes take effect\n"
16537 " immediately whether the channel is in use or not.\n"
16538 "\n"
16539 " <rx|tx> which direction do you want to change (relative to our module)\n"
16540 " <chan num> is the channel number relative to the device\n"
16541 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16542 return NULL;
16543 case CLI_GENERATE:
16544 return NULL;
16545 }
16546
16547 if (a->argc != 6)
16548 return CLI_SHOWUSAGE;
16549
16550 if (!strcasecmp("rx", a->argv[3]))
16551 tx = 0; /* rx */
16552 else if (!strcasecmp("tx", a->argv[3]))
16553 tx = 1; /* tx */
16554 else
16555 return CLI_SHOWUSAGE;
16556
16557 channel = atoi(a->argv[4]);
16558 gain = atof(a->argv[5]);
16559
16561 for (tmp = iflist; tmp; tmp = tmp->next) {
16562
16563 if (tmp->channel != channel)
16564 continue;
16565
16566 if (tmp->subs[SUB_REAL].dfd == -1)
16567 break;
16568
16569 if (tx)
16570 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16571 else
16572 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16573
16574 if (res) {
16575 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16577 return CLI_FAILURE;
16578 }
16579
16580 ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16581 tx ? "tx" : "rx", gain, channel);
16582
16583 if (tx) {
16584 tmp->txgain = gain;
16585 } else {
16586 tmp->rxgain = gain;
16587 }
16588 break;
16589 }
16591
16592 if (tmp)
16593 return CLI_SUCCESS;
16594
16595 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16596 return CLI_FAILURE;
16597
16598}
16599
16600static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16601{
16602 int channel;
16603 int on;
16604 struct dahdi_pvt *dahdi_chan = NULL;
16605
16606 switch (cmd) {
16607 case CLI_INIT:
16608 e->command = "dahdi set dnd";
16609 e->usage =
16610 "Usage: dahdi set dnd <chan#> <on|off>\n"
16611 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16612 " Changes take effect immediately.\n"
16613 " <chan num> is the channel number\n"
16614 " <on|off> Enable or disable DND mode?\n"
16615 ;
16616 return NULL;
16617 case CLI_GENERATE:
16618 return NULL;
16619 }
16620
16621 if (a->argc != 5)
16622 return CLI_SHOWUSAGE;
16623
16624 if ((channel = atoi(a->argv[3])) <= 0) {
16625 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16626 return CLI_SHOWUSAGE;
16627 }
16628
16629 if (ast_true(a->argv[4]))
16630 on = 1;
16631 else if (ast_false(a->argv[4]))
16632 on = 0;
16633 else {
16634 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16635 return CLI_SHOWUSAGE;
16636 }
16637
16639 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16640 if (dahdi_chan->channel != channel)
16641 continue;
16642
16643 /* Found the channel. Actually set it */
16644 dahdi_dnd(dahdi_chan, on);
16645 break;
16646 }
16648
16649 if (!dahdi_chan) {
16650 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16651 return CLI_FAILURE;
16652 }
16653
16654 return CLI_SUCCESS;
16655}
16656
16657static char *dahdi_set_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16658{
16659 int channel;
16660 int on;
16661 int override = 1;
16662 struct dahdi_pvt *dahdi_chan = NULL;
16663
16664 switch (cmd) {
16665 case CLI_INIT:
16666 e->command = "dahdi set mwi";
16667 e->usage =
16668 "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16669 " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16670 " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16671 " When active, this setting will override the voicemail status to set MWI.\n"
16672 " Once cleared, the voicemail status will resume control of MWI.\n"
16673 " Changes are queued for when the channel is idle and persist until cleared.\n"
16674 " <chan num> is the channel number\n"
16675 " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16676 ;
16677 return NULL;
16678 case CLI_GENERATE:
16679 return NULL;
16680 }
16681
16682 if (a->argc != 5)
16683 return CLI_SHOWUSAGE;
16684
16685 if ((channel = atoi(a->argv[3])) <= 0) {
16686 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16687 return CLI_SHOWUSAGE;
16688 }
16689
16690 if (ast_true(a->argv[4])) {
16691 on = 1;
16692 } else if (ast_false(a->argv[4])) {
16693 on = 0;
16694 } else if (!strcmp(a->argv[4], "reset")) {
16695 override = 0;
16696 } else {
16697 ast_cli(a->fd, "Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16698 return CLI_SHOWUSAGE;
16699 }
16700
16702 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16703 if (dahdi_chan->channel != channel)
16704 continue;
16705
16706 /* Found the channel. Actually set it */
16707 if (override) {
16708 dahdi_chan->mwioverride_disposition = on;
16709 ast_cli(a->fd, "MWI '%s' queued for channel %d\n", on ? "enable" : "disable", channel);
16710 }
16711 dahdi_chan->mwioverride_active = override;
16712 /* The do_monitor thread will take care of actually sending the MWI
16713 * at an appropriate time for the channel. */
16714 break;
16715 }
16717
16718 if (!dahdi_chan) {
16719 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16720 return CLI_FAILURE;
16721 }
16722
16723 return CLI_SUCCESS;
16724}
16725
16726static struct ast_cli_entry dahdi_cli[] = {
16728 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16729 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16730 AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16731 AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16732 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16733 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16734 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16735 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16736 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16737 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16738 AST_CLI_DEFINE(dahdi_set_mwi, "Sets/unsets MWI (Message Waiting Indicator) manually on a channel"),
16739};
16740
16741#define TRANSFER 0
16742#define HANGUP 1
16743
16744static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16745{
16746 if (p) {
16747 switch (mode) {
16748 case TRANSFER:
16749 p->fake_event = DAHDI_EVENT_WINKFLASH;
16750 break;
16751 case HANGUP:
16752 p->fake_event = DAHDI_EVENT_ONHOOK;
16753 break;
16754 default:
16755 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
16756 }
16757 }
16758 return 0;
16759}
16760static struct dahdi_pvt *find_channel(int channel)
16761{
16762 struct dahdi_pvt *p;
16763
16765 for (p = iflist; p; p = p->next) {
16766 if (p->channel == channel) {
16767 break;
16768 }
16769 }
16771 return p;
16772}
16773
16774/*!
16775 * \internal
16776 * \brief Get private struct using given numeric channel string.
16777 *
16778 * \param channel Numeric channel number string get private struct.
16779 *
16780 * \retval pvt on success.
16781 * \retval NULL on error.
16782 */
16783static struct dahdi_pvt *find_channel_from_str(const char *channel)
16784{
16785 int chan_num;
16786
16787 if (sscanf(channel, "%30d", &chan_num) != 1) {
16788 /* Not numeric string. */
16789 return NULL;
16790 }
16791
16792 return find_channel(chan_num);
16793}
16794
16795static int action_dahdidndon(struct mansession *s, const struct message *m)
16796{
16797 struct dahdi_pvt *p;
16798 const char *channel = astman_get_header(m, "DAHDIChannel");
16799
16800 if (ast_strlen_zero(channel)) {
16801 astman_send_error(s, m, "No channel specified");
16802 return 0;
16803 }
16805 if (!p) {
16806 astman_send_error(s, m, "No such channel");
16807 return 0;
16808 }
16809 dahdi_dnd(p, 1);
16810 astman_send_ack(s, m, "DND Enabled");
16811 return 0;
16812}
16813
16814static int action_dahdidndoff(struct mansession *s, const struct message *m)
16815{
16816 struct dahdi_pvt *p;
16817 const char *channel = astman_get_header(m, "DAHDIChannel");
16818
16819 if (ast_strlen_zero(channel)) {
16820 astman_send_error(s, m, "No channel specified");
16821 return 0;
16822 }
16824 if (!p) {
16825 astman_send_error(s, m, "No such channel");
16826 return 0;
16827 }
16828 dahdi_dnd(p, 0);
16829 astman_send_ack(s, m, "DND Disabled");
16830 return 0;
16831}
16832
16833static int action_transfer(struct mansession *s, const struct message *m)
16834{
16835 struct dahdi_pvt *p;
16836 const char *channel = astman_get_header(m, "DAHDIChannel");
16837
16838 if (ast_strlen_zero(channel)) {
16839 astman_send_error(s, m, "No channel specified");
16840 return 0;
16841 }
16843 if (!p) {
16844 astman_send_error(s, m, "No such channel");
16845 return 0;
16846 }
16847 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16848 astman_send_error(s, m, "Channel signaling is not analog");
16849 return 0;
16850 }
16852 astman_send_ack(s, m, "DAHDITransfer");
16853 return 0;
16854}
16855
16856static int action_transferhangup(struct mansession *s, const struct message *m)
16857{
16858 struct dahdi_pvt *p;
16859 const char *channel = astman_get_header(m, "DAHDIChannel");
16860
16861 if (ast_strlen_zero(channel)) {
16862 astman_send_error(s, m, "No channel specified");
16863 return 0;
16864 }
16866 if (!p) {
16867 astman_send_error(s, m, "No such channel");
16868 return 0;
16869 }
16870 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16871 astman_send_error(s, m, "Channel signaling is not analog");
16872 return 0;
16873 }
16875 astman_send_ack(s, m, "DAHDIHangup");
16876 return 0;
16877}
16878
16879static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16880{
16881 struct dahdi_pvt *p;
16882 const char *channel = astman_get_header(m, "DAHDIChannel");
16883 const char *number = astman_get_header(m, "Number");
16884 int i;
16885
16886 if (ast_strlen_zero(channel)) {
16887 astman_send_error(s, m, "No channel specified");
16888 return 0;
16889 }
16890 if (ast_strlen_zero(number)) {
16891 astman_send_error(s, m, "No number specified");
16892 return 0;
16893 }
16895 if (!p) {
16896 astman_send_error(s, m, "No such channel");
16897 return 0;
16898 }
16899 if (!p->owner) {
16900 astman_send_error(s, m, "Channel does not have it's owner");
16901 return 0;
16902 }
16903 for (i = 0; i < strlen(number); i++) {
16904 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16905 dahdi_queue_frame(p, &f);
16906 }
16907 astman_send_ack(s, m, "DAHDIDialOffhook");
16908 return 0;
16909}
16910
16911static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16912{
16913 struct dahdi_pvt *tmp = NULL;
16914 const char *id = astman_get_header(m, "ActionID");
16915 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16916 char idText[256];
16917 int channels = 0;
16918 int dahdichanquery;
16919
16920 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16921 /* Not numeric string. */
16922 dahdichanquery = -1;
16923 }
16924
16925 idText[0] = '\0';
16926 if (!ast_strlen_zero(id)) {
16927 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16928 }
16929
16930 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16931
16933
16934 for (tmp = iflist; tmp; tmp = tmp->next) {
16935 if (tmp->channel > 0) {
16936 int alm;
16937
16938 /* If a specific channel is queried for, only deliver status for that channel */
16939 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16940 continue;
16941
16942 alm = get_alarms(tmp);
16943 channels++;
16944 if (tmp->owner) {
16945 /* Add data if we have a current call */
16946 astman_append(s,
16947 "Event: DAHDIShowChannels\r\n"
16948 "DAHDIChannel: %d\r\n"
16949 "Channel: %s\r\n"
16950 "Uniqueid: %s\r\n"
16951 "AccountCode: %s\r\n"
16952 "Signalling: %s\r\n"
16953 "SignallingCode: %d\r\n"
16954 "Context: %s\r\n"
16955 "DND: %s\r\n"
16956 "Alarm: %s\r\n"
16957 "Description: %s\r\n"
16958 "%s"
16959 "\r\n",
16960 tmp->channel,
16961 ast_channel_name(tmp->owner),
16962 ast_channel_uniqueid(tmp->owner),
16964 sig2str(tmp->sig),
16965 tmp->sig,
16966 tmp->context,
16967 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16968 alarm2str(alm),
16969 tmp->description, idText);
16970 } else {
16971 astman_append(s,
16972 "Event: DAHDIShowChannels\r\n"
16973 "DAHDIChannel: %d\r\n"
16974 "Signalling: %s\r\n"
16975 "SignallingCode: %d\r\n"
16976 "Context: %s\r\n"
16977 "DND: %s\r\n"
16978 "Alarm: %s\r\n"
16979 "Description: %s\r\n"
16980 "%s"
16981 "\r\n",
16982 tmp->channel, sig2str(tmp->sig), tmp->sig,
16983 tmp->context,
16984 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16985 alarm2str(alm),
16986 tmp->description, idText);
16987 }
16988 }
16989 }
16990
16992
16993 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16994 astman_append(s, "Items: %d\r\n", channels);
16996 return 0;
16997}
16998
16999static int action_dahdishowstatus(struct mansession *s, const struct message *m)
17000{
17001 const char *id = astman_get_header(m, "ActionID");
17002 int span;
17003 int res;
17004 char alarmstr[50];
17005 int ctl;
17006 char idText[256];
17007 int numspans = 0;
17008 struct dahdi_spaninfo spaninfo;
17009
17010 ctl = open("/dev/dahdi/ctl", O_RDWR);
17011 if (ctl < 0) {
17012 astman_send_error(s, m, "No DAHDI detected");
17013 return 0;
17014 }
17015
17016 idText[0] = '\0';
17017 if (!ast_strlen_zero(id)) {
17018 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
17019 }
17020 astman_send_listack(s, m, "DAHDI span statuses will follow", "start");
17021
17022 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17023 spaninfo.spanno = span;
17024 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17025 if (res) {
17026 continue;
17027 }
17028 numspans++;
17029 build_alarm_info(alarmstr, &spaninfo);
17030 astman_append(s,
17031 "Event: DAHDIShowStatus\r\n"
17032 "Span: %d\r\n"
17033 "Description: %s\r\n"
17034 "Alarms: %s\r\n"
17035 "IRQ: %d\r\n"
17036 "bpviol: %d\r\n"
17037 "CRC: %d\r\n"
17038 "Framing: %s\r\n"
17039 "Coding: %s\r\n"
17040 "Options: %s\r\n"
17041 "LBO: %s\r\n"
17042 "%s"
17043 "\r\n",
17044 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17045 spaninfo.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17046 spaninfo.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17047 spaninfo.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17048 "CAS",
17049 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17050 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17051 spaninfo.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17052 "Unk",
17053 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17054 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17055 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
17056 lbostr[spaninfo.lbo],
17057 idText);
17058 }
17059 close(ctl);
17060
17061 astman_send_list_complete_start(s, m, "DAHDIShowStatusComplete", numspans);
17062 astman_append(s, "Items: %d\r\n", numspans);
17064 return 0;
17065}
17066
17067#if defined(HAVE_PRI)
17068static int action_prishowspans(struct mansession *s, const struct message *m)
17069{
17070 int count;
17071 int idx;
17072 int span_query;
17073 struct dahdi_pri *dspan;
17074 const char *id = astman_get_header(m, "ActionID");
17075 const char *span_str = astman_get_header(m, "Span");
17076 char action_id[256];
17077 const char *show_cmd = "PRIShowSpans";
17078
17079 /* NOTE: Asking for span 0 gets all spans. */
17080 if (!ast_strlen_zero(span_str)) {
17081 span_query = atoi(span_str);
17082 } else {
17083 span_query = 0;
17084 }
17085
17086 if (!ast_strlen_zero(id)) {
17087 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
17088 } else {
17089 action_id[0] = '\0';
17090 }
17091
17092 astman_send_listack(s, m, "Span status will follow", "start");
17093
17094 count = 0;
17095 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
17096 dspan = &pris[idx];
17097
17098 /* If a specific span is asked for, only deliver status for that span. */
17099 if (0 < span_query && dspan->pri.span != span_query) {
17100 continue;
17101 }
17102
17103 if (dspan->pri.pri) {
17104 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
17105 action_id);
17106 }
17107 }
17108
17109 astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
17110 astman_append(s, "Items: %d\r\n", count);
17112 return 0;
17113}
17114#endif /* defined(HAVE_PRI) */
17115
17116#if defined(HAVE_SS7)
17117static int linkset_addsigchan(int sigchan)
17118{
17119 struct dahdi_ss7 *link;
17120 int res;
17121 int curfd;
17122 struct dahdi_params params;
17123 struct dahdi_bufferinfo bi;
17124 struct dahdi_spaninfo si;
17125
17126 if (sigchan < 0) {
17127 ast_log(LOG_ERROR, "Invalid sigchan!\n");
17128 return -1;
17129 }
17130 if (cur_ss7type < 0) {
17131 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
17132 return -1;
17133 }
17134 if (cur_pointcode < 0) {
17135 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
17136 return -1;
17137 }
17138 if (cur_adjpointcode < 0) {
17139 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
17140 return -1;
17141 }
17142 if (cur_defaultdpc < 0) {
17143 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
17144 return -1;
17145 }
17146 if (cur_networkindicator < 0) {
17147 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
17148 return -1;
17149 }
17150 link = ss7_resolve_linkset(cur_linkset);
17151 if (!link) {
17152 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17153 return -1;
17154 }
17155 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
17156 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
17157 return -1;
17158 }
17159
17160 curfd = link->ss7.numsigchans;
17161
17162 /* Open signaling channel */
17163 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
17164 if (link->ss7.fds[curfd] < 0) {
17165 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
17166 strerror(errno));
17167 return -1;
17168 }
17169 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
17170 dahdi_close_ss7_fd(link, curfd);
17171 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
17172 strerror(errno));
17173 return -1;
17174 }
17175
17176 /* Get signaling channel parameters */
17177 memset(&params, 0, sizeof(params));
17178 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
17179 if (res) {
17180 dahdi_close_ss7_fd(link, curfd);
17181 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
17182 strerror(errno));
17183 return -1;
17184 }
17185 if (params.sigtype != DAHDI_SIG_HDLCFCS
17186 && params.sigtype != DAHDI_SIG_HARDHDLC
17187 && params.sigtype != DAHDI_SIG_MTP2) {
17188 dahdi_close_ss7_fd(link, curfd);
17189 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
17190 return -1;
17191 }
17192
17193 /* Set signaling channel buffer policy. */
17194 memset(&bi, 0, sizeof(bi));
17195 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
17196 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
17197 bi.numbufs = 32;
17198 bi.bufsize = 512;
17199 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
17200 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
17201 sigchan, strerror(errno));
17202 dahdi_close_ss7_fd(link, curfd);
17203 return -1;
17204 }
17205
17206 /* Get current signaling channel alarm status. */
17207 memset(&si, 0, sizeof(si));
17208 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
17209 if (res) {
17210 dahdi_close_ss7_fd(link, curfd);
17211 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
17212 strerror(errno));
17213 }
17214
17215 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
17216 (params.sigtype == DAHDI_SIG_MTP2)
17217 ? SS7_TRANSPORT_DAHDIMTP2
17218 : SS7_TRANSPORT_DAHDIDCHAN,
17219 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
17220 if (res) {
17221 dahdi_close_ss7_fd(link, curfd);
17222 return -1;
17223 }
17224
17225 ++link->ss7.numsigchans;
17226
17227 return 0;
17228}
17229#endif /* defined(HAVE_SS7) */
17230
17231#if defined(HAVE_SS7)
17232static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17233{
17234 int span;
17235 switch (cmd) {
17236 case CLI_INIT:
17237 e->command = "ss7 set debug {on|off} linkset";
17238 e->usage =
17239 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
17240 " Enables debugging on a given SS7 linkset\n";
17241 return NULL;
17242 case CLI_GENERATE:
17243 return NULL;
17244 }
17245
17246 if (a->argc < 6) {
17247 return CLI_SHOWUSAGE;
17248 }
17249
17250 span = atoi(a->argv[5]);
17251 if ((span < 1) || (span > NUM_SPANS)) {
17252 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
17253 return CLI_SUCCESS;
17254 }
17255 if (!linksets[span-1].ss7.ss7) {
17256 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
17257 } else {
17258 if (!strcasecmp(a->argv[3], "on")) {
17259 linksets[span - 1].ss7.debug = 1;
17260 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
17261 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
17262 } else {
17263 linksets[span - 1].ss7.debug = 0;
17264 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
17265 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
17266 }
17267 }
17268
17269 return CLI_SUCCESS;
17270}
17271#endif /* defined(HAVE_SS7) */
17272
17273#if defined(HAVE_SS7)
17274static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17275{
17276 int linkset, cic;
17277 int blocked, i;
17278 int do_block = 0;
17279 unsigned int dpc;
17280
17281 switch (cmd) {
17282 case CLI_INIT:
17283 e->command = "ss7 {block|unblock} cic";
17284 e->usage =
17285 "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
17286 " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
17287 return NULL;
17288 case CLI_GENERATE:
17289 return NULL;
17290 }
17291
17292 if (a->argc == 6) {
17293 linkset = atoi(a->argv[3]);
17294 } else {
17295 return CLI_SHOWUSAGE;
17296 }
17297
17298 if (!strcasecmp(a->argv[1], "block")) {
17299 do_block = 1;
17300 } else if (strcasecmp(a->argv[1], "unblock")) {
17301 return CLI_SHOWUSAGE;
17302 }
17303
17304 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17305 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17306 return CLI_SUCCESS;
17307 }
17308
17309 if (!linksets[linkset-1].ss7.ss7) {
17310 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17311 return CLI_SUCCESS;
17312 }
17313
17314 cic = atoi(a->argv[5]);
17315 if (cic < 1) {
17316 ast_cli(a->fd, "Invalid CIC specified!\n");
17317 return CLI_SUCCESS;
17318 }
17319
17320 dpc = atoi(a->argv[4]);
17321 if (dpc < 1) {
17322 ast_cli(a->fd, "Invalid DPC specified!\n");
17323 return CLI_SUCCESS;
17324 }
17325
17326 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
17327 if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
17328 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
17329 if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
17330 if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
17331 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17332 } else {
17333 ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
17334 }
17335 } else if (!do_block && blocked) {
17336 ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
17337 } else {
17338 ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
17339 }
17340 return CLI_SUCCESS;
17341 }
17342 }
17343
17344 ast_cli(a->fd, "Invalid CIC specified!\n");
17345 return CLI_SUCCESS;
17346}
17347#endif /* defined(HAVE_SS7) */
17348
17349#if defined(HAVE_SS7)
17350static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17351{
17352 int linkset, i;
17353 enum {
17354 DO_BLOCK,
17355 DO_UNBLOCK,
17356 DO_RESET,
17357 } do_what;
17358
17359 switch (cmd) {
17360 case CLI_INIT:
17361 e->command = "ss7 {reset|block|unblock} linkset";
17362 e->usage =
17363 "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
17364 " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
17365 return NULL;
17366 case CLI_GENERATE:
17367 return NULL;
17368 }
17369
17370 if (a->argc == 4) {
17371 linkset = atoi(a->argv[3]);
17372 } else {
17373 return CLI_SHOWUSAGE;
17374 }
17375
17376 if (!strcasecmp(a->argv[1], "block")) {
17377 do_what = DO_BLOCK;
17378 } else if (!strcasecmp(a->argv[1], "unblock")) {
17379 do_what = DO_UNBLOCK;
17380 } else if (!strcasecmp(a->argv[1], "reset")) {
17381 do_what = DO_RESET;
17382 } else {
17383 return CLI_SHOWUSAGE;
17384 }
17385
17386 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17387 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17388 return CLI_SUCCESS;
17389 }
17390
17391 if (!linksets[linkset - 1].ss7.ss7) {
17392 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17393 return CLI_SUCCESS;
17394 }
17395
17396 for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
17397 /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
17398 if (linksets[linkset - 1].ss7.pvts[i]) {
17399 switch (do_what) {
17400 case DO_BLOCK:
17401 case DO_UNBLOCK:
17402 if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
17403 ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
17404 (do_what == DO_BLOCK) ? "blocking" : "unblocking",
17405 linksets[linkset - 1].ss7.pvts[i]->cic);
17406 }
17407 break;
17408 case DO_RESET:
17409 if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
17410 linksets[linkset - 1].ss7.pvts[i]->cic,
17411 linksets[linkset - 1].ss7.pvts[i]->dpc)) {
17412 ast_cli(a->fd, "Sent reset request on CIC %d\n",
17413 linksets[linkset - 1].ss7.pvts[i]->cic);
17414 }
17415 break;
17416 }
17417 }
17418 }
17419
17420 return CLI_SUCCESS;
17421}
17422#endif /* defined(HAVE_SS7) */
17423
17424#if defined(HAVE_SS7)
17425static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17426{
17427 int linkset, cic, range, chanpos;
17428 int i, dpc, orient = 0;
17429 int do_block = 0;
17430 unsigned char state[255];
17431
17432 switch (cmd) {
17433 case CLI_INIT:
17434 e->command = "ss7 {block|unblock} group";
17435 e->usage =
17436 "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
17437 " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
17438 return NULL;
17439 case CLI_GENERATE:
17440 return NULL;
17441 }
17442
17443 if (a->argc == 7 || a->argc == 8) {
17444 linkset = atoi(a->argv[3]);
17445 } else {
17446 return CLI_SHOWUSAGE;
17447 }
17448
17449 if (!strcasecmp(a->argv[1], "block")) {
17450 do_block = 1;
17451 } else if (strcasecmp(a->argv[1], "unblock")) {
17452 return CLI_SHOWUSAGE;
17453 }
17454
17455 if (a->argc == 8) {
17456 if (!strcasecmp(a->argv[7], "H")) {
17457 orient = 1;
17458 } else {
17459 return CLI_SHOWUSAGE;
17460 }
17461 }
17462
17463 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17464 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17465 return CLI_SUCCESS;
17466 }
17467
17468 if (!linksets[linkset-1].ss7.ss7) {
17469 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17470 return CLI_SUCCESS;
17471 }
17472
17473 cic = atoi(a->argv[5]);
17474 if (cic < 1) {
17475 ast_cli(a->fd, "Invalid CIC specified!\n");
17476 return CLI_SUCCESS;
17477 }
17478
17479 range = atoi(a->argv[6]);
17480 /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
17481 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17482 ast_cli(a->fd, "Invalid range specified!\n");
17483 return CLI_SUCCESS;
17484 }
17485
17486 dpc = atoi(a->argv[4]);
17487 if (dpc < 1) {
17488 ast_cli(a->fd, "Invalid DPC specified!\n");
17489 return CLI_SUCCESS;
17490 }
17491
17492 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17493 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17494 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17495 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17496 return CLI_SHOWUSAGE;
17497 }
17498
17499 memset(state, 0, sizeof(state));
17500 for (i = 0; i <= range; ++i) {
17501 state[i] = 1;
17502 }
17503
17504 /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
17505 chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
17506 if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
17507 ast_cli(a->fd, "Unable allocate new ss7call\n");
17508 } else {
17509 ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
17510 orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
17511 }
17512
17513 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17514
17515 /* Break poll on the linkset so it sends our messages */
17516 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17517 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17518 }
17519 return CLI_SUCCESS;
17520}
17521#endif /* defined(HAVE_SS7) */
17522
17523#if defined(HAVE_SS7)
17524static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17525{
17526 int linkset, cic, range;
17527 unsigned int dpc;
17528
17529 switch (cmd) {
17530 case CLI_INIT:
17531 e->command = "ss7 reset group";
17532 e->usage =
17533 "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
17534 " Send a GRS for the given CIC range on the specified linkset\n";
17535 return NULL;
17536 case CLI_GENERATE:
17537 return NULL;
17538 }
17539
17540 if (a->argc == 7) {
17541 linkset = atoi(a->argv[3]);
17542 } else {
17543 return CLI_SHOWUSAGE;
17544 }
17545
17546 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17547 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17548 return CLI_SUCCESS;
17549 }
17550
17551 if (!linksets[linkset-1].ss7.ss7) {
17552 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17553 return CLI_SUCCESS;
17554 }
17555
17556 cic = atoi(a->argv[5]);
17557
17558 if (cic < 1) {
17559 ast_cli(a->fd, "Invalid CIC specified!\n");
17560 return CLI_SUCCESS;
17561 }
17562
17563 range = atoi(a->argv[6]);
17564 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17565 ast_cli(a->fd, "Invalid range specified!\n");
17566 return CLI_SUCCESS;
17567 }
17568
17569 dpc = atoi(a->argv[4]);
17570 if (dpc < 1) {
17571 ast_cli(a->fd, "Invalid DPC specified!\n");
17572 return CLI_SUCCESS;
17573 }
17574
17575 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17576 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17577 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17578 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17579 return CLI_SHOWUSAGE;
17580 }
17581
17582 if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17583 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17584 } else {
17585 ast_cli(a->fd, "GRS sent ... \n");
17586 }
17587
17588 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17589
17590 /* Break poll on the linkset so it sends our messages */
17591 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17592 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17593 }
17594 return CLI_SUCCESS;
17595}
17596#endif /* defined(HAVE_SS7) */
17597
17598#if defined(HAVE_SS7)
17599static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17600{
17601 int linkset;
17602
17603 switch (cmd) {
17604 case CLI_INIT:
17605 e->command = "ss7 show calls";
17606 e->usage =
17607 "Usage: ss7 show calls <linkset>\n"
17608 " Show SS7 calls on the specified linkset\n";
17609 return NULL;
17610 case CLI_GENERATE:
17611 return NULL;
17612 }
17613
17614 if (a->argc == 4) {
17615 linkset = atoi(a->argv[3]);
17616 } else {
17617 return CLI_SHOWUSAGE;
17618 }
17619
17620 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17621 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17622 return CLI_SUCCESS;
17623 }
17624
17625 if (!linksets[linkset-1].ss7.ss7) {
17626 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17627 return CLI_SUCCESS;
17628 }
17629
17630 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17631 isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17632 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17633
17634 return CLI_SUCCESS;
17635}
17636#endif /* defined(HAVE_SS7) */
17637
17638#if defined(HAVE_SS7)
17639static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17640{
17641 int linkset, cic, res;
17642 unsigned int dpc;
17643
17644 switch (cmd) {
17645 case CLI_INIT:
17646 e->command = "ss7 reset cic";
17647 e->usage =
17648 "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17649 " Send a RSC for the given CIC on the specified linkset\n";
17650 return NULL;
17651 case CLI_GENERATE:
17652 return NULL;
17653 }
17654
17655 if (a->argc == 6) {
17656 linkset = atoi(a->argv[3]);
17657 } else {
17658 return CLI_SHOWUSAGE;
17659 }
17660
17661 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17662 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17663 return CLI_SUCCESS;
17664 }
17665
17666 if (!linksets[linkset-1].ss7.ss7) {
17667 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17668 return CLI_SUCCESS;
17669 }
17670
17671 cic = atoi(a->argv[5]);
17672
17673 if (cic < 1) {
17674 ast_cli(a->fd, "Invalid CIC specified!\n");
17675 return CLI_SUCCESS;
17676 }
17677
17678 dpc = atoi(a->argv[4]);
17679 if (dpc < 1) {
17680 ast_cli(a->fd, "Invalid DPC specified!\n");
17681 return CLI_SUCCESS;
17682 }
17683
17684 res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17685
17686 ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
17687
17688 return CLI_SUCCESS;
17689}
17690#endif /* defined(HAVE_SS7) */
17691
17692#if defined(HAVE_SS7)
17693static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17694{
17695 int linkset;
17696 unsigned int slc;
17697 unsigned int arg = 0;
17698 const char *res;
17699
17700 switch (cmd) {
17701 case CLI_INIT:
17702 e->command = "ss7 mtp3";
17703 e->usage =
17704 "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17705 " Send a NET MNG message\n"
17706 " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17707 return NULL;
17708 case CLI_GENERATE:
17709 return NULL;
17710 }
17711
17712 if (a->argc < 5) {
17713 return CLI_SHOWUSAGE;
17714 }
17715
17716 linkset = atoi(a->argv[2]);
17717 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17718 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17719 return CLI_SUCCESS;
17720 }
17721 if (!linksets[linkset-1].ss7.ss7) {
17722 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17723 return CLI_SUCCESS;
17724 }
17725
17726 slc = atoi(a->argv[3]);
17727
17728 if (a->argc == 6) {
17729 arg = atoi(a->argv[5]);
17730 }
17731
17732 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17733 res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17734 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17735
17736 /* Break poll on the linkset so it sends our messages */
17737 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17738 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17739 }
17740
17741 ast_cli(a->fd, "%s", res);
17742
17743 return CLI_SUCCESS;
17744}
17745#endif /* defined(HAVE_SS7) */
17746
17747#if defined(HAVE_SS7)
17748static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17749{
17750 int linkset;
17751 unsigned int slc = 0;
17752
17753 switch (cmd) {
17754 case CLI_INIT:
17755 e->command = "ss7 restart mtp3";
17756 e->usage =
17757 "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17758 " Restart link\n";
17759 return NULL;
17760 case CLI_GENERATE:
17761 return NULL;
17762 }
17763
17764 if (a->argc < 5) {
17765 return CLI_SHOWUSAGE;
17766 }
17767
17768 linkset = atoi(a->argv[3]);
17769 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17770 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17771 return CLI_SUCCESS;
17772 }
17773 if (!linksets[linkset-1].ss7.ss7) {
17774 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17775 return CLI_SUCCESS;
17776 }
17777
17778 slc = atoi(a->argv[4]);
17779
17780 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17781 mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17782 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17783
17784 /* Break poll on the linkset so it sends our messages */
17785 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17786 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17787 }
17788
17789 return CLI_SUCCESS;
17790}
17791#endif /* defined(HAVE_SS7) */
17792
17793#if defined(HAVE_SS7)
17794static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17795{
17796 int linkset;
17797 struct sig_ss7_linkset *ss7;
17798 switch (cmd) {
17799 case CLI_INIT:
17800 e->command = "ss7 show linkset";
17801 e->usage =
17802 "Usage: ss7 show linkset <span>\n"
17803 " Shows the status of an SS7 linkset.\n";
17804 return NULL;
17805 case CLI_GENERATE:
17806 return NULL;
17807 }
17808
17809 if (a->argc < 4) {
17810 return CLI_SHOWUSAGE;
17811 }
17812
17813 linkset = atoi(a->argv[3]);
17814 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17815 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17816 return CLI_SUCCESS;
17817 }
17818 ss7 = &linksets[linkset - 1].ss7;
17819 if (!ss7->ss7) {
17820 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17821 return CLI_SUCCESS;
17822 }
17823
17824 ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
17825 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17826 ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
17827 ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
17828 ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
17829 ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
17830 ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
17831 ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17832 ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
17833 ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17834
17835 return CLI_SUCCESS;
17836}
17837#endif /* defined(HAVE_SS7) */
17838
17839#if defined(HAVE_SS7)
17840static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17841{
17842 int linkset;
17843
17844 switch (cmd) {
17845 case CLI_INIT:
17846 e->command = "ss7 show channels";
17847 e->usage =
17848 "Usage: ss7 show channels\n"
17849 " Displays SS7 channel information at a glance.\n";
17850 return NULL;
17851 case CLI_GENERATE:
17852 return NULL;
17853 }
17854
17855 if (a->argc != 3) {
17856 return CLI_SHOWUSAGE;
17857 }
17858
17860 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17861 if (linksets[linkset].ss7.ss7) {
17862 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17863 }
17864 }
17865 return CLI_SUCCESS;
17866}
17867#endif /* defined(HAVE_SS7) */
17868
17869#if defined(HAVE_SS7)
17870static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17871{
17872#define FORMAT "%5s %5s %6s %12s %-12s\n"
17873#define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17874 int i, linkset, dpc = 0;
17875 struct sig_ss7_linkset *ss7;
17876 char *state;
17877 char blocking[12];
17878
17879 switch (cmd) {
17880 case CLI_INIT:
17881 e->command = "ss7 show cics";
17882 e->usage =
17883 "Usage: ss7 show cics <linkset> [dpc]\n"
17884 " Shows the cics of an SS7 linkset.\n";
17885 return NULL;
17886 case CLI_GENERATE:
17887 return NULL;
17888 }
17889
17890 if (a->argc < 4 || a->argc > 5) {
17891 return CLI_SHOWUSAGE;
17892 }
17893
17894 linkset = atoi(a->argv[3]);
17895
17896 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17897 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17898 return CLI_SUCCESS;
17899 }
17900
17901 if (!linksets[linkset-1].ss7.ss7) {
17902 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17903 return CLI_SUCCESS;
17904 }
17905 ss7 = &linksets[linkset-1].ss7;
17906
17907 if (a->argc == 5) {
17908 dpc = atoi(a->argv[4]);
17909 if (dpc < 1) {
17910 ast_cli(a->fd, "Invalid DPC specified!\n");
17911 return CLI_SUCCESS;
17912 }
17913 }
17914
17915 ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
17916
17917 for (i = 0; i < ss7->numchans; i++) {
17918 if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
17919 struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
17920
17921 if (ss7->pvts[i]->owner) {
17922 state = "Used";
17923 } else if (ss7->pvts[i]->ss7call) {
17924 state = "Pending";
17925 } else if (!p->inservice) {
17926 state = "NotInServ";
17927 } else {
17928 state = "Idle";
17929 }
17930
17931 if (p->locallyblocked) {
17932 strcpy(blocking, "L:");
17934 strcat(blocking, "M");
17935 } else {
17936 strcat(blocking, " ");
17937 }
17938
17940 strcat(blocking, "H");
17941 } else {
17942 strcat(blocking, " ");
17943 }
17944 } else {
17945 strcpy(blocking, " ");
17946 }
17947
17948 if (p->remotelyblocked) {
17949 strcat(blocking, " R:");
17951 strcat(blocking, "M");
17952 } else {
17953 strcat(blocking, " ");
17954 }
17955
17957 strcat(blocking, "H");
17958 } else {
17959 strcat(blocking, " ");
17960 }
17961 }
17962
17963 ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
17964 }
17965 }
17966
17967 return CLI_SUCCESS;
17968#undef FORMAT
17969#undef FORMAT2
17970}
17971#endif /* defined(HAVE_SS7) */
17972
17973#if defined(HAVE_SS7)
17974static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17975{
17976 switch (cmd) {
17977 case CLI_INIT:
17978 e->command = "ss7 show version";
17979 e->usage =
17980 "Usage: ss7 show version\n"
17981 " Show the libss7 version\n";
17982 return NULL;
17983 case CLI_GENERATE:
17984 return NULL;
17985 }
17986
17987 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17988
17989 return CLI_SUCCESS;
17990}
17991#endif /* defined(HAVE_SS7) */
17992
17993#if defined(HAVE_SS7)
17994static struct ast_cli_entry dahdi_ss7_cli[] = {
17995 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17996 AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
17997 AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
17998 AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
17999 AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
18000 AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
18001 AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
18002 AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
18003 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
18004 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
18005 AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
18006 AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
18007 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
18008};
18009#endif /* defined(HAVE_SS7) */
18010
18011#if defined(HAVE_PRI)
18012#if defined(HAVE_PRI_CCSS)
18013/*!
18014 * \internal
18015 * \brief CC agent initialization.
18016 * \since 1.8
18017 *
18018 * \param agent CC core agent control.
18019 * \param chan Original channel the agent will attempt to recall.
18020 *
18021 * \details
18022 * This callback is called when the CC core is initialized. Agents should allocate
18023 * any private data necessary for the call and assign it to the private_data
18024 * on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the
18025 * specific agent type, they should be set in this function as well.
18026 *
18027 * \retval 0 on success.
18028 * \retval -1 on error.
18029 */
18030static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
18031{
18032 struct dahdi_pvt *pvt;
18033 struct sig_pri_chan *pvt_chan;
18034 int res;
18035
18036 ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
18037
18038 pvt = ast_channel_tech_pvt(chan);
18039 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
18040 pvt_chan = pvt->sig_pvt;
18041 } else {
18042 pvt_chan = NULL;
18043 }
18044 if (!pvt_chan) {
18045 return -1;
18046 }
18047
18049
18050 res = sig_pri_cc_agent_init(agent, pvt_chan);
18051 if (res) {
18053 }
18054 return res;
18055}
18056#endif /* defined(HAVE_PRI_CCSS) */
18057#endif /* defined(HAVE_PRI) */
18058
18059#if defined(HAVE_PRI)
18060#if defined(HAVE_PRI_CCSS)
18061/*!
18062 * \internal
18063 * \brief Destroy private data on the agent.
18064 * \since 1.8
18065 *
18066 * \param agent CC core agent control.
18067 *
18068 * \details
18069 * The core will call this function upon completion
18070 * or failure of CC.
18071 */
18072static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
18073{
18075
18077}
18078#endif /* defined(HAVE_PRI_CCSS) */
18079#endif /* defined(HAVE_PRI) */
18080
18081#if defined(HAVE_PRI)
18082#if defined(HAVE_PRI_CCSS)
18083static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
18084 .type = dahdi_pri_cc_type,
18085 .init = dahdi_pri_cc_agent_init,
18086 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
18087 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
18088 .respond = sig_pri_cc_agent_req_rsp,
18089 .status_request = sig_pri_cc_agent_status_req,
18090 .stop_ringing = sig_pri_cc_agent_stop_ringing,
18091 .party_b_free = sig_pri_cc_agent_party_b_free,
18092 .start_monitoring = sig_pri_cc_agent_start_monitoring,
18093 .callee_available = sig_pri_cc_agent_callee_available,
18094 .destructor = dahdi_pri_cc_agent_destructor,
18095};
18096#endif /* defined(HAVE_PRI_CCSS) */
18097#endif /* defined(HAVE_PRI) */
18098
18099#if defined(HAVE_PRI)
18100#if defined(HAVE_PRI_CCSS)
18101static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
18102 .type = dahdi_pri_cc_type,
18103 .request_cc = sig_pri_cc_monitor_req_cc,
18104 .suspend = sig_pri_cc_monitor_suspend,
18105 .unsuspend = sig_pri_cc_monitor_unsuspend,
18106 .status_response = sig_pri_cc_monitor_status_rsp,
18107 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
18108 .destructor = sig_pri_cc_monitor_destructor,
18109};
18110#endif /* defined(HAVE_PRI_CCSS) */
18111#endif /* defined(HAVE_PRI) */
18112
18113static int __unload_module(void)
18114{
18115 struct dahdi_pvt *p;
18116#if defined(HAVE_PRI) || defined(HAVE_SS7)
18117 int i, j;
18118#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18119
18120#ifdef HAVE_PRI
18121 for (i = 0; i < NUM_SPANS; i++) {
18122 if (pris[i].pri.master != AST_PTHREADT_NULL) {
18123 pthread_cancel(pris[i].pri.master);
18124 pthread_kill(pris[i].pri.master, SIGURG);
18125 }
18126 }
18127 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18128 ast_unregister_application(dahdi_send_keypad_facility_app);
18129#ifdef HAVE_PRI_PROG_W_CAUSE
18130 ast_unregister_application(dahdi_send_callrerouting_facility_app);
18131#endif
18132#endif
18133#if defined(HAVE_SS7)
18134 for (i = 0; i < NUM_SPANS; i++) {
18135 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
18136 pthread_cancel(linksets[i].ss7.master);
18137 pthread_kill(linksets[i].ss7.master, SIGURG);
18138 }
18139 }
18140 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18141#endif /* defined(HAVE_SS7) */
18142#if defined(HAVE_OPENR2)
18143 dahdi_r2_destroy_links();
18144 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18145 ast_unregister_application(dahdi_accept_r2_call_app);
18146#endif
18147
18149
18151 ast_manager_unregister("DAHDIDialOffhook");
18152 ast_manager_unregister("DAHDIHangup");
18153 ast_manager_unregister("DAHDITransfer");
18154 ast_manager_unregister("DAHDIDNDoff");
18155 ast_manager_unregister("DAHDIDNDon");
18156 ast_manager_unregister("DAHDIShowChannels");
18157 ast_manager_unregister("DAHDIShowStatus");
18158 ast_manager_unregister("DAHDIRestart");
18159#if defined(HAVE_PRI)
18160 ast_manager_unregister("PRIShowSpans");
18161 ast_manager_unregister("PRIDebugSet");
18162 ast_manager_unregister("PRIDebugFileSet");
18163 ast_manager_unregister("PRIDebugFileUnset");
18164#endif /* defined(HAVE_PRI) */
18166
18167 /* Hangup all interfaces if they have an owner */
18169 for (p = iflist; p; p = p->next) {
18170 if (p->owner)
18172 }
18174
18177 pthread_cancel(monitor_thread);
18178 pthread_kill(monitor_thread, SIGURG);
18179 pthread_join(monitor_thread, NULL);
18180 }
18183
18185
18186#if defined(HAVE_PRI)
18187 for (i = 0; i < NUM_SPANS; i++) {
18188 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18189 pthread_join(pris[i].pri.master, NULL);
18190 }
18191 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
18192 dahdi_close_pri_fd(&(pris[i]), j);
18193 }
18194 sig_pri_stop_pri(&pris[i].pri);
18195 }
18196#if defined(HAVE_PRI_CCSS)
18197 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
18198 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
18199#endif /* defined(HAVE_PRI_CCSS) */
18201#endif
18202
18203#if defined(HAVE_SS7)
18204 for (i = 0; i < NUM_SPANS; i++) {
18205 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18206 pthread_join(linksets[i].ss7.master, NULL);
18207 }
18208 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
18209 dahdi_close_ss7_fd(&(linksets[i]), j);
18210 }
18211 if (linksets[i].ss7.ss7) {
18212 ss7_destroy(linksets[i].ss7.ss7);
18213 linksets[i].ss7.ss7 = NULL;
18214 }
18215 }
18216#endif /* defined(HAVE_SS7) */
18218
18220
18223 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
18224 return 0;
18225}
18226
18227static int unload_module(void)
18228{
18229#if defined(HAVE_PRI) || defined(HAVE_SS7)
18230 int y;
18231#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18232#ifdef HAVE_PRI
18233 for (y = 0; y < NUM_SPANS; y++)
18234 ast_mutex_destroy(&pris[y].pri.lock);
18235#endif
18236#if defined(HAVE_SS7)
18237 for (y = 0; y < NUM_SPANS; y++)
18238 ast_mutex_destroy(&linksets[y].ss7.lock);
18239#endif /* defined(HAVE_SS7) */
18240 return __unload_module();
18241}
18242
18243static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
18244{
18245 char *c, *chan;
18246 int x, start, finish;
18247 struct dahdi_pvt *tmp;
18248
18249 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
18250 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
18251 return -1;
18252 }
18253
18254 c = ast_strdupa(value);
18255
18256 while ((chan = strsep(&c, ","))) {
18257 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18258 /* Range */
18259 } else if (sscanf(chan, "%30d", &start)) {
18260 /* Just one */
18261 finish = start;
18262 } else if (!strcasecmp(chan, "pseudo")) {
18263 finish = start = CHAN_PSEUDO;
18264 } else {
18265 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18266 return -1;
18267 }
18268 if (finish < start) {
18269 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18270 x = finish;
18271 finish = start;
18272 start = x;
18273 }
18274
18275 for (x = start; x <= finish; x++) {
18276 if (conf->wanted_channels_start &&
18277 (x < conf->wanted_channels_start ||
18278 x > conf->wanted_channels_end)
18279 ) {
18280 continue;
18281 }
18282 tmp = mkintf(x, conf, reload);
18283
18284 if (tmp) {
18285 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18286 } else {
18287 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18288 (reload == 1) ? "reconfigure" : "register", value);
18289 return -1;
18290 }
18291 if (x == CHAN_PSEUDO) {
18292 has_pseudo = 1;
18293 }
18294 }
18295 }
18296
18297 return 0;
18298}
18299
18300/** The length of the parameters list of 'dahdichan'.
18301 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
18302#define MAX_CHANLIST_LEN 80
18303
18304static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
18305{
18306 char *parse = ast_strdupa(data);
18307 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18308 unsigned int param_count;
18309 unsigned int x;
18310
18311 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18312 return;
18313
18314 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18315
18316 /* first parameter is tap length, process it here */
18317
18318 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18319
18320 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18321 confp->chan.echocancel.head.tap_length = x;
18322 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18323 confp->chan.echocancel.head.tap_length = 128;
18324
18325 /* now process any remaining parameters */
18326
18327 for (x = 1; x < param_count; x++) {
18328 struct {
18329 char *name;
18330 char *value;
18331 } param;
18332
18333 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18334 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18335 continue;
18336 }
18337
18338 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18339 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18340 continue;
18341 }
18342
18343 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18344
18345 if (param.value) {
18346 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18347 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18348 continue;
18349 }
18350 }
18351 confp->chan.echocancel.head.param_count++;
18352 }
18353}
18354
18355#if defined(HAVE_PRI)
18356#if defined(HAVE_PRI_DISPLAY_TEXT)
18357/*!
18358 * \internal
18359 * \brief Determine the configured display text options.
18360 * \since 10.0
18361 *
18362 * \param value Configuration value string.
18363 *
18364 * \return Configured display text option flags.
18365 */
18366static unsigned long dahdi_display_text_option(const char *value)
18367{
18368 char *val_str;
18369 char *opt_str;
18370 unsigned long options;
18371
18372 options = 0;
18373 val_str = ast_strdupa(value);
18374
18375 for (;;) {
18376 opt_str = strsep(&val_str, ",");
18377 if (!opt_str) {
18378 break;
18379 }
18380 opt_str = ast_strip(opt_str);
18381 if (!*opt_str) {
18382 continue;
18383 }
18384
18385 if (!strcasecmp(opt_str, "block")) {
18386 options |= PRI_DISPLAY_OPTION_BLOCK;
18387 } else if (!strcasecmp(opt_str, "name_initial")) {
18388 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
18389 } else if (!strcasecmp(opt_str, "name_update")) {
18390 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
18391 } else if (!strcasecmp(opt_str, "name")) {
18392 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
18393 } else if (!strcasecmp(opt_str, "text")) {
18394 options |= PRI_DISPLAY_OPTION_TEXT;
18395 }
18396 }
18397 return options;
18398}
18399#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
18400#endif /* defined(HAVE_PRI) */
18401
18402#if defined(HAVE_PRI)
18403#if defined(HAVE_PRI_DATETIME_SEND)
18404/*!
18405 * \internal
18406 * \brief Determine the configured date/time send policy option.
18407 * \since 10.0
18408 *
18409 * \param value Configuration value string.
18410 *
18411 * \return Configured date/time send policy option.
18412 */
18413static int dahdi_datetime_send_option(const char *value)
18414{
18415 int option;
18416
18417 option = PRI_DATE_TIME_SEND_DEFAULT;
18418
18419 if (ast_false(value)) {
18420 option = PRI_DATE_TIME_SEND_NO;
18421 } else if (!strcasecmp(value, "date")) {
18422 option = PRI_DATE_TIME_SEND_DATE;
18423 } else if (!strcasecmp(value, "date_hh")) {
18424 option = PRI_DATE_TIME_SEND_DATE_HH;
18425 } else if (!strcasecmp(value, "date_hhmm")) {
18426 option = PRI_DATE_TIME_SEND_DATE_HHMM;
18427 } else if (!strcasecmp(value, "date_hhmmss")) {
18428 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
18429 }
18430
18431 return option;
18432}
18433#endif /* defined(HAVE_PRI_DATETIME_SEND) */
18434#endif /* defined(HAVE_PRI) */
18435
18436/*! process_dahdi() - ignore keyword 'channel' and similar */
18437#define PROC_DAHDI_OPT_NOCHAN (1 << 0)
18438/*! process_dahdi() - No warnings on non-existing cofiguration keywords */
18439#define PROC_DAHDI_OPT_NOWARN (1 << 1)
18440
18441static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
18442{
18443 int count_pattern = 0;
18444 int norval = 0;
18445 char *temp = NULL;
18446
18447 for (; ;) {
18448 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18449 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18450 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18451 break;
18452 }
18453
18454 busy_cadence->pattern[count_pattern] = norval;
18455
18456 count_pattern++;
18457 if (count_pattern == 4) {
18458 break;
18459 }
18460
18461 temp = strchr(v->value, ',');
18462 if (temp == NULL) {
18463 break;
18464 }
18465 v->value = temp + 1;
18466 }
18467 busy_cadence->length = count_pattern;
18468
18469 if (count_pattern % 2 != 0) {
18470 /* The pattern length must be divisible by two */
18471 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18472 }
18473
18474}
18475
18476static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
18477{
18478 struct dahdi_pvt *tmp;
18479 int y;
18480 struct ast_variable *dahdichan = NULL;
18481
18482 /* Re-parse any cadences from beginning, rather than appending until we run out of room */
18484
18485 for (; v; v = v->next) {
18487 continue;
18488
18489 /* Create the interface list */
18490 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
18492 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
18493 continue;
18494 }
18495 if (build_channels(confp, v->value, reload, v->lineno)) {
18496 if (confp->ignore_failed_channels) {
18497 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
18498 continue;
18499 } else {
18500 return -1;
18501 }
18502 }
18503 ast_debug(1, "Channel '%s' configured.\n", v->value);
18504 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
18506 } else if (!strcasecmp(v->name, "buffers")) {
18507 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
18508 ast_log(LOG_WARNING, "Using default buffer policy.\n");
18509 confp->chan.buf_no = numbufs;
18510 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
18511 }
18512 } else if (!strcasecmp(v->name, "faxbuffers")) {
18513 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
18514 confp->chan.usefaxbuffers = 1;
18515 }
18516 } else if (!strcasecmp(v->name, "dahdichan")) {
18517 /* Only process the last dahdichan value. */
18518 dahdichan = v;
18519 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
18521 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18523 } else if (!strcasecmp(v->name, "dring1context")) {
18525 } else if (!strcasecmp(v->name, "dring2context")) {
18527 } else if (!strcasecmp(v->name, "dring3context")) {
18529 } else if (!strcasecmp(v->name, "dring1range")) {
18530 confp->chan.drings.ringnum[0].range = atoi(v->value);
18531 } else if (!strcasecmp(v->name, "dring2range")) {
18532 confp->chan.drings.ringnum[1].range = atoi(v->value);
18533 } else if (!strcasecmp(v->name, "dring3range")) {
18534 confp->chan.drings.ringnum[2].range = atoi(v->value);
18535 } else if (!strcasecmp(v->name, "dring1")) {
18536 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]);
18537 } else if (!strcasecmp(v->name, "dring2")) {
18538 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]);
18539 } else if (!strcasecmp(v->name, "dring3")) {
18540 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]);
18541 } else if (!strcasecmp(v->name, "usecallerid")) {
18542 confp->chan.use_callerid = ast_true(v->value);
18543 } else if (!strcasecmp(v->name, "cidsignalling")) {
18544 if (!strcasecmp(v->value, "bell"))
18546 else if (!strcasecmp(v->value, "v23"))
18548 else if (!strcasecmp(v->value, "dtmf"))
18550 else if (!strcasecmp(v->value, "smdi"))
18552 else if (!strcasecmp(v->value, "v23_jp"))
18554 else if (ast_true(v->value))
18556 } else if (!strcasecmp(v->name, "cidstart")) {
18557 if (!strcasecmp(v->value, "ring"))
18558 confp->chan.cid_start = CID_START_RING;
18559 else if (!strcasecmp(v->value, "polarity_in"))
18561 else if (!strcasecmp(v->value, "polarity"))
18563 else if (!strcasecmp(v->value, "dtmf"))
18565 else if (ast_true(v->value))
18566 confp->chan.cid_start = CID_START_RING;
18567 } else if (!strcasecmp(v->name, "threewaycalling")) {
18568 confp->chan.threewaycalling = ast_true(v->value);
18569 } else if (!strcasecmp(v->name, "threewaysilenthold")) {
18571 } else if (!strcasecmp(v->name, "cancallforward")) {
18572 confp->chan.cancallforward = ast_true(v->value);
18573 } else if (!strcasecmp(v->name, "relaxdtmf")) {
18574 if (ast_true(v->value))
18576 else
18577 confp->chan.dtmfrelax = 0;
18578 } else if (!strcasecmp(v->name, "mailbox")) {
18579 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
18580 } else if (!strcasecmp(v->name, "description")) {
18581 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18582 } else if (!strcasecmp(v->name, "hasvoicemail")) {
18583 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18584 /*
18585 * hasvoicemail is a users.conf legacy voicemail enable method.
18586 * hasvoicemail is only going to work for app_voicemail mailboxes.
18587 */
18588 if (strchr(cat, '@')) {
18589 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18590 } else {
18591 snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18592 "%s@default", cat);
18593 }
18594 }
18595 } else if (!strcasecmp(v->name, "adsi")) {
18596 confp->chan.adsi = ast_true(v->value);
18597 } else if (!strcasecmp(v->name, "usesmdi")) {
18598 confp->chan.use_smdi = ast_true(v->value);
18599 } else if (!strcasecmp(v->name, "smdiport")) {
18600 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18601 } else if (!strcasecmp(v->name, "transfer")) {
18602 confp->chan.transfer = ast_true(v->value);
18603 } else if (!strcasecmp(v->name, "canpark")) {
18604 confp->chan.canpark = ast_true(v->value);
18605 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18606 confp->chan.echocanbridged = ast_true(v->value);
18607 } else if (!strcasecmp(v->name, "busydetect")) {
18608 confp->chan.busydetect = ast_true(v->value);
18609 } else if (!strcasecmp(v->name, "busycount")) {
18610 confp->chan.busycount = atoi(v->value);
18611 } else if (!strcasecmp(v->name, "busypattern")) {
18613 } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18615 } else if (!strcasecmp(v->name, "callprogress")) {
18616 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18617 if (ast_true(v->value))
18619 } else if (!strcasecmp(v->name, "waitfordialtone")) {
18620 confp->chan.waitfordialtone = atoi(v->value);
18621 } else if (!strcasecmp(v->name, "dialtone_detect")) {
18622 if (!strcasecmp(v->value, "always")) {
18623 confp->chan.dialtone_detect = -1;
18624 } else if (ast_true(v->value)) {
18626 } else if (ast_false(v->value)) {
18627 confp->chan.dialtone_detect = 0;
18628 } else {
18629 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18630 }
18631 } else if (!strcasecmp(v->name, "faxdetect")) {
18632 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18633 if (!strcasecmp(v->value, "incoming")) {
18635 } else if (!strcasecmp(v->value, "outgoing")) {
18637 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18639 } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18640 if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18641 confp->chan.faxdetect_timeout = 0;
18642 }
18643 } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18644 if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18645 || confp->chan.firstdigit_timeout <= 0) {
18647 }
18648 } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18649 if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18650 || confp->chan.interdigit_timeout <= 0) {
18652 }
18653 } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18654 if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18655 || confp->chan.matchdigit_timeout <= 0) {
18657 }
18658 } else if (!strcasecmp(v->name, "echocancel")) {
18659 process_echocancel(confp, v->value, v->lineno);
18660 } else if (!strcasecmp(v->name, "echotraining")) {
18661 if (sscanf(v->value, "%30d", &y) == 1) {
18662 if ((y < 10) || (y > 4000)) {
18663 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18664 } else {
18665 confp->chan.echotraining = y;
18666 }
18667 } else if (ast_true(v->value)) {
18668 confp->chan.echotraining = 400;
18669 } else
18670 confp->chan.echotraining = 0;
18671 } else if (!strcasecmp(v->name, "hidecallerid")) {
18672 confp->chan.hidecallerid = ast_true(v->value);
18673 } else if (!strcasecmp(v->name, "hidecalleridname")) {
18674 confp->chan.hidecalleridname = ast_true(v->value);
18675 } else if (!strcasecmp(v->name, "pulsedial")) {
18676 confp->chan.pulse = ast_true(v->value);
18677 } else if (!strcasecmp(v->name, "callreturn")) {
18678 confp->chan.callreturn = ast_true(v->value);
18679 } else if (!strcasecmp(v->name, "callwaiting")) {
18680 confp->chan.callwaiting = ast_true(v->value);
18681 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18683 } else if (!strcasecmp(v->name, "context")) {
18684 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18685 } else if (!strcasecmp(v->name, "language")) {
18686 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18687 } else if (!strcasecmp(v->name, "progzone")) {
18688 ast_copy_string(progzone, v->value, sizeof(progzone));
18689 } else if (!strcasecmp(v->name, "mohinterpret")
18690 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18691 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18692 } else if (!strcasecmp(v->name, "mohsuggest")) {
18693 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18694 } else if (!strcasecmp(v->name, "parkinglot")) {
18695 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18696 } else if (!strcasecmp(v->name, "stripmsd")) {
18697 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18698 confp->chan.stripmsd = atoi(v->value);
18699 } else if (!strcasecmp(v->name, "jitterbuffers")) {
18700 numbufs = atoi(v->value);
18701 } else if (!strcasecmp(v->name, "group")) {
18702 confp->chan.group = ast_get_group(v->value);
18703 } else if (!strcasecmp(v->name, "callgroup")) {
18704 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18705 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a call group\n");
18706 }
18707 if (!strcasecmp(v->value, "none"))
18708 confp->chan.callgroup = 0;
18709 else
18710 confp->chan.callgroup = ast_get_group(v->value);
18711 } else if (!strcasecmp(v->name, "pickupgroup")) {
18712 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18713 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a pickup group\n");
18714 }
18715 if (!strcasecmp(v->value, "none"))
18716 confp->chan.pickupgroup = 0;
18717 else
18718 confp->chan.pickupgroup = ast_get_group(v->value);
18719 } else if (!strcasecmp(v->name, "namedcallgroup")) {
18720 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18721 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named call group\n");
18722 }
18724 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18725 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18726 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named pickup group\n");
18727 }
18729 } else if (!strcasecmp(v->name, "setvar")) {
18730 if (v->value) {
18731 char *varval = NULL;
18732 struct ast_variable *tmpvar;
18733 char varname[strlen(v->value) + 1];
18734 strcpy(varname, v->value); /* safe */
18735 if ((varval = strchr(varname, '='))) {
18736 *varval++ = '\0';
18737 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18738 if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18739 tmpvar->next = confp->chan.vars;
18740 confp->chan.vars = tmpvar;
18741 }
18742 }
18743 }
18744 }
18745 } else if (!strcasecmp(v->name, "immediate")) {
18746 confp->chan.immediate = ast_true(v->value);
18747 } else if (!strcasecmp(v->name, "immediatering")) {
18748 confp->chan.immediatering = ast_true(v->value);
18749 } else if (!strcasecmp(v->name, "transfertobusy")) {
18750 confp->chan.transfertobusy = ast_true(v->value);
18751 } else if (!strcasecmp(v->name, "dialmode")) {
18752 if (!strcasecmp(v->value, "pulse")) {
18754 } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18756 } else if (!strcasecmp(v->value, "none")) {
18758 } else {
18760 }
18761 } else if (!strcasecmp(v->name, "mwimonitor")) {
18762 confp->chan.mwimonitor_neon = 0;
18763 confp->chan.mwimonitor_fsk = 0;
18764 confp->chan.mwimonitor_rpas = 0;
18765 if (strcasestr(v->value, "fsk")) {
18766 confp->chan.mwimonitor_fsk = 1;
18767 }
18768 if (strcasestr(v->value, "rpas")) {
18769 confp->chan.mwimonitor_rpas = 1;
18770 }
18771 if (strcasestr(v->value, "neon")) {
18772 confp->chan.mwimonitor_neon = 1;
18773 }
18774 /* If set to true or yes, assume that simple fsk is desired */
18775 if (ast_true(v->value)) {
18776 confp->chan.mwimonitor_fsk = 1;
18777 }
18778 } else if (!strcasecmp(v->name, "hwrxgain")) {
18779 confp->chan.hwrxgain_enabled = 0;
18780 if (strcasecmp(v->value, "disabled")) {
18781 if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18782 confp->chan.hwrxgain_enabled = 1;
18783 } else {
18784 ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18785 }
18786 }
18787 } else if (!strcasecmp(v->name, "hwtxgain")) {
18788 confp->chan.hwtxgain_enabled = 0;
18789 if (strcasecmp(v->value, "disabled")) {
18790 if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18791 confp->chan.hwtxgain_enabled = 1;
18792 } else {
18793 ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18794 }
18795 }
18796 } else if (!strcasecmp(v->name, "cid_rxgain")) {
18797 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18798 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18799 }
18800 } else if (!strcasecmp(v->name, "rxgain")) {
18801 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18802 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18803 }
18804 } else if (!strcasecmp(v->name, "txgain")) {
18805 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18806 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18807 }
18808 } else if (!strcasecmp(v->name, "txdrc")) {
18809 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18810 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18811 }
18812 } else if (!strcasecmp(v->name, "rxdrc")) {
18813 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18814 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18815 }
18816 } else if (!strcasecmp(v->name, "tonezone")) {
18817 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18818 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18819 }
18820 } else if (!strcasecmp(v->name, "callerid")) {
18821 if (!strcasecmp(v->value, "asreceived")) {
18822 confp->chan.cid_num[0] = '\0';
18823 confp->chan.cid_name[0] = '\0';
18824 } else {
18825 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18826 }
18827 } else if (!strcasecmp(v->name, "fullname")) {
18828 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18829 } else if (!strcasecmp(v->name, "cid_number")) {
18830 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18831 } else if (!strcasecmp(v->name, "cid_tag")) {
18832 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18833 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18834 confp->chan.dahditrcallerid = ast_true(v->value);
18835 } else if (!strcasecmp(v->name, "restrictcid")) {
18836 confp->chan.restrictcid = ast_true(v->value);
18837 } else if (!strcasecmp(v->name, "usecallingpres")) {
18838 confp->chan.use_callingpres = ast_true(v->value);
18839 } else if (!strcasecmp(v->name, "accountcode")) {
18840 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18841 } else if (!strcasecmp(v->name, "amaflags")) {
18843 if (y < 0)
18844 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18845 else
18846 confp->chan.amaflags = y;
18847 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18848 confp->chan.polarityonanswerdelay = atoi(v->value);
18849 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18851 } else if (!strcasecmp(v->name, "ani_info_digits")) {
18852 confp->chan.ani_info_digits = atoi(v->value);
18853 } else if (!strcasecmp(v->name, "ani_wink_time")) {
18854 confp->chan.ani_wink_time = atoi(v->value);
18855 } else if (!strcasecmp(v->name, "ani_timeout")) {
18856 confp->chan.ani_timeout = atoi(v->value);
18857 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18859 } else if (!strcasecmp(v->name, "autoreoriginate")) {
18860 confp->chan.reoriginate = ast_true(v->value);
18861 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18862 confp->chan.sendcalleridafter = atoi(v->value);
18863 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18865 } else if (ast_cc_is_config_param(v->name)) {
18866 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18867 } else if (!strcasecmp(v->name, "mwisendtype")) {
18868#ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18869 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18870 mwisend_rpas = 1;
18871 } else {
18872 mwisend_rpas = 0;
18873 }
18874#else
18875 /* Default is fsk, to turn it off you must specify nofsk */
18876 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18877 if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18878 confp->chan.mwisend_fsk = 0;
18879 } else { /* Default FSK */
18880 confp->chan.mwisend_fsk = 1;
18881 }
18882 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18883 confp->chan.mwisend_rpas = 1;
18884 } else {
18885 confp->chan.mwisend_rpas = 0;
18886 }
18887 if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18888 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18889 }
18890 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18891 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18892 }
18893 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18894 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18895 }
18896#endif
18897 } else if (reload != 1) {
18898 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18899 int orig_radio = confp->chan.radio;
18900 int orig_outsigmod = confp->chan.outsigmod;
18901 int orig_auto = confp->is_sig_auto;
18902
18903 confp->chan.radio = 0;
18904 confp->chan.outsigmod = -1;
18905 confp->is_sig_auto = 0;
18906 if (!strcasecmp(v->value, "em")) {
18907 confp->chan.sig = SIG_EM;
18908 } else if (!strcasecmp(v->value, "em_e1")) {
18909 confp->chan.sig = SIG_EM_E1;
18910 } else if (!strcasecmp(v->value, "em_w")) {
18911 confp->chan.sig = SIG_EMWINK;
18912 } else if (!strcasecmp(v->value, "fxs_ls")) {
18913 confp->chan.sig = SIG_FXSLS;
18914 } else if (!strcasecmp(v->value, "fxs_gs")) {
18915 confp->chan.sig = SIG_FXSGS;
18916 } else if (!strcasecmp(v->value, "fxs_ks")) {
18917 confp->chan.sig = SIG_FXSKS;
18918 } else if (!strcasecmp(v->value, "fxo_ls")) {
18919 confp->chan.sig = SIG_FXOLS;
18920 } else if (!strcasecmp(v->value, "fxo_gs")) {
18921 confp->chan.sig = SIG_FXOGS;
18922 } else if (!strcasecmp(v->value, "fxo_ks")) {
18923 confp->chan.sig = SIG_FXOKS;
18924 } else if (!strcasecmp(v->value, "fxs_rx")) {
18925 confp->chan.sig = SIG_FXSKS;
18926 confp->chan.radio = 1;
18927 } else if (!strcasecmp(v->value, "fxo_rx")) {
18928 confp->chan.sig = SIG_FXOLS;
18929 confp->chan.radio = 1;
18930 } else if (!strcasecmp(v->value, "fxs_tx")) {
18931 confp->chan.sig = SIG_FXSLS;
18932 confp->chan.radio = 1;
18933 } else if (!strcasecmp(v->value, "fxo_tx")) {
18934 confp->chan.sig = SIG_FXOGS;
18935 confp->chan.radio = 1;
18936 } else if (!strcasecmp(v->value, "em_rx")) {
18937 confp->chan.sig = SIG_EM;
18938 confp->chan.radio = 1;
18939 } else if (!strcasecmp(v->value, "em_tx")) {
18940 confp->chan.sig = SIG_EM;
18941 confp->chan.radio = 1;
18942 } else if (!strcasecmp(v->value, "em_rxtx")) {
18943 confp->chan.sig = SIG_EM;
18944 confp->chan.radio = 2;
18945 } else if (!strcasecmp(v->value, "em_txrx")) {
18946 confp->chan.sig = SIG_EM;
18947 confp->chan.radio = 2;
18948 } else if (!strcasecmp(v->value, "sf")) {
18949 confp->chan.sig = SIG_SF;
18950 } else if (!strcasecmp(v->value, "sf_w")) {
18951 confp->chan.sig = SIG_SFWINK;
18952 } else if (!strcasecmp(v->value, "sf_featd")) {
18953 confp->chan.sig = SIG_FEATD;
18954 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18955 confp->chan.sig = SIG_FEATDMF;
18956 } else if (!strcasecmp(v->value, "sf_featb")) {
18957 confp->chan.sig = SIG_SF_FEATB;
18958 } else if (!strcasecmp(v->value, "sf")) {
18959 confp->chan.sig = SIG_SF;
18960 } else if (!strcasecmp(v->value, "sf_rx")) {
18961 confp->chan.sig = SIG_SF;
18962 confp->chan.radio = 1;
18963 } else if (!strcasecmp(v->value, "sf_tx")) {
18964 confp->chan.sig = SIG_SF;
18965 confp->chan.radio = 1;
18966 } else if (!strcasecmp(v->value, "sf_rxtx")) {
18967 confp->chan.sig = SIG_SF;
18968 confp->chan.radio = 2;
18969 } else if (!strcasecmp(v->value, "sf_txrx")) {
18970 confp->chan.sig = SIG_SF;
18971 confp->chan.radio = 2;
18972 } else if (!strcasecmp(v->value, "featd")) {
18973 confp->chan.sig = SIG_FEATD;
18974 } else if (!strcasecmp(v->value, "featdmf")) {
18975 confp->chan.sig = SIG_FEATDMF;
18976 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18977 confp->chan.sig = SIG_FEATDMF_TA;
18978 } else if (!strcasecmp(v->value, "e911")) {
18979 confp->chan.sig = SIG_E911;
18980 } else if (!strcasecmp(v->value, "fgccama")) {
18981 confp->chan.sig = SIG_FGC_CAMA;
18982 } else if (!strcasecmp(v->value, "fgccamamf")) {
18983 confp->chan.sig = SIG_FGC_CAMAMF;
18984 } else if (!strcasecmp(v->value, "featb")) {
18985 confp->chan.sig = SIG_FEATB;
18986#ifdef HAVE_PRI
18987 } else if (!strcasecmp(v->value, "pri_net")) {
18988 confp->chan.sig = SIG_PRI;
18989 confp->pri.pri.nodetype = PRI_NETWORK;
18990 } else if (!strcasecmp(v->value, "pri_cpe")) {
18991 confp->chan.sig = SIG_PRI;
18992 confp->pri.pri.nodetype = PRI_CPE;
18993 } else if (!strcasecmp(v->value, "bri_cpe")) {
18994 confp->chan.sig = SIG_BRI;
18995 confp->pri.pri.nodetype = PRI_CPE;
18996 } else if (!strcasecmp(v->value, "bri_net")) {
18997 confp->chan.sig = SIG_BRI;
18998 confp->pri.pri.nodetype = PRI_NETWORK;
18999 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
19000 confp->chan.sig = SIG_BRI_PTMP;
19001 confp->pri.pri.nodetype = PRI_CPE;
19002 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
19003#if defined(HAVE_PRI_CALL_HOLD)
19004 confp->chan.sig = SIG_BRI_PTMP;
19005 confp->pri.pri.nodetype = PRI_NETWORK;
19006#else
19007 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
19008#endif /* !defined(HAVE_PRI_CALL_HOLD) */
19009#endif
19010#if defined(HAVE_SS7)
19011 } else if (!strcasecmp(v->value, "ss7")) {
19012 confp->chan.sig = SIG_SS7;
19013#endif /* defined(HAVE_SS7) */
19014#ifdef HAVE_OPENR2
19015 } else if (!strcasecmp(v->value, "mfcr2")) {
19016 confp->chan.sig = SIG_MFCR2;
19017#endif
19018 } else if (!strcasecmp(v->value, "auto")) {
19019 confp->is_sig_auto = 1;
19020 } else {
19021 confp->chan.outsigmod = orig_outsigmod;
19022 confp->chan.radio = orig_radio;
19023 confp->is_sig_auto = orig_auto;
19024 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19025 }
19026 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
19027 if (!strcasecmp(v->value, "em")) {
19028 confp->chan.outsigmod = SIG_EM;
19029 } else if (!strcasecmp(v->value, "em_e1")) {
19030 confp->chan.outsigmod = SIG_EM_E1;
19031 } else if (!strcasecmp(v->value, "em_w")) {
19032 confp->chan.outsigmod = SIG_EMWINK;
19033 } else if (!strcasecmp(v->value, "sf")) {
19034 confp->chan.outsigmod = SIG_SF;
19035 } else if (!strcasecmp(v->value, "sf_w")) {
19036 confp->chan.outsigmod = SIG_SFWINK;
19037 } else if (!strcasecmp(v->value, "sf_featd")) {
19038 confp->chan.outsigmod = SIG_FEATD;
19039 } else if (!strcasecmp(v->value, "sf_featdmf")) {
19040 confp->chan.outsigmod = SIG_FEATDMF;
19041 } else if (!strcasecmp(v->value, "sf_featb")) {
19042 confp->chan.outsigmod = SIG_SF_FEATB;
19043 } else if (!strcasecmp(v->value, "sf")) {
19044 confp->chan.outsigmod = SIG_SF;
19045 } else if (!strcasecmp(v->value, "featd")) {
19046 confp->chan.outsigmod = SIG_FEATD;
19047 } else if (!strcasecmp(v->value, "featdmf")) {
19048 confp->chan.outsigmod = SIG_FEATDMF;
19049 } else if (!strcasecmp(v->value, "featdmf_ta")) {
19050 confp->chan.outsigmod = SIG_FEATDMF_TA;
19051 } else if (!strcasecmp(v->value, "e911")) {
19052 confp->chan.outsigmod = SIG_E911;
19053 } else if (!strcasecmp(v->value, "fgccama")) {
19054 confp->chan.outsigmod = SIG_FGC_CAMA;
19055 } else if (!strcasecmp(v->value, "fgccamamf")) {
19056 confp->chan.outsigmod = SIG_FGC_CAMAMF;
19057 } else if (!strcasecmp(v->value, "featb")) {
19058 confp->chan.outsigmod = SIG_FEATB;
19059 } else {
19060 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
19061 }
19062#ifdef HAVE_PRI
19063 } else if (!strcasecmp(v->name, "pridialplan")) {
19064 if (!strcasecmp(v->value, "national")) {
19065 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
19066 } else if (!strcasecmp(v->value, "unknown")) {
19067 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
19068 } else if (!strcasecmp(v->value, "private")) {
19069 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
19070 } else if (!strcasecmp(v->value, "international")) {
19071 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
19072 } else if (!strcasecmp(v->value, "local")) {
19073 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
19074 } else if (!strcasecmp(v->value, "dynamic")) {
19075 confp->pri.pri.dialplan = -1;
19076 } else if (!strcasecmp(v->value, "redundant")) {
19077 confp->pri.pri.dialplan = -2;
19078 } else {
19079 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
19080 }
19081 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
19082 if (!strcasecmp(v->value, "national")) {
19083 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
19084 } else if (!strcasecmp(v->value, "unknown")) {
19085 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
19086 } else if (!strcasecmp(v->value, "private")) {
19087 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
19088 } else if (!strcasecmp(v->value, "international")) {
19089 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
19090 } else if (!strcasecmp(v->value, "local")) {
19091 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
19092 } else if (!strcasecmp(v->value, "from_channel")) {
19093 confp->pri.pri.localdialplan = 0;
19094 } else if (!strcasecmp(v->value, "dynamic")) {
19095 confp->pri.pri.localdialplan = -1;
19096 } else if (!strcasecmp(v->value, "redundant")) {
19097 confp->pri.pri.localdialplan = -2;
19098 } else {
19099 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
19100 }
19101 } else if (!strcasecmp(v->name, "pricpndialplan")) {
19102 if (!strcasecmp(v->value, "national")) {
19103 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
19104 } else if (!strcasecmp(v->value, "unknown")) {
19105 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
19106 } else if (!strcasecmp(v->value, "private")) {
19107 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
19108 } else if (!strcasecmp(v->value, "international")) {
19109 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
19110 } else if (!strcasecmp(v->value, "local")) {
19111 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
19112 } else if (!strcasecmp(v->value, "from_channel")) {
19113 confp->pri.pri.cpndialplan = 0;
19114 } else if (!strcasecmp(v->value, "dynamic")) {
19115 confp->pri.pri.cpndialplan = -1;
19116 } else if (!strcasecmp(v->value, "redundant")) {
19117 confp->pri.pri.cpndialplan = -2;
19118 } else {
19119 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
19120 }
19121 } else if (!strcasecmp(v->name, "switchtype")) {
19122 if (!strcasecmp(v->value, "national"))
19123 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
19124 else if (!strcasecmp(v->value, "ni1"))
19125 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
19126 else if (!strcasecmp(v->value, "dms100"))
19127 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
19128 else if (!strcasecmp(v->value, "4ess"))
19129 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
19130 else if (!strcasecmp(v->value, "5ess"))
19131 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
19132 else if (!strcasecmp(v->value, "euroisdn"))
19133 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
19134 else if (!strcasecmp(v->value, "qsig"))
19135 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
19136 else {
19137 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
19138 return -1;
19139 }
19140 } else if (!strcasecmp(v->name, "msn")) {
19141 ast_copy_string(confp->pri.pri.msn_list, v->value,
19142 sizeof(confp->pri.pri.msn_list));
19143 } else if (!strcasecmp(v->name, "nsf")) {
19144 if (!strcasecmp(v->value, "sdn"))
19145 confp->pri.pri.nsf = PRI_NSF_SDN;
19146 else if (!strcasecmp(v->value, "megacom"))
19147 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
19148 else if (!strcasecmp(v->value, "tollfreemegacom"))
19149 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
19150 else if (!strcasecmp(v->value, "accunet"))
19151 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
19152 else if (!strcasecmp(v->value, "none"))
19153 confp->pri.pri.nsf = PRI_NSF_NONE;
19154 else {
19155 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
19156 confp->pri.pri.nsf = PRI_NSF_NONE;
19157 }
19158 } else if (!strcasecmp(v->name, "priindication")) {
19159 if (!strcasecmp(v->value, "outofband"))
19160 confp->chan.priindication_oob = 1;
19161 else if (!strcasecmp(v->value, "inband"))
19162 confp->chan.priindication_oob = 0;
19163 else
19164 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
19165 v->value, v->lineno);
19166 } else if (!strcasecmp(v->name, "priexclusive")) {
19167 confp->chan.priexclusive = ast_true(v->value);
19168 } else if (!strcasecmp(v->name, "internationalprefix")) {
19169 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
19170 } else if (!strcasecmp(v->name, "nationalprefix")) {
19171 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
19172 } else if (!strcasecmp(v->name, "localprefix")) {
19173 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
19174 } else if (!strcasecmp(v->name, "privateprefix")) {
19175 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
19176 } else if (!strcasecmp(v->name, "unknownprefix")) {
19177 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
19178 } else if (!strcasecmp(v->name, "resetinterval")) {
19179 if (!strcasecmp(v->value, "never"))
19180 confp->pri.pri.resetinterval = -1;
19181 else if (atoi(v->value) >= 60)
19182 confp->pri.pri.resetinterval = atoi(v->value);
19183 else
19184 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
19185 v->value, v->lineno);
19186 } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
19187 confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
19188 } else if (!strcasecmp(v->name, "minunused")) {
19189 confp->pri.pri.minunused = atoi(v->value);
19190 } else if (!strcasecmp(v->name, "minidle")) {
19191 confp->pri.pri.minidle = atoi(v->value);
19192 } else if (!strcasecmp(v->name, "idleext")) {
19193 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
19194 } else if (!strcasecmp(v->name, "idledial")) {
19195 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
19196 } else if (!strcasecmp(v->name, "overlapdial")) {
19197 if (ast_true(v->value)) {
19198 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19199 } else if (!strcasecmp(v->value, "incoming")) {
19200 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
19201 } else if (!strcasecmp(v->value, "outgoing")) {
19202 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
19203 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
19204 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19205 } else {
19206 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
19207 }
19208#ifdef HAVE_PRI_PROG_W_CAUSE
19209 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
19210 if (!strcasecmp(v->value, "logical")) {
19211 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
19212 } else if (!strcasecmp(v->value, "physical")) {
19213 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19214 } else {
19215 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
19216 }
19217#endif
19218 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
19219 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
19220#if defined(HAVE_PRI_SERVICE_MESSAGES)
19221 } else if (!strcasecmp(v->name, "service_message_support")) {
19222 /* assuming switchtype for this channel group has been configured already */
19223 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
19224 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
19225 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
19226 confp->pri.pri.enable_service_message_support = 1;
19227 } else {
19228 confp->pri.pri.enable_service_message_support = 0;
19229 }
19230#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
19231#ifdef HAVE_PRI_INBANDDISCONNECT
19232 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
19233 confp->pri.pri.inbanddisconnect = ast_true(v->value);
19234#endif
19235 } else if (!strcasecmp(v->name, "pritimer")) {
19236#ifdef PRI_GETSET_TIMERS
19237 char tmp[20];
19238 char *timerc;
19239 char *c;
19240 int timer;
19241 int timeridx;
19242
19243 ast_copy_string(tmp, v->value, sizeof(tmp));
19244 c = tmp;
19245 timerc = strsep(&c, ",");
19246 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
19247 timeridx = pri_timer2idx(timerc);
19248 timer = atoi(c);
19249 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
19251 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19252 v->lineno);
19253 } else if (!timer) {
19255 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19256 c, timerc, v->lineno);
19257 } else {
19258 confp->pri.pri.pritimers[timeridx] = timer;
19259 }
19260 } else {
19262 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19263 v->value, v->lineno);
19264 }
19265#endif /* PRI_GETSET_TIMERS */
19266 } else if (!strcasecmp(v->name, "facilityenable")) {
19267 confp->pri.pri.facilityenable = ast_true(v->value);
19268#if defined(HAVE_PRI_AOC_EVENTS)
19269 } else if (!strcasecmp(v->name, "aoc_enable")) {
19270 confp->pri.pri.aoc_passthrough_flag = 0;
19271 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
19272 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
19273 }
19274 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
19275 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
19276 }
19277 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
19278 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
19279 }
19280 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
19281 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
19282#endif /* defined(HAVE_PRI_AOC_EVENTS) */
19283#if defined(HAVE_PRI_CALL_HOLD)
19284 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
19285 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
19286#endif /* defined(HAVE_PRI_CALL_HOLD) */
19287 } else if (!strcasecmp(v->name, "moh_signaling")
19288 || !strcasecmp(v->name, "moh_signalling")) {
19289 if (!strcasecmp(v->value, "moh")) {
19290 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19291 } else if (!strcasecmp(v->value, "notify")) {
19292 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
19293#if defined(HAVE_PRI_CALL_HOLD)
19294 } else if (!strcasecmp(v->value, "hold")) {
19295 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
19296#endif /* defined(HAVE_PRI_CALL_HOLD) */
19297 } else {
19298 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19299 }
19300#if defined(HAVE_PRI_CCSS)
19301 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
19302 if (!strcasecmp(v->value, "global")) {
19303 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
19304 } else if (!strcasecmp(v->value, "specific")) {
19305 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19306 } else {
19307 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19308 }
19309 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
19310 if (!strcasecmp(v->value, "release")) {
19311 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
19312 } else if (!strcasecmp(v->value, "retain")) {
19313 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19314 } else if (!strcasecmp(v->value, "do_not_care")) {
19315 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
19316 } else {
19317 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19318 }
19319 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
19320 if (!strcasecmp(v->value, "release")) {
19321 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
19322 } else if (!strcasecmp(v->value, "retain")) {
19323 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19324 } else {
19325 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19326 }
19327#endif /* defined(HAVE_PRI_CCSS) */
19328#if defined(HAVE_PRI_CALL_WAITING)
19329 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
19330 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
19331 if (confp->pri.pri.max_call_waiting_calls < 0) {
19332 /* Negative values are not allowed. */
19333 confp->pri.pri.max_call_waiting_calls = 0;
19334 }
19335 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
19336 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
19337#endif /* defined(HAVE_PRI_CALL_WAITING) */
19338#if defined(HAVE_PRI_MWI)
19339 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
19340 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
19341 sizeof(confp->pri.pri.mwi_mailboxes));
19342 } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
19343 ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
19344 sizeof(confp->pri.pri.mwi_vm_boxes));
19345 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
19346 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
19347 sizeof(confp->pri.pri.mwi_vm_numbers));
19348#endif /* defined(HAVE_PRI_MWI) */
19349 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
19350 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
19351 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
19352 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
19353 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
19354 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
19355#if defined(HAVE_PRI_DISPLAY_TEXT)
19356 } else if (!strcasecmp(v->name, "display_send")) {
19357 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
19358 } else if (!strcasecmp(v->name, "display_receive")) {
19359 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
19360#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19361#if defined(HAVE_PRI_MCID)
19362 } else if (!strcasecmp(v->name, "mcid_send")) {
19363 confp->pri.pri.mcid_send = ast_true(v->value);
19364#endif /* defined(HAVE_PRI_MCID) */
19365#if defined(HAVE_PRI_DATETIME_SEND)
19366 } else if (!strcasecmp(v->name, "datetime_send")) {
19367 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
19368#endif /* defined(HAVE_PRI_DATETIME_SEND) */
19369 } else if (!strcasecmp(v->name, "layer1_presence")) {
19370 if (!strcasecmp(v->value, "required")) {
19371 confp->pri.pri.layer1_ignored = 0;
19372 } else if (!strcasecmp(v->value, "ignore")) {
19373 confp->pri.pri.layer1_ignored = 1;
19374 } else {
19375 /* Default */
19376 confp->pri.pri.layer1_ignored = 0;
19377 }
19378#if defined(HAVE_PRI_L2_PERSISTENCE)
19379 } else if (!strcasecmp(v->name, "layer2_persistence")) {
19380 if (!strcasecmp(v->value, "keep_up")) {
19381 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
19382 } else if (!strcasecmp(v->value, "leave_down")) {
19383 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
19384 } else {
19385 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
19386 }
19387#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
19388 } else if (!strcasecmp(v->name, "colp_send")) {
19389 if (!strcasecmp(v->value, "block")) {
19390 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
19391 } else if (!strcasecmp(v->value, "connect")) {
19392 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
19393 } else if (!strcasecmp(v->value, "update")) {
19394 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19395 } else {
19396 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19397 }
19398#endif /* HAVE_PRI */
19399#if defined(HAVE_SS7)
19400 } else if (!strcasecmp(v->name, "ss7type")) {
19401 if (!strcasecmp(v->value, "itu")) {
19402 cur_ss7type = SS7_ITU;
19403 } else if (!strcasecmp(v->value, "ansi")) {
19404 cur_ss7type = SS7_ANSI;
19405 } else {
19406 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
19407 }
19408 } else if (!strcasecmp(v->name, "slc")) {
19409 cur_slc = atoi(v->value);
19410 } else if (!strcasecmp(v->name, "linkset")) {
19411 cur_linkset = atoi(v->value);
19412 } else if (!strcasecmp(v->name, "pointcode")) {
19413 cur_pointcode = parse_pointcode(v->value);
19414 } else if (!strcasecmp(v->name, "adjpointcode")) {
19415 cur_adjpointcode = parse_pointcode(v->value);
19416 } else if (!strcasecmp(v->name, "defaultdpc")) {
19417 cur_defaultdpc = parse_pointcode(v->value);
19418 } else if (!strcasecmp(v->name, "cicbeginswith")) {
19419 cur_cicbeginswith = atoi(v->value);
19420 } else if (!strcasecmp(v->name, "networkindicator")) {
19421 if (!strcasecmp(v->value, "national")) {
19422 cur_networkindicator = SS7_NI_NAT;
19423 } else if (!strcasecmp(v->value, "national_spare")) {
19424 cur_networkindicator = SS7_NI_NAT_SPARE;
19425 } else if (!strcasecmp(v->value, "international")) {
19426 cur_networkindicator = SS7_NI_INT;
19427 } else if (!strcasecmp(v->value, "international_spare")) {
19428 cur_networkindicator = SS7_NI_INT_SPARE;
19429 } else {
19430 cur_networkindicator = -1;
19431 }
19432 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
19433 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
19434 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
19435 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
19436 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
19437 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
19438 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
19439 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
19440 } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
19441 ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
19442 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
19443 if (!strcasecmp(v->value, "national")) {
19444 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19445 } else if (!strcasecmp(v->value, "international")) {
19446 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19447 } else if (!strcasecmp(v->value, "subscriber")) {
19448 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19449 } else if (!strcasecmp(v->value, "unknown")) {
19450 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19451 } else if (!strcasecmp(v->value, "dynamic")) {
19452 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19453 } else {
19454 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
19455 }
19456 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
19457 if (!strcasecmp(v->value, "national")) {
19458 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19459 } else if (!strcasecmp(v->value, "international")) {
19460 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19461 } else if (!strcasecmp(v->value, "subscriber")) {
19462 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19463 } else if (!strcasecmp(v->value, "unknown")) {
19464 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19465 } else if (!strcasecmp(v->value, "dynamic")) {
19466 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19467 } else {
19468 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
19469 }
19470 } else if (!strcasecmp(v->name, "sigchan")) {
19471 int sigchan, res;
19472 sigchan = atoi(v->value);
19473 res = linkset_addsigchan(sigchan);
19474 if (res < 0) {
19475 return -1;
19476 }
19477 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
19478 struct dahdi_ss7 *link;
19479 link = ss7_resolve_linkset(cur_linkset);
19480 if (!link) {
19481 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19482 return -1;
19483 }
19484 if (ast_true(v->value)) {
19485 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19486 } else {
19487 link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19488 }
19489 } else if (!strcasecmp(v->name, "ss7_autoacm")) {
19490 struct dahdi_ss7 *link;
19491 link = ss7_resolve_linkset(cur_linkset);
19492 if (!link) {
19493 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19494 return -1;
19495 }
19496 if (ast_true(v->value)) {
19497 link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19498 } else {
19499 link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19500 }
19501 } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
19502 struct dahdi_ss7 *link;
19503 link = ss7_resolve_linkset(cur_linkset);
19504 if (!link) {
19505 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19506 return -1;
19507 }
19508 if (ast_true(v->value)) {
19509 link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19510 } else {
19511 link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19512 }
19513 } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
19514 struct dahdi_ss7 *link;
19515 link = ss7_resolve_linkset(cur_linkset);
19516 if (!link) {
19517 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19518 return -1;
19519 }
19520 if (ast_true(v->value)) {
19521 link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19522 } else {
19523 link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19524 }
19525 } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
19526 struct dahdi_ss7 *link;
19527 link = ss7_resolve_linkset(cur_linkset);
19528 if (!link) {
19529 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19530 return -1;
19531 }
19532 if (ast_true(v->value)) {
19533 link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19534 } else {
19535 link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19536 }
19537 } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
19538 struct dahdi_ss7 *link;
19539 link = ss7_resolve_linkset(cur_linkset);
19540 if (!link) {
19541 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19542 return -1;
19543 }
19544 if (!link->ss7.ss7) {
19545 ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
19546 } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19547 ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
19548 }
19549 } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
19550 struct dahdi_ss7 *link;
19551 link = ss7_resolve_linkset(cur_linkset);
19552 if (!link) {
19553 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19554 return -1;
19555 }
19556 if (!link->ss7.ss7) {
19557 ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
19558 } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19559 ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
19560 }
19561 } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
19562 struct dahdi_ss7 *link;
19563 link = ss7_resolve_linkset(cur_linkset);
19564 if (!link) {
19565 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19566 return -1;
19567 }
19568 if (!link->ss7.ss7) {
19569 ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
19570 } else if (ast_true(v->value)) {
19571 ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19572 } else {
19573 ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19574 }
19575 } else if (!strcasecmp(v->name, "non_isdn_access")) {
19576 struct dahdi_ss7 *link;
19577 link = ss7_resolve_linkset(cur_linkset);
19578 if (!link) {
19579 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19580 return -1;
19581 }
19582 if (!link->ss7.ss7) {
19583 ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
19584 } else if (ast_true(v->value)) {
19585 ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19586 } else {
19587 ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19588 }
19589 } else if (!strcasecmp(v->name, "sls_shift")) {
19590 struct dahdi_ss7 *link;
19591 int sls_shift = atoi(v->value);
19592
19593 if (sls_shift < 0 || sls_shift > 7) {
19594 ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
19595 return -1;
19596 }
19597
19598 link = ss7_resolve_linkset(cur_linkset);
19599 if (!link) {
19600 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19601 return -1;
19602 }
19603 if (!link->ss7.ss7) {
19604 ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
19605 } else {
19606 ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19607 }
19608 } else if (!strcasecmp(v->name, "cause_location")) {
19609 struct dahdi_ss7 *link;
19610 int cause_location = atoi(v->value);
19611
19612 if (cause_location < 0 || cause_location > 15) {
19613 ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
19614 return -1;
19615 }
19616 link = ss7_resolve_linkset(cur_linkset);
19617 if (!link) {
19618 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19619 return -1;
19620 }
19621 if (!link->ss7.ss7) {
19622 ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19623 } else {
19624 ss7_set_cause_location(link->ss7.ss7, cause_location);
19625 }
19626#endif /* defined(HAVE_SS7) */
19627#ifdef HAVE_OPENR2
19628 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19629 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19630 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);
19631 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19632 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19633 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19634 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19635 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19636 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19637 confp->mfcr2.variant = OR2_VAR_ITU;
19638 }
19639 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19640 confp->mfcr2.mfback_timeout = atoi(v->value);
19641 if (!confp->mfcr2.mfback_timeout) {
19642 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19643 confp->mfcr2.mfback_timeout = -1;
19644 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19645 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19646 }
19647 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19648 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19649 if (confp->mfcr2.metering_pulse_timeout > 500) {
19650 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19651 }
19652#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19653 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19654 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19655 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19656 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19657 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19658 confp->mfcr2.dtmf_time_on = atoi(v->value);
19659 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19660 confp->mfcr2.dtmf_time_off = atoi(v->value);
19661#endif
19662#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19663 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19664 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19665#endif
19666 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19667 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19668 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19669 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19670 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19671 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19672 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19673 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19674 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19675 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19676 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19677 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19678 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19679 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19680#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19681 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19682 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19683#endif
19684 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19685 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19686 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19687 confp->mfcr2.max_ani = atoi(v->value);
19688 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19689 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19690 }
19691 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19692 confp->mfcr2.max_dnis = atoi(v->value);
19693 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19694 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19695 }
19696 } else if (!strcasecmp(v->name, "mfcr2_category")) {
19697 confp->mfcr2.category = openr2_proto_get_category(v->value);
19698 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19699 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19700 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19701 v->value, v->lineno);
19702 }
19703 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19704 openr2_log_level_t tmplevel;
19705 char *clevel;
19706 char *logval;
19707 char copy[strlen(v->value) + 1];
19708 strcpy(copy, v->value); /* safe */
19709 logval = copy;
19710 while (logval) {
19711 clevel = strsep(&logval,",");
19712 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19713 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19714 continue;
19715 }
19716 confp->mfcr2.loglevel |= tmplevel;
19717 }
19718#endif /* HAVE_OPENR2 */
19719 } else if (!strcasecmp(v->name, "cadence")) {
19720 /* setup to scan our argument */
19721 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19722 int i;
19723 struct dahdi_ring_cadence new_cadence;
19724 int cid_location = -1;
19725 int firstcadencepos = 0;
19726 char original_args[80];
19727 int cadence_is_ok = 1;
19728
19729 ast_copy_string(original_args, v->value, sizeof(original_args));
19730 /* 16 cadences allowed (8 pairs) */
19731 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]);
19732
19733 /* Cadence must be even (on/off) */
19734 if (element_count % 2 == 1) {
19735 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19736 cadence_is_ok = 0;
19737 }
19738
19739 /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19740 if (element_count > ARRAY_LEN(c)) {
19741 element_count = ARRAY_LEN(c);
19742 }
19743
19744 /* Ring cadences cannot be negative */
19745 for (i = 0; i < element_count; i++) {
19746 if (c[i] == 0) {
19747 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19748 cadence_is_ok = 0;
19749 break;
19750 } else if (c[i] < 0) {
19751 if (i % 2 == 1) {
19752 /* Silence duration, negative possibly okay */
19753 if (cid_location == -1) {
19754 cid_location = i;
19755 c[i] *= -1;
19756 } else {
19757 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19758 cadence_is_ok = 0;
19759 break;
19760 }
19761 } else {
19762 if (firstcadencepos == 0) {
19763 firstcadencepos = i; /* only recorded to avoid duplicate specification */
19764 /* duration will be passed negative to the DAHDI driver */
19765 } else {
19766 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19767 cadence_is_ok = 0;
19768 break;
19769 }
19770 }
19771 }
19772 }
19773
19774 /* Substitute our scanned cadence */
19775 for (i = 0; i < 16; i++) {
19776 new_cadence.ringcadence[i] = c[i];
19777 }
19778
19779 if (cadence_is_ok) {
19780 /* ---we scanned it without getting annoyed; now some sanity checks--- */
19781 if (element_count < 2) {
19782 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19783 } else {
19784 if (cid_location == -1) {
19785 /* user didn't say; default to first pause */
19786 cid_location = 1;
19787 } else {
19788 /* convert element_index to cidrings value */
19789 cid_location = (cid_location + 1) / 2;
19790 }
19791 /* ---we like their cadence; try to install it--- */
19793 /* this is the first user-defined cadence; clear the default user cadences */
19794 num_cadence = 0;
19795 if ((num_cadence+1) >= NUM_CADENCE_MAX)
19796 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19797 else {
19798 cadences[num_cadence] = new_cadence;
19799 cidrings[num_cadence++] = cid_location;
19800 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19801 }
19802 }
19803 }
19804 } else if (!strcasecmp(v->name, "ringtimeout")) {
19805 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19806 } else if (!strcasecmp(v->name, "prewink")) {
19807 confp->timing.prewinktime = atoi(v->value);
19808 } else if (!strcasecmp(v->name, "preflash")) {
19809 confp->timing.preflashtime = atoi(v->value);
19810 } else if (!strcasecmp(v->name, "wink")) {
19811 confp->timing.winktime = atoi(v->value);
19812 } else if (!strcasecmp(v->name, "flash")) {
19813 confp->timing.flashtime = atoi(v->value);
19814 } else if (!strcasecmp(v->name, "start")) {
19815 confp->timing.starttime = atoi(v->value);
19816 } else if (!strcasecmp(v->name, "rxwink")) {
19817 confp->timing.rxwinktime = atoi(v->value);
19818 } else if (!strcasecmp(v->name, "rxflash")) {
19819 confp->timing.rxflashtime = atoi(v->value);
19820 } else if (!strcasecmp(v->name, "debounce")) {
19821 confp->timing.debouncetime = atoi(v->value);
19822 } else if (!strcasecmp(v->name, "toneduration")) {
19823 int toneduration;
19824 int ctlfd;
19825 int res;
19826 struct dahdi_dialparams dps;
19827
19828 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19829 if (ctlfd == -1) {
19830 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19831 return -1;
19832 }
19833
19834 toneduration = atoi(v->value);
19835 if (toneduration > -1) {
19836 memset(&dps, 0, sizeof(dps));
19837
19838 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19839 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19840 if (res < 0) {
19841 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19842 close(ctlfd);
19843 return -1;
19844 }
19845 }
19846 close(ctlfd);
19847 } else if (!strcasecmp(v->name, "defaultcic")) {
19849 } else if (!strcasecmp(v->name, "defaultozz")) {
19851 } else if (!strcasecmp(v->name, "mwilevel")) {
19852 mwilevel = atoi(v->value);
19853 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19854 dtmfcid_level = atoi(v->value);
19855 } else if (!strcasecmp(v->name, "reportalarms")) {
19856 if (!strcasecmp(v->value, "all"))
19858 if (!strcasecmp(v->value, "none"))
19859 report_alarms = 0;
19860 else if (!strcasecmp(v->value, "channels"))
19862 else if (!strcasecmp(v->value, "spans"))
19864 }
19865 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19866 ast_log(LOG_NOTICE, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19867 }
19868
19869 if (dahdichan) {
19870 /* Process the deferred dahdichan value. */
19871 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19872 if (confp->ignore_failed_channels) {
19874 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19875 dahdichan->value);
19876 } else {
19877 return -1;
19878 }
19879 }
19880 }
19881
19882 /*
19883 * Since confp has already filled individual dahdi_pvt objects with channels
19884 * at this point, clear the variables in confp's pvt.
19885 */
19886 if (confp->chan.vars) {
19888 confp->chan.vars = NULL;
19889 }
19890
19891 /* mark the first channels of each DAHDI span to watch for their span alarms */
19892 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19893 if (!tmp->destroy && tmp->span != y) {
19894 tmp->manages_span_alarms = 1;
19895 y = tmp->span;
19896 } else {
19897 tmp->manages_span_alarms = 0;
19898 }
19899 }
19900
19901 /*< \todo why check for the pseudo in the per-channel section.
19902 * Any actual use for manual setup of the pseudo channel? */
19903 if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19904 /* use the default configuration for a channel, so
19905 that any settings from real configured channels
19906 don't "leak" into the pseudo channel config
19907 */
19909
19910 if (conf.chan.cc_params) {
19912 } else {
19913 tmp = NULL;
19914 }
19915 if (tmp) {
19916 ast_verb(3, "Automatically generated pseudo channel\n");
19917 has_pseudo = 1;
19918 } else {
19919 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19920 }
19921 ast_cc_config_params_destroy(conf.chan.cc_params);
19922 }
19923
19924 /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19927
19928 return 0;
19929}
19930
19931/*!
19932 * \internal
19933 * \brief Deep copy struct dahdi_chan_conf.
19934 * \since 1.8
19935 *
19936 * \param dest Destination.
19937 * \param src Source.
19938 */
19939static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
19940{
19941 struct ast_cc_config_params *cc_params;
19942
19943 cc_params = dest->chan.cc_params;
19944 *dest = *src;
19945 dest->chan.cc_params = cc_params;
19947}
19948
19949/*!
19950 * \internal
19951 * \brief Setup DAHDI channel driver.
19952 *
19953 * \param reload enum: load_module(0), reload(1), restart(2).
19954 * \param default_conf Default config parameters. So cc_params can be properly destroyed.
19955 * \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
19956 * \param conf Local config parameters. So cc_params can be properly destroyed.
19957 *
19958 * \retval 0 on success.
19959 * \retval -1 on error.
19960 */
19961static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
19962{
19963 struct ast_config *cfg;
19964 struct ast_config *ucfg;
19965 struct ast_variable *v;
19966 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19967 const char *chans;
19968 const char *cat;
19969 int res;
19970
19971#ifdef HAVE_PRI
19972 char *c;
19973 int spanno;
19974 int i;
19975 int logicalspan;
19976 int trunkgroup;
19977 int dchannels[SIG_PRI_NUM_DCHANS];
19978#endif
19979 int have_cfg_now;
19980 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19981
19982 cfg = ast_config_load(config, config_flags);
19983 have_cfg_now = !!cfg;
19984 if (!cfg) {
19985 /* Error if we have no config file */
19986 if (had_cfg_before) {
19987 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19989 }
19990 cfg = ast_config_new();/* Dummy config */
19991 if (!cfg) {
19992 return 0;
19993 }
19994 ucfg = ast_config_load("users.conf", config_flags);
19995 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19996 ast_config_destroy(cfg);
19997 return 0;
19998 }
19999 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20000 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20001 ast_config_destroy(cfg);
20002 return 0;
20003 }
20004 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
20005 ucfg = ast_config_load("users.conf", config_flags);
20006 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
20007 return 0;
20008 }
20009 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20010 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20011 return 0;
20012 }
20014 cfg = ast_config_load(config, config_flags);
20015 have_cfg_now = !!cfg;
20016 if (!cfg) {
20017 if (had_cfg_before) {
20018 /* We should have been able to load the config. */
20019 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
20020 ast_config_destroy(ucfg);
20021 return 0;
20022 }
20023 cfg = ast_config_new();/* Dummy config */
20024 if (!cfg) {
20025 ast_config_destroy(ucfg);
20026 return 0;
20027 }
20028 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20029 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20030 ast_config_destroy(ucfg);
20031 return 0;
20032 }
20033 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
20034 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
20035 return 0;
20036 } else {
20038 ucfg = ast_config_load("users.conf", config_flags);
20039 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20040 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
20041 ast_config_destroy(cfg);
20042 return 0;
20043 }
20044 }
20045 had_cfg_before = have_cfg_now;
20046
20047 /* It's a little silly to lock it, but we might as well just to be sure */
20049#ifdef HAVE_PRI
20050 if (reload != 1) {
20051 /* Process trunkgroups first */
20052 v = ast_variable_browse(cfg, "trunkgroups");
20053 while (v) {
20054 if (!strcasecmp(v->name, "trunkgroup")) {
20055 trunkgroup = atoi(v->value);
20056 if (trunkgroup > 0) {
20057 if ((c = strchr(v->value, ','))) {
20058 i = 0;
20059 memset(dchannels, 0, sizeof(dchannels));
20060 while (c && (i < SIG_PRI_NUM_DCHANS)) {
20061 dchannels[i] = atoi(c + 1);
20062 if (dchannels[i] < 0) {
20063 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);
20064 } else
20065 i++;
20066 c = strchr(c + 1, ',');
20067 }
20068 if (i) {
20069 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20070 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);
20071 } else
20072 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");
20073 } else
20074 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20075 } else
20076 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20077 } else
20078 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20079 } else if (!strcasecmp(v->name, "spanmap")) {
20080 spanno = atoi(v->value);
20081 if (spanno > 0) {
20082 if ((c = strchr(v->value, ','))) {
20083 trunkgroup = atoi(c + 1);
20084 if (trunkgroup > 0) {
20085 if ((c = strchr(c + 1, ',')))
20086 logicalspan = atoi(c + 1);
20087 else
20088 logicalspan = 0;
20089 if (logicalspan >= 0) {
20090 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20091 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20092 } else
20093 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20094 } else
20095 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);
20096 } else
20097 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
20098 } else
20099 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20100 } else
20101 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
20102 } else {
20103 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
20104 }
20105 v = v->next;
20106 }
20107 }
20108#endif
20109
20110 /* Copy the default jb config over global_jbconf */
20111 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
20112
20113 mwimonitornotify[0] = '\0';
20114
20115 v = ast_variable_browse(cfg, "channels");
20116 if ((res = process_dahdi(base_conf,
20117 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
20118 v, reload, 0))) {
20120 ast_config_destroy(cfg);
20121 if (ucfg) {
20122 ast_config_destroy(ucfg);
20123 }
20124 return res;
20125 }
20126
20127 /* Now get configuration from all normal sections in chan_dahdi.conf: */
20128 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
20129 /* [channels] and [trunkgroups] are used. Let's also reserve
20130 * [globals] and [general] for future use
20131 */
20132 if (!strcasecmp(cat, "general") ||
20133 !strcasecmp(cat, "trunkgroups") ||
20134 !strcasecmp(cat, "globals") ||
20135 !strcasecmp(cat, "channels")) {
20136 continue;
20137 }
20138
20139 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
20140 if (ast_strlen_zero(chans)) {
20141 /* Section is useless without a dahdichan value present. */
20142 continue;
20143 }
20144
20145 /* Copy base_conf to conf. */
20146 deep_copy_dahdi_chan_conf(conf, base_conf);
20147
20148 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20150 ast_config_destroy(cfg);
20151 if (ucfg) {
20152 ast_config_destroy(ucfg);
20153 }
20154 return res;
20155 }
20156 }
20157
20158 ast_config_destroy(cfg);
20159
20160 if (ucfg) {
20161 /* Reset base_conf, so things don't leak from chan_dahdi.conf */
20162 deep_copy_dahdi_chan_conf(base_conf, default_conf);
20163 process_dahdi(base_conf,
20164 "" /* Must be empty for the general category. Silly voicemail mailbox. */,
20165 ast_variable_browse(ucfg, "general"), 1, 0);
20166
20167 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
20168 if (!strcasecmp(cat, "general")) {
20169 continue;
20170 }
20171
20172 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
20173 if (ast_strlen_zero(chans)) {
20174 /* Section is useless without a dahdichan value present. */
20175 continue;
20176 }
20177
20178 /* Copy base_conf to conf. */
20179 deep_copy_dahdi_chan_conf(conf, base_conf);
20180
20182 ast_config_destroy(ucfg);
20184 return res;
20185 }
20186 }
20187 ast_config_destroy(ucfg);
20188 }
20190
20191#ifdef HAVE_PRI
20192 if (reload != 1) {
20193 int x;
20194 for (x = 0; x < NUM_SPANS; x++) {
20195 if (pris[x].pri.pvts[0] &&
20196 pris[x].pri.master == AST_PTHREADT_NULL) {
20197 prepare_pri(pris + x);
20198 if (sig_pri_start_pri(&pris[x].pri)) {
20199 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
20200 return -1;
20201 } else
20202 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
20203 }
20204 }
20205 }
20206#endif
20207#if defined(HAVE_SS7)
20208 if (reload != 1) {
20209 int x;
20210 for (x = 0; x < NUM_SPANS; x++) {
20211 if (linksets[x].ss7.ss7) {
20212 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
20213 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
20214 return -1;
20215 } else
20216 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
20217 }
20218 }
20219 }
20220#endif /* defined(HAVE_SS7) */
20221#ifdef HAVE_OPENR2
20222 if (reload != 1) {
20223 struct r2link_entry *cur;
20224 int x = 0;
20225 AST_LIST_LOCK(&r2links);
20226 AST_LIST_TRAVERSE(&r2links, cur, list) {
20227 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20228 if (r2->r2master == AST_PTHREADT_NULL) {
20229 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20230 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
20231 return -1;
20232 } else {
20233 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
20234 }
20235 x++;
20236 }
20237 }
20238 AST_LIST_UNLOCK(&r2links);
20239 }
20240#endif
20241 /* And start the monitor for the first time */
20243 return 0;
20244}
20245
20246/*!
20247 * \internal
20248 * \brief Setup DAHDI channel driver.
20249 *
20250 * \param reload enum: load_module(0), reload(1), restart(2).
20251 *
20252 * \retval 0 on success.
20253 * \retval -1 on error.
20254 */
20255static int setup_dahdi(int reload)
20256{
20257 int res;
20258 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20259 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20261
20262 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20263 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20264 } else {
20265 res = -1;
20266 }
20269 ast_cc_config_params_destroy(conf.chan.cc_params);
20270
20271 return res;
20272}
20273
20274/*!
20275 * \brief Load the module
20276 *
20277 * Module loading including tests for configuration or dependencies.
20278 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
20279 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
20280 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
20281 * configuration file or other non-critical problem return
20282 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
20283 */
20284static int load_module(void)
20285{
20286 int res;
20287#if defined(HAVE_PRI) || defined(HAVE_SS7)
20288 int y;
20289#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20290
20291 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20293 }
20294
20297 }
20301
20305 }
20306
20307#ifdef HAVE_PRI
20308 memset(pris, 0, sizeof(pris));
20309 for (y = 0; y < NUM_SPANS; y++) {
20310 sig_pri_init_pri(&pris[y].pri);
20311 }
20312 pri_set_error(dahdi_pri_error);
20313 pri_set_message(dahdi_pri_message);
20314 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20315#ifdef HAVE_PRI_PROG_W_CAUSE
20316 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20317#endif
20318#if defined(HAVE_PRI_CCSS)
20319 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20320 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20323 }
20324#endif /* defined(HAVE_PRI_CCSS) */
20325 if (sig_pri_load(
20326#if defined(HAVE_PRI_CCSS)
20327 dahdi_pri_cc_type
20328#else
20329 NULL
20330#endif /* defined(HAVE_PRI_CCSS) */
20331 )) {
20334 }
20335#endif
20336#if defined(HAVE_SS7)
20337 memset(linksets, 0, sizeof(linksets));
20338 for (y = 0; y < NUM_SPANS; y++) {
20339 sig_ss7_init_linkset(&linksets[y].ss7);
20340 }
20341 ss7_set_error(dahdi_ss7_error);
20342 ss7_set_message(dahdi_ss7_message);
20343 ss7_set_hangup(sig_ss7_cb_hangup);
20344 ss7_set_notinservice(sig_ss7_cb_notinservice);
20345 ss7_set_call_null(sig_ss7_cb_call_null);
20346#endif /* defined(HAVE_SS7) */
20347 res = setup_dahdi(0);
20348 /* Make sure we can register our DAHDI channel type */
20349 if (res) {
20352 }
20354 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20357 }
20358#ifdef HAVE_PRI
20359 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20360#endif
20361#if defined(HAVE_SS7)
20362 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20363#endif /* defined(HAVE_SS7) */
20364#ifdef HAVE_OPENR2
20365 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20366 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20367#endif
20368
20370
20372 memset(round_robin, 0, sizeof(round_robin));
20373 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20375 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20378 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20379 ast_manager_register_xml("DAHDIShowStatus", 0, action_dahdishowstatus);
20381#if defined(HAVE_PRI)
20382 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20383 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20384 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20385 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20386#endif /* defined(HAVE_PRI) */
20387
20389
20390 return res;
20391}
20392
20393static int dahdi_sendtext(struct ast_channel *c, const char *text)
20394{
20395#define END_SILENCE_LEN 400
20396#define HEADER_MS 50
20397#define TRAILER_MS 5
20398#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20399#define ASCII_BYTES_PER_CHAR 80
20400
20401 unsigned char *buf,*mybuf;
20402 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20403 struct pollfd fds[1];
20404 int size,res,fd,len,x;
20405 int bytes=0;
20406 int idx;
20407
20408 /*
20409 * Initial carrier (imaginary)
20410 *
20411 * Note: The following float variables are used by the
20412 * PUT_CLID_MARKMS and PUT_CLID() macros.
20413 */
20414 float cr = 1.0;
20415 float ci = 0.0;
20416 float scont = 0.0;
20417
20418 if (!text[0]) {
20419 return(0); /* if nothing to send, don't */
20420 }
20421 idx = dahdi_get_index(c, p, 0);
20422 if (idx < 0) {
20423 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20424 return -1;
20425 }
20426 if ((!p->tdd) && (!p->mate)) {
20427#if defined(HAVE_PRI)
20428#if defined(HAVE_PRI_DISPLAY_TEXT)
20429 ast_mutex_lock(&p->lock);
20431 sig_pri_sendtext(p->sig_pvt, text);
20432 }
20434#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20435#endif /* defined(HAVE_PRI) */
20436 return(0); /* if not in TDD mode, just return */
20437 }
20438 if (p->mate)
20440 else
20441 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20442 if (!buf)
20443 return -1;
20444 mybuf = buf;
20445 if (p->mate) {
20446 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20447 struct ast_format *codec = AST_LAW(p);
20448
20449 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20451 }
20452 /* Put actual message */
20453 for (x = 0; text[x]; x++) {
20454 PUT_CLID(text[x]);
20455 }
20456 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20458 }
20459 len = bytes;
20460 buf = mybuf;
20461 } else {
20462 len = tdd_generate(p->tdd, buf, text);
20463 if (len < 1) {
20464 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20465 ast_free(mybuf);
20466 return -1;
20467 }
20468 }
20469 memset(buf + len, 0x7f, END_SILENCE_LEN);
20471 fd = p->subs[idx].dfd;
20472 while (len) {
20473 if (ast_check_hangup(c)) {
20474 ast_free(mybuf);
20475 return -1;
20476 }
20477 size = len;
20478 if (size > READ_SIZE)
20479 size = READ_SIZE;
20480 fds[0].fd = fd;
20481 fds[0].events = POLLOUT | POLLPRI;
20482 fds[0].revents = 0;
20483 res = poll(fds, 1, -1);
20484 if (!res) {
20485 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20486 continue;
20487 }
20488 /* if got exception */
20489 if (fds[0].revents & POLLPRI) {
20490 ast_free(mybuf);
20491 return -1;
20492 }
20493 if (!(fds[0].revents & POLLOUT)) {
20494 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20495 continue;
20496 }
20497 res = write(fd, buf, size);
20498 if (res != size) {
20499 if (res == -1) {
20500 ast_free(mybuf);
20501 return -1;
20502 }
20503 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20504 break;
20505 }
20506 len -= size;
20507 buf += size;
20508 }
20509 ast_free(mybuf);
20510 return(0);
20511}
20512
20513
20514static int reload(void)
20515{
20516 int res = 0;
20517
20518 res = setup_dahdi(1);
20519 if (res) {
20520 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20521 return -1;
20522 }
20523 return 0;
20524}
20525
20526/* This is a workaround so that menuselect displays a proper description
20527 * AST_MODULE_INFO(, , "DAHDI Telephony"
20528 */
20529
20531 .support_level = AST_MODULE_SUPPORT_CORE,
20532 .load = load_module,
20533 .unload = unload_module,
20534 .reload = reload,
20535 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
20536 .requires = "ccss",
20537 .optional_modules = "res_smdi",
Common implementation-independent jitterbuffer stuff.
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
ADSI Support (built upon Caller*ID)
A-Law to Signed linear conversion.
#define AST_LIN2A(a)
Definition: alaw.h:50
#define AST_ALAW(a)
Definition: alaw.h:84
char digit
jack_status_t status
Definition: app_jack.c:146
const char * str
Definition: app_jack.c:147
char * text
Definition: app_queue.c:1668
struct sla_ringing_trunk * last
Definition: app_sla.c:332
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:341
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
Asterisk main include file. File version handling, generic pbx functions.
#define AST_FILE_MODE
Definition: asterisk.h:32
#define PATH_MAX
Definition: asterisk.h:40
static struct chans chans
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Bridging API.
ast_transfer_result
Definition: bridge.h:1098
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4677
void dahdi_native_unload(void)
int dahdi_native_load(const struct ast_channel_tech *tech)
Native DAHDI bridging support.
static int tmp()
Definition: bt_open.c:389
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define PUT_CLID(byte)
Definition: callerid.h:412
#define CID_SIG_V23_JP
Definition: callerid.h:63
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1253
#define CID_TYPE_MDMF
Definition: callerid.h:75
#define CID_UNKNOWN_NUMBER
Definition: callerid.h:55
int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for 'n' samples.
Definition: callerid.c:271
#define CID_SIG_SMDI
Definition: callerid.h:64
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
Definition: callerid.c:1247
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:316
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:426
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:434
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
Definition: callerid.c:952
#define AST_PRES_RESTRICTED
Definition: callerid.h:433
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:833
void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:189
#define MAX_CALLERID_SIZE
Definition: callerid.h:50
const char * ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
Convert redirecting reason value to text code.
Definition: callerid.c:1449
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1101
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1242
#define PUT_CLID_MARKMS
Definition: callerid.h:397
#define CID_NOMSGWAITING
Definition: callerid.h:57
#define CID_SIG_DTMF
Definition: callerid.h:62
#define CID_PRIVATE_NUMBER
Definition: callerid.h:53
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:130
#define CID_MSGWAITING
Definition: callerid.h:56
#define CID_SIG_V23
Definition: callerid.h:61
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:570
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:211
#define CID_START_RING
Definition: callerid.h:66
#define CID_START_POLARITY
Definition: callerid.h:67
#define CID_SIG_BELL
Definition: callerid.h:60
#define CID_QUALIFIER
Definition: callerid.h:58
void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:205
#define CID_START_POLARITY_IN
Definition: callerid.h:68
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1292
#define CID_START_DTMF_NOALERT
Definition: callerid.h:69
Internal Asterisk hangup causes.
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:145
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:115
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:108
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:120
#define AST_CAUSE_NOTDEFINED
Definition: causes.h:155
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:121
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:154
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
enum cc_state state
Definition: ccss.c:393
Call Completion Supplementary Services API.
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1162
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:692
void(* ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
Callback made from ast_cc_callback for certain channel types.
Definition: ccss.h:1562
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1217
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
Definition: ccss.c:854
@ AST_CC_MONITOR_NEVER
Definition: ccss.h:76
@ AST_CC_MONITOR_ALWAYS
Definition: ccss.h:87
@ AST_CC_MONITOR_NATIVE
Definition: ccss.h:78
@ AST_CC_MONITOR_GENERIC
Definition: ccss.h:83
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1195
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:876
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1232
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition: ccss.c:840
int ast_cc_set_param(struct ast_cc_config_params *params, const char *const name, const char *value)
set a CCSS configuration parameter, given its name
Definition: ccss.c:801
static sqlite3 * db
static PGresult * result
Definition: cel_pgsql.c:84
static struct ao2_container * pvts
Definition: chan_console.c:174
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:681
static int dahdi_create_channel_range(int start, int end)
Definition: chan_dahdi.c:11527
static int dahdi_confmute(struct dahdi_pvt *p, int muted)
Definition: chan_dahdi.c:5199
static ast_mutex_t ss_thread_lock
Definition: chan_dahdi.c:763
static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
Definition: chan_dahdi.c:11089
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:801
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4755
static void release_doomed_pris(void)
Definition: chan_dahdi.c:1283
static struct dahdi_pvt * round_robin[64]
Definition: chan_dahdi.c:3690
#define HANGUP
Definition: chan_dahdi.c:16742
static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
Definition: chan_dahdi.c:2234
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5169
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3765
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4766
static char * dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15994
static void my_set_confirmanswer(void *pvt, int flag)
Definition: chan_dahdi.c:2190
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:802
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:9249
static int my_callwait(void *pvt)
Definition: chan_dahdi.c:1664
static int restore_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5262
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3783
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
Definition: chan_dahdi.c:746
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:9352
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3553
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12498
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4717
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4464
static int my_check_confirmanswer(void *pvt)
Definition: chan_dahdi.c:2196
static const char *const events[]
Definition: chan_dahdi.c:4597
static int reset_conf(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4829
static int my_is_dialing(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2958
static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
Definition: chan_dahdi.c:2929
static struct ast_manager_event_blob * dahdichannel_to_ami(struct stasis_message *msg)
Definition: chan_dahdi.c:1910
static void my_cancel_cidspill(void *pvt)
Definition: chan_dahdi.c:2213
static int numbufs
Definition: chan_dahdi.c:731
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4785
static int my_set_echocanceller(void *pvt, int enable)
Definition: chan_dahdi.c:2753
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9796
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:721
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4632
static void my_hangup_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2826
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:13444
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7464
static char * dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16353
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:800
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3724
#define DEFAULT_RINGT
Definition: chan_dahdi.c:804
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:680
static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
Definition: chan_dahdi.c:5393
static int my_stop_cid_detect(void *pvt)
Definition: chan_dahdi.c:1413
static int my_get_sub_fd(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2050
static void my_set_needringing(void *pvt, int value)
Definition: chan_dahdi.c:2789
static char * dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15725
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:618
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Callback made when dial failed to get a channel out of dahdi_request().
Definition: chan_dahdi.c:14151
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16783
static int __unload_module(void)
Definition: chan_dahdi.c:18113
static void dahdi_softhangup_all(void)
Definition: chan_dahdi.c:15818
static void dahdi_train_ec(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4953
static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
Definition: chan_dahdi.c:18243
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_dahdi.c:9271
static enum analog_event dahdievent_to_analogevent(int event)
Definition: chan_dahdi.c:2606
static int dahdi_digit_begin(struct ast_channel *ast, char digit)
Definition: chan_dahdi.c:4497
static void my_unlock_private(void *pvt)
Definition: chan_dahdi.c:1897
#define HEADER_MS
#define TRANSFER
Definition: chan_dahdi.c:16741
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_dahdi.c:7424
static void my_set_dialing(void *pvt, int is_dialing)
Definition: chan_dahdi.c:2083
static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
Definition: chan_dahdi.c:1817
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
Definition: chan_dahdi.c:2842
static int mwisend_rpas
Definition: chan_dahdi.c:723
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9814
static int my_on_hook(void *pvt)
Definition: chan_dahdi.c:2974
static int attempt_transfer(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7508
static int cidrings[NUM_CADENCE_MAX]
cidrings says in which pause to transmit the cid information, where the first pause is 1,...
Definition: chan_dahdi.c:701
static void my_set_pulsedial(void *pvt, int flag)
Definition: chan_dahdi.c:2228
static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_dahdi.c:4559
static char * dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16443
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:782
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7708
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9862
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3749
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:5150
struct analog_callback analog_callbacks
Definition: chan_dahdi.c:3616
static void dahdi_destroy_channel_range(int start, int end)
Definition: chan_dahdi.c:11445
static char * dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16075
static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2571
static void my_set_alarm(void *pvt, int in_alarm)
Definition: chan_dahdi.c:2076
static int num_restart_pending
Definition: chan_dahdi.c:766
static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
Definition: chan_dahdi.c:1760
static int my_get_event(void *pvt)
Definition: chan_dahdi.c:2710
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13477
static int dahdi_devicestate(const char *data)
Definition: chan_dahdi.c:14089
static int user_has_defined_cadences
Definition: chan_dahdi.c:686
static int dahdi_callwait(struct ast_channel *ast)
Definition: chan_dahdi.c:5359
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3740
static void my_set_callwaiting(void *pvt, int callwaiting_enable)
Definition: chan_dahdi.c:2206
static int distinctiveringaftercid
Definition: chan_dahdi.c:729
static int my_is_off_hook(void *pvt)
Definition: chan_dahdi.c:2724
char * name
Definition: chan_dahdi.c:4621
#define END_SILENCE_LEN
static int mwi_send_init(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:11260
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4346
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
Definition: chan_dahdi.c:1941
static int my_check_waitingfordt(void *pvt)
Definition: chan_dahdi.c:2179
static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
Definition: chan_dahdi.c:19961
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7694
static void my_set_outgoing(void *pvt, int is_outgoing)
Definition: chan_dahdi.c:2090
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16744
static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
Definition: chan_dahdi.c:2017
static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5827
static int dahdi_hangup(struct ast_channel *ast)
Definition: chan_dahdi.c:6250
static void * analog_ss_thread(void *data)
Definition: chan_dahdi.c:9889
static int dahdi_sendtext(struct ast_channel *c, const char *text)
Definition: chan_dahdi.c:20393
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:1968
static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
Definition: chan_dahdi.c:2379
#define PROC_DAHDI_OPT_NOCHAN
Definition: chan_dahdi.c:18437
static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
Definition: chan_dahdi.c:18441
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1253
static void my_get_and_handle_alarms(void *pvt)
Definition: chan_dahdi.c:2027
static void my_lock_private(void *pvt)
Definition: chan_dahdi.c:1891
static int dahdi_answer(struct ast_channel *ast)
Definition: chan_dahdi.c:6699
static const char tdesc[]
Definition: chan_dahdi.c:648
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5018
static int dahdi_restart(void)
Definition: chan_dahdi.c:15846
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16833
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5155
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11859
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5236
static char * dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16600
static void handle_clear_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:3796
static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
Definition: chan_dahdi.c:6794
static char * dahdi_sig2str(int sig)
Definition: chan_dahdi.c:4651
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:5182
static int my_stop_callwait(void *pvt)
Definition: chan_dahdi.c:1650
static struct ast_channel * dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
Definition: chan_dahdi.c:9521
static int check_for_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7541
static struct dahdi_ring_cadence AS_RP_cadence
Definition: chan_dahdi.c:709
static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
Definition: chan_dahdi.c:1526
#define NUM_SPANS
Definition: chan_dahdi.c:674
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4898
#define AST_LAW(p)
Definition: chan_dahdi.c:642
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4421
static int restart_monitor(void)
Definition: chan_dahdi.c:12173
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3568
static int my_confmute(void *pvt, int mute)
Definition: chan_dahdi.c:2222
#define READ_SIZE
Definition: chan_dahdi.c:794
static void * mwi_thread(void *data)
Definition: chan_dahdi.c:11103
#define CALLPROGRESS_FAX
Definition: chan_dahdi.c:682
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
Definition: chan_dahdi.c:1698
static int sigtype_to_signalling(int sigtype)
Definition: chan_dahdi.c:12479
static void my_decrease_ss_count(void)
Definition: chan_dahdi.c:2255
static char * handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16278
static int has_voicemail(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5293
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5600
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4843
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4427
static void my_start_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2806
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4481
static int setup_dahdi(int reload)
Definition: chan_dahdi.c:20255
STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,.to_ami=dahdichannel_to_ami,)
static char * dahdi_set_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16657
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16795
static int report_alarms
Definition: chan_dahdi.c:738
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1180
static int mwilevel
Definition: chan_dahdi.c:733
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:922
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:646
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
Definition: chan_dahdi.c:6843
static int set_actual_txgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5116
static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: chan_dahdi.c:7231
static int my_wait_event(void *pvt)
Definition: chan_dahdi.c:2703
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9777
static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
Definition: chan_dahdi.c:2423
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1233
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9476
static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
Definition: chan_dahdi.c:1429
#define TRAILER_MS
static int set_actual_rxgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:5133
static int my_start(void *pvt)
Definition: chan_dahdi.c:2921
static ast_mutex_t restart_lock
Definition: chan_dahdi.c:764
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7749
static char defaultcic[64]
Definition: chan_dahdi.c:717
int alarm
Definition: chan_dahdi.c:4620
static const char config[]
Definition: chan_dahdi.c:669
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16911
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6777
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5816
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:762
static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
Definition: chan_dahdi.c:18304
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5552
static struct ast_frame * dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8773
static void my_answer_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2815
static struct ast_channel * dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_dahdi.c:13908
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:603
static int my_have_progressdetect(void *pvt)
Definition: chan_dahdi.c:3590
static char * dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16522
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Definition: chan_dahdi.c:7062
#define CANPROGRESSDETECT(p)
Definition: chan_dahdi.c:715
static char * dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15769
static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:5068
static int my_train_echocanceller(void *pvt)
Definition: chan_dahdi.c:2949
static const char * event2str(int event)
Definition: chan_dahdi.c:4642
#define CALLPROGRESS_PROGRESS
Definition: chan_dahdi.c:679
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4399
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2795
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4970
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8651
static void handle_alarms(struct dahdi_pvt *p, int alms)
Definition: chan_dahdi.c:7727
static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
Definition: chan_dahdi.c:7594
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:990
static struct dahdi_pvt * duplicate_pseudo(struct dahdi_pvt *src)
Definition: chan_dahdi.c:13683
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4318
#define ISTRUNK(p)
Definition: chan_dahdi.c:711
static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
Definition: chan_dahdi.c:2005
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
Definition: chan_dahdi.c:9843
static struct ast_channel * dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Definition: chan_dahdi.c:9530
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:4998
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:773
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:811
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7344
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
Definition: chan_dahdi.c:757
#define ASCII_BYTES_PER_CHAR
static void my_all_subchannels_hungup(void *pvt)
Definition: chan_dahdi.c:2263
static int my_ring(void *pvt)
Definition: chan_dahdi.c:2767
static int my_start_cid_detect(void *pvt, int cid_signalling)
Definition: chan_dahdi.c:1396
static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
Definition: chan_dahdi.c:7202
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:923
static char * dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16410
static int my_complete_conference_update(void *pvt, int needconference)
Definition: chan_dahdi.c:2323
static struct @114 alarms[]
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
Definition: chan_dahdi.c:805
static int mwi_send_process_buffer(struct dahdi_pvt *pvt, int num_read)
Definition: chan_dahdi.c:11313
#define HEADER_LEN
static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
Definition: chan_dahdi.c:2057
static void my_increase_ss_count(void)
Definition: chan_dahdi.c:2248
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:736
static int has_pseudo
Definition: chan_dahdi.c:688
static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: chan_dahdi.c:2596
static int my_wink(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:1801
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1157
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:626
static int my_conf_add(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2313
static int my_dsp_reset_and_flush_digits(void *pvt)
Definition: chan_dahdi.c:1751
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6763
#define PROC_DAHDI_OPT_NOWARN
Definition: chan_dahdi.c:18439
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:803
static int my_has_voicemail(void *pvt)
Definition: chan_dahdi.c:2589
static char progzone[10]
Definition: chan_dahdi.c:726
static int load_module(void)
Load the module.
Definition: chan_dahdi.c:20284
#define sig2str
Definition: chan_dahdi.c:4715
static struct ast_frame * dahdi_read(struct ast_channel *ast)
Definition: chan_dahdi.c:8788
#define FORMAT
static const char * my_get_orig_dialstring(void *pvt)
Definition: chan_dahdi.c:2241
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:15984
static struct ast_custom_function polarity_function
Definition: chan_dahdi.c:2915
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7567
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13747
#define gen_pvt_field_callback(type, field)
Definition: chan_dahdi.c:3603
static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
Definition: chan_dahdi.c:2874
static int send_cwcidspill(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5277
static int my_conf_del(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2303
#define FORMAT2
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:690
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16814
static int unload_module(void)
Definition: chan_dahdi.c:18227
static int reload(void)
Definition: chan_dahdi.c:20514
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:18476
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16726
#define POLARITY_IDLE
Definition: chan_dahdi.c:913
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:640
static int num_cadence
Definition: chan_dahdi.c:685
static enum analog_sigtype dahdisig_to_analogsig(int sig)
Definition: chan_dahdi.c:1182
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4393
static char defaultozz[64]
Definition: chan_dahdi.c:718
void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
Definition: chan_dahdi.c:7400
static int dtmfcid_level
Definition: chan_dahdi.c:734
#define CHAN_PSEUDO
Definition: chan_dahdi.c:677
static int my_off_hook(void *pvt)
Definition: chan_dahdi.c:2783
const char *const subnames[]
Definition: chan_dahdi.c:916
static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2580
static int usedistinctiveringdetection
Definition: chan_dahdi.c:728
static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: chan_dahdi.c:2888
static char * dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15961
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16760
static void * my_get_sigpvt_bridged_channel(struct ast_channel *chan)
Definition: chan_dahdi.c:2036
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5323
static int set_hwgain(int fd, float gain, int tx_direction)
Definition: chan_dahdi.c:4988
static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
Definition: chan_dahdi.c:2139
static void build_alarm_info(char *restrict alarmstr, struct dahdi_spaninfo *spaninfo)
Definition: chan_dahdi.c:16314
static int my_check_for_conference(void *pvt)
Definition: chan_dahdi.c:2373
static int mwi_send_process_event(struct dahdi_pvt *pvt, int event)
Definition: chan_dahdi.c:11401
static int my_flash(void *pvt)
Definition: chan_dahdi.c:2774
#define POLARITY_REV
Definition: chan_dahdi.c:914
static int ss_thread_count
Definition: chan_dahdi.c:765
static const char *const lbostr[]
Definition: chan_dahdi.c:605
int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
Definition: chan_dahdi.c:3692
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:737
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:19939
static void my_deadlock_avoidance_private(void *pvt)
Definition: chan_dahdi.c:1903
static struct dahdi_pvt * handle_init_event(struct dahdi_pvt *i, int event)
Definition: chan_dahdi.c:11595
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5907
static void my_set_ringtimeout(void *pvt, int ringt)
Definition: chan_dahdi.c:2133
static void monitor_pfds_clean(void *arg)
Definition: chan_dahdi.c:11854
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16879
static int ifcount
Definition: chan_dahdi.c:749
#define NUM_CADENCE_MAX
Definition: chan_dahdi.c:684
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1350
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:761
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16856
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:714
static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
Definition: chan_dahdi.c:6228
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5925
static int action_dahdishowstatus(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16999
DAHDI internal API definitions.
#define SIG_FEATB
Definition: chan_dahdi.h:781
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:784
#define SIG_SFWINK
Definition: chan_dahdi.h:793
#define SIG_EMWINK
Definition: chan_dahdi.h:778
#define SIG_MFCR2
Definition: chan_dahdi.h:808
#define SIG_FXSLS
Definition: chan_dahdi.h:786
#define MAX_SLAVES
Definition: chan_dahdi.h:95
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:825
#define SIG_SF_FEATB
Definition: chan_dahdi.h:796
#define SIG_FXSKS
Definition: chan_dahdi.h:788
#define SIG_FXOGS
Definition: chan_dahdi.h:790
#define SUB_REAL
Definition: chan_dahdi.h:57
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:795
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:841
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:811
#define SIG_FXOKS
Definition: chan_dahdi.h:791
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:785
#define SIG_FXSGS
Definition: chan_dahdi.h:787
#define SIG_FEATDMF
Definition: chan_dahdi.h:780
#define SIG_EM_E1
Definition: chan_dahdi.h:797
#define SIG_SF_FEATD
Definition: chan_dahdi.h:794
#define SIG_SS7
Definition: chan_dahdi.h:805
#define SIG_BRI
Definition: chan_dahdi.h:801
@ DAHDI_IFLIST_NONE
Definition: chan_dahdi.h:117
@ DAHDI_IFLIST_MAIN
Definition: chan_dahdi.h:118
#define SIG_FEATD
Definition: chan_dahdi.h:779
#define SIG_BRI_PTMP
Definition: chan_dahdi.h:802
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:783
@ MWI_SEND_SA
Definition: chan_dahdi.h:102
@ MWI_SEND_PAUSE
Definition: chan_dahdi.h:104
@ MWI_SEND_SA_WAIT
Definition: chan_dahdi.h:103
@ MWI_SEND_DONE
Definition: chan_dahdi.h:107
@ MWI_SEND_SPILL
Definition: chan_dahdi.h:105
@ MWI_SEND_CLEANUP
Definition: chan_dahdi.h:106
#define SIG_FXOLS
Definition: chan_dahdi.h:789
#define SIG_E911
Definition: chan_dahdi.h:782
#define SIG_PRI
Definition: chan_dahdi.h:800
#define SIG_EM
Definition: chan_dahdi.h:777
#define SIG_SF
Definition: chan_dahdi.h:792
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:882
static struct ast_timer * timer
Definition: chan_iax2.c:364
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3194
const char * ast_channel_name(const struct ast_channel *chan)
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2873
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1610
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1663
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1299
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10586
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1840
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2917
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
struct ast_namedgroups * ast_ref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7760
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
Definition: channel.c:10473
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
unsigned long long ast_group_t
Definition: channel.h:215
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2993
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1158
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update)
Set the caller information based on another caller source.
Definition: channel.c:2026
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
#define ast_channel_trylock(chan)
Definition: channel.h:2970
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1257
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:891
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:2018
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1657
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7356
int ast_channel_fd(const struct ast_channel *chan, int which)
void ast_channel_internal_fd_set(struct ast_channel *chan, int which, int value)
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1185
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:2034
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7697
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2518
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel.
Definition: channel.c:4365
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1235
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1210
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define AST_CHANNEL_NAME
Definition: channel.h:173
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1710
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2864
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10604
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2445
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2477
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4379
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1049
@ AST_FLAG_END_DTMF_ONLY
Definition: channel.h:1027
@ AST_FLAG_BLOCKING
Definition: channel.h:1005
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7754
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7444
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3015
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7640
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1593
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
#define AST_MAX_EXTENSION
Definition: channel.h:134
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DIALING_OFFHOOK
Definition: channelstate.h:44
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_PRERING
Definition: channelstate.h:45
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_OFFHOOK
Definition: channelstate.h:38
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_UP
Definition: channelstate.h:42
@ AST_STATE_RESERVED
Definition: channelstate.h:37
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7408
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define RESULT_FAILURE
Definition: cli.h:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct channel_usage channels
#define container_of(ptr, type, member)
Definition: codec_dahdi.c:277
short word
short int16_t
Definition: db.h:59
Device state management.
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:471
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53
@ AST_DEVICE_BUSY
Definition: devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
Convenient Signal Processing routines.
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition: dsp.c:1916
threshold
Definition: dsp.h:71
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
#define DSP_TONE_STATE_DIALTONE
Definition: dsp.h:54
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1810
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
Definition: dsp.c:1804
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition: dsp.c:1499
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1857
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition: dsp.c:1911
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
Definition: dsp.c:1906
#define DSP_TONE_STATE_RINGING
Definition: dsp.h:53
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1793
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1892
char * bs
Definition: eagi_proxy.c:73
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
char * address
Definition: f2c.h:59
#define abs(x)
Definition: f2c.h:195
long int flag
Definition: f2c.h:83
#define max(a, b)
Definition: f2c.h:198
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Media Format Cache API.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:637
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2047
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7608
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
const char * ext
Definition: http.c:150
#define AST_APP_ARG(name)
Define an application argument.
#define ast_app_separate_args(a, b, c, d)
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX"....
Definition: main/app.c:582
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
Replace a variable in the given list with a new value.
Definition: main/config.c:668
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:784
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
#define AST_FRAME_DTMF
#define AST_OPTION_RELAXDTMF
#define AST_OPTION_TONE_VERIFY
#define AST_OPTION_RXGAIN
#define AST_OPTION_DIGIT_DETECT
#define AST_OPTION_OPRMODE
#define ast_frfree(fr)
#define AST_OPTION_CC_AGENT_TYPE
#define AST_OPTION_TDD
#define AST_OPTION_FAX_DETECT
#define AST_OPTION_TXGAIN
#define AST_OPTION_ECHOCAN
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_NULL
@ AST_FRAME_IMAGE
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_FRAME_TEXT
@ AST_CONTROL_RING
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_RADIO_UNKEY
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
@ AST_CONTROL_RADIO_KEY
@ AST_CONTROL_HOLD
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
#define AST_OPTION_AUDIO_MODE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
Definition: logger.c:2378
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int ast_callid
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
Definition: logger.c:2356
void ast_log_callid(int level, const char *file, int line, const char *function, ast_callid callid, const char *fmt,...)
Used for sending a log message with a known call_id This is a modified logger function which is funct...
Definition: logger.c:2501
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
#define ast_verbose_callid(callid,...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:291
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
Definition: linkedlists.h:234
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Definition: linkedlists.h:582
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Asterisk locking-related definitions:
#define DLA_LOCK(lock)
Definition: lock.h:492
#define DLA_UNLOCK(lock)
Definition: lock.h:490
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:474
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:479
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_mutex_unlock(a)
Definition: lock.h:190
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
#define ast_mutex_trylock(a)
Definition: lock.h:191
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_destroy(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
int errno
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10128
#define EVENT_FLAG_CALL
Definition: manager.h:76
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DRIVER
Definition: module.h:341
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Music on hold handling.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7788
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7798
Asterisk MWI API.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:254
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
Definition: mwi.c:235
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:378
Call Parking API.
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
Definition: parking.c:179
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
Core PBX routines and definitions.
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4190
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition: pbx.c:4195
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6969
Call Pickup API.
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
struct stasis_forward * sub
Definition: res_corosync.c:240
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
static int debug
Global debug status.
Definition: res_xmpp.c:441
#define NULL
Definition: resample.c:96
Say numbers and dates (maybe words one day too)
int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1277
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:793
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3678
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4170
int analog_config_complete(struct analog_pvt *p)
Definition: sig_analog.c:4114
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
Definition: sig_analog.c:1593
int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
Definition: sig_analog.c:990
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
Definition: sig_analog.c:4109
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, void *private_data)
Definition: sig_analog.c:4081
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:4132
enum analog_sigtype sigtype
Definition: sig_analog.c:69
struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
Definition: sig_analog.c:770
void * analog_handle_init_event(struct analog_pvt *i, int event)
Definition: sig_analog.c:3798
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1490
int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan)
Definition: sig_analog.c:2757
Interface header for analog signaling module.
#define ANALOG_MAX_CID
Definition: sig_analog.h:33
analog_dsp_digitmode
Definition: sig_analog.h:114
@ ANALOG_DIGITMODE_DTMF
Definition: sig_analog.h:115
@ ANALOG_DIGITMODE_MF
Definition: sig_analog.h:116
#define ANALOG_INTER_DIGIT_TIMEOUT
Default time (ms) to detect following digits.
Definition: sig_analog.h:40
#define ANALOG_MATCH_DIGIT_TIMEOUT
Default time (ms) to wait, in case of ambiguous match.
Definition: sig_analog.h:42
@ ANALOG_DIALMODE_DTMF
Definition: sig_analog.h:122
@ ANALOG_DIALMODE_PULSE
Definition: sig_analog.h:121
@ ANALOG_DIALMODE_NONE
Definition: sig_analog.h:123
@ ANALOG_DIALMODE_BOTH
Definition: sig_analog.h:120
#define RING_PATTERNS
Definition: sig_analog.h:35
analog_event
Definition: sig_analog.h:79
@ ANALOG_EVENT_NONE
Definition: sig_analog.h:80
@ ANALOG_EVENT_HOOKCOMPLETE
Definition: sig_analog.h:89
@ ANALOG_EVENT_DTMFDOWN
Definition: sig_analog.h:104
@ ANALOG_EVENT_RINGEROFF
Definition: sig_analog.h:88
@ ANALOG_EVENT_PULSE_START
Definition: sig_analog.h:90
@ ANALOG_EVENT_DTMFCID
Definition: sig_analog.h:102
@ ANALOG_EVENT_TX_CED_DETECTED
Definition: sig_analog.h:97
@ ANALOG_EVENT_NEONMWI_ACTIVE
Definition: sig_analog.h:95
@ ANALOG_EVENT_RINGBEGIN
Definition: sig_analog.h:92
@ ANALOG_EVENT_ONHOOK
Definition: sig_analog.h:81
@ ANALOG_EVENT_EC_DISABLED
Definition: sig_analog.h:93
@ ANALOG_EVENT_WINKFLASH
Definition: sig_analog.h:83
@ ANALOG_EVENT_ERROR
Definition: sig_analog.h:101
@ ANALOG_EVENT_PULSEDIGIT
Definition: sig_analog.h:103
@ ANALOG_EVENT_RINGERON
Definition: sig_analog.h:87
@ ANALOG_EVENT_RX_CED_DETECTED
Definition: sig_analog.h:98
@ ANALOG_EVENT_ALARM
Definition: sig_analog.h:84
@ ANALOG_EVENT_DIALCOMPLETE
Definition: sig_analog.h:86
@ ANALOG_EVENT_EC_NLP_ENABLED
Definition: sig_analog.h:100
@ ANALOG_EVENT_POLARITY
Definition: sig_analog.h:91
@ ANALOG_EVENT_NEONMWI_INACTIVE
Definition: sig_analog.h:96
@ ANALOG_EVENT_DTMFUP
Definition: sig_analog.h:105
@ ANALOG_EVENT_EC_NLP_DISABLED
Definition: sig_analog.h:99
@ ANALOG_EVENT_RINGOFFHOOK
Definition: sig_analog.h:82
@ ANALOG_EVENT_REMOVED
Definition: sig_analog.h:94
@ ANALOG_EVENT_NOALARM
Definition: sig_analog.h:85
@ ANALOG_DIAL_OP_REPLACE
Definition: sig_analog.h:134
analog_sub
Definition: sig_analog.h:108
@ ANALOG_SUB_THREEWAY
Definition: sig_analog.h:111
@ ANALOG_SUB_REAL
Definition: sig_analog.h:109
@ ANALOG_SUB_CALLWAIT
Definition: sig_analog.h:110
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
Definition: sig_analog.h:38
analog_sigtype
Definition: sig_analog.h:45
@ ANALOG_SIG_FEATD
Definition: sig_analog.h:56
@ ANALOG_SIG_FEATDMF_TA
Definition: sig_analog.h:66
@ ANALOG_SIG_FGC_CAMAMF
Definition: sig_analog.h:60
@ ANALOG_SIG_FXOLS
Definition: sig_analog.h:47
@ ANALOG_SIG_FEATDMF
Definition: sig_analog.h:57
@ ANALOG_SIG_EM_E1
Definition: sig_analog.h:55
@ ANALOG_SIG_EMWINK
Definition: sig_analog.h:53
@ ANALOG_SIG_FXOKS
Definition: sig_analog.h:48
@ ANALOG_SIG_SF
Definition: sig_analog.h:63
@ ANALOG_SIG_FGC_CAMA
Definition: sig_analog.h:59
@ ANALOG_SIG_FXSLS
Definition: sig_analog.h:50
@ ANALOG_SIG_EM
Definition: sig_analog.h:54
@ ANALOG_SIG_FXOGS
Definition: sig_analog.h:49
@ ANALOG_SIG_NONE
Definition: sig_analog.h:46
@ ANALOG_SIG_FXSGS
Definition: sig_analog.h:52
@ ANALOG_SIG_SF_FEATDMF
Definition: sig_analog.h:65
@ ANALOG_SIG_SFWINK
Definition: sig_analog.h:62
@ ANALOG_SIG_FEATB
Definition: sig_analog.h:61
@ ANALOG_SIG_SF_FEATD
Definition: sig_analog.h:64
@ ANALOG_SIG_FXSKS
Definition: sig_analog.h:51
analog_tone
Definition: sig_analog.h:70
@ ANALOG_TONE_CONGESTION
Definition: sig_analog.h:73
@ ANALOG_TONE_INFO
Definition: sig_analog.h:76
@ ANALOG_TONE_DIALTONE
Definition: sig_analog.h:74
@ ANALOG_TONE_DIALRECALL
Definition: sig_analog.h:75
@ ANALOG_TONE_STUTTER
Definition: sig_analog.h:72
@ ANALOG_TONE_RINGTONE
Definition: sig_analog.h:71
@ ANALOG_CID_START_RING
Definition: sig_analog.h:129
@ ANALOG_CID_START_DTMF_NOALERT
Definition: sig_analog.h:130
@ ANALOG_CID_START_POLARITY
Definition: sig_analog.h:127
@ ANALOG_CID_START_POLARITY_IN
Definition: sig_analog.h:128
Interface header for PRI signaling module.
int sig_pri_is_chan_available(struct sig_pri_chan *pvt)
void sig_pri_unload(void)
sig_pri_law
Definition: sig_pri.h:67
@ SIG_PRI_DEFLAW
Definition: sig_pri.h:68
@ SIG_PRI_ULAW
Definition: sig_pri.h:69
@ SIG_PRI_ALAW
Definition: sig_pri.h:70
#define SIG_PRI_DEBUG_NORMAL
Definition: sig_pri.h:41
@ SIG_PRI_COLP_UPDATE
Definition: sig_pri.h:441
@ SIG_PRI_COLP_CONNECT
Definition: sig_pri.h:439
@ SIG_PRI_COLP_BLOCK
Definition: sig_pri.h:437
int pri_send_callrerouting_facility_exec(struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason)
int sig_pri_ami_show_spans(struct mansession *s, const char *show_cmd, struct sig_pri_span *pri, const int *dchannels, const char *action_id)
int sig_pri_cc_agent_status_req(struct ast_cc_agent *agent)
struct sig_pri_callback sig_pri_callbacks
int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:239
int sig_pri_cc_agent_start_offer_timer(struct ast_cc_agent *agent)
int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
int sig_pri_cc_monitor_unsuspend(struct ast_cc_monitor *monitor)
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
#define DAHDI_OVERLAPDIAL_OUTGOING
Definition: sig_pri.h:252
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)
int sig_pri_cc_monitor_req_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
int sig_pri_start_pri(struct sig_pri_span *pri)
int sig_pri_cc_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
void sig_pri_cli_show_channels(int fd, struct sig_pri_span *pri)
void sig_pri_cc_agent_req_rsp(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
int sig_pri_cc_monitor_suspend(struct ast_cc_monitor *monitor)
@ SIG_PRI_RESET_IDLE
The channel is not being RESTARTed.
Definition: sig_pri.h:154
#define DAHDI_OVERLAPDIAL_BOTH
Definition: sig_pri.h:254
void sig_pri_stop_pri(struct sig_pri_span *pri)
void sig_pri_cc_agent_destructor(struct ast_cc_agent *agent)
void sig_pri_cli_show_spans(int fd, int span, struct sig_pri_span *pri)
void sig_pri_init_pri(struct sig_pri_span *pri)
#define SIG_PRI_AOC_GRANT_D
Definition: sig_pri.h:54
#define DAHDI_OVERLAPDIAL_NONE
Definition: sig_pri.h:251
int sig_pri_cc_agent_start_monitoring(struct ast_cc_agent *agent)
#define DAHDI_CHAN_MAPPING_LOGICAL
Definition: sig_pri.h:248
int sig_pri_cc_agent_init(struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
int sig_pri_load(const char *cc_type_name)
@ SIG_PRI_CALL_LEVEL_PROCEEDING
Definition: sig_pri.h:143
@ SIG_PRI_MOH_SIGNALING_MOH
Definition: sig_pri.h:75
@ SIG_PRI_MOH_SIGNALING_NOTIFY
Definition: sig_pri.h:77
int sig_pri_cc_agent_callee_available(struct ast_cc_agent *agent)
#define DAHDI_OVERLAPDIAL_INCOMING
Definition: sig_pri.h:253
struct ast_channel * sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
#define SIG_PRI_AOC_GRANT_E
Definition: sig_pri.h:55
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
void sig_pri_cc_monitor_destructor(void *monitor_pvt)
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
struct sig_pri_chan * sig_pri_chan_new(void *pvt_data, struct sig_pri_span *pri, int logicalspan, int channo, int trunkgroup)
void pri_event_noalarm(struct sig_pri_span *pri, int index, int before_start_pri)
void sig_pri_cli_show_span(int fd, int *dchannels, struct sig_pri_span *pri)
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
#define SIG_PRI_AOC_GRANT_S
Definition: sig_pri.h:53
sig_pri_tone
Definition: sig_pri.h:57
@ SIG_PRI_TONE_RINGTONE
Definition: sig_pri.h:58
@ SIG_PRI_TONE_INFO
Definition: sig_pri.h:63
@ SIG_PRI_TONE_DIALTONE
Definition: sig_pri.h:61
@ SIG_PRI_TONE_BUSY
Definition: sig_pri.h:64
@ SIG_PRI_TONE_STUTTER
Definition: sig_pri.h:59
@ SIG_PRI_TONE_CONGESTION
Definition: sig_pri.h:60
@ SIG_PRI_TONE_DIALRECALL
Definition: sig_pri.h:62
void pri_event_alarm(struct sig_pri_span *pri, int index, int before_start_pri)
int sig_pri_cc_agent_stop_offer_timer(struct ast_cc_agent *agent)
void sig_pri_cli_show_channels_header(int fd)
void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm)
int sig_pri_cc_agent_party_b_free(struct ast_cc_agent *agent)
int sig_pri_cc_monitor_status_rsp(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
#define DAHDI_CHAN_MAPPING_PHYSICAL
Definition: sig_pri.h:247
int sig_pri_cc_agent_stop_ringing(struct ast_cc_agent *agent)
int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
int pri_send_keypad_facility_exec(struct sig_pri_chan *p, const char *digits)
Interface header for SS7 signaling module.
void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *c, int lock)
void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
void sig_ss7_cli_show_channels_header(int fd)
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
#define LINKSET_FLAG_AUTOACM
Definition: sig_ss7.h:72
int sig_ss7_reset_group(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, int range)
int sig_ss7_available(struct sig_ss7_chan *p)
void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
int sig_ss7_reset_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
void * ss7_linkset(void *data)
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
#define SS7_BLOCKED_MAINTENANCE
Definition: sig_ss7.h:74
int sig_ss7_group_blocking(struct sig_ss7_linkset *linkset, int do_block, int startcic, int endcic, unsigned char state[], int type)
int sig_ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
#define SIG_SS7_DEBUG
Definition: sig_ss7.h:43
struct sig_ss7_callback sig_ss7_callbacks
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
sig_ss7_tone
Definition: sig_ss7.h:78
@ SIG_SS7_TONE_DIALRECALL
Definition: sig_ss7.h:83
@ SIG_SS7_TONE_INFO
Definition: sig_ss7.h:84
@ SIG_SS7_TONE_STUTTER
Definition: sig_ss7.h:80
@ SIG_SS7_TONE_RINGTONE
Definition: sig_ss7.h:79
@ SIG_SS7_TONE_CONGESTION
Definition: sig_ss7.h:81
@ SIG_SS7_TONE_DIALTONE
Definition: sig_ss7.h:82
@ SIG_SS7_TONE_BUSY
Definition: sig_ss7.h:85
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
int sig_ss7_cic_blocking(struct sig_ss7_linkset *linkset, int do_block, int cic)
#define LINKSET_FLAG_DEFAULTECHOCONTROL
Definition: sig_ss7.h:71
sig_ss7_law
Definition: sig_ss7.h:88
@ SIG_SS7_DEFLAW
Definition: sig_ss7.h:89
@ SIG_SS7_ULAW
Definition: sig_ss7.h:90
@ SIG_SS7_ALAW
Definition: sig_ss7.h:91
#define LINKSET_FLAG_USEECHOCONTROL
Definition: sig_ss7.h:70
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
#define LINKSET_FLAG_INITIALHWBLO
Definition: sig_ss7.h:69
int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode, int cur_slc)
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
#define SS7_BLOCKED_HARDWARE
Definition: sig_ss7.h:75
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
int sig_ss7_find_cic_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
SMDI support for Asterisk.
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
Definition: res_smdi.c:563
struct ast_smdi_md_message * ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
Get the next SMDI message from the queue.
Definition: res_smdi.c:539
#define SMDI_MAX_FILENAME_LEN
Definition: smdi.h:42
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
void stasis_subscription_cb_noop(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback function that does nothing.
Definition: stasis.c:810
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
Definition: stasis_cache.c:686
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
int(*const play_tone)(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: sig_analog.h:182
unsigned int immediate
Definition: sig_analog.h:298
unsigned int immediatering
Definition: sig_analog.h:299
unsigned int permcallwaiting
Definition: sig_analog.h:300
unsigned int canpark
Definition: sig_analog.h:295
unsigned int dahditrcallerid
Definition: sig_analog.h:296
int polarityonanswerdelay
Definition: sig_analog.h:324
char cid_num[AST_MAX_EXTENSION]
Definition: sig_analog.h:328
int redirecting_reason
Definition: sig_analog.h:356
unsigned int permhidecallerid
Definition: sig_analog.h:301
unsigned int callwaitingcallerid
Definition: sig_analog.h:309
unsigned int ani_wink_time
Definition: sig_analog.h:289
enum analog_sigtype outsigmod
Definition: sig_analog.h:320
unsigned int usedistinctiveringdetection
Definition: sig_analog.h:308
unsigned int answeronpolarityswitch
Definition: sig_analog.h:291
unsigned int threewaycalling
Definition: sig_analog.h:303
unsigned int pulse
Definition: sig_analog.h:302
int echotraining
Definition: sig_analog.h:322
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
Definition: sig_analog.h:284
int onhooktime
Definition: sig_analog.h:281
unsigned int hanguponpolarityswitch
Definition: sig_analog.h:297
enum analog_cid_start cid_start
Definition: sig_analog.h:326
unsigned int callreturn
Definition: sig_analog.h:293
struct ast_channel * owner
Definition: sig_analog.h:277
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: sig_analog.h:313
unsigned int call_qualifier
Definition: sig_analog.h:349
unsigned int ani_timeout
Definition: sig_analog.h:288
int ringt_base
Definition: sig_analog.h:376
int fxsoffhookstate
Definition: sig_analog.h:282
unsigned int ani_info_digits
Definition: sig_analog.h:287
enum analog_dialmode dialmode
Definition: sig_analog.h:321
unsigned int cancallforward
Definition: sig_analog.h:294
struct analog_subchannel subs[3]
Definition: sig_analog.h:279
int cid_signalling
Definition: sig_analog.h:323
unsigned int transfer
Definition: sig_analog.h:305
unsigned int transfertobusy
Definition: sig_analog.h:306
unsigned int inalarm
Definition: sig_analog.h:341
char cid_name[AST_MAX_EXTENSION]
Definition: sig_analog.h:329
int stripmsd
Definition: sig_analog.h:325
unsigned int calledsubscriberheld
Definition: sig_analog.h:292
char mohsuggest[MAX_MUSICCLASS]
Definition: sig_analog.h:327
unsigned int use_callerid
Definition: sig_analog.h:307
struct ast_channel * ss_astchan
Definition: sig_analog.h:372
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:315
struct ast_party_caller caller
Definition: sig_analog.h:355
struct ast_channel * owner
Definition: sig_analog.h:264
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:606
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:857
Callbacks defined by CC monitors.
Definition: ccss.h:542
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:549
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:648
struct ast_format_cap * capabilities
Definition: channel.h:652
const char *const type
Definition: channel.h:649
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
const char * data
char x
Definition: extconf.c:81
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
const ast_string_field name
struct ast_flags flags
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
char chan_name[AST_CHANNEL_NAME]
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
int pattern[4]
Definition: dsp.h:68
Configuration relating to call pickup.
Structure used to handle boolean flags.
Definition: utils.h:199
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
unsigned int flags
const char * src
General jitterbuffer configuration.
Definition: abstract_jb.h:70
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Definition: manager.h:502
struct ast_module * self
Definition: module.h:356
The structure that contains MWI state.
Definition: mwi.h:455
int new_msgs
Definition: mwi.h:459
Caller Party information.
Definition: channel.h:420
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:435
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:429
struct ast_party_id id
Connected party ID.
Definition: channel.h:460
struct ast_party_dialed::@208 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:388
struct ast_party_subaddress subaddress
Subscriber subaddress.
Definition: channel.h:346
char * tag
User-set "tag".
Definition: channel.h:356
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:279
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281
char * str
Subscriber name (Malloced)
Definition: channel.h:266
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:297
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:295
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:512
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:544
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:529
unsigned char valid
TRUE if the subaddress information is valid/present.
Definition: channel.h:330
char * str
Malloced subaddress string.
Definition: channel.h:315
An SMDI message desk message.
Definition: smdi.h:65
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
char number[64]
Definition: callerid.c:54
Definition: astman.c:88
All configuration options for http media cache.
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
Definition: chan_dahdi.c:952
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
Definition: chan_dahdi.c:974
int ignore_failed_channels
Definition: chan_dahdi.c:968
struct dahdi_params timing
Definition: chan_dahdi.c:965
int wanted_channels_end
Don't create channels above this number (infinity by default)
Definition: chan_dahdi.c:986
struct dahdi_pvt chan
Definition: chan_dahdi.c:953
int wanted_channels_start
Don't create channels below this number.
Definition: chan_dahdi.c:980
struct ringContextData ringContext[3]
Definition: chan_dahdi.h:71
struct distRingData ringnum[3]
Definition: chan_dahdi.h:70
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:272
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:713
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits.
Definition: chan_dahdi.h:316
unsigned int immediatering
TRUE if audible ringback should be provided when immediate = yes.
Definition: chan_dahdi.h:322
unsigned int threewaysilenthold
TRUE if a three way dial tone should time out to silence.
Definition: chan_dahdi.h:373
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:168
unsigned int permcallwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:334
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:158
float txdrc
Definition: chan_dahdi.h:164
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:485
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:584
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:537
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:243
unsigned int bufferoverrideinuse
Definition: chan_dahdi.h:278
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:556
int bufsize
Definition: chan_dahdi.h:138
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:469
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:262
int faxbuf_policy
Definition: chan_dahdi.h:142
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
Definition: chan_dahdi.h:310
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
Definition: chan_dahdi.h:696
struct timeval dtmfcid_delay
Definition: chan_dahdi.h:591
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:408
struct dahdi_pvt * next
Definition: chan_dahdi.h:169
unsigned int doreoriginate
Internal flag for if we should actually process a reorigination.
Definition: chan_dahdi.h:293
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:597
struct tdd_state * tdd
Definition: chan_dahdi.h:702
int waitfordialtonetemp
Transient variable. Same as waitfordialtone, but temporarily set for a specific call,...
Definition: chan_dahdi.h:660
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:601
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:727
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:641
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:526
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:603
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
Definition: chan_dahdi.h:711
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:552
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:734
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:152
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
Definition: chan_dahdi.h:339
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:433
char * origcid_name
Definition: chan_dahdi.h:539
struct mwisend_info mwisend_data
Definition: chan_dahdi.h:480
int cid_suppress_expire
Definition: chan_dahdi.h:595
struct timeval flashtime
Definition: chan_dahdi.h:692
int oprmode
Definition: chan_dahdi.h:151
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:685
unsigned int mwimonitor_rpas
TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
Definition: chan_dahdi.h:429
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
unsigned int confirmanswer
TRUE if to wait for a DTMF digit to confirm answer.
Definition: chan_dahdi.h:245
unsigned int restartpending
Definition: chan_dahdi.h:357
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:431
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:328
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:675
int whichwink
Definition: chan_dahdi.h:697
float rxdrc
Definition: chan_dahdi.h:165
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:231
char * origcid_num
Definition: chan_dahdi.h:538
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:465
unsigned int ani_wink_time
INTEGER, length of time to wait before sending ANI wink in ms.
Definition: chan_dahdi.h:200
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:656
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:451
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition: chan_dahdi.h:178
int outsigmod
Definition: chan_dahdi.h:150
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:403
unsigned int answeronpolarityswitch
TRUE if we can use a polarity reversal to mark when an outgoing call is answered by the remote party.
Definition: chan_dahdi.h:184
unsigned int threewaycalling
TRUE if three way calling is enabled.
Definition: chan_dahdi.h:368
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
int distinctivering
Definition: chan_dahdi.h:719
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls.
Definition: chan_dahdi.h:397
int dtmfrelax
Definition: chan_dahdi.h:720
unsigned int pulse
TRUE if we will pulse dial.
Definition: chan_dahdi.h:354
int dialtone_scanning_time_elapsed
Definition: chan_dahdi.h:670
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:349
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:709
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:154
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:634
int tonezone
Definition: chan_dahdi.h:167
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:541
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:156
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
Definition: chan_dahdi.h:664
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:738
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:226
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:502
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
Definition: chan_dahdi.h:651
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:622
time_t guardtime
Definition: chan_dahdi.h:587
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:729
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:285
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:547
char dialstring[AST_CHANNEL_NAME]
Definition: chan_dahdi.h:772
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:704
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:496
unsigned int firstradio
TRUE if over a radio and dahdi_read() has been called.
Definition: chan_dahdi.h:280
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:460
struct dahdi_pvt::@115 echocancel
Echo cancel parameters.
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:302
unsigned int echobreak
XXX BOOLEAN Purpose???
Definition: chan_dahdi.h:264
struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS]
Definition: chan_dahdi.h:628
int faxbuf_no
Definition: chan_dahdi.h:141
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
Definition: chan_dahdi.h:219
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:579
struct ast_channel * owner
Definition: chan_dahdi.h:127
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:545
unsigned int faxhandled
TRUE if a fax tone has already been handled.
Definition: chan_dahdi.h:274
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:479
struct callerid_state * cs
Definition: chan_dahdi.h:126
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:524
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:574
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:624
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:418
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:253
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:467
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:554
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:722
unsigned int didtdd
Definition: chan_dahdi.h:251
char echorest[20]
Filled with 'w'. XXX Purpose??
Definition: chan_dahdi.h:636
struct dahdi_pvt * slaves[MAX_SLAVES]
Definition: chan_dahdi.h:134
void * sig_pvt
Definition: chan_dahdi.h:764
int confno
Definition: chan_dahdi.h:557
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
Definition: chan_dahdi.h:195
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:590
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
Definition: chan_dahdi.h:435
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:423
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:608
int cid_start
Definition: chan_dahdi.h:589
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
Definition: chan_dahdi.h:250
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:363
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:500
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:344
unsigned int ani_info_digits
INTEGER, number of ANI INFO digits on a CAMA trunk. older switches use 1 INFO digit,...
Definition: chan_dahdi.h:190
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition: chan_dahdi.h:206
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
Definition: chan_dahdi.h:308
struct timeval waitingfordt
Definition: chan_dahdi.h:691
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:694
struct dahdi_pvt * prev
Definition: chan_dahdi.h:170
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition: chan_dahdi.h:569
int callingpres
Definition: chan_dahdi.h:592
int dialmode
Definition: chan_dahdi.h:149
unsigned int reoriginate
TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call.
Definition: chan_dahdi.h:289
int buf_policy
Definition: chan_dahdi.h:140
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:599
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:491
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
Definition: chan_dahdi.h:238
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:518
int cidcwexpire
Definition: chan_dahdi.h:594
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:295
int callwaitingrepeat
Definition: chan_dahdi.h:593
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:761
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:765
unsigned int mate
TRUE if TDD in MATE mode.
Definition: chan_dahdi.h:326
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:162
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:680
int amaflags
Definition: chan_dahdi.h:701
struct dahdi_echocanparams head
Definition: chan_dahdi.h:627
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
int cid_signalling
Definition: chan_dahdi.h:588
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:699
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:382
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:413
int buf_no
Definition: chan_dahdi.h:139
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:324
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:535
ast_mutex_t lock
Definition: chan_dahdi.h:125
unsigned int inservice
TRUE if channel is out of reset and ready.
Definition: chan_dahdi.h:442
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:507
unsigned int digital
TRUE if the transfer capability of the call is digital.
Definition: chan_dahdi.h:260
int channel
Definition: chan_dahdi.h:585
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:700
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
Definition: chan_dahdi.h:437
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:646
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:615
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:356
unsigned int calledsubscriberheld
TRUE if Called Subscriber held is enabled. This allows a single incoming call to hold a DAHDI channel...
Definition: chan_dahdi.h:213
int muting
TRUE if confrence is muted.
Definition: chan_dahdi.h:763
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:531
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:690
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:517
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:390
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:160
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:736
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:564
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:258
unsigned int usefaxbuffers
Definition: chan_dahdi.h:276
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:543
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
Definition: chan_dahdi.h:512
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:669
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:482
int inconference
Definition: chan_dahdi.h:136
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:533
ast_group_t groupmatch
Definition: chan_dahdi.c:13731
unsigned int needanswer
Definition: chan_dahdi.h:86
unsigned int needringing
Definition: chan_dahdi.h:83
unsigned int linear
Definition: chan_dahdi.h:90
unsigned int needhold
Definition: chan_dahdi.h:88
unsigned int needunhold
Definition: chan_dahdi.h:89
struct ast_frame f
Definition: chan_dahdi.h:82
unsigned int inthreeway
Definition: chan_dahdi.h:91
struct ast_channel * owner
Definition: chan_dahdi.h:79
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92
unsigned int needflash
Definition: chan_dahdi.h:87
unsigned int needbusy
Definition: chan_dahdi.h:84
short buffer[AST_FRIENDLY_OFFSET/2+READ_SIZE]
Definition: chan_dahdi.h:81
unsigned int needcongestion
Definition: chan_dahdi.h:85
int ring[3]
Definition: chan_dahdi.h:63
Definition: search.h:40
Definition: astman.c:222
Definition: logger.c:172
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:326
struct dahdi_pvt * pvt
Definition: chan_dahdi.c:11084
unsigned char buf[READ_SIZE]
Definition: chan_dahdi.c:11085
mwisend_states mwisend_current
Definition: chan_dahdi.h:112
struct timeval pause
Definition: chan_dahdi.h:111
Number structure.
Definition: app_followme.c:154
struct ast_channel * peer
char contextData[AST_MAX_CONTEXT]
Definition: chan_dahdi.h:67
void(*const handle_dchan_exception)(struct sig_pri_span *pri, int index)
Definition: sig_pri.h:202
unsigned int immediate
Definition: sig_pri.h:282
struct sig_pri_span * pri
Definition: sig_pri.h:355
void * chan_pvt
Definition: sig_pri.h:374
enum sig_pri_reset_state resetting
Channel reset/restart state.
Definition: sig_pri.h:361
unsigned int allocated
TRUE when this channel is allocated.
Definition: sig_pri.h:339
unsigned int use_callingpres
Definition: sig_pri.h:286
unsigned int priexclusive
Definition: sig_pri.h:283
unsigned int hidecallerid
Definition: sig_pri.h:280
unsigned int priindication_oob
Definition: sig_pri.h:284
unsigned int hidecalleridname
Definition: sig_pri.h:281
char context[AST_MAX_CONTEXT]
Definition: sig_pri.h:287
unsigned int inalarm
Definition: sig_pri.h:324
int channel
Definition: sig_pri.h:290
unsigned int no_b_channel
TRUE if this interface has no B channel. (call hold and call waiting)
Definition: sig_pri.h:343
int stripmsd
Definition: sig_pri.h:289
unsigned int use_callerid
Definition: sig_pri.h:285
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_pri.h:288
q931_call * call
Definition: sig_pri.h:356
struct sig_pri_chan * pvts[SIG_PRI_MAX_CHANNELS]
Definition: sig_pri.h:614
struct pri * pri
Definition: sig_pri.h:602
int nodetype
Definition: sig_pri.h:555
int numchans
Definition: sig_pri.h:613
char idleext[AST_MAX_EXTENSION]
Definition: sig_pri.h:550
int switchtype
Definition: sig_pri.h:556
int minunused
Definition: sig_pri.h:553
int fds[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:457
int minidle
Definition: sig_pri.h:554
int trunkgroup
Definition: sig_pri.h:558
pthread_t master
Definition: sig_pri.h:615
int dialplan
Definition: sig_pri.h:504
int congestion_devstate
Congestion device state of the span.
Definition: sig_pri.h:627
void * no_b_chan_end
Definition: sig_pri.h:612
void * no_b_chan_iflist
Definition: sig_pri.h:607
ast_mutex_t lock
Definition: sig_pri.h:616
char idledial[AST_MAX_EXTENSION]
Definition: sig_pri.h:552
void(*const lock_private)(void *pvt)
Definition: sig_ss7.h:157
unsigned int immediate
Definition: sig_ss7.h:221
void * chan_pvt
Definition: sig_ss7.h:190
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int dpc
Definition: sig_ss7.h:202
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls.
Definition: sig_ss7.h:220
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
struct ast_channel * owner
Definition: sig_ss7.h:192
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:237
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
int channel
Definition: sig_ss7.h:200
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:238
int fds[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:323
pthread_t master
Definition: sig_ss7.h:319
struct ss7 * ss7
Definition: sig_ss7.h:321
ast_mutex_t lock
Definition: sig_ss7.h:320
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:322
struct sla_ringing_trunk * next
Definition: app_sla.c:308
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
TTY/TDD Generation support.
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:296
struct tdd_state * tdd_new(void)
Definition: tdd.c:103
void tdd_free(struct tdd_state *tdd)
Definition: tdd.c:218
int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
Definition: tdd.c:148
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
Definition: tdd.c:161
Handy terminal functions for vt* terms.
#define COLOR_MAGENTA
Definition: term.h:60
#define COLOR_BLACK
Definition: term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235
#define COLOR_GREEN
Definition: term.h:54
const char * args
static struct test_options options
static struct test_val b
static struct test_val a
static struct test_val c
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
General Asterisk channel transcoding definitions.
#define IS_DIGITAL(cap)
Definition: transcap.h:45
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:36
u-Law to Signed linear conversion
#define AST_MULAW(a)
Definition: ulaw.h:85
#define AST_LIN2MU(a)
Definition: ulaw.h:49
FILE * out
Definition: utils/frame.c:33
Utility functions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ast_clear_flag(p, flag)
Definition: utils.h:77
long int ast_random(void)
Definition: utils.c:2312
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:666