]> git.ipfire.org Git - thirdparty/asterisk.git/blob - channels/chan_dahdi.c
af94ce4dca6dbb5287ea5eae42bd9f97f9eb8ae1
[thirdparty/asterisk.git] / channels / chan_dahdi.c
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"
118 #include "asterisk/stringfields.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"
124 #include "asterisk/features_config.h"
125 #include "asterisk/bridge.h"
126 #include "asterisk/stasis_channels.h"
127 #include "asterisk/parking.h"
128 #include "asterisk/format_cache.h"
129 #include "chan_dahdi.h"
130 #include "dahdi/bridge_native_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 </enumlist>
280 </info>
281 <info name="Dial_Resource" language="en_US" tech="DAHDI">
282 <para>DAHDI allows several modifiers to be specified as part of the resource.</para>
283 <para>The general syntax is :</para>
284 <para><literal>Dial(DAHDI/pseudo[/extension])</literal></para>
285 <para><literal>Dial(DAHDI/&lt;channel#&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
286 <para><literal>Dial(DAHDI/(g|G|r|R)&lt;group#(0-63)&gt;[c|r&lt;cadence#&gt;|d][/extension])</literal></para>
287 <para>The following modifiers may be used before the channel number:</para>
288 <enumlist>
289 <enum name="g">
290 <para>Search forward, dialing on first available channel in group (lowest to highest).</para>
291 </enum>
292 <enum name="G">
293 <para>Search backward, dialing on first available channel in group (highest to lowest).</para>
294 </enum>
295 <enum name="r">
296 <para>Round robin search forward, picking up from where last left off (lowest to highest).</para>
297 </enum>
298 <enum name="R">
299 <para>Round robin search backward, picking up from where last left off (highest to lowest).</para>
300 </enum>
301 </enumlist>
302 <para>The following modifiers may be used after the channel number:</para>
303 <enumlist>
304 <enum name="c">
305 <para>Wait for DTMF digit <literal>#</literal> before providing answer supervision.</para>
306 <para>This can be useful on outbound calls via FXO ports, as otherwise
307 they would indicate answer immediately.</para>
308 </enum>
309 <enum name="d">
310 <para>Force bearer capability for ISDN/SS7 call to digital.</para>
311 </enum>
312 <enum name="i">
313 <para>ISDN span channel restriction.</para>
314 <para>Used by CC to ensure that the CC recall goes out the same span.
315 Also to make ISDN channel names dialable when the sequence number
316 is stripped off. (Used by DTMF attended transfer feature.)</para>
317 </enum>
318 <enum name="r">
319 <para>Specifies the distinctive ring cadence number to use immediately after
320 specifying this option. There are 4 default built-in cadences, and up to 24
321 total cadences may be configured.</para>
322 </enum>
323 </enumlist>
324 <example title="Dial 555-1212 on first available channel in group 1, searching from highest to lowest">
325 same => n,Dial(DAHDI/g1/5551212)
326 </example>
327 <example title="Ringing FXS channel 4 with ring cadence 2">
328 same => n,Dial(DAHDI/4r2)
329 </example>
330 <example title="Dial 555-1212 on channel 3 and require answer confirmation">
331 same => n,Dial(DAHDI/3c/5551212)
332 </example>
333 </info>
334 <manager name="DAHDITransfer" language="en_US">
335 <synopsis>
336 Transfer DAHDI Channel.
337 </synopsis>
338 <syntax>
339 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
340 <parameter name="DAHDIChannel" required="true">
341 <para>DAHDI channel number to transfer.</para>
342 </parameter>
343 </syntax>
344 <description>
345 <para>Simulate a flash hook event by the user connected to the channel.</para>
346 <note><para>Valid only for analog channels.</para></note>
347 </description>
348 </manager>
349 <manager name="DAHDIHangup" language="en_US">
350 <synopsis>
351 Hangup 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 hangup.</para>
357 </parameter>
358 </syntax>
359 <description>
360 <para>Simulate an on-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="DAHDIDialOffhook" language="en_US">
365 <synopsis>
366 Dial over DAHDI channel while offhook.
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 dial digits.</para>
372 </parameter>
373 <parameter name="Number" required="true">
374 <para>Digits to dial.</para>
375 </parameter>
376 </syntax>
377 <description>
378 <para>Generate DTMF control frames to the bridged peer.</para>
379 </description>
380 </manager>
381 <manager name="DAHDIDNDon" language="en_US">
382 <synopsis>
383 Toggle DAHDI channel Do Not Disturb status ON.
384 </synopsis>
385 <syntax>
386 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
387 <parameter name="DAHDIChannel" required="true">
388 <para>DAHDI channel number to set DND on.</para>
389 </parameter>
390 </syntax>
391 <description>
392 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
393 <note><para>Feature only supported by analog channels.</para></note>
394 </description>
395 </manager>
396 <manager name="DAHDIDNDoff" language="en_US">
397 <synopsis>
398 Toggle DAHDI channel Do Not Disturb status OFF.
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 off.</para>
404 </parameter>
405 </syntax>
406 <description>
407 <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
408 <note><para>Feature only supported by analog channels.</para></note>
409 </description>
410 </manager>
411 <manager name="DAHDIShowChannels" language="en_US">
412 <synopsis>
413 Show status of DAHDI channels.
414 </synopsis>
415 <syntax>
416 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
417 <parameter name="DAHDIChannel">
418 <para>Specify the specific channel number to show. Show all channels if zero or not present.</para>
419 </parameter>
420 </syntax>
421 <description>
422 <para>Similar to the CLI command "dahdi show channels".</para>
423 </description>
424 </manager>
425 <manager name="DAHDIRestart" language="en_US">
426 <synopsis>
427 Fully Restart DAHDI channels (terminates calls).
428 </synopsis>
429 <syntax>
430 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
431 </syntax>
432 <description>
433 <para>Equivalent to the CLI command "dahdi restart".</para>
434 </description>
435 </manager>
436 <manager name="PRIShowSpans" language="en_US">
437 <synopsis>
438 Show status of PRI spans.
439 </synopsis>
440 <syntax>
441 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
442 <parameter name="Span">
443 <para>Specify the specific span to show. Show all spans if zero or not present.</para>
444 </parameter>
445 </syntax>
446 <description>
447 <para>Similar to the CLI command "pri show spans".</para>
448 </description>
449 </manager>
450 <manager name="PRIDebugSet" language="en_US">
451 <synopsis>
452 Set PRI debug levels for a span
453 </synopsis>
454 <syntax>
455 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
456 <parameter name="Span" required="true">
457 <para>Which span to affect.</para>
458 </parameter>
459 <parameter name="Level" required="true">
460 <para>What debug level to set. May be a numerical value or a text value from the list below</para>
461 <enumlist>
462 <enum name="off" />
463 <enum name="on" />
464 <enum name="hex" />
465 <enum name="intense" />
466 </enumlist>
467 </parameter>
468 </syntax>
469 <description>
470 <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
471 </description>
472 </manager>
473 <manager name="PRIDebugFileSet" language="en_US">
474 <synopsis>
475 Set the file used for PRI debug message output
476 </synopsis>
477 <syntax>
478 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
479 <parameter name="File" required="true">
480 <para>Path of file to write debug output.</para>
481 </parameter>
482 </syntax>
483 <description>
484 <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
485 </description>
486 </manager>
487 <manager name="PRIDebugFileUnset" language="en_US">
488 <synopsis>
489 Disables file output for PRI debug messages
490 </synopsis>
491 <syntax>
492 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
493 </syntax>
494 </manager>
495 <managerEvent language="en_US" name="AlarmClear">
496 <managerEventInstance class="EVENT_FLAG_SYSTEM">
497 <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
498 <syntax>
499 <parameter name="DAHDIChannel">
500 <para>The DAHDI channel on which the alarm was cleared.</para>
501 <note><para>This is not an Asterisk channel identifier.</para></note>
502 </parameter>
503 </syntax>
504 </managerEventInstance>
505 </managerEvent>
506 <managerEvent language="en_US" name="SpanAlarmClear">
507 <managerEventInstance class="EVENT_FLAG_SYSTEM">
508 <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
509 <syntax>
510 <parameter name="Span">
511 <para>The span on which the alarm was cleared.</para>
512 </parameter>
513 </syntax>
514 </managerEventInstance>
515 </managerEvent>
516 <managerEvent language="en_US" name="DNDState">
517 <managerEventInstance class="EVENT_FLAG_SYSTEM">
518 <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
519 <syntax>
520 <parameter name="DAHDIChannel">
521 <para>The DAHDI channel on which DND status changed.</para>
522 <note><para>This is not an Asterisk channel identifier.</para></note>
523 </parameter>
524 <parameter name="Status">
525 <enumlist>
526 <enum name="enabled"/>
527 <enum name="disabled"/>
528 </enumlist>
529 </parameter>
530 </syntax>
531 </managerEventInstance>
532 </managerEvent>
533 <managerEvent language="en_US" name="Alarm">
534 <managerEventInstance class="EVENT_FLAG_SYSTEM">
535 <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
536 <syntax>
537 <parameter name="DAHDIChannel">
538 <para>The channel on which the alarm occurred.</para>
539 <note><para>This is not an Asterisk channel identifier.</para></note>
540 </parameter>
541 <parameter name="Alarm">
542 <para>A textual description of the alarm that occurred.</para>
543 </parameter>
544 </syntax>
545 </managerEventInstance>
546 </managerEvent>
547 <managerEvent language="en_US" name="SpanAlarm">
548 <managerEventInstance class="EVENT_FLAG_SYSTEM">
549 <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
550 <syntax>
551 <parameter name="Span">
552 <para>The span on which the alarm occurred.</para>
553 </parameter>
554 <parameter name="Alarm">
555 <para>A textual description of the alarm that occurred.</para>
556 </parameter>
557 </syntax>
558 </managerEventInstance>
559 </managerEvent>
560 <managerEvent language="en_US" name="DAHDIChannel">
561 <managerEventInstance class="EVENT_FLAG_CALL">
562 <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
563 <syntax>
564 <channel_snapshot/>
565 <parameter name="DAHDIGroup">
566 <para>The DAHDI logical group associated with this channel.</para>
567 </parameter>
568 <parameter name="DAHDISpan">
569 <para>The DAHDI span associated with this channel.</para>
570 </parameter>
571 <parameter name="DAHDIChannel">
572 <para>The DAHDI channel associated with this channel.</para>
573 </parameter>
574 </syntax>
575 </managerEventInstance>
576 </managerEvent>
577 ***/
578
579 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
580
581 static const char * const lbostr[] = {
582 "0 db (CSU)/0-133 feet (DSX-1)",
583 "133-266 feet (DSX-1)",
584 "266-399 feet (DSX-1)",
585 "399-533 feet (DSX-1)",
586 "533-655 feet (DSX-1)",
587 "-7.5db (CSU)",
588 "-15db (CSU)",
589 "-22.5db (CSU)"
590 };
591
592 /*! Global jitterbuffer configuration - by default, jb is disabled
593 * \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
594 static struct ast_jb_conf default_jbconf =
595 {
596 .flags = 0,
597 .max_size = 200,
598 .resync_threshold = 1000,
599 .impl = "fixed",
600 .target_extra = 40,
601 };
602 static struct ast_jb_conf global_jbconf;
603
604 /*!
605 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
606 * the user hangs up to reset the state machine so ring works properly.
607 * This is used to be able to support kewlstart by putting the zhone in
608 * groundstart mode since their forward disconnect supervision is entirely
609 * broken even though their documentation says it isn't and their support
610 * is entirely unwilling to provide any assistance with their channel banks
611 * even though their web site says they support their products for life.
612 */
613 /* #define ZHONE_HACK */
614
615 /*! \brief Typically, how many rings before we should send Caller*ID */
616 #define DEFAULT_CIDRINGS 1
617
618 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
619
620
621 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
622 #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))
623
624 static const char tdesc[] = "DAHDI Telephony"
625 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
626 " w/"
627 #if defined(HAVE_PRI)
628 "PRI"
629 #endif /* defined(HAVE_PRI) */
630 #if defined(HAVE_SS7)
631 #if defined(HAVE_PRI)
632 " & "
633 #endif /* defined(HAVE_PRI) */
634 "SS7"
635 #endif /* defined(HAVE_SS7) */
636 #if defined(HAVE_OPENR2)
637 #if defined(HAVE_PRI) || defined(HAVE_SS7)
638 " & "
639 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
640 "MFC/R2"
641 #endif /* defined(HAVE_OPENR2) */
642 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
643 ;
644
645 static const char config[] = "chan_dahdi.conf";
646
647 #ifdef LOTS_OF_SPANS
648 #define NUM_SPANS DAHDI_MAX_SPANS
649 #else
650 #define NUM_SPANS 32
651 #endif
652
653 #define CHAN_PSEUDO -2
654
655 #define CALLPROGRESS_PROGRESS 1
656 #define CALLPROGRESS_FAX_OUTGOING 2
657 #define CALLPROGRESS_FAX_INCOMING 4
658 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
659
660 #define NUM_CADENCE_MAX 25
661 static int num_cadence = 4;
662 static int user_has_defined_cadences = 0;
663
664 static int has_pseudo;
665
666 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
667 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
668 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
669 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
670 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
671 };
672
673 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
674 * is 1, the second pause is 2 and so on.
675 */
676
677 static int cidrings[NUM_CADENCE_MAX] = {
678 2, /*!< Right after first long ring */
679 4, /*!< Right after long part */
680 3, /*!< After third chirp */
681 2, /*!< Second spell */
682 };
683
684 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
685 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
686
687 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
688 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
689
690 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
691 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
692
693 static char defaultcic[64] = "";
694 static char defaultozz[64] = "";
695
696 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
697 static char mwimonitornotify[PATH_MAX] = "";
698 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
699 static int mwisend_rpas = 0;
700 #endif
701
702 static char progzone[10] = "";
703
704 static int usedistinctiveringdetection = 0;
705 static int distinctiveringaftercid = 0;
706
707 static int numbufs = 4;
708
709 static int mwilevel = 512;
710 static int dtmfcid_level = 256;
711
712 #define REPORT_CHANNEL_ALARMS 1
713 #define REPORT_SPAN_ALARMS 2
714 static int report_alarms = REPORT_CHANNEL_ALARMS;
715
716 #ifdef HAVE_PRI
717 static int pridebugfd = -1;
718 static char pridebugfilename[1024] = "";
719 #endif
720
721 /*! \brief Protect the interface list (of dahdi_pvt's) */
722 AST_MUTEX_DEFINE_STATIC(iflock);
723
724
725 static int ifcount = 0;
726
727 #ifdef HAVE_PRI
728 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
729 #endif
730
731 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
732 when it's doing something critical. */
733 AST_MUTEX_DEFINE_STATIC(monlock);
734
735 /*! \brief This is the thread for the monitor which checks for input on the channels
736 which are not currently in use. */
737 static pthread_t monitor_thread = AST_PTHREADT_NULL;
738 static ast_cond_t ss_thread_complete;
739 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
740 AST_MUTEX_DEFINE_STATIC(restart_lock);
741 static int ss_thread_count = 0;
742 static int num_restart_pending = 0;
743
744 static int restart_monitor(void);
745
746 static int dahdi_sendtext(struct ast_channel *c, const char *text);
747
748 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
749 static inline int dahdi_get_event(int fd)
750 {
751 int j;
752 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
753 return -1;
754 return j;
755 }
756
757 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
758 static inline int dahdi_wait_event(int fd)
759 {
760 int i, j = 0;
761 i = DAHDI_IOMUX_SIGEVENT;
762 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
763 return -1;
764 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
765 return -1;
766 return j;
767 }
768
769 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
770 #define READ_SIZE 160
771
772 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
773 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
774
775 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) /*!< 300 ms */
776 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
777 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) /*!< 100 ms */
778 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */
779 #define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */
780 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
781 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
782
783 /*!
784 * \brief Configured ring timeout base.
785 * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
786 */
787 static int ringt_base = DEFAULT_RINGT;
788
789 #if defined(HAVE_SS7)
790
791 struct dahdi_ss7 {
792 struct sig_ss7_linkset ss7;
793 };
794
795 static struct dahdi_ss7 linksets[NUM_SPANS];
796
797 static int cur_ss7type = -1;
798 static int cur_slc = -1;
799 static int cur_linkset = -1;
800 static int cur_pointcode = -1;
801 static int cur_cicbeginswith = -1;
802 static int cur_adjpointcode = -1;
803 static int cur_networkindicator = -1;
804 static int cur_defaultdpc = -1;
805 #endif /* defined(HAVE_SS7) */
806
807 #ifdef HAVE_OPENR2
808 struct dahdi_mfcr2_conf {
809 openr2_variant_t variant;
810 int mfback_timeout;
811 int metering_pulse_timeout;
812 int max_ani;
813 int max_dnis;
814 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
815 int dtmf_time_on;
816 int dtmf_time_off;
817 #endif
818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
819 int dtmf_end_timeout;
820 #endif
821 signed int get_ani_first:2;
822 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
823 signed int skip_category_request:2;
824 #endif
825 unsigned int call_files:1;
826 unsigned int allow_collect_calls:1;
827 unsigned int charge_calls:1;
828 unsigned int accept_on_offer:1;
829 unsigned int forced_release:1;
830 unsigned int double_answer:1;
831 signed int immediate_accept:2;
832 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
833 signed int dtmf_dialing:2;
834 signed int dtmf_detection:2;
835 #endif
836 char logdir[OR2_MAX_PATH];
837 char r2proto_file[OR2_MAX_PATH];
838 openr2_log_level_t loglevel;
839 openr2_calling_party_category_t category;
840 };
841
842 /* MFC-R2 pseudo-link structure */
843 struct dahdi_mfcr2 {
844 int index; /*!< Unique index for CLI */
845 pthread_t r2master; /*!< Thread of master */
846 openr2_context_t *protocol_context; /*!< OpenR2 context handle */
847 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */
848 int numchans; /*!< Number of channels in this R2 block */
849 int live_chans; /*!< Number of unremoved channels in this R2 block */
850 int nodev; /*!< Link disconnected? */
851 struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */
852 };
853
854 struct r2link_entry {
855 struct dahdi_mfcr2 mfcr2;
856 AST_LIST_ENTRY(r2link_entry) list;
857 };
858 static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
859 static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
860
861
862 /* how many r2links have been malloc'd */
863 static int r2links_count = 0;
864
865 #endif /* HAVE_OPENR2 */
866
867 #ifdef HAVE_PRI
868
869 struct dahdi_pri {
870 int dchannels[SIG_PRI_NUM_DCHANS]; /*!< What channel are the dchannels on */
871 int mastertrunkgroup; /*!< What trunk group is our master */
872 int prilogicalspan; /*!< Logical span number within trunk group */
873 struct sig_pri_span pri;
874 };
875
876 static struct dahdi_pri pris[NUM_SPANS];
877
878 #if defined(HAVE_PRI_CCSS)
879 /*! DAHDI PRI CCSS agent and monitor type name. */
880 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
881 #endif /* defined(HAVE_PRI_CCSS) */
882
883 #else
884 /*! Shut up the compiler */
885 struct dahdi_pri;
886 #endif
887
888 /* Polarity states */
889 #define POLARITY_IDLE 0
890 #define POLARITY_REV 1
891
892 const char * const subnames[] = {
893 "Real",
894 "Callwait",
895 "Threeway"
896 };
897
898 static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
899 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
900
901 #if defined(HAVE_PRI)
902 struct doomed_pri {
903 struct sig_pri_span *pri;
904 AST_LIST_ENTRY(doomed_pri) list;
905 };
906 static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
907
908 static void pri_destroy_span(struct sig_pri_span *pri);
909
910 static struct dahdi_parms_pseudo {
911 int buf_no; /*!< Number of buffers */
912 int buf_policy; /*!< Buffer policy */
913 int faxbuf_no; /*!< Number of Fax buffers */
914 int faxbuf_policy; /*!< Fax buffer policy */
915 } dahdi_pseudo_parms;
916 #endif /* defined(HAVE_PRI) */
917
918 /*! \brief Channel configuration from chan_dahdi.conf .
919 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
920 * Generally there is a field here for every possible configuration item.
921 *
922 * The state of fields is saved along the parsing and whenever a 'channel'
923 * statement is reached, the current dahdi_chan_conf is used to configure the
924 * channel (struct dahdi_pvt)
925 *
926 * \see dahdi_chan_init for the default values.
927 */
928 struct dahdi_chan_conf {
929 struct dahdi_pvt chan;
930 #ifdef HAVE_PRI
931 struct dahdi_pri pri;
932 #endif
933
934 #if defined(HAVE_SS7)
935 struct dahdi_ss7 ss7;
936 #endif /* defined(HAVE_SS7) */
937
938 #ifdef HAVE_OPENR2
939 struct dahdi_mfcr2_conf mfcr2;
940 #endif
941 struct dahdi_params timing;
942 int is_sig_auto; /*!< Use channel signalling from DAHDI? */
943 /*! Continue configuration even if a channel is not there. */
944 int ignore_failed_channels;
945
946 /*!
947 * \brief The serial port to listen for SMDI data on
948 * \note Set from the "smdiport" string read in from chan_dahdi.conf
949 */
950 char smdi_port[SMDI_MAX_FILENAME_LEN];
951
952 /*!
953 * \brief Don't create channels below this number
954 * \note by default is 0 (no limit)
955 */
956 int wanted_channels_start;
957
958 /*!
959 * \brief Don't create channels above this number (infinity by default)
960 * \note by default is 0 (special value that means "no limit").
961 */
962 int wanted_channels_end;
963 };
964
965 /*! returns a new dahdi_chan_conf with default values (by-value) */
966 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
967 {
968 /* recall that if a field is not included here it is initialized
969 * to 0 or equivalent
970 */
971 struct dahdi_chan_conf conf = {
972 #ifdef HAVE_PRI
973 .pri.pri = {
974 .nsf = PRI_NSF_NONE,
975 .switchtype = PRI_SWITCH_NI2,
976 .dialplan = PRI_UNKNOWN + 1,
977 .localdialplan = PRI_NATIONAL_ISDN + 1,
978 .nodetype = PRI_CPE,
979 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
980
981 #if defined(HAVE_PRI_CCSS)
982 .cc_ptmp_recall_mode = 1,/* specificRecall */
983 .cc_qsig_signaling_link_req = 1,/* retain */
984 .cc_qsig_signaling_link_rsp = 1,/* retain */
985 #endif /* defined(HAVE_PRI_CCSS) */
986
987 .minunused = 2,
988 .idleext = "",
989 .idledial = "",
990 .internationalprefix = "",
991 .nationalprefix = "",
992 .localprefix = "",
993 .privateprefix = "",
994 .unknownprefix = "",
995 .colp_send = SIG_PRI_COLP_UPDATE,
996 .resetinterval = -1,
997 },
998 #endif
999 #if defined(HAVE_SS7)
1000 .ss7.ss7 = {
1001 .called_nai = SS7_NAI_NATIONAL,
1002 .calling_nai = SS7_NAI_NATIONAL,
1003 .internationalprefix = "",
1004 .nationalprefix = "",
1005 .subscriberprefix = "",
1006 .unknownprefix = "",
1007 .networkroutedprefix = ""
1008 },
1009 #endif /* defined(HAVE_SS7) */
1010 #ifdef HAVE_OPENR2
1011 .mfcr2 = {
1012 .variant = OR2_VAR_ITU,
1013 .mfback_timeout = -1,
1014 .metering_pulse_timeout = -1,
1015 .max_ani = 10,
1016 .max_dnis = 4,
1017 .get_ani_first = -1,
1018 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1019 .skip_category_request = -1,
1020 #endif
1021 .call_files = 0,
1022 .allow_collect_calls = 0,
1023 .charge_calls = 1,
1024 .accept_on_offer = 1,
1025 .forced_release = 0,
1026 .double_answer = 0,
1027 .immediate_accept = -1,
1028 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1029 .dtmf_dialing = -1,
1030 .dtmf_detection = -1,
1031 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1032 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1033 #endif
1034 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1035 .dtmf_end_timeout = -1,
1036 #endif
1037 .logdir = "",
1038 .r2proto_file = "",
1039 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1040 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1041 },
1042 #endif
1043 .chan = {
1044 .context = "default",
1045 .immediatering = 1,
1046 .cid_num = "",
1047 .cid_name = "",
1048 .cid_tag = "",
1049 .mohinterpret = "default",
1050 .mohsuggest = "",
1051 .parkinglot = "",
1052 .transfertobusy = 1,
1053 .dialmode = 0,
1054
1055 .ani_info_digits = 2,
1056 .ani_wink_time = 1000,
1057 .ani_timeout = 10000,
1058
1059 .cid_signalling = CID_SIG_BELL,
1060 .cid_start = CID_START_RING,
1061 .dahditrcallerid = 0,
1062 .use_callerid = 1,
1063 .sig = -1,
1064 .outsigmod = -1,
1065
1066 .cid_rxgain = +5.0,
1067
1068 .tonezone = -1,
1069
1070 .echocancel.head.tap_length = 1,
1071
1072 .busycount = 3,
1073
1074 .accountcode = "",
1075
1076 .mailbox = "",
1077
1078 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1079 .mwisend_fsk = 1,
1080 #endif
1081 .polarityonanswerdelay = 600,
1082
1083 .sendcalleridafter = DEFAULT_CIDRINGS,
1084
1085 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1086 .buf_no = numbufs,
1087 .usefaxbuffers = 0,
1088 .cc_params = ast_cc_config_params_init(),
1089 .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
1090 .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
1091 .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
1092 },
1093 .timing = {
1094 .prewinktime = -1,
1095 .preflashtime = -1,
1096 .winktime = -1,
1097 .flashtime = -1,
1098 .starttime = -1,
1099 .rxwinktime = -1,
1100 .rxflashtime = -1,
1101 .debouncetime = -1
1102 },
1103 .is_sig_auto = 1,
1104 .ignore_failed_channels = 1,
1105 .smdi_port = "/dev/ttyS0",
1106 };
1107
1108 return conf;
1109 }
1110
1111
1112 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
1113 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
1114 const char *data, int *cause);
1115 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1116 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1117 static int dahdi_sendtext(struct ast_channel *c, const char *text);
1118 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1119 static int dahdi_hangup(struct ast_channel *ast);
1120 static int dahdi_answer(struct ast_channel *ast);
1121 static struct ast_frame *dahdi_read(struct ast_channel *ast);
1122 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1123 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1124 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1125 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1126 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1127 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1128 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1129 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1130 static int dahdi_devicestate(const char *data);
1131 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1132
1133 static struct ast_channel_tech dahdi_tech = {
1134 .type = "DAHDI",
1135 .description = tdesc,
1136 .requester = dahdi_request,
1137 .send_digit_begin = dahdi_digit_begin,
1138 .send_digit_end = dahdi_digit_end,
1139 .send_text = dahdi_sendtext,
1140 .call = dahdi_call,
1141 .hangup = dahdi_hangup,
1142 .answer = dahdi_answer,
1143 .read = dahdi_read,
1144 .write = dahdi_write,
1145 .exception = dahdi_exception,
1146 .indicate = dahdi_indicate,
1147 .fixup = dahdi_fixup,
1148 .setoption = dahdi_setoption,
1149 .queryoption = dahdi_queryoption,
1150 .func_channel_read = dahdi_func_read,
1151 .func_channel_write = dahdi_func_write,
1152 .devicestate = dahdi_devicestate,
1153 .cc_callback = dahdi_cc_callback,
1154 };
1155
1156 #define GET_CHANNEL(p) ((p)->channel)
1157
1158 static enum analog_sigtype dahdisig_to_analogsig(int sig)
1159 {
1160 switch (sig) {
1161 case SIG_FXOLS:
1162 return ANALOG_SIG_FXOLS;
1163 case SIG_FXOGS:
1164 return ANALOG_SIG_FXOGS;
1165 case SIG_FXOKS:
1166 return ANALOG_SIG_FXOKS;
1167 case SIG_FXSLS:
1168 return ANALOG_SIG_FXSLS;
1169 case SIG_FXSGS:
1170 return ANALOG_SIG_FXSGS;
1171 case SIG_FXSKS:
1172 return ANALOG_SIG_FXSKS;
1173 case SIG_EMWINK:
1174 return ANALOG_SIG_EMWINK;
1175 case SIG_EM:
1176 return ANALOG_SIG_EM;
1177 case SIG_EM_E1:
1178 return ANALOG_SIG_EM_E1;
1179 case SIG_FEATD:
1180 return ANALOG_SIG_FEATD;
1181 case SIG_FEATDMF:
1182 return ANALOG_SIG_FEATDMF;
1183 case SIG_E911:
1184 return SIG_E911;
1185 case SIG_FGC_CAMA:
1186 return ANALOG_SIG_FGC_CAMA;
1187 case SIG_FGC_CAMAMF:
1188 return ANALOG_SIG_FGC_CAMAMF;
1189 case SIG_FEATB:
1190 return ANALOG_SIG_FEATB;
1191 case SIG_SFWINK:
1192 return ANALOG_SIG_SFWINK;
1193 case SIG_SF:
1194 return ANALOG_SIG_SF;
1195 case SIG_SF_FEATD:
1196 return ANALOG_SIG_SF_FEATD;
1197 case SIG_SF_FEATDMF:
1198 return ANALOG_SIG_SF_FEATDMF;
1199 case SIG_FEATDMF_TA:
1200 return ANALOG_SIG_FEATDMF_TA;
1201 case SIG_SF_FEATB:
1202 return ANALOG_SIG_FEATB;
1203 default:
1204 return -1;
1205 }
1206 }
1207
1208
1209 static int analog_tone_to_dahditone(enum analog_tone tone)
1210 {
1211 switch (tone) {
1212 case ANALOG_TONE_RINGTONE:
1213 return DAHDI_TONE_RINGTONE;
1214 case ANALOG_TONE_STUTTER:
1215 return DAHDI_TONE_STUTTER;
1216 case ANALOG_TONE_CONGESTION:
1217 return DAHDI_TONE_CONGESTION;
1218 case ANALOG_TONE_DIALTONE:
1219 return DAHDI_TONE_DIALTONE;
1220 case ANALOG_TONE_DIALRECALL:
1221 return DAHDI_TONE_DIALRECALL;
1222 case ANALOG_TONE_INFO:
1223 return DAHDI_TONE_INFO;
1224 default:
1225 return -1;
1226 }
1227 }
1228
1229 static int analogsub_to_dahdisub(enum analog_sub analogsub)
1230 {
1231 int index;
1232
1233 switch (analogsub) {
1234 case ANALOG_SUB_REAL:
1235 index = SUB_REAL;
1236 break;
1237 case ANALOG_SUB_CALLWAIT:
1238 index = SUB_CALLWAIT;
1239 break;
1240 case ANALOG_SUB_THREEWAY:
1241 index = SUB_THREEWAY;
1242 break;
1243 default:
1244 ast_log(LOG_ERROR, "Unidentified sub!\n");
1245 index = SUB_REAL;
1246 }
1247
1248 return index;
1249 }
1250
1251 /*!
1252 * \internal
1253 * \brief release all members on the doomed pris list
1254 * \since 13.0
1255 *
1256 * Called priodically by the monitor threads to release spans marked for
1257 * removal.
1258 */
1259 static void release_doomed_pris(void)
1260 {
1261 #ifdef HAVE_PRI
1262 struct doomed_pri *entry;
1263
1264 AST_LIST_LOCK(&doomed_pris);
1265 while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1266 /* The span destruction must be done with this lock not held */
1267 AST_LIST_UNLOCK(&doomed_pris);
1268 ast_debug(4, "Destroying span %d from doomed queue.\n",
1269 entry->pri->span);
1270 pri_destroy_span(entry->pri);
1271 ast_free(entry);
1272 AST_LIST_LOCK(&doomed_pris);
1273 }
1274 AST_LIST_UNLOCK(&doomed_pris);
1275 #endif
1276 }
1277
1278 #ifdef HAVE_PRI
1279 /*!
1280 * \brief Queue a span for destruction
1281 * \since 13.0
1282 *
1283 * \param pri the span to destroy
1284 *
1285 * Add a span to the list of spans to be destroyed later on
1286 * by the monitor thread. Allows destroying a span while holding its
1287 * lock.
1288 */
1289 static void pri_queue_for_destruction(struct sig_pri_span *pri)
1290 {
1291 struct doomed_pri *entry;
1292
1293 AST_LIST_LOCK(&doomed_pris);
1294 AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1295 if (entry->pri == pri) {
1296 AST_LIST_UNLOCK(&doomed_pris);
1297 return;
1298 }
1299 }
1300 entry = ast_calloc(sizeof(struct doomed_pri), 1);
1301 if (!entry) {
1302 /* Nothing useful to do here. Panic? */
1303 ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
1304 AST_LIST_UNLOCK(&doomed_pris);
1305 return;
1306 }
1307 entry->pri = pri;
1308 ast_debug(4, "Queue span %d for destruction.\n", pri->span);
1309 AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
1310 AST_LIST_UNLOCK(&doomed_pris);
1311 }
1312 #endif
1313
1314 /*!
1315 * \internal
1316 * \brief Send a dial string to DAHDI.
1317 * \since 12.0.0
1318 *
1319 * \param pvt DAHDI private pointer
1320 * \param operation DAHDI dial operation to do to string
1321 * \param dial_str Dial string to send
1322 *
1323 * \retval 0 on success.
1324 * \retval non-zero on error.
1325 */
1326 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
1327 {
1328 int res;
1329 int offset;
1330 const char *pos;
1331 struct dahdi_dialoperation zo = {
1332 .op = operation,
1333 };
1334
1335 /* Convert the W's to ww. */
1336 pos = dial_str;
1337 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1338 if (!*pos) {
1339 break;
1340 }
1341 if (*pos == 'W') {
1342 /* Convert 'W' to "ww" */
1343 ++pos;
1344 if (offset >= sizeof(zo.dialstr) - 3) {
1345 /* No room to expand */
1346 break;
1347 }
1348 zo.dialstr[offset] = 'w';
1349 ++offset;
1350 zo.dialstr[offset] = 'w';
1351 continue;
1352 }
1353 zo.dialstr[offset] = *pos++;
1354 }
1355 /* The zo initialization has already terminated the dialstr. */
1356
1357 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1358 pvt->channel, dial_str, zo.dialstr);
1359 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1360 if (res) {
1361 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1362 pvt->channel, dial_str, strerror(errno));
1363 }
1364
1365 return res;
1366 }
1367
1368 static enum analog_event dahdievent_to_analogevent(int event);
1369 static int bump_gains(struct dahdi_pvt *p);
1370 static int dahdi_setlinear(int dfd, int linear);
1371
1372 static int my_start_cid_detect(void *pvt, int cid_signalling)
1373 {
1374 struct dahdi_pvt *p = pvt;
1375 int index = SUB_REAL;
1376 p->cs = callerid_new(cid_signalling);
1377 if (!p->cs) {
1378 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1379 return -1;
1380 }
1381 bump_gains(p);
1382 dahdi_setlinear(p->subs[index].dfd, 0);
1383
1384 return 0;
1385 }
1386
1387 static int restore_gains(struct dahdi_pvt *p);
1388
1389 static int my_stop_cid_detect(void *pvt)
1390 {
1391 struct dahdi_pvt *p = pvt;
1392 int index = SUB_REAL;
1393
1394 if (p->cs) {
1395 callerid_free(p->cs);
1396 }
1397
1398 /* Restore linear mode after Caller*ID processing */
1399 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1400 restore_gains(p);
1401
1402 return 0;
1403 }
1404
1405 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
1406 {
1407 struct dahdi_pvt *p = pvt;
1408 struct analog_pvt *analog_p = p->sig_pvt;
1409 struct pollfd poller;
1410 char *name, *num;
1411 int index = SUB_REAL;
1412 int res;
1413 unsigned char buf[256];
1414 int flags;
1415
1416 poller.fd = p->subs[SUB_REAL].dfd;
1417 poller.events = POLLPRI | POLLIN;
1418 poller.revents = 0;
1419
1420 res = poll(&poller, 1, timeout);
1421
1422 if (poller.revents & POLLPRI) {
1423 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
1424 return 1;
1425 }
1426
1427 if (poller.revents & POLLIN) {
1428 /*** NOTES ***/
1429 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1430 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1431 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1432 * a failure and die, and returning 2 means no event was received. */
1433 res = read(p->subs[index].dfd, buf, sizeof(buf));
1434 if (res < 0) {
1435 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1436 return -1;
1437 }
1438
1439 if (analog_p->ringt > 0) {
1440 if (!(--analog_p->ringt)) {
1441 /* only return if we timeout from a ring event */
1442 return -1;
1443 }
1444 }
1445
1446 if (p->cid_signalling == CID_SIG_V23_JP) {
1447 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1448 } else {
1449 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1450 }
1451 if (res < 0) {
1452 /*
1453 * The previous diagnostic message output likely
1454 * explains why it failed.
1455 */
1456 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1457 return -1;
1458 }
1459
1460 if (res == 1) {
1461 callerid_get(p->cs, &name, &num, &flags);
1462 if (name)
1463 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
1464 if (num)
1465 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1466
1467 if (flags & (CID_PRIVATE_NUMBER | CID_UNKNOWN_NUMBER)) {
1468 /* If we got a presentation, we must set it on the channel */
1469 struct ast_channel *chan = analog_p->ss_astchan;
1470 struct ast_party_caller caller;
1471
1472 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1473 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1474 AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED : AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED;
1475 ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1476 ast_party_caller_free(&caller);
1477 }
1478
1479 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
1480 return 0;
1481 }
1482 }
1483
1484 *ev = ANALOG_EVENT_NONE;
1485 return 2;
1486 }
1487
1488 static const char *event2str(int event);
1489
1490 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
1491 {
1492 unsigned char buf[256];
1493 int distMatches;
1494 int curRingData[RING_PATTERNS];
1495 int receivedRingT;
1496 int counter1;
1497 int counter;
1498 int i;
1499 int res;
1500 int checkaftercid = 0;
1501 const char *matched_context;
1502 struct dahdi_pvt *p = pvt;
1503 struct analog_pvt *analog_p = p->sig_pvt;
1504
1505 if (ringdata == NULL) {
1506 ringdata = curRingData;
1507 } else {
1508 checkaftercid = 1;
1509 }
1510
1511 /* We must have a ring by now so lets try to listen for distinctive ringing */
1512 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1513 /* Clear the current ring data array so we don't have old data in it. */
1514 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1515 ringdata[receivedRingT] = 0;
1516 receivedRingT = 0;
1517
1518 if (checkaftercid && distinctiveringaftercid) {
1519 ast_verb(3, "Detecting post-CID distinctive ring\n");
1520 }
1521
1522 for (;;) {
1523 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1524 res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1525 if (res) {
1526 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1527 ast_hangup(chan);
1528 return 1;
1529 }
1530 if (i & DAHDI_IOMUX_SIGEVENT) {
1531 res = dahdi_get_event(p->subs[idx].dfd);
1532 ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1533 if (res == DAHDI_EVENT_NOALARM) {
1534 p->inalarm = 0;
1535 analog_p->inalarm = 0;
1536 } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1537 /* Let us detect distinctive ring */
1538 ringdata[receivedRingT] = analog_p->ringt;
1539
1540 if (analog_p->ringt < analog_p->ringt_base / 2) {
1541 break;
1542 }
1543 /* Increment the ringT counter so we can match it against
1544 values in chan_dahdi.conf for distinctive ring */
1545 if (++receivedRingT == RING_PATTERNS) {
1546 break;
1547 }
1548 }
1549 } else if (i & DAHDI_IOMUX_READ) {
1550 res = read(p->subs[idx].dfd, buf, sizeof(buf));
1551 if (res < 0) {
1552 if (errno != ELAST) {
1553 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1554 ast_hangup(chan);
1555 return 1;
1556 }
1557 break;
1558 }
1559 if (analog_p->ringt > 0) {
1560 if (!(--analog_p->ringt)) {
1561 break;
1562 }
1563 }
1564 }
1565 }
1566 }
1567
1568 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1569 ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1570 matched_context = p->defcontext;
1571 for (counter = 0; counter < 3; counter++) {
1572 int range = p->drings.ringnum[counter].range;
1573
1574 distMatches = 0;
1575 ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1576 p->drings.ringnum[counter].ring[0],
1577 p->drings.ringnum[counter].ring[1],
1578 p->drings.ringnum[counter].ring[2],
1579 range);
1580 for (counter1 = 0; counter1 < 3; counter1++) {
1581 int ring = p->drings.ringnum[counter].ring[counter1];
1582
1583 if (ring == -1) {
1584 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1585 ringdata[counter1]);
1586 distMatches++;
1587 } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1588 ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1589 ringdata[counter1], ring - range, ring + range);
1590 distMatches++;
1591 } else {
1592 /* The current dring pattern cannot match. */
1593 break;
1594 }
1595 }
1596
1597 if (distMatches == 3) {
1598 /* The ring matches, set the context to whatever is for distinctive ring.. */
1599 matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1600 ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1601 break;
1602 }
1603 }
1604
1605 /* Set selected distinctive ring context if not already set. */
1606 if (strcmp(p->context, matched_context) != 0) {
1607 ast_copy_string(p->context, matched_context, sizeof(p->context));
1608 ast_channel_context_set(chan, matched_context);
1609 }
1610
1611 return 0;
1612 }
1613
1614 static int my_stop_callwait(void *pvt)
1615 {
1616 struct dahdi_pvt *p = pvt;
1617 p->callwaitingrepeat = 0;
1618 p->cidcwexpire = 0;
1619 p->cid_suppress_expire = 0;
1620
1621 return 0;
1622 }
1623
1624 static int send_callerid(struct dahdi_pvt *p);
1625 static int save_conference(struct dahdi_pvt *p);
1626 static int restore_conference(struct dahdi_pvt *p);
1627
1628 static int my_callwait(void *pvt)
1629 {
1630 struct dahdi_pvt *p = pvt;
1631
1632 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1633 if (p->cidspill) {
1634 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1635 ast_free(p->cidspill);
1636 }
1637
1638 /*
1639 * SAS: Subscriber Alert Signal, 440Hz for 300ms
1640 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1641 */
1642 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1643 return -1;
1644 save_conference(p);
1645 /* Silence */
1646 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1647 if (!p->callwaitrings && p->callwaitingcallerid) {
1648 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1649 p->callwaitcas = 1;
1650 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1651 } else {
1652 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1653 p->callwaitcas = 0;
1654 p->cidlen = 2400 + READ_SIZE * 4;
1655 }
1656 p->cidpos = 0;
1657 send_callerid(p);
1658
1659 return 0;
1660 }
1661
1662 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
1663 {
1664 struct dahdi_pvt *p = pvt;
1665 struct analog_pvt *analog_p = p->sig_pvt;
1666
1667 ast_debug(2, "Starting cid spill\n");
1668
1669 if (p->cidspill) {
1670 ast_log(LOG_WARNING, "cidspill already exists??\n");
1671 ast_free(p->cidspill);
1672 }
1673
1674 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1675 int pres = ast_party_id_presentation(&caller->id);
1676 if (cwcid == 0) {
1677 /* Some CPE support additional parameters for on-hook Caller*ID,
1678 * such as redirecting reason and call qualifier, so send those
1679 * if available.
1680 * I don't know of any CPE that supports this for Call Waiting (unfortunately),
1681 * so don't send those for call waiting as that will just lengthen the CID spill
1682 * for no good reason.
1683 */
1684 p->cidlen = ast_callerid_full_generate(p->cidspill,
1685 caller->id.name.str,
1686 caller->id.number.str,
1687 NULL,
1688 analog_p->redirecting_reason,
1689 pres,
1690 analog_p->call_qualifier,
1691 CID_TYPE_MDMF,
1692 AST_LAW(p));
1693 } else {
1694 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1695 caller->id.name.str, caller->id.number.str);
1696 p->callwaitcas = 0;
1697 p->cidcwexpire = 0;
1698 p->cidlen = ast_callerid_callwaiting_full_generate(p->cidspill,
1699 caller->id.name.str,
1700 caller->id.number.str,
1701 NULL,
1702 -1,
1703 pres,
1704 0,
1705 AST_LAW(p));
1706 p->cidlen += READ_SIZE * 4;
1707 }
1708 p->cidpos = 0;
1709 p->cid_suppress_expire = 0;
1710 send_callerid(p);
1711 }
1712 return 0;
1713 }
1714
1715 static int my_dsp_reset_and_flush_digits(void *pvt)
1716 {
1717 struct dahdi_pvt *p = pvt;
1718 if (p->dsp)
1719 ast_dsp_digitreset(p->dsp);
1720
1721 return 0;
1722 }
1723
1724 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
1725 {
1726 struct dahdi_pvt *p = pvt;
1727
1728 if (p->channel == CHAN_PSEUDO)
1729 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1730
1731 if (mode == ANALOG_DIGITMODE_DTMF) {
1732 /* If we do hardware dtmf, no need for a DSP */
1733 if (p->hardwaredtmf) {
1734 if (p->dsp) {
1735 ast_dsp_free(p->dsp);
1736 p->dsp = NULL;
1737 }
1738 return 0;
1739 }
1740
1741 if (!p->dsp) {
1742 p->dsp = ast_dsp_new();
1743 if (!p->dsp) {
1744 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1745 return -1;
1746 }
1747 }
1748
1749 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
1750 } else if (mode == ANALOG_DIGITMODE_MF) {
1751 if (!p->dsp) {
1752 p->dsp = ast_dsp_new();
1753 if (!p->dsp) {
1754 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1755 return -1;
1756 }
1757 }
1758 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
1759 }
1760 return 0;
1761 }
1762
1763 static int dahdi_wink(struct dahdi_pvt *p, int index);
1764
1765 static int my_wink(void *pvt, enum analog_sub sub)
1766 {
1767 struct dahdi_pvt *p = pvt;
1768 int index = analogsub_to_dahdisub(sub);
1769 if (index != SUB_REAL) {
1770 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1771 }
1772 return dahdi_wink(p, index);
1773 }
1774
1775 static void wakeup_sub(struct dahdi_pvt *p, int a);
1776
1777 static int reset_conf(struct dahdi_pvt *p);
1778
1779 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1780
1781 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
1782 {
1783 struct ast_frame *f = *dest;
1784 struct dahdi_pvt *p = pvt;
1785 int idx = analogsub_to_dahdisub(analog_index);
1786
1787 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1788 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1789 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1790
1791 if (f->subclass.integer == 'f') {
1792 if (f->frametype == AST_FRAME_DTMF_END) {
1793 /* Fax tone -- Handle and return NULL */
1794 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1795 /* If faxbuffers are configured, use them for the fax transmission */
1796 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1797 struct dahdi_bufferinfo bi = {
1798 .txbufpolicy = p->faxbuf_policy,
1799 .bufsize = p->bufsize,
1800 .numbufs = p->faxbuf_no
1801 };
1802 int res;
1803
1804 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1805 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1806 } else {
1807 p->bufferoverrideinuse = 1;
1808 }
1809 }
1810 p->faxhandled = 1;
1811 if (p->dsp) {
1812 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1813 ast_dsp_set_features(p->dsp, p->dsp_features);
1814 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1815 }
1816 if (strcmp(ast_channel_exten(ast), "fax")) {
1817 const char *target_context = ast_channel_context(ast);
1818
1819 /*
1820 * We need to unlock 'ast' here because ast_exists_extension has the
1821 * potential to start autoservice on the channel. Such action is prone
1822 * to deadlock if the channel is locked.
1823 *
1824 * ast_async_goto() has its own restriction on not holding the
1825 * channel lock.
1826 */
1827 ast_mutex_unlock(&p->lock);
1828 ast_channel_unlock(ast);
1829 if (ast_exists_extension(ast, target_context, "fax", 1,
1830 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1831 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1832 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1833 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1834 if (ast_async_goto(ast, target_context, "fax", 1))
1835 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1836 } else {
1837 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1838 }
1839 ast_channel_lock(ast);
1840 ast_mutex_lock(&p->lock);
1841 } else {
1842 ast_debug(1, "Already in a fax extension, not redirecting\n");
1843 }
1844 } else {
1845 ast_debug(1, "Fax already handled\n");
1846 }
1847 dahdi_confmute(p, 0);
1848 }
1849 p->subs[idx].f.frametype = AST_FRAME_NULL;
1850 p->subs[idx].f.subclass.integer = 0;
1851 *dest = &p->subs[idx].f;
1852 }
1853 }
1854
1855 static void my_lock_private(void *pvt)
1856 {
1857 struct dahdi_pvt *p = pvt;
1858 ast_mutex_lock(&p->lock);
1859 }
1860
1861 static void my_unlock_private(void *pvt)
1862 {
1863 struct dahdi_pvt *p = pvt;
1864 ast_mutex_unlock(&p->lock);
1865 }
1866
1867 static void my_deadlock_avoidance_private(void *pvt)
1868 {
1869 struct dahdi_pvt *p = pvt;
1870
1871 DEADLOCK_AVOIDANCE(&p->lock);
1872 }
1873
1874 static struct ast_manager_event_blob *dahdichannel_to_ami(struct stasis_message *msg)
1875 {
1876 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1877 struct ast_channel_blob *obj = stasis_message_data(msg);
1878 struct ast_json *group, *span, *channel;
1879
1880 channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1881 if (!channel_string) {
1882 return NULL;
1883 }
1884
1885 group = ast_json_object_get(obj->blob, "group");
1886 span = ast_json_object_get(obj->blob, "span");
1887 channel = ast_json_object_get(obj->blob, "channel");
1888
1889 return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1890 "%s"
1891 "DAHDIGroup: %llu\r\n"
1892 "DAHDISpan: %u\r\n"
1893 "DAHDIChannel: %s\r\n",
1894 ast_str_buffer(channel_string),
1895 (ast_group_t)ast_json_integer_get(group),
1896 (unsigned int)ast_json_integer_get(span),
1897 ast_json_string_get(channel));
1898 }
1899
1900 STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,
1901 .to_ami = dahdichannel_to_ami,
1902 );
1903
1904 /*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1905 static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
1906 {
1907 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1908
1909 ast_assert(dahdi_channel != NULL);
1910
1911 blob = ast_json_pack("{s: I, s: i, s: s}",
1912 "group", (ast_json_int_t)group,
1913 "span", span,
1914 "channel", dahdi_channel);
1915 if (!blob) {
1916 return;
1917 }
1918
1919 ast_channel_lock(chan);
1920 ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1921 ast_channel_unlock(chan);
1922 }
1923
1924 /*!
1925 * \internal
1926 * \brief Post an AMI DAHDI channel association event.
1927 * \since 1.8
1928 *
1929 * \param p DAHDI private pointer
1930 * \param chan Channel associated with the private pointer
1931 */
1932 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
1933 {
1934 char ch_name[23];
1935
1936 if (p->channel < CHAN_PSEUDO) {
1937 /* No B channel */
1938 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1939 } else if (p->channel == CHAN_PSEUDO) {
1940 /* Pseudo channel */
1941 strcpy(ch_name, "pseudo");
1942 } else {
1943 /* Real channel */
1944 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1945 }
1946 publish_dahdichannel(chan, p->group, p->span, ch_name);
1947 }
1948
1949 #ifdef HAVE_PRI
1950 /*!
1951 * \internal
1952 * \brief Post an AMI DAHDI channel association event.
1953 * \since 1.8
1954 *
1955 * \param pvt DAHDI private pointer
1956 * \param chan Channel associated with the private pointer
1957 */
1958 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
1959 {
1960 struct dahdi_pvt *p = pvt;
1961
1962 dahdi_ami_channel_event(p, chan);
1963 }
1964 #endif
1965
1966 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
1967 * returns the last value of the linear setting
1968 */
1969 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
1970 {
1971 struct dahdi_pvt *p = pvt;
1972 int oldval;
1973 int idx = analogsub_to_dahdisub(sub);
1974
1975 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
1976 oldval = p->subs[idx].linear;
1977 p->subs[idx].linear = linear_mode ? 1 : 0;
1978 return oldval;
1979 }
1980
1981 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
1982 {
1983 struct dahdi_pvt *p = pvt;
1984 int idx = analogsub_to_dahdisub(sub);
1985
1986 p->subs[idx].inthreeway = inthreeway;
1987 }
1988
1989 static int get_alarms(struct dahdi_pvt *p);
1990 static void handle_alarms(struct dahdi_pvt *p, int alms);
1991 static void my_get_and_handle_alarms(void *pvt)
1992 {
1993 int res;
1994 struct dahdi_pvt *p = pvt;
1995
1996 res = get_alarms(p);
1997 handle_alarms(p, res);
1998 }
1999
2000 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
2001 {
2002 RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(chan), ast_channel_cleanup);
2003
2004 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
2005 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2006
2007 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
2008 return p->sig_pvt;
2009 }
2010 }
2011 return NULL;
2012 }
2013
2014 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
2015 {
2016 struct dahdi_pvt *p = pvt;
2017 int dahdi_sub = analogsub_to_dahdisub(sub);
2018 return p->subs[dahdi_sub].dfd;
2019 }
2020
2021 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
2022 {
2023 struct dahdi_pvt *p = pvt;
2024
2025 /* Choose proper cadence */
2026 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2027 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2028 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
2029 *cid_rings = cidrings[p->distinctivering - 1];
2030 } else {
2031 if (p->distinctivering > 0) {
2032 ast_log(LOG_WARNING, "Cadence %d is not defined, falling back to default ring cadence\n", p->distinctivering);
2033 }
2034 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2035 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2036 *cid_rings = p->sendcalleridafter;
2037 }
2038 }
2039
2040 static void my_set_alarm(void *pvt, int in_alarm)
2041 {
2042 struct dahdi_pvt *p = pvt;
2043
2044 p->inalarm = in_alarm;
2045 }
2046
2047 static void my_set_dialing(void *pvt, int is_dialing)
2048 {
2049 struct dahdi_pvt *p = pvt;
2050
2051 p->dialing = is_dialing;
2052 }
2053
2054 static void my_set_outgoing(void *pvt, int is_outgoing)
2055 {
2056 struct dahdi_pvt *p = pvt;
2057
2058 p->outgoing = is_outgoing;
2059 }
2060
2061 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2062 static void my_set_digital(void *pvt, int is_digital)
2063 {
2064 struct dahdi_pvt *p = pvt;
2065
2066 p->digital = is_digital;
2067 }
2068 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2069
2070 #if defined(HAVE_SS7)
2071 static void my_set_inservice(void *pvt, int is_inservice)
2072 {
2073 struct dahdi_pvt *p = pvt;
2074
2075 p->inservice = is_inservice;
2076 }
2077 #endif /* defined(HAVE_SS7) */
2078
2079 #if defined(HAVE_SS7)
2080 static void my_set_locallyblocked(void *pvt, int is_blocked)
2081 {
2082 struct dahdi_pvt *p = pvt;
2083
2084 p->locallyblocked = is_blocked;
2085 }
2086 #endif /* defined(HAVE_SS7) */
2087
2088 #if defined(HAVE_SS7)
2089 static void my_set_remotelyblocked(void *pvt, int is_blocked)
2090 {
2091 struct dahdi_pvt *p = pvt;
2092
2093 p->remotelyblocked = is_blocked;
2094 }
2095 #endif /* defined(HAVE_SS7) */
2096
2097 static void my_set_ringtimeout(void *pvt, int ringt)
2098 {
2099 struct dahdi_pvt *p = pvt;
2100 p->ringt = ringt;
2101 }
2102
2103 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
2104 {
2105 struct dahdi_pvt *p = pvt;
2106
2107 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
2108 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
2109 gettimeofday(&p->waitingfordt, NULL);
2110 ast_setstate(ast, AST_STATE_OFFHOOK);
2111 }
2112 }
2113
2114 static int my_check_waitingfordt(void *pvt)
2115 {
2116 struct dahdi_pvt *p = pvt;
2117
2118 if (p->waitingfordt.tv_sec) {
2119 return 1;
2120 }
2121
2122 return 0;
2123 }
2124
2125 static void my_set_confirmanswer(void *pvt, int flag)
2126 {
2127 struct dahdi_pvt *p = pvt;
2128 p->confirmanswer = flag;
2129 }
2130
2131 static int my_check_confirmanswer(void *pvt)
2132 {
2133 struct dahdi_pvt *p = pvt;
2134 if (p->confirmanswer) {
2135 return 1;
2136 }
2137
2138 return 0;
2139 }
2140
2141 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2142 {
2143 struct dahdi_pvt *p = pvt;
2144
2145 p->callwaiting = callwaiting_enable;
2146 }
2147
2148 static void my_cancel_cidspill(void *pvt)
2149 {
2150 struct dahdi_pvt *p = pvt;
2151
2152 ast_free(p->cidspill);
2153 p->cidspill = NULL;
2154 restore_conference(p);
2155 }
2156
2157 static int my_confmute(void *pvt, int mute)
2158 {
2159 struct dahdi_pvt *p = pvt;
2160 return dahdi_confmute(p, mute);
2161 }
2162
2163 static void my_set_pulsedial(void *pvt, int flag)
2164 {
2165 struct dahdi_pvt *p = pvt;
2166 p->pulsedial = flag;
2167 }
2168
2169 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
2170 {
2171 struct dahdi_pvt *p = pvt;
2172
2173 p->owner = new_owner;
2174 }
2175
2176 static const char *my_get_orig_dialstring(void *pvt)
2177 {
2178 struct dahdi_pvt *p = pvt;
2179
2180 return p->dialstring;
2181 }
2182
2183 static void my_increase_ss_count(void)
2184 {
2185 ast_mutex_lock(&ss_thread_lock);
2186 ss_thread_count++;
2187 ast_mutex_unlock(&ss_thread_lock);
2188 }
2189
2190 static void my_decrease_ss_count(void)
2191 {
2192 ast_mutex_lock(&ss_thread_lock);
2193 ss_thread_count--;
2194 ast_cond_signal(&ss_thread_complete);
2195 ast_mutex_unlock(&ss_thread_lock);
2196 }
2197
2198 static void my_all_subchannels_hungup(void *pvt)
2199 {
2200 struct dahdi_pvt *p = pvt;
2201 int res, law;
2202
2203 p->faxhandled = 0;
2204 p->didtdd = 0;
2205
2206 if (p->dsp) {
2207 ast_dsp_free(p->dsp);
2208 p->dsp = NULL;
2209 }
2210
2211 p->law = p->law_default;
2212 law = p->law_default;
2213 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2214 if (res < 0)
2215 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2216
2217 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
2218
2219 #if 1
2220 {
2221 int i;
2222 p->owner = NULL;
2223 /* Cleanup owners here */
2224 for (i = 0; i < 3; i++) {
2225 p->subs[i].owner = NULL;
2226 }
2227 }
2228 #endif
2229
2230 reset_conf(p);
2231 if (num_restart_pending == 0) {
2232 restart_monitor();
2233 }
2234 }
2235
2236 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2237
2238 static int my_conf_del(void *pvt, enum analog_sub sub)
2239 {
2240 struct dahdi_pvt *p = pvt;
2241 int x = analogsub_to_dahdisub(sub);
2242
2243 return conf_del(p, &p->subs[x], x);
2244 }
2245
2246 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2247
2248 static int my_conf_add(void *pvt, enum analog_sub sub)
2249 {
2250 struct dahdi_pvt *p = pvt;
2251 int x = analogsub_to_dahdisub(sub);
2252
2253 return conf_add(p, &p->subs[x], x, 0);
2254 }
2255
2256 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2257
2258 static int my_complete_conference_update(void *pvt, int needconference)
2259 {
2260 struct dahdi_pvt *p = pvt;
2261 int needconf = needconference;
2262 int x;
2263 int useslavenative;
2264 struct dahdi_pvt *slave = NULL;
2265
2266 useslavenative = isslavenative(p, &slave);
2267
2268 /* If we have a slave, add him to our conference now. or DAX
2269 if this is slave native */
2270 for (x = 0; x < MAX_SLAVES; x++) {
2271 if (p->slaves[x]) {
2272 if (useslavenative)
2273 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2274 else {
2275 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2276 needconf++;
2277 }
2278 }
2279 }
2280 /* If we're supposed to be in there, do so now */
2281 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2282 if (useslavenative)
2283 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2284 else {
2285 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2286 needconf++;
2287 }
2288 }
2289 /* If we have a master, add ourselves to his conference */
2290 if (p->master) {
2291 if (isslavenative(p->master, NULL)) {
2292 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
2293 } else {
2294 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2295 }
2296 }
2297 if (!needconf) {
2298 /* Nobody is left (or should be left) in our conference.
2299 Kill it. */
2300 p->confno = -1;
2301 }
2302
2303 return 0;
2304 }
2305
2306 static int check_for_conference(struct dahdi_pvt *p);
2307
2308 static int my_check_for_conference(void *pvt)
2309 {
2310 struct dahdi_pvt *p = pvt;
2311 return check_for_conference(p);
2312 }
2313
2314 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)
2315 {
2316 struct dahdi_pvt *p = pvt;
2317 int da, db;
2318 int tchan;
2319 int tinthreeway;
2320
2321 da = analogsub_to_dahdisub(a);
2322 db = analogsub_to_dahdisub(b);
2323
2324 tchan = p->subs[da].chan;
2325 p->subs[da].chan = p->subs[db].chan;
2326 p->subs[db].chan = tchan;
2327
2328 tinthreeway = p->subs[da].inthreeway;
2329 p->subs[da].inthreeway = p->subs[db].inthreeway;
2330 p->subs[db].inthreeway = tinthreeway;
2331
2332 p->subs[da].owner = ast_a;
2333 p->subs[db].owner = ast_b;
2334
2335 if (ast_a)
2336 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2337 if (ast_b)
2338 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2339
2340 wakeup_sub(p, a);
2341 wakeup_sub(p, b);
2342
2343 return;
2344 }
2345
2346 /*!
2347 * \internal
2348 * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
2349 * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
2350 *
2351 * \param callid_created value returned from ast_callid_threadstorage_auto()
2352 * \param i, state, startpbx, idx, law, assignedids, requestor, callid
2353 */
2354 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);
2355
2356 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);
2357
2358 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
2359 {
2360 ast_callid callid = 0;
2361 int callid_created = ast_callid_threadstorage_auto(&callid);
2362 struct dahdi_pvt *p = pvt;
2363 int dsub = analogsub_to_dahdisub(sub);
2364
2365 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2366 }
2367
2368 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2369 static int dahdi_setlaw(int dfd, int law)
2370 {
2371 int res;
2372 res = ioctl(dfd, DAHDI_SETLAW, &law);
2373 if (res)
2374 return res;
2375 return 0;
2376 }
2377 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2378
2379 #if defined(HAVE_PRI)
2380 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
2381 enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
2382 const struct ast_channel *requestor)
2383 {
2384 struct dahdi_pvt *p = pvt;
2385 int audio;
2386 int newlaw = -1;
2387 ast_callid callid = 0;
2388 int callid_created = ast_callid_threadstorage_auto(&callid);
2389
2390 switch (p->sig) {
2391 case SIG_PRI_LIB_HANDLE_CASES:
2392 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2393 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
2394 break;
2395 }
2396 /* Fall through */
2397 default:
2398 /* Set to audio mode at this point */
2399 audio = 1;
2400 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2401 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
2402 p->channel, audio, strerror(errno));
2403 }
2404 break;
2405 }
2406
2407 if (law != SIG_PRI_DEFLAW) {
2408 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2409 }
2410
2411 ast_copy_string(p->exten, exten, sizeof(p->exten));
2412
2413 switch (law) {
2414 case SIG_PRI_DEFLAW:
2415 newlaw = 0;
2416 break;
2417 case SIG_PRI_ALAW:
2418 newlaw = DAHDI_LAW_ALAW;
2419 break;
2420 case SIG_PRI_ULAW:
2421 newlaw = DAHDI_LAW_MULAW;
2422 break;
2423 }
2424
2425 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2426 }
2427 #endif /* defined(HAVE_PRI) */
2428
2429 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
2430
2431 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2432 /*!
2433 * \internal
2434 * \brief Open the PRI/SS7 channel media path.
2435 * \since 1.8
2436 *
2437 * \param p Channel private control structure.
2438 */
2439 static void my_pri_ss7_open_media(void *p)
2440 {
2441 struct dahdi_pvt *pvt = p;
2442 int res;
2443 int dfd;
2444 int set_val;
2445
2446 dfd = pvt->subs[SUB_REAL].dfd;
2447
2448 /* Open the media path. */
2449 set_val = 1;
2450 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2451 if (res < 0) {
2452 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
2453 pvt->channel, strerror(errno));
2454 }
2455
2456 /* Set correct companding law for this call. */
2457 res = dahdi_setlaw(dfd, pvt->law);
2458 if (res < 0) {
2459 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
2460 }
2461
2462 /* Set correct gain for this call. */
2463 if (pvt->digital) {
2464 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
2465 } else {
2466 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
2467 pvt->law);
2468 }
2469 if (res < 0) {
2470 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
2471 }
2472
2473 if (pvt->dsp_features && pvt->dsp) {
2474 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
2475 }
2476 }
2477 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2478
2479 #if defined(HAVE_PRI)
2480 /*!
2481 * \internal
2482 * \brief Ask DAHDI to dial the given dial string.
2483 * \since 1.8.11
2484 *
2485 * \param p Channel private control structure.
2486 * \param dial_string String to pass to DAHDI to dial.
2487 *
2488 * \note The channel private lock needs to be held when calling.
2489 */
2490 static void my_pri_dial_digits(void *p, const char *dial_string)
2491 {
2492 char dial_str[DAHDI_MAX_DTMF_BUF];
2493 struct dahdi_pvt *pvt = p;
2494 int res;
2495
2496 snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
2497 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2498 if (!res) {
2499 pvt->dialing = 1;
2500 }
2501 }
2502 #endif /* defined(HAVE_PRI) */
2503
2504 static int unalloc_sub(struct dahdi_pvt *p, int x);
2505
2506 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
2507 {
2508 struct dahdi_pvt *p = pvt;
2509
2510 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2511 }
2512
2513 static int alloc_sub(struct dahdi_pvt *p, int x);
2514
2515 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
2516 {
2517 struct dahdi_pvt *p = pvt;
2518
2519 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2520 }
2521
2522 static int has_voicemail(struct dahdi_pvt *p);
2523
2524 static int my_has_voicemail(void *pvt)
2525 {
2526 struct dahdi_pvt *p = pvt;
2527
2528 return has_voicemail(p);
2529 }
2530
2531 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
2532 {
2533 struct dahdi_pvt *p = pvt;
2534 int index;
2535
2536 index = analogsub_to_dahdisub(sub);
2537
2538 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2539 }
2540
2541 static enum analog_event dahdievent_to_analogevent(int event)
2542 {
2543 enum analog_event res;
2544
2545 switch (event) {
2546 case DAHDI_EVENT_ONHOOK:
2547 res = ANALOG_EVENT_ONHOOK;
2548 break;
2549 case DAHDI_EVENT_RINGOFFHOOK:
2550 res = ANALOG_EVENT_RINGOFFHOOK;
2551 break;
2552 case DAHDI_EVENT_WINKFLASH:
2553 res = ANALOG_EVENT_WINKFLASH;
2554 break;
2555 case DAHDI_EVENT_ALARM:
2556 res = ANALOG_EVENT_ALARM;
2557 break;
2558 case DAHDI_EVENT_NOALARM:
2559 res = ANALOG_EVENT_NOALARM;
2560 break;
2561 case DAHDI_EVENT_DIALCOMPLETE:
2562 res = ANALOG_EVENT_DIALCOMPLETE;
2563 break;
2564 case DAHDI_EVENT_RINGERON:
2565 res = ANALOG_EVENT_RINGERON;
2566 break;
2567 case DAHDI_EVENT_RINGEROFF:
2568 res = ANALOG_EVENT_RINGEROFF;
2569 break;
2570 case DAHDI_EVENT_HOOKCOMPLETE:
2571 res = ANALOG_EVENT_HOOKCOMPLETE;
2572 break;
2573 case DAHDI_EVENT_PULSE_START:
2574 res = ANALOG_EVENT_PULSE_START;
2575 break;
2576 case DAHDI_EVENT_POLARITY:
2577 res = ANALOG_EVENT_POLARITY;
2578 break;
2579 case DAHDI_EVENT_RINGBEGIN:
2580 res = ANALOG_EVENT_RINGBEGIN;
2581 break;
2582 case DAHDI_EVENT_EC_DISABLED:
2583 res = ANALOG_EVENT_EC_DISABLED;
2584 break;
2585 case DAHDI_EVENT_REMOVED:
2586 res = ANALOG_EVENT_REMOVED;
2587 break;
2588 case DAHDI_EVENT_NEONMWI_ACTIVE:
2589 res = ANALOG_EVENT_NEONMWI_ACTIVE;
2590 break;
2591 case DAHDI_EVENT_NEONMWI_INACTIVE:
2592 res = ANALOG_EVENT_NEONMWI_INACTIVE;
2593 break;
2594 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2595 case DAHDI_EVENT_TX_CED_DETECTED:
2596 res = ANALOG_EVENT_TX_CED_DETECTED;
2597 break;
2598 case DAHDI_EVENT_RX_CED_DETECTED:
2599 res = ANALOG_EVENT_RX_CED_DETECTED;
2600 break;
2601 case DAHDI_EVENT_EC_NLP_DISABLED:
2602 res = ANALOG_EVENT_EC_NLP_DISABLED;
2603 break;
2604 case DAHDI_EVENT_EC_NLP_ENABLED:
2605 res = ANALOG_EVENT_EC_NLP_ENABLED;
2606 break;
2607 #endif
2608 case DAHDI_EVENT_PULSEDIGIT:
2609 res = ANALOG_EVENT_PULSEDIGIT;
2610 break;
2611 case DAHDI_EVENT_DTMFDOWN:
2612 res = ANALOG_EVENT_DTMFDOWN;
2613 break;
2614 case DAHDI_EVENT_DTMFUP:
2615 res = ANALOG_EVENT_DTMFUP;
2616 break;
2617 default:
2618 switch(event & 0xFFFF0000) {
2619 case DAHDI_EVENT_PULSEDIGIT:
2620 case DAHDI_EVENT_DTMFDOWN:
2621 case DAHDI_EVENT_DTMFUP:
2622 /* The event includes a digit number in the low word.
2623 * Converting it to a 'enum analog_event' would remove
2624 * that information. Thus it is returned as-is.
2625 */
2626 return event;
2627 }
2628
2629 res = ANALOG_EVENT_ERROR;
2630 break;
2631 }
2632
2633 return res;
2634 }
2635
2636 static inline int dahdi_wait_event(int fd);
2637
2638 static int my_wait_event(void *pvt)
2639 {
2640 struct dahdi_pvt *p = pvt;
2641
2642 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2643 }
2644
2645 static int my_get_event(void *pvt)
2646 {
2647 struct dahdi_pvt *p = pvt;
2648 int res;
2649
2650 if (p->fake_event) {
2651 res = p->fake_event;
2652 p->fake_event = 0;
2653 } else
2654 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2655
2656 return dahdievent_to_analogevent(res);
2657 }
2658
2659 static int my_is_off_hook(void *pvt)
2660 {
2661 struct dahdi_pvt *p = pvt;
2662 int res;
2663 struct dahdi_params par;
2664
2665 memset(&par, 0, sizeof(par));
2666
2667 if (p->subs[SUB_REAL].dfd > -1)
2668 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2669 else {
2670 /* Assume not off hook on CVRS */
2671 res = 0;
2672 par.rxisoffhook = 0;
2673 }
2674 if (res) {
2675 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2676 }
2677
2678 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2679 /* When "onhook" that means no battery on the line, and thus
2680 it is out of service..., if it's on a TDM card... If it's a channel
2681 bank, there is no telling... */
2682 return (par.rxbits > -1) || par.rxisoffhook;
2683 }
2684
2685 return par.rxisoffhook;
2686 }
2687
2688 static int my_set_echocanceller(void *pvt, int enable)
2689 {
2690 struct dahdi_pvt *p = pvt;
2691
2692 if (enable)
2693 dahdi_ec_enable(p);
2694 else
2695 dahdi_ec_disable(p);
2696
2697 return 0;
2698 }
2699
2700 static int dahdi_ring_phone(struct dahdi_pvt *p);
2701
2702 static int my_ring(void *pvt)
2703 {
2704 struct dahdi_pvt *p = pvt;
2705
2706 return dahdi_ring_phone(p);
2707 }
2708
2709 static int my_flash(void *pvt)
2710 {
2711 struct dahdi_pvt *p = pvt;
2712 int func = DAHDI_FLASH;
2713 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2714 }
2715
2716 static inline int dahdi_set_hook(int fd, int hs);
2717
2718 static int my_off_hook(void *pvt)
2719 {
2720 struct dahdi_pvt *p = pvt;
2721 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2722 }
2723
2724 static void my_set_needringing(void *pvt, int value)
2725 {
2726 struct dahdi_pvt *p = pvt;
2727 p->subs[SUB_REAL].needringing = value;
2728 }
2729
2730 static void my_set_polarity(void *pvt, int value)
2731 {
2732 struct dahdi_pvt *p = pvt;
2733
2734 if (p->channel == CHAN_PSEUDO) {
2735 return;
2736 }
2737 p->polarity = value;
2738 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2739 }
2740
2741 static void my_start_polarityswitch(void *pvt)
2742 {
2743 struct dahdi_pvt *p = pvt;
2744
2745 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
2746 my_set_polarity(pvt, 0);
2747 }
2748 }
2749
2750 static void my_answer_polarityswitch(void *pvt)
2751 {
2752 struct dahdi_pvt *p = pvt;
2753
2754 if (!p->answeronpolarityswitch) {
2755 return;
2756 }
2757
2758 my_set_polarity(pvt, 1);
2759 }
2760
2761 static void my_hangup_polarityswitch(void *pvt)
2762 {
2763 struct dahdi_pvt *p = pvt;
2764
2765 if (!p->hanguponpolarityswitch) {
2766 return;
2767 }
2768
2769 if (p->answeronpolarityswitch) {
2770 my_set_polarity(pvt, 0);
2771 } else {
2772 my_set_polarity(pvt, 1);
2773 }
2774 }
2775
2776 /*! \brief Return DAHDI pivot if channel is FXO signalled */
2777 static struct dahdi_pvt *fxo_pvt(struct ast_channel *chan)
2778 {
2779 int res;
2780 struct dahdi_params dahdip;
2781 struct dahdi_pvt *pvt = NULL;
2782
2783 if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
2784 ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", ast_channel_name(chan));
2785 return NULL;
2786 }
2787
2788 memset(&dahdip, 0, sizeof(dahdip));
2789 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2790
2791 if (res) {
2792 ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2793 return NULL;
2794 }
2795 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2796 ast_log(LOG_WARNING, "%s is not FXO signalled\n", ast_channel_name(chan));
2797 return NULL;
2798 }
2799
2800 pvt = ast_channel_tech_pvt(chan);
2801 if (!dahdi_analog_lib_handles(pvt->sig, 0, 0)) {
2802 ast_log(LOG_WARNING, "Channel signalling is not analog");
2803 return NULL;
2804 }
2805
2806 return pvt;
2807 }
2808
2809 static int polarity_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
2810 {
2811 struct dahdi_pvt *pvt;
2812
2813 pvt = fxo_pvt(chan);
2814 if (!pvt) {
2815 return -1;
2816 }
2817
2818 snprintf(buffer, buflen, "%d", pvt->polarity);
2819
2820 return 0;
2821 }
2822
2823 static int polarity_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2824 {
2825 struct dahdi_pvt *pvt;
2826 int polarity;
2827
2828 pvt = fxo_pvt(chan);
2829 if (!pvt) {
2830 return -1;
2831 }
2832
2833 if (!strcasecmp(value, "idle")) {
2834 polarity = POLARITY_IDLE;
2835 } else if (!strcasecmp(value, "reverse")) {
2836 polarity = POLARITY_REV;
2837 } else {
2838 polarity = atoi(value);
2839 }
2840
2841 if (polarity != POLARITY_IDLE && polarity != POLARITY_REV) {
2842 ast_log(LOG_WARNING, "Invalid polarity: '%s'\n", value);
2843 return -1;
2844 }
2845
2846 my_set_polarity(pvt, polarity);
2847 return 0;
2848 }
2849
2850 static struct ast_custom_function polarity_function = {
2851 .name = "POLARITY",
2852 .write = polarity_write,
2853 .read = polarity_read,
2854 };
2855
2856 static int my_start(void *pvt)
2857 {
2858 struct dahdi_pvt *p = pvt;
2859 int x = DAHDI_START;
2860
2861 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2862 }
2863
2864 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
2865 {
2866 struct dahdi_pvt *p = pvt;
2867
2868 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2869 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2870 return -1;
2871 }
2872
2873 if (sub != ANALOG_SUB_REAL) {
2874 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2875 dop->dialstr, p->channel, sub);
2876 return -1;
2877 }
2878
2879 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2880 }
2881
2882 static void dahdi_train_ec(struct dahdi_pvt *p);
2883
2884 static int my_train_echocanceller(void *pvt)
2885 {
2886 struct dahdi_pvt *p = pvt;
2887
2888 dahdi_train_ec(p);
2889
2890 return 0;
2891 }
2892
2893 static int my_is_dialing(void *pvt, enum analog_sub sub)
2894 {
2895 struct dahdi_pvt *p = pvt;
2896 int index;
2897 int x;
2898
2899 index = analogsub_to_dahdisub(sub);
2900
2901 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2902 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2903 return -1;
2904 }
2905
2906 return x;
2907 }
2908
2909 static int my_on_hook(void *pvt)
2910 {
2911 struct dahdi_pvt *p = pvt;
2912 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2913 }
2914
2915 #if defined(HAVE_PRI)
2916 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
2917 {
2918 struct dahdi_pvt *old_chan = chan_old;
2919 struct dahdi_pvt *new_chan = chan_new;
2920
2921 new_chan->owner = old_chan->owner;
2922 old_chan->owner = NULL;
2923 if (new_chan->owner) {
2924 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
2925 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
2926 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
2927 old_chan->subs[SUB_REAL].owner = NULL;
2928 }
2929 /* Copy any DSP that may be present */
2930 new_chan->dsp = old_chan->dsp;
2931 new_chan->dsp_features = old_chan->dsp_features;
2932 old_chan->dsp = NULL;
2933 old_chan->dsp_features = 0;
2934
2935 /* Transfer flags from the old channel. */
2936 new_chan->dialing = old_chan->dialing;
2937 new_chan->digital = old_chan->digital;
2938 new_chan->outgoing = old_chan->outgoing;
2939 old_chan->dialing = 0;
2940 old_chan->digital = 0;
2941 old_chan->outgoing = 0;
2942
2943 /* More stuff to transfer to the new channel. */
2944 new_chan->law = old_chan->law;
2945 strcpy(new_chan->dialstring, old_chan->dialstring);
2946 }
2947 #endif /* defined(HAVE_PRI) */
2948
2949 #if defined(HAVE_PRI)
2950 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
2951 {
2952 switch (tone) {
2953 case SIG_PRI_TONE_RINGTONE:
2954 return DAHDI_TONE_RINGTONE;
2955 case SIG_PRI_TONE_STUTTER:
2956 return DAHDI_TONE_STUTTER;
2957 case SIG_PRI_TONE_CONGESTION:
2958 return DAHDI_TONE_CONGESTION;
2959 case SIG_PRI_TONE_DIALTONE:
2960 return DAHDI_TONE_DIALTONE;
2961 case SIG_PRI_TONE_DIALRECALL:
2962 return DAHDI_TONE_DIALRECALL;
2963 case SIG_PRI_TONE_INFO:
2964 return DAHDI_TONE_INFO;
2965 case SIG_PRI_TONE_BUSY:
2966 return DAHDI_TONE_BUSY;
2967 default:
2968 return -1;
2969 }
2970 }
2971 #endif /* defined(HAVE_PRI) */
2972
2973 #if defined(HAVE_PRI)
2974 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
2975 {
2976 int x;
2977
2978 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
2979 switch (x) {
2980 case DAHDI_EVENT_NONE:
2981 break;
2982 case DAHDI_EVENT_ALARM:
2983 case DAHDI_EVENT_NOALARM:
2984 if (sig_pri_is_alarm_ignored(pri)) {
2985 break;
2986 }
2987 /* Fall through */
2988 default:
2989 ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
2990 event2str(x), x, pri->span);
2991 break;
2992 }
2993 /* Keep track of alarm state */
2994 switch (x) {
2995 case DAHDI_EVENT_ALARM:
2996 pri_event_alarm(pri, index, 0);
2997 break;
2998 case DAHDI_EVENT_NOALARM:
2999 pri_event_noalarm(pri, index, 0);
3000 break;
3001 case DAHDI_EVENT_REMOVED:
3002 pri_queue_for_destruction(pri);
3003 break;
3004 default:
3005 break;
3006 }
3007 }
3008 #endif /* defined(HAVE_PRI) */
3009
3010 #if defined(HAVE_PRI)
3011 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
3012 {
3013 struct dahdi_pvt *p = pvt;
3014
3015 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
3016 }
3017 #endif /* defined(HAVE_PRI) */
3018
3019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3020 /*!
3021 * \internal
3022 * \brief Set the caller id information.
3023 * \since 1.8
3024 *
3025 * \param pvt DAHDI private structure
3026 * \param caller Caller-id information to set.
3027 */
3028 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
3029 {
3030 struct dahdi_pvt *p = pvt;
3031
3032 ast_copy_string(p->cid_num,
3033 S_COR(caller->id.number.valid, caller->id.number.str, ""),
3034 sizeof(p->cid_num));
3035 ast_copy_string(p->cid_name,
3036 S_COR(caller->id.name.valid, caller->id.name.str, ""),
3037 sizeof(p->cid_name));
3038 ast_copy_string(p->cid_subaddr,
3039 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
3040 sizeof(p->cid_subaddr));
3041 p->cid_ton = caller->id.number.plan;
3042 p->callingpres = ast_party_id_presentation(&caller->id);
3043 if (caller->id.tag) {
3044 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
3045 }
3046 ast_copy_string(p->cid_ani,
3047 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
3048 sizeof(p->cid_ani));
3049 p->cid_ani2 = caller->ani2;
3050 }
3051 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3052
3053 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3054 /*!
3055 * \internal
3056 * \brief Set the Dialed Number Identifier.
3057 * \since 1.8
3058 *
3059 * \param pvt DAHDI private structure
3060 * \param dnid Dialed Number Identifier string.
3061 */
3062 static void my_set_dnid(void *pvt, const char *dnid)
3063 {
3064 struct dahdi_pvt *p = pvt;
3065
3066 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
3067 }
3068 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
3069
3070 #if defined(HAVE_PRI)
3071 /*!
3072 * \internal
3073 * \brief Set the Redirecting Directory Number Information Service (RDNIS).
3074 * \since 1.8
3075 *
3076 * \param pvt DAHDI private structure
3077 * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
3078 */
3079 static void my_set_rdnis(void *pvt, const char *rdnis)
3080 {
3081 struct dahdi_pvt *p = pvt;
3082
3083 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
3084 }
3085 #endif /* defined(HAVE_PRI) */
3086
3087 #if defined(HAVE_PRI)
3088 /*!
3089 * \internal
3090 * \brief Make a dialstring for native ISDN CC to recall properly.
3091 * \since 1.8
3092 *
3093 * \param priv Channel private control structure.
3094 * \param buf Where to put the modified dialstring.
3095 * \param buf_size Size of modified dialstring buffer.
3096 *
3097 * \details
3098 * original dialstring:
3099 * \verbatim
3100 DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3101 \endverbatim
3102 *
3103 * The modified dialstring will have prefixed the channel-group section
3104 * with the ISDN channel restriction.
3105 *
3106 * buf:
3107 * \verbatim
3108 DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]]
3109 \endverbatim
3110 *
3111 * The routine will check to see if the ISDN channel restriction is already
3112 * in the original dialstring.
3113 */
3114 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
3115 {
3116 char *dial;
3117 struct dahdi_pvt *pvt;
3118 AST_DECLARE_APP_ARGS(args,
3119 AST_APP_ARG(tech); /* channel technology token */
3120 AST_APP_ARG(group); /* channel/group token */
3121 //AST_APP_ARG(ext); /* extension token */
3122 //AST_APP_ARG(opts); /* options token */
3123 //AST_APP_ARG(other); /* Any remining unused arguments */
3124 );
3125
3126 pvt = priv;
3127 dial = ast_strdupa(pvt->dialstring);
3128 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
3129 if (!args.tech) {
3130 ast_copy_string(buf, pvt->dialstring, buf_size);
3131 return;
3132 }
3133 if (!args.group) {
3134 /* Append the ISDN span channel restriction to the dialstring. */
3135 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
3136 return;
3137 }
3138 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
3139 /* The ISDN span channel restriction is not needed or already
3140 * in the dialstring. */
3141 ast_copy_string(buf, pvt->dialstring, buf_size);
3142 return;
3143 }
3144 /* Insert the ISDN span channel restriction into the dialstring. */
3145 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
3146 }
3147 #endif /* defined(HAVE_PRI) */
3148
3149 #if defined(HAVE_PRI)
3150 /*!
3151 * \internal
3152 * \brief Reevaluate the PRI span device state.
3153 * \since 1.8
3154 *
3155 * \param pri Asterisk D channel control structure.
3156 *
3157 * \note Assumes the pri->lock is already obtained.
3158 */
3159 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
3160 {
3161 unsigned idx;
3162 unsigned num_b_chans; /* Number of B channels provisioned on the span. */
3163 unsigned in_use; /* Number of B channels in use on the span. */
3164 unsigned in_alarm; /* TRUE if the span is in alarm condition. */
3165 enum ast_device_state new_state;
3166
3167 /* Count the number of B channels and the number of B channels in use. */
3168 num_b_chans = 0;
3169 in_use = 0;
3170 in_alarm = 1;
3171 for (idx = pri->numchans; idx--;) {
3172 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
3173 /* This is a B channel interface. */
3174 ++num_b_chans;
3175 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
3176 ++in_use;
3177 }
3178 if (!pri->pvts[idx]->inalarm) {
3179 /* There is a channel that is not in alarm. */
3180 in_alarm = 0;
3181 }
3182 }
3183 }
3184
3185 /* Update the span congestion device state and report any change. */
3186 if (in_alarm) {
3187 new_state = AST_DEVICE_UNAVAILABLE;
3188 } else {
3189 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
3190 }
3191 if (pri->congestion_devstate != new_state) {
3192 pri->congestion_devstate = new_state;
3193 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
3194 }
3195 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
3196 /* Update the span threshold device state and report any change. */
3197 if (in_alarm) {
3198 new_state = AST_DEVICE_UNAVAILABLE;
3199 } else if (!in_use) {
3200 new_state = AST_DEVICE_NOT_INUSE;
3201 } else if (!pri->user_busy_threshold) {
3202 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
3203 } else {
3204 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
3205 : AST_DEVICE_BUSY;
3206 }
3207 if (pri->threshold_devstate != new_state) {
3208 pri->threshold_devstate = new_state;
3209 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
3210 }
3211 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
3212 }
3213 #endif /* defined(HAVE_PRI) */
3214
3215 #if defined(HAVE_PRI)
3216 /*!
3217 * \internal
3218 * \brief Reference this module.
3219 * \since 1.8
3220 */
3221 static void my_module_ref(void)
3222 {
3223 ast_module_ref(ast_module_info->self);
3224 }
3225 #endif /* defined(HAVE_PRI) */
3226
3227 #if defined(HAVE_PRI)
3228 /*!
3229 * \internal
3230 * \brief Unreference this module.
3231 * \since 1.8
3232 */
3233 static void my_module_unref(void)
3234 {
3235 ast_module_unref(ast_module_info->self);
3236 }
3237 #endif /* defined(HAVE_PRI) */
3238
3239 #if defined(HAVE_PRI)
3240 #if defined(HAVE_PRI_CALL_WAITING)
3241 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3242 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3243 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
3244
3245 struct sig_pri_callback sig_pri_callbacks =
3246 {
3247 .handle_dchan_exception = my_handle_dchan_exception,
3248 .play_tone = my_pri_play_tone,
3249 .set_echocanceller = my_set_echocanceller,
3250 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3251 .lock_private = my_lock_private,
3252 .unlock_private = my_unlock_private,
3253 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3254 .new_ast_channel = my_new_pri_ast_channel,
3255 .fixup_chans = my_pri_fixup_chans,
3256 .set_alarm = my_set_alarm,
3257 .set_dialing = my_set_dialing,
3258 .set_outgoing = my_set_outgoing,
3259 .set_digital = my_set_digital,
3260 .set_callerid = my_set_callerid,
3261 .set_dnid = my_set_dnid,
3262 .set_rdnis = my_set_rdnis,
3263 .new_nobch_intf = dahdi_new_pri_nobch_channel,
3264 #if defined(HAVE_PRI_CALL_WAITING)
3265 .init_config = my_pri_init_config,
3266 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3267 .get_orig_dialstring = my_get_orig_dialstring,
3268 .make_cc_dialstring = my_pri_make_cc_dialstring,
3269 .update_span_devstate = dahdi_pri_update_span_devstate,
3270 .module_ref = my_module_ref,
3271 .module_unref = my_module_unref,
3272 .dial_digits = my_pri_dial_digits,
3273 .open_media = my_pri_ss7_open_media,
3274 .ami_channel_event = my_ami_channel_event,
3275 .destroy_later = pri_queue_for_destruction,
3276 };
3277 #endif /* defined(HAVE_PRI) */
3278
3279 #if defined(HAVE_SS7)
3280 /*!
3281 * \internal
3282 * \brief Handle the SS7 link exception.
3283 * \since 1.8
3284 *
3285 * \param linkset Controlling linkset for the channel.
3286 * \param which Link index of the signaling channel.
3287 */
3288 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
3289 {
3290 int event;
3291
3292 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3293 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
3294 linkset->span, which);
3295 return;
3296 }
3297 switch (event) {
3298 case DAHDI_EVENT_NONE:
3299 break;
3300 case DAHDI_EVENT_ALARM:
3301 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3302 event2str(event), event, linkset->span, which);
3303 sig_ss7_link_alarm(linkset, which);
3304 break;
3305 case DAHDI_EVENT_NOALARM:
3306 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3307 event2str(event), event, linkset->span, which);
3308 sig_ss7_link_noalarm(linkset, which);
3309 break;
3310 default:
3311 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
3312 event2str(event), event, linkset->span, which);
3313 break;
3314 }
3315 }
3316 #endif /* defined(HAVE_SS7) */
3317
3318 #if defined(HAVE_SS7)
3319 static void my_ss7_set_loopback(void *pvt, int enable)
3320 {
3321 struct dahdi_pvt *p = pvt;
3322
3323 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3324 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
3325 strerror(errno));
3326 }
3327 }
3328 #endif /* defined(HAVE_SS7) */
3329
3330 #if defined(HAVE_SS7)
3331 /*!
3332 * \internal
3333 * \brief Find the linkset to which SS7 belongs.
3334 * \since 11.0
3335 *
3336 * \param ss7 structure to match on.
3337 *
3338 * \retval linkset if found.
3339 * \retval NULL if not found.
3340 */
3341 static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
3342 {
3343 int idx;
3344
3345 if (!ss7) {
3346 return NULL;
3347 }
3348
3349 for (idx = 0; idx < NUM_SPANS; ++idx) {
3350 if (linksets[idx].ss7.ss7 == ss7) {
3351 return &linksets[idx].ss7;
3352 }
3353 }
3354 return NULL;
3355 }
3356 #endif /* defined(HAVE_SS7) */
3357
3358 #if defined(HAVE_SS7)
3359 /*!
3360 * \internal
3361 * \brief Create a new asterisk channel structure for SS7.
3362 * \since 1.8
3363 *
3364 * \param pvt Private channel structure.
3365 * \param state Initial state of new channel.
3366 * \param law Companding law to use.
3367 * \param exten Dialplan extension for incoming call.
3368 * \param requestor Channel requesting this new channel.
3369 * \param assignedids
3370 *
3371 * \retval ast_channel on success.
3372 * \retval NULL on error.
3373 */
3374 static 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)
3375 {
3376 struct dahdi_pvt *p = pvt;
3377 int audio;
3378 int newlaw;
3379 ast_callid callid = 0;
3380 int callid_created = ast_callid_threadstorage_auto(&callid);
3381
3382 /* Set to audio mode at this point */
3383 audio = 1;
3384 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3385 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
3386 p->channel, audio, strerror(errno));
3387
3388 if (law != SIG_SS7_DEFLAW) {
3389 dahdi_setlaw(p->subs[SUB_REAL].dfd,
3390 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3391 }
3392
3393 ast_copy_string(p->exten, exten, sizeof(p->exten));
3394
3395 newlaw = -1;
3396 switch (law) {
3397 case SIG_SS7_DEFLAW:
3398 newlaw = 0;
3399 break;
3400 case SIG_SS7_ALAW:
3401 newlaw = DAHDI_LAW_ALAW;
3402 break;
3403 case SIG_SS7_ULAW:
3404 newlaw = DAHDI_LAW_MULAW;
3405 break;
3406 }
3407 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3408 }
3409 #endif /* defined(HAVE_SS7) */
3410
3411 #if defined(HAVE_SS7)
3412 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3413 {
3414 switch (tone) {
3415 case SIG_SS7_TONE_RINGTONE:
3416 return DAHDI_TONE_RINGTONE;
3417 case SIG_SS7_TONE_STUTTER:
3418 return DAHDI_TONE_STUTTER;
3419 case SIG_SS7_TONE_CONGESTION:
3420 return DAHDI_TONE_CONGESTION;
3421 case SIG_SS7_TONE_DIALTONE:
3422 return DAHDI_TONE_DIALTONE;
3423 case SIG_SS7_TONE_DIALRECALL:
3424 return DAHDI_TONE_DIALRECALL;
3425 case SIG_SS7_TONE_INFO:
3426 return DAHDI_TONE_INFO;
3427 case SIG_SS7_TONE_BUSY:
3428 return DAHDI_TONE_BUSY;
3429 default:
3430 return -1;
3431 }
3432 }
3433 #endif /* defined(HAVE_SS7) */
3434
3435 #if defined(HAVE_SS7)
3436 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
3437 {
3438 struct dahdi_pvt *p = pvt;
3439
3440 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3441 }
3442 #endif /* defined(HAVE_SS7) */
3443
3444 #if defined(HAVE_SS7)
3445 struct sig_ss7_callback sig_ss7_callbacks =
3446 {
3447 .lock_private = my_lock_private,
3448 .unlock_private = my_unlock_private,
3449 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3450
3451 .set_echocanceller = my_set_echocanceller,
3452 .set_loopback = my_ss7_set_loopback,
3453
3454 .new_ast_channel = my_new_ss7_ast_channel,
3455 .play_tone = my_ss7_play_tone,
3456
3457 .handle_link_exception = my_handle_link_exception,
3458 .set_alarm = my_set_alarm,
3459 .set_dialing = my_set_dialing,
3460 .set_outgoing = my_set_outgoing,
3461 .set_digital = my_set_digital,
3462 .set_inservice = my_set_inservice,
3463 .set_locallyblocked = my_set_locallyblocked,
3464 .set_remotelyblocked = my_set_remotelyblocked,
3465 .set_callerid = my_set_callerid,
3466 .set_dnid = my_set_dnid,
3467 .open_media = my_pri_ss7_open_media,
3468 .find_linkset = my_ss7_find_linkset,
3469 };
3470 #endif /* defined(HAVE_SS7) */
3471
3472 /*!
3473 * \brief Send MWI state change
3474 *
3475 * \param mailbox This is the mailbox associated with the FXO line that the
3476 * MWI state has changed on.
3477 * \param thereornot This argument should simply be set to 1 or 0, to indicate
3478 * whether there are messages waiting or not.
3479 *
3480 * This function does two things:
3481 *
3482 * 1) It generates an internal Asterisk event notifying any other module that
3483 * cares about MWI that the state of a mailbox has changed.
3484 *
3485 * 2) It runs the script specified by the mwimonitornotify option to allow
3486 * some custom handling of the state change.
3487 */
3488 static void notify_message(char *mailbox, int thereornot)
3489 {
3490 char s[sizeof(mwimonitornotify) + 164];
3491
3492 if (ast_strlen_zero(mailbox)) {
3493 return;
3494 }
3495
3496 ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3497 if (!ast_strlen_zero(mwimonitornotify)) {
3498 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3499 ast_safe_system(s);
3500 }
3501 }
3502
3503 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
3504 {
3505 struct dahdi_pvt *p = pvt;
3506
3507 if (neon_mwievent > -1 && !p->mwimonitor_neon)
3508 return;
3509
3510 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3511 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3512 notify_message(p->mailbox, 1);
3513 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3514 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3515 notify_message(p->mailbox, 0);
3516 }
3517 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3518 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3519 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3520 ast_hangup(chan);
3521 return;
3522 }
3523 }
3524
3525 static int my_have_progressdetect(void *pvt)
3526 {
3527 struct dahdi_pvt *p = pvt;
3528
3529 if ((p->callprogress & CALLPROGRESS_PROGRESS)
3530 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3531 return 1;
3532 } else {
3533 /* Don't have progress detection. */
3534 return 0;
3535 }
3536 }
3537
3538 #define gen_pvt_field_callback(type, field) \
3539 static type my_get_##field(void *pvt) \
3540 { \
3541 struct dahdi_pvt *p = pvt; \
3542 return p->field; \
3543 }
3544
3545 gen_pvt_field_callback(int, firstdigit_timeout);
3546 gen_pvt_field_callback(int, interdigit_timeout);
3547 gen_pvt_field_callback(int, matchdigit_timeout);
3548
3549 #undef gen_pvt_field_callback
3550
3551 struct analog_callback analog_callbacks =
3552 {
3553 .play_tone = my_play_tone,
3554 .get_event = my_get_event,
3555 .wait_event = my_wait_event,
3556 .is_off_hook = my_is_off_hook,
3557 .set_echocanceller = my_set_echocanceller,
3558 .ring = my_ring,
3559 .flash = my_flash,
3560 .off_hook = my_off_hook,
3561 .dial_digits = my_dial_digits,
3562 .train_echocanceller = my_train_echocanceller,
3563 .on_hook = my_on_hook,
3564 .is_dialing = my_is_dialing,
3565 .allocate_sub = my_allocate_sub,
3566 .unallocate_sub = my_unallocate_sub,
3567 .swap_subs = my_swap_subchannels,
3568 .has_voicemail = my_has_voicemail,
3569 .check_for_conference = my_check_for_conference,
3570 .conf_add = my_conf_add,
3571 .conf_del = my_conf_del,
3572 .complete_conference_update = my_complete_conference_update,
3573 .start = my_start,
3574 .all_subchannels_hungup = my_all_subchannels_hungup,
3575 .lock_private = my_lock_private,
3576 .unlock_private = my_unlock_private,
3577 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3578 .handle_dtmf = my_handle_dtmf,
3579 .wink = my_wink,
3580 .new_ast_channel = my_new_analog_ast_channel,
3581 .dsp_set_digitmode = my_dsp_set_digitmode,
3582 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3583 .send_callerid = my_send_callerid,
3584 .callwait = my_callwait,
3585 .stop_callwait = my_stop_callwait,
3586 .get_callerid = my_get_callerid,
3587 .start_cid_detect = my_start_cid_detect,
3588 .stop_cid_detect = my_stop_cid_detect,
3589 .handle_notify_message = my_handle_notify_message,
3590 .increase_ss_count = my_increase_ss_count,
3591 .decrease_ss_count = my_decrease_ss_count,
3592 .distinctive_ring = my_distinctive_ring,
3593 .set_linear_mode = my_set_linear_mode,
3594 .set_inthreeway = my_set_inthreeway,
3595 .get_and_handle_alarms = my_get_and_handle_alarms,
3596 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3597 .get_sub_fd = my_get_sub_fd,
3598 .set_cadence = my_set_cadence,
3599 .set_alarm = my_set_alarm,
3600 .set_dialing = my_set_dialing,
3601 .set_outgoing = my_set_outgoing,
3602 .set_ringtimeout = my_set_ringtimeout,
3603 .set_waitingfordt = my_set_waitingfordt,
3604 .check_waitingfordt = my_check_waitingfordt,
3605 .set_confirmanswer = my_set_confirmanswer,
3606 .check_confirmanswer = my_check_confirmanswer,
3607 .set_callwaiting = my_set_callwaiting,
3608 .cancel_cidspill = my_cancel_cidspill,
3609 .confmute = my_confmute,
3610 .set_pulsedial = my_set_pulsedial,
3611 .set_new_owner = my_set_new_owner,
3612 .get_orig_dialstring = my_get_orig_dialstring,
3613 .set_needringing = my_set_needringing,
3614 .set_polarity = my_set_polarity,
3615 .start_polarityswitch = my_start_polarityswitch,
3616 .answer_polarityswitch = my_answer_polarityswitch,
3617 .hangup_polarityswitch = my_hangup_polarityswitch,
3618 .have_progressdetect = my_have_progressdetect,
3619 .get_firstdigit_timeout = my_get_firstdigit_timeout,
3620 .get_matchdigit_timeout = my_get_matchdigit_timeout,
3621 .get_interdigit_timeout = my_get_interdigit_timeout,
3622 };
3623
3624 /*! Round robin search locations. */
3625 static struct dahdi_pvt *round_robin[64]; /* groups can range from 0-63 */
3626
3627 int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
3628 {
3629 int res;
3630 if (p->subs[SUB_REAL].owner == ast)
3631 res = 0;
3632 else if (p->subs[SUB_CALLWAIT].owner == ast)
3633 res = 1;
3634 else if (p->subs[SUB_THREEWAY].owner == ast)
3635 res = 2;
3636 else {
3637 res = -1;
3638 if (!nullok)
3639 ast_log(LOG_WARNING,
3640 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3641 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3642 }
3643 return res;
3644 }
3645
3646 /*!
3647 * \internal
3648 * \brief Obtain the specified subchannel owner lock if the owner exists.
3649 *
3650 * \param pvt Channel private struct.
3651 * \param sub_idx Subchannel owner to lock.
3652 *
3653 * \note Assumes the pvt->lock is already obtained.
3654 *
3655 * \note
3656 * Because deadlock avoidance may have been necessary, you need to confirm
3657 * the state of things before continuing.
3658 */
3659 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
3660 {
3661 for (;;) {
3662 if (!pvt->subs[sub_idx].owner) {
3663 /* No subchannel owner pointer */
3664 break;
3665 }
3666 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3667 /* Got subchannel owner lock */
3668 break;
3669 }
3670 /* We must unlock the private to avoid the possibility of a deadlock */
3671 DEADLOCK_AVOIDANCE(&pvt->lock);
3672 }
3673 }
3674
3675 static void wakeup_sub(struct dahdi_pvt *p, int a)
3676 {
3677 dahdi_lock_sub_owner(p, a);
3678 if (p->subs[a].owner) {
3679 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
3680 ast_channel_unlock(p->subs[a].owner);
3681 }
3682 }
3683
3684 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
3685 {
3686 for (;;) {
3687 if (p->owner) {
3688 if (ast_channel_trylock(p->owner)) {
3689 DEADLOCK_AVOIDANCE(&p->lock);
3690 } else {
3691 ast_queue_frame(p->owner, f);
3692 ast_channel_unlock(p->owner);
3693 break;
3694 }
3695 } else
3696 break;
3697 }
3698 }
3699
3700 static void publish_channel_alarm_clear(int channel)
3701 {
3702 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3703 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3704 if (!dahdi_chan) {
3705 return;
3706 }
3707
3708 ast_str_set(&dahdi_chan, 0, "%d", channel);
3709 ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3710 body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3711 if (!body) {
3712 return;
3713 }
3714
3715 ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3716 }
3717
3718 static void publish_span_alarm_clear(int span)
3719 {
3720 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3721
3722 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3723 body = ast_json_pack("{s: i}", "Span", span);
3724 if (!body) {
3725 return;
3726 }
3727
3728 ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3729 }
3730
3731 static void handle_clear_alarms(struct dahdi_pvt *p)
3732 {
3733 #if defined(HAVE_PRI)
3734 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
3735 return;
3736 }
3737 #endif /* defined(HAVE_PRI) */
3738
3739 if (report_alarms & REPORT_CHANNEL_ALARMS) {
3740 publish_channel_alarm_clear(p->channel);
3741 }
3742 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
3743 publish_span_alarm_clear(p->span);
3744 }
3745 }
3746
3747 #ifdef HAVE_OPENR2
3748 static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)
3749 {
3750 const struct dahdi_mfcr2 *r2link = p->mfcr2;
3751 struct r2link_entry *cur;
3752 AST_LIST_LOCK(&r2links);
3753 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
3754 if (r2link == &cur->mfcr2) {
3755 ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);
3756 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
3757 break;
3758 }
3759 }
3760 AST_LIST_TRAVERSE_SAFE_END;
3761 AST_LIST_UNLOCK(&r2links);
3762 }
3763
3764 static int dahdi_r2_answer(struct dahdi_pvt *p)
3765 {
3766 int res = 0;
3767 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
3768 * and does not has support for openr2_chan_answer_call_with_mode
3769 * */
3770 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3771 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
3772 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
3773 if (!double_answer) {
3774 /* this still can result in double answer if the channel context
3775 * was configured that way */
3776 res = openr2_chan_answer_call(p->r2chan);
3777 } else if (wants_double_answer) {
3778 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3779 } else {
3780 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3781 }
3782 #else
3783 res = openr2_chan_answer_call(p->r2chan);
3784 #endif
3785 return res;
3786 }
3787
3788
3789
3790 /* should be called with the ast_channel locked */
3791 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
3792 {
3793 openr2_calling_party_category_t cat;
3794 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
3795 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3796 if (ast_strlen_zero(catstr)) {
3797 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
3798 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3799 return p->mfcr2_category;
3800 }
3801 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3802 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
3803 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3804 return p->mfcr2_category;
3805 }
3806 ast_debug(1, "Using category %s\n", catstr);
3807 return cat;
3808 }
3809
3810 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3811 {
3812 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3813 ast_mutex_lock(&p->lock);
3814 if (p->mfcr2call) {
3815 ast_mutex_unlock(&p->lock);
3816 /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
3817 interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
3818 can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
3819 the other end will see our seize as a forced release and drop the call, we will see an invalid
3820 pattern that will be seen and treated as protocol error. */
3821 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3822 return;
3823 }
3824 p->mfcr2call = 1;
3825 /* better safe than sorry ... */
3826 p->cid_name[0] = '\0';
3827 p->cid_num[0] = '\0';
3828 p->cid_subaddr[0] = '\0';
3829 p->rdnis[0] = '\0';
3830 p->exten[0] = '\0';
3831 p->mfcr2_ani_index = '\0';
3832 p->mfcr2_dnis_index = '\0';
3833 p->mfcr2_dnis_matched = 0;
3834 p->mfcr2_answer_pending = 0;
3835 p->mfcr2_call_accepted = 0;
3836 ast_mutex_unlock(&p->lock);
3837 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3838 }
3839
3840 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
3841 {
3842 int res;
3843 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3844 ast_mutex_lock(&p->lock);
3845 p->inalarm = alarm ? 1 : 0;
3846 if (p->inalarm) {
3847 res = get_alarms(p);
3848 if (res == DAHDI_ALARM_NOTOPEN) {
3849 mfcr2_queue_for_destruction(p);
3850 }
3851 handle_alarms(p, res);
3852 } else {
3853 handle_clear_alarms(p);
3854 }
3855 ast_mutex_unlock(&p->lock);
3856 }
3857
3858 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
3859 {
3860 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3861
3862 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3863 ast_mutex_lock(&p->lock);
3864 /* Disconnected? */
3865 if (errorcode == ENODEV) {
3866 struct dahdi_mfcr2 *r2link = p->mfcr2;
3867 p->mfcr2call = 0;
3868 if (r2link) {
3869 r2link->nodev = 1;
3870 }
3871 }
3872 ast_mutex_unlock(&p->lock);
3873 }
3874
3875 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3876 {
3877 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3878 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3879 if (p->owner) {
3880 ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
3881 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
3882 }
3883 ast_mutex_lock(&p->lock);
3884 p->mfcr2call = 0;
3885 ast_mutex_unlock(&p->lock);
3886 }
3887
3888 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3889 {
3890 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3891 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3892 p->channel, openr2_proto_get_disconnect_string(cause));
3893 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
3894 openr2_chan_set_idle(p->r2chan);
3895 ast_mutex_lock(&p->lock);
3896 p->mfcr2call = 0;
3897 ast_mutex_unlock(&p->lock);
3898 }
3899 }
3900
3901 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
3902 {
3903 struct dahdi_pvt *p;
3904 struct ast_channel *c;
3905 ast_callid callid = 0;
3906 int callid_created = ast_callid_threadstorage_auto(&callid);
3907 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3908 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
3909 openr2_proto_get_category_string(category));
3910 p = openr2_chan_get_client_data(r2chan);
3911 /* if collect calls are not allowed and this is a collect call, reject it! */
3912 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3913 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
3914 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3915 goto dahdi_r2_on_call_offered_cleanup;
3916 }
3917 ast_mutex_lock(&p->lock);
3918 p->mfcr2_recvd_category = category;
3919 /* if we're not supposed to use CID, clear whatever we have */
3920 if (!p->use_callerid) {
3921 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
3922 p->cid_num[0] = 0;
3923 p->cid_name[0] = 0;
3924 }
3925 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
3926 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3927 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
3928 p->exten[0] = 's';
3929 p->exten[1] = 0;
3930 }
3931 ast_mutex_unlock(&p->lock);
3932 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3933 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
3934 p->channel, p->exten, p->context);
3935 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
3936 goto dahdi_r2_on_call_offered_cleanup;
3937 }
3938 if (!p->mfcr2_accept_on_offer) {
3939 /* The user wants us to start the PBX thread right away without accepting the call first */
3940 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3941 if (c) {
3942 /* Done here, don't disable reading now since we still need to generate MF tones to accept
3943 the call or reject it and detect the tone off condition of the other end, all of this
3944 will be done in the PBX thread now */
3945 goto dahdi_r2_on_call_offered_cleanup;
3946 }
3947 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
3948 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
3949 } else if (p->mfcr2_charge_calls) {
3950 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
3951 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
3952 } else {
3953 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
3954 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
3955 }
3956
3957 dahdi_r2_on_call_offered_cleanup:
3958 ast_callid_threadstorage_auto_clean(callid, callid_created);
3959 }
3960
3961 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
3962 {
3963 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3964 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
3965 ast_mutex_lock(&p->lock);
3966 p->mfcr2call = 0;
3967 ast_mutex_unlock(&p->lock);
3968 }
3969
3970 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
3971 {
3972 struct dahdi_pvt *p = NULL;
3973 struct ast_channel *c = NULL;
3974 ast_callid callid = 0;
3975 int callid_created = ast_callid_threadstorage_auto(&callid);
3976 p = openr2_chan_get_client_data(r2chan);
3977 dahdi_ec_enable(p);
3978 p->mfcr2_call_accepted = 1;
3979 /* if it's an incoming call ... */
3980 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
3981 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
3982 /* If accept on offer is not set, it means at this point the PBX thread is already
3983 launched (was launched in the 'on call offered' handler) and therefore this callback
3984 is being executed already in the PBX thread rather than the monitor thread, don't launch
3985 any other thread, just disable the openr2 reading and answer the call if needed */
3986 if (!p->mfcr2_accept_on_offer) {
3987 openr2_chan_disable_read(r2chan);
3988 if (p->mfcr2_answer_pending) {
3989 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
3990 dahdi_r2_answer(p);
3991 }
3992 goto dahdi_r2_on_call_accepted_cleanup;
3993 }
3994 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3995 if (c) {
3996 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
3997 library to forget about it */
3998 openr2_chan_disable_read(r2chan);
3999 goto dahdi_r2_on_call_accepted_cleanup;
4000 }
4001 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
4002 /* failed to create the channel, bail out and report it as an out of order line */
4003 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4004 goto dahdi_r2_on_call_accepted_cleanup;
4005 }
4006 /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
4007 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
4008 p->subs[SUB_REAL].needringing = 1;
4009 p->dialing = 0;
4010 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
4011 openr2_chan_disable_read(r2chan);
4012
4013 dahdi_r2_on_call_accepted_cleanup:
4014 ast_callid_threadstorage_auto_clean(callid, callid_created);
4015 }
4016
4017 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
4018 {
4019 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4020 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
4021 p->subs[SUB_REAL].needanswer = 1;
4022 }
4023
4024 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
4025 {
4026 /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
4027 }
4028
4029 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
4030 {
4031 switch (cause) {
4032 case OR2_CAUSE_BUSY_NUMBER:
4033 return AST_CAUSE_BUSY;
4034 case OR2_CAUSE_NETWORK_CONGESTION:
4035 return AST_CAUSE_CONGESTION;
4036 case OR2_CAUSE_OUT_OF_ORDER:
4037 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
4038 case OR2_CAUSE_UNALLOCATED_NUMBER:
4039 return AST_CAUSE_UNREGISTERED;
4040 case OR2_CAUSE_NO_ANSWER:
4041 return AST_CAUSE_NO_ANSWER;
4042 case OR2_CAUSE_NORMAL_CLEARING:
4043 return AST_CAUSE_NORMAL_CLEARING;
4044 case OR2_CAUSE_UNSPECIFIED:
4045 default:
4046 return AST_CAUSE_NOTDEFINED;
4047 }
4048 }
4049
4050 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
4051 {
4052 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4053 char cause_str[50];
4054 struct ast_control_pvt_cause_code *cause_code;
4055 int datalen = sizeof(*cause_code);
4056
4057 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
4058 ast_mutex_lock(&p->lock);
4059 if (!p->owner) {
4060 ast_mutex_unlock(&p->lock);
4061 /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
4062 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
4063 return;
4064 }
4065
4066 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
4067 datalen += strlen(cause_str);
4068 cause_code = ast_alloca(datalen);
4069 memset(cause_code, 0, datalen);
4070 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
4071 ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
4072 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
4073 ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
4074 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
4075 ast_channel_hangupcause_set(p->owner, cause_code->ast_cause);
4076
4077 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
4078 be done in dahdi_hangup */
4079 if (ast_channel_state(p->owner) == AST_STATE_UP) {
4080 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4081 ast_mutex_unlock(&p->lock);
4082 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
4083 /* being the forward side we must report what happened to the call to whoever requested it */
4084 switch (cause) {
4085 case OR2_CAUSE_BUSY_NUMBER:
4086 p->subs[SUB_REAL].needbusy = 1;
4087 break;
4088 case OR2_CAUSE_NETWORK_CONGESTION:
4089 case OR2_CAUSE_OUT_OF_ORDER:
4090 case OR2_CAUSE_UNALLOCATED_NUMBER:
4091 case OR2_CAUSE_NO_ANSWER:
4092 case OR2_CAUSE_UNSPECIFIED:
4093 case OR2_CAUSE_NORMAL_CLEARING:
4094 p->subs[SUB_REAL].needcongestion = 1;
4095 break;
4096 default:
4097 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
4098 }
4099 ast_mutex_unlock(&p->lock);
4100 } else {
4101 ast_mutex_unlock(&p->lock);
4102 /* being the backward side and not UP yet, we only need to request hangup */
4103 /* TODO: what about doing this same thing when were AST_STATE_UP? */
4104 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
4105 }
4106 }
4107
4108 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
4109 {
4110 switch (level) {
4111 case OR2_LOG_NOTICE:
4112 ast_verbose("%s", logmessage);
4113 break;
4114 case OR2_LOG_WARNING:
4115 ast_log(LOG_WARNING, "%s", logmessage);
4116 break;
4117 case OR2_LOG_ERROR:
4118 ast_log(LOG_ERROR, "%s", logmessage);
4119 break;
4120 case OR2_LOG_STACK_TRACE:
4121 case OR2_LOG_MF_TRACE:
4122 case OR2_LOG_CAS_TRACE:
4123 case OR2_LOG_DEBUG:
4124 case OR2_LOG_EX_DEBUG:
4125 ast_debug(1, "%s", logmessage);
4126 break;
4127 default:
4128 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
4129 ast_debug(1, "%s", logmessage);
4130 break;
4131 }
4132 }
4133
4134 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
4135 {
4136 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4137 ast_mutex_lock(&p->lock);
4138 p->remotelyblocked = 1;
4139 ast_mutex_unlock(&p->lock);
4140 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4141 }
4142
4143 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
4144 {
4145 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4146 ast_mutex_lock(&p->lock);
4147 p->remotelyblocked = 0;
4148 ast_mutex_unlock(&p->lock);
4149 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4150 }
4151
4152 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4153 __attribute__((format (printf, 3, 0)));
4154 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
4155 {
4156 #define CONTEXT_TAG "Context - "
4157 char logmsg[256];
4158 char completemsg[sizeof(logmsg) * 2];
4159 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4160 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
4161 dahdi_r2_write_log(level, completemsg);
4162 #undef CONTEXT_TAG
4163 }
4164
4165 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4166 __attribute__((format (printf, 3, 0)));
4167 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
4168 {
4169 #define CHAN_TAG "Chan "
4170 char logmsg[256];
4171 char completemsg[sizeof(logmsg) * 2];
4172 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
4173 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
4174 dahdi_r2_write_log(level, completemsg);
4175 #undef CHAN_TAG
4176 }
4177
4178 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
4179 {
4180 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4181 /* if 'immediate' is set, let's stop requesting DNIS */
4182 if (p->immediate) {
4183 return 0;
4184 }
4185 p->exten[p->mfcr2_dnis_index] = digit;
4186 p->rdnis[p->mfcr2_dnis_index] = digit;
4187 p->mfcr2_dnis_index++;
4188 p->exten[p->mfcr2_dnis_index] = 0;
4189 p->rdnis[p->mfcr2_dnis_index] = 0;
4190 /* if the DNIS is a match and cannot match more, stop requesting DNIS */
4191 if ((p->mfcr2_dnis_matched ||
4192 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
4193 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
4194 return 0;
4195 }
4196 /* otherwise keep going */
4197 return 1;
4198 }
4199
4200 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
4201 {
4202 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4203 p->cid_num[p->mfcr2_ani_index] = digit;
4204 p->cid_name[p->mfcr2_ani_index] = digit;
4205 p->mfcr2_ani_index++;
4206 p->cid_num[p->mfcr2_ani_index] = 0;
4207 p->cid_name[p->mfcr2_ani_index] = 0;
4208 }
4209
4210 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4211 {
4212 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4213 }
4214
4215 static openr2_event_interface_t dahdi_r2_event_iface = {
4216 .on_call_init = dahdi_r2_on_call_init,
4217 .on_call_offered = dahdi_r2_on_call_offered,
4218 .on_call_accepted = dahdi_r2_on_call_accepted,
4219 .on_call_answered = dahdi_r2_on_call_answered,
4220 .on_call_disconnect = dahdi_r2_on_call_disconnect,
4221 .on_call_end = dahdi_r2_on_call_end,
4222 .on_call_read = dahdi_r2_on_call_read,
4223 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4224 .on_os_error = dahdi_r2_on_os_error,
4225 .on_protocol_error = dahdi_r2_on_protocol_error,
4226 .on_line_blocked = dahdi_r2_on_line_blocked,
4227 .on_line_idle = dahdi_r2_on_line_idle,
4228 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
4229 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4230 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4231 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4232 /* so far we do nothing with billing pulses */
4233 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4234 };
4235
4236 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4237 {
4238 return AST_ALAW(sample);
4239 }
4240
4241 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4242 {
4243 return AST_LIN2A(sample);
4244 }
4245
4246 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4247 dahdi_r2_alaw_to_linear,
4248 dahdi_r2_linear_to_alaw
4249 };
4250
4251 #endif /* HAVE_OPENR2 */
4252
4253 static void swap_subs(struct dahdi_pvt *p, int a, int b)
4254 {
4255 int tchan;
4256 int tinthreeway;
4257 struct ast_channel *towner;
4258
4259 ast_debug(1, "Swapping %d and %d\n", a, b);
4260
4261 tchan = p->subs[a].chan;
4262 towner = p->subs[a].owner;
4263 tinthreeway = p->subs[a].inthreeway;
4264
4265 p->subs[a].chan = p->subs[b].chan;
4266 p->subs[a].owner = p->subs[b].owner;
4267 p->subs[a].inthreeway = p->subs[b].inthreeway;
4268
4269 p->subs[b].chan = tchan;
4270 p->subs[b].owner = towner;
4271 p->subs[b].inthreeway = tinthreeway;
4272
4273 if (p->subs[a].owner)
4274 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4275 if (p->subs[b].owner)
4276 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4277 wakeup_sub(p, a);
4278 wakeup_sub(p, b);
4279 }
4280
4281 static int dahdi_open(char *fn)
4282 {
4283 int fd;
4284 int isnum;
4285 int chan = 0;
4286 int bs;
4287 int x;
4288 isnum = 1;
4289 for (x = 0; x < strlen(fn); x++) {
4290 if (!isdigit(fn[x])) {
4291 isnum = 0;
4292 break;
4293 }
4294 }
4295 if (isnum) {
4296 chan = atoi(fn);
4297 if (chan < 1) {
4298 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4299 return -1;
4300 }
4301 fn = "/dev/dahdi/channel";
4302 }
4303 fd = open(fn, O_RDWR | O_NONBLOCK);
4304 if (fd < 0) {
4305 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4306 return -1;
4307 }
4308 if (chan) {
4309 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4310 x = errno;
4311 close(fd);
4312 errno = x;
4313 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4314 return -1;
4315 }
4316 }
4317 bs = READ_SIZE;
4318 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4319 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4320 x = errno;
4321 close(fd);
4322 errno = x;
4323 return -1;
4324 }
4325 return fd;
4326 }
4327
4328 static void dahdi_close(int fd)
4329 {
4330 if (fd > 0)
4331 close(fd);
4332 }
4333
4334 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
4335 {
4336 dahdi_close(chan_pvt->subs[sub_num].dfd);
4337 chan_pvt->subs[sub_num].dfd = -1;
4338 }
4339
4340 #if defined(HAVE_PRI)
4341 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
4342 {
4343 dahdi_close(pri->pri.fds[fd_num]);
4344 pri->pri.fds[fd_num] = -1;
4345 }
4346 #endif /* defined(HAVE_PRI) */
4347
4348 #if defined(HAVE_SS7)
4349 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
4350 {
4351 dahdi_close(ss7->ss7.fds[fd_num]);
4352 ss7->ss7.fds[fd_num] = -1;
4353 }
4354 #endif /* defined(HAVE_SS7) */
4355
4356 static int dahdi_setlinear(int dfd, int linear)
4357 {
4358 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4359 }
4360
4361
4362 static int alloc_sub(struct dahdi_pvt *p, int x)
4363 {
4364 struct dahdi_bufferinfo bi;
4365 int res;
4366 if (p->subs[x].dfd >= 0) {
4367 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4368 return -1;
4369 }
4370
4371 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4372 if (p->subs[x].dfd <= -1) {
4373 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4374 return -1;
4375 }
4376
4377 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4378 if (!res) {
4379 bi.txbufpolicy = p->buf_policy;
4380 bi.rxbufpolicy = p->buf_policy;
4381 bi.numbufs = p->buf_no;
4382 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4383 if (res < 0) {
4384 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4385 }
4386 } else
4387 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4388
4389 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4390 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4391 dahdi_close_sub(p, x);
4392 p->subs[x].dfd = -1;
4393 return -1;
4394 }
4395 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4396 return 0;
4397 }
4398
4399 static int unalloc_sub(struct dahdi_pvt *p, int x)
4400 {
4401 if (!x) {
4402 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4403 return -1;
4404 }
4405 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4406 dahdi_close_sub(p, x);
4407 p->subs[x].linear = 0;
4408 p->subs[x].chan = 0;
4409 p->subs[x].owner = NULL;
4410 p->subs[x].inthreeway = 0;
4411 p->polarity = POLARITY_IDLE;
4412 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4413 return 0;
4414 }
4415
4416 static int digit_to_dtmfindex(char digit)
4417 {
4418 if (isdigit(digit))
4419 return DAHDI_TONE_DTMF_BASE + (digit - '0');
4420 else if (digit >= 'A' && digit <= 'D')
4421 return DAHDI_TONE_DTMF_A + (digit - 'A');
4422 else if (digit >= 'a' && digit <= 'd')
4423 return DAHDI_TONE_DTMF_A + (digit - 'a');
4424 else if (digit == '*')
4425 return DAHDI_TONE_DTMF_s;
4426 else if (digit == '#')
4427 return DAHDI_TONE_DTMF_p;
4428 else
4429 return -1;
4430 }
4431
4432 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
4433 {
4434 struct dahdi_pvt *pvt;
4435 int idx;
4436 int dtmf;
4437 int res;
4438
4439 pvt = ast_channel_tech_pvt(chan);
4440
4441 ast_mutex_lock(&pvt->lock);
4442
4443 idx = dahdi_get_index(chan, pvt, 0);
4444
4445 if ((idx != SUB_REAL) || !pvt->owner)
4446 goto out;
4447
4448 #ifdef HAVE_PRI
4449 switch (pvt->sig) {
4450 case SIG_PRI_LIB_HANDLE_CASES:
4451 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4452 if (!res)
4453 goto out;
4454 break;
4455 default:
4456 break;
4457 }
4458 #endif
4459 dtmf = digit_to_dtmfindex(digit);
4460 if (dtmf == -1) {
4461 /* Not a valid DTMF digit */
4462 goto out;
4463 }
4464
4465 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4466 char dial_str[] = { 'T', digit, '\0' };
4467
4468 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4469 if (!res) {
4470 pvt->dialing = 1;
4471 }
4472 } else {
4473 pvt->dialing = 1;
4474 pvt->begindigit = digit;
4475
4476 /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4477 dtmf = DAHDI_FLUSH_WRITE;
4478 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4479 if (res) {
4480 ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4481 pvt->channel, strerror(errno));
4482 }
4483
4484 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4485 ast_channel_name(chan), digit);
4486 }
4487
4488 out:
4489 ast_mutex_unlock(&pvt->lock);
4490
4491 return 0;
4492 }
4493
4494 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
4495 {
4496 struct dahdi_pvt *pvt;
4497 int res = 0;
4498 int idx;
4499 int x;
4500
4501 pvt = ast_channel_tech_pvt(chan);
4502
4503 ast_mutex_lock(&pvt->lock);
4504
4505 idx = dahdi_get_index(chan, pvt, 0);
4506
4507 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4508 goto out;
4509
4510 #ifdef HAVE_PRI
4511 /* This means that the digit was already sent via PRI signalling */
4512 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4513 goto out;
4514 }
4515 #endif
4516
4517 if (pvt->begindigit) {
4518 x = -1;
4519 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4520 ast_channel_name(chan), digit);
4521 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4522 pvt->dialing = 0;
4523 pvt->begindigit = 0;
4524 }
4525
4526 out:
4527 ast_mutex_unlock(&pvt->lock);
4528
4529 return res;
4530 }
4531
4532 static const char * const events[] = {
4533 "No event",
4534 "On hook",
4535 "Ring/Answered",
4536 "Wink/Flash",
4537 "Alarm",
4538 "No more alarm",
4539 "HDLC Abort",
4540 "HDLC Overrun",
4541 "HDLC Bad FCS",
4542 "Dial Complete",
4543 "Ringer On",
4544 "Ringer Off",
4545 "Hook Transition Complete",
4546 "Bits Changed",
4547 "Pulse Start",
4548 "Timer Expired",
4549 "Timer Ping",
4550 "Polarity Reversal",
4551 "Ring Begin",
4552 };
4553
4554 static struct {
4555 int alarm;
4556 char *name;
4557 } alarms[] = {
4558 { DAHDI_ALARM_RED, "Red Alarm" },
4559 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
4560 { DAHDI_ALARM_BLUE, "Blue Alarm" },
4561 { DAHDI_ALARM_RECOVER, "Recovering" },
4562 { DAHDI_ALARM_LOOPBACK, "Loopback" },
4563 { DAHDI_ALARM_NOTOPEN, "Not Open" },
4564 { DAHDI_ALARM_NONE, "None" },
4565 };
4566
4567 static char *alarm2str(int alm)
4568 {
4569 int x;
4570 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4571 if (alarms[x].alarm & alm)
4572 return alarms[x].name;
4573 }
4574 return alm ? "Unknown Alarm" : "No Alarm";
4575 }
4576
4577 static const char *event2str(int event)
4578 {
4579 static char buf[256];
4580 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4581 return events[event];
4582 sprintf(buf, "Event %d", event); /* safe */
4583 return buf;
4584 }
4585
4586 static char *dahdi_sig2str(int sig)
4587 {
4588 static char buf[256];
4589 switch (sig) {
4590 case SIG_EM:
4591 return "E & M Immediate";
4592 case SIG_EMWINK:
4593 return "E & M Wink";
4594 case SIG_EM_E1:
4595 return "E & M E1";
4596 case SIG_FEATD:
4597 return "Feature Group D (DTMF)";
4598 case SIG_FEATDMF:
4599 return "Feature Group D (MF)";
4600 case SIG_FEATDMF_TA:
4601 return "Feature Group D (MF) Tandem Access";
4602 case SIG_FEATB:
4603 return "Feature Group B (MF)";
4604 case SIG_E911:
4605 return "E911 (MF)";
4606 case SIG_FGC_CAMA:
4607 return "FGC/CAMA (Dialpulse)";
4608 case SIG_FGC_CAMAMF:
4609 return "FGC/CAMA (MF)";
4610 case SIG_FXSLS:
4611 return "FXS Loopstart";
4612 case SIG_FXSGS:
4613 return "FXS Groundstart";
4614 case SIG_FXSKS:
4615 return "FXS Kewlstart";
4616 case SIG_FXOLS:
4617 return "FXO Loopstart";
4618 case SIG_FXOGS:
4619 return "FXO Groundstart";
4620 case SIG_FXOKS:
4621 return "FXO Kewlstart";
4622 case SIG_PRI:
4623 return "ISDN PRI";
4624 case SIG_BRI:
4625 return "ISDN BRI Point to Point";
4626 case SIG_BRI_PTMP:
4627 return "ISDN BRI Point to MultiPoint";
4628 case SIG_SS7:
4629 return "SS7";
4630 case SIG_MFCR2:
4631 return "MFC/R2";
4632 case SIG_SF:
4633 return "SF (Tone) Immediate";
4634 case SIG_SFWINK:
4635 return "SF (Tone) Wink";
4636 case SIG_SF_FEATD:
4637 return "SF (Tone) with Feature Group D (DTMF)";
4638 case SIG_SF_FEATDMF:
4639 return "SF (Tone) with Feature Group D (MF)";
4640 case SIG_SF_FEATB:
4641 return "SF (Tone) with Feature Group B (MF)";
4642 case 0:
4643 return "Pseudo";
4644 default:
4645 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4646 return buf;
4647 }
4648 }
4649
4650 #define sig2str dahdi_sig2str
4651
4652 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
4653 {
4654 /* If the conference already exists, and we're already in it
4655 don't bother doing anything */
4656 struct dahdi_confinfo zi;
4657
4658 memset(&zi, 0, sizeof(zi));
4659 zi.chan = 0;
4660
4661 if (slavechannel > 0) {
4662 /* If we have only one slave, do a digital mon */
4663 zi.confmode = DAHDI_CONF_DIGITALMON;
4664 zi.confno = slavechannel;
4665 } else {
4666 if (!idx) {
4667 /* Real-side and pseudo-side both participate in conference */
4668 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4669 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4670 } else
4671 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4672 zi.confno = p->confno;
4673 }
4674 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4675 return 0;
4676 if (c->dfd < 0)
4677 return 0;
4678 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4679 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4680 return -1;
4681 }
4682 if (slavechannel < 1) {
4683 p->confno = zi.confno;
4684 }
4685 c->curconf = zi;
4686 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4687 return 0;
4688 }
4689
4690 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
4691 {
4692 /* If they're listening to our channel, they're ours */
4693 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4694 return 1;
4695 /* If they're a talker on our (allocated) conference, they're ours */
4696 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4697 return 1;
4698 return 0;
4699 }
4700
4701 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
4702 {
4703 struct dahdi_confinfo zi;
4704 if (/* Can't delete if there's no dfd */
4705 (c->dfd < 0) ||
4706 /* Don't delete from the conference if it's not our conference */
4707 !isourconf(p, c)
4708 /* Don't delete if we don't think it's conferenced at all (implied) */
4709 ) return 0;
4710 memset(&zi, 0, sizeof(zi));
4711 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4712 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4713 return -1;
4714 }
4715 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4716 memcpy(&c->curconf, &zi, sizeof(c->curconf));
4717 return 0;
4718 }
4719
4720 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
4721 {
4722 int x;
4723 int useslavenative;
4724 struct dahdi_pvt *slave = NULL;
4725 /* Start out optimistic */
4726 useslavenative = 1;
4727 /* Update conference state in a stateless fashion */
4728 for (x = 0; x < 3; x++) {
4729 /* Any three-way calling makes slave native mode *definitely* out
4730 of the question */
4731 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4732 useslavenative = 0;
4733 }
4734 /* If we don't have any 3-way calls, check to see if we have
4735 precisely one slave */
4736 if (useslavenative) {
4737 for (x = 0; x < MAX_SLAVES; x++) {
4738 if (p->slaves[x]) {
4739 if (slave) {
4740 /* Whoops already have a slave! No
4741 slave native and stop right away */
4742 slave = NULL;
4743 useslavenative = 0;
4744 break;
4745 } else {
4746 /* We have one slave so far */
4747 slave = p->slaves[x];
4748 }
4749 }
4750 }
4751 }
4752 /* If no slave, slave native definitely out */
4753 if (!slave)
4754 useslavenative = 0;
4755 else if (slave->law != p->law) {
4756 useslavenative = 0;
4757 slave = NULL;
4758 }
4759 if (out)
4760 *out = slave;
4761 return useslavenative;
4762 }
4763
4764 static int reset_conf(struct dahdi_pvt *p)
4765 {
4766 p->confno = -1;
4767 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4768 if (p->subs[SUB_REAL].dfd > -1) {
4769 struct dahdi_confinfo zi;
4770
4771 memset(&zi, 0, sizeof(zi));
4772 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4773 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4774 }
4775 return 0;
4776 }
4777
4778 void dahdi_conf_update(struct dahdi_pvt *p)
4779 {
4780 int needconf = 0;
4781 int x;
4782 int useslavenative;
4783 struct dahdi_pvt *slave = NULL;
4784
4785 useslavenative = isslavenative(p, &slave);
4786 /* Start with the obvious, general stuff */
4787 for (x = 0; x < 3; x++) {
4788 /* Look for three way calls */
4789 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4790 conf_add(p, &p->subs[x], x, 0);
4791 needconf++;
4792 } else {
4793 conf_del(p, &p->subs[x], x);
4794 }
4795 }
4796 /* If we have a slave, add him to our conference now. or DAX
4797 if this is slave native */
4798 for (x = 0; x < MAX_SLAVES; x++) {
4799 if (p->slaves[x]) {
4800 if (useslavenative)
4801 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4802 else {
4803 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4804 needconf++;
4805 }
4806 }
4807 }
4808 /* If we're supposed to be in there, do so now */
4809 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4810 if (useslavenative)
4811 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4812 else {
4813 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4814 needconf++;
4815 }
4816 }
4817 /* If we have a master, add ourselves to his conference */
4818 if (p->master) {
4819 if (isslavenative(p->master, NULL)) {
4820 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
4821 } else {
4822 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4823 }
4824 }
4825 if (!needconf) {
4826 /* Nobody is left (or should be left) in our conference.
4827 Kill it. */
4828 p->confno = -1;
4829 }
4830 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4831 }
4832
4833 void dahdi_ec_enable(struct dahdi_pvt *p)
4834 {
4835 int res;
4836 if (!p)
4837 return;
4838 if (p->echocanon) {
4839 ast_debug(1, "Echo cancellation already on\n");
4840 return;
4841 }
4842 if (p->digital) {
4843 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4844 return;
4845 }
4846 if (p->echocancel.head.tap_length) {
4847 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4848 switch (p->sig) {
4849 #if defined(HAVE_PRI)
4850 case SIG_PRI_LIB_HANDLE_CASES:
4851 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4852 /*
4853 * PRI nobch pseudo channel. Does not need ec anyway.
4854 * Does not handle ioctl(DAHDI_AUDIOMODE)
4855 */
4856 return;
4857 }
4858 /* Fall through */
4859 #endif /* defined(HAVE_PRI) */
4860 #if defined(HAVE_SS7)
4861 case SIG_SS7:
4862 #endif /* defined(HAVE_SS7) */
4863 {
4864 int x = 1;
4865
4866 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4867 if (res)
4868 ast_log(LOG_WARNING,
4869 "Unable to enable audio mode on channel %d (%s)\n",
4870 p->channel, strerror(errno));
4871 }
4872 break;
4873 default:
4874 break;
4875 }
4876 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4877 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4878 if (res) {
4879 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4880 } else {
4881 p->echocanon = 1;
4882 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4883 }
4884 } else
4885 ast_debug(1, "No echo cancellation requested\n");
4886 }
4887
4888 static void dahdi_train_ec(struct dahdi_pvt *p)
4889 {
4890 int x;
4891 int res;
4892
4893 if (p && p->echocanon && p->echotraining) {
4894 x = p->echotraining;
4895 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4896 if (res)
4897 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4898 else
4899 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4900 } else {
4901 ast_debug(1, "No echo training requested\n");
4902 }
4903 }
4904
4905 void dahdi_ec_disable(struct dahdi_pvt *p)
4906 {
4907 int res;
4908
4909 if (p->echocanon) {
4910 struct dahdi_echocanparams ecp = { .tap_length = 0 };
4911
4912 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4913
4914 if (res)
4915 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4916 else
4917 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4918 }
4919
4920 p->echocanon = 0;
4921 }
4922
4923 static int set_hwgain(int fd, float gain, int tx_direction)
4924 {
4925 struct dahdi_hwgain hwgain;
4926
4927 hwgain.newgain = gain * 10.0;
4928 hwgain.tx = tx_direction;
4929 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4930 }
4931
4932 /* perform a dynamic range compression transform on the given sample */
4933 static int drc_sample(int sample, float drc)
4934 {
4935 float neg;
4936 float shallow, steep;
4937 float max = SHRT_MAX;
4938
4939 neg = (sample < 0 ? -1 : 1);
4940 steep = drc*sample;
4941 shallow = neg*(max-max/drc)+(float)sample/drc;
4942 if (fabsf(steep) < fabsf(shallow)) {
4943 sample = steep;
4944 }
4945 else {
4946 sample = shallow;
4947 }
4948
4949 return sample;
4950 }
4951
4952
4953 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
4954 {
4955 int j;
4956 int k;
4957
4958 float linear_gain = pow(10.0, gain / 20.0);
4959
4960 switch (law) {
4961 case DAHDI_LAW_ALAW:
4962 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4963 if (gain || drc) {
4964 k = AST_ALAW(j);
4965 if (drc) {
4966 k = drc_sample(k, drc);
4967 }
4968 k = (float)k * linear_gain;
4969 if (k > 32767) {
4970 k = 32767;
4971 } else if (k < -32768) {
4972 k = -32768;
4973 }
4974 g->txgain[j] = AST_LIN2A(k);
4975 } else {
4976 g->txgain[j] = j;
4977 }
4978 }
4979 break;
4980 case DAHDI_LAW_MULAW:
4981 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4982 if (gain || drc) {
4983 k = AST_MULAW(j);
4984 if (drc) {
4985 k = drc_sample(k, drc);
4986 }
4987 k = (float)k * linear_gain;
4988 if (k > 32767) {
4989 k = 32767;
4990 } else if (k < -32768) {
4991 k = -32768;
4992 }
4993 g->txgain[j] = AST_LIN2MU(k);
4994
4995 } else {
4996 g->txgain[j] = j;
4997 }
4998 }
4999 break;
5000 }
5001 }
5002
5003 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
5004 {
5005 int j;
5006 int k;
5007 float linear_gain = pow(10.0, gain / 20.0);
5008
5009 switch (law) {
5010 case DAHDI_LAW_ALAW:
5011 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5012 if (gain || drc) {
5013 k = AST_ALAW(j);
5014 if (drc) {
5015 k = drc_sample(k, drc);
5016 }
5017 k = (float)k * linear_gain;
5018 if (k > 32767) {
5019 k = 32767;
5020 } else if (k < -32768) {
5021 k = -32768;
5022 }
5023 g->rxgain[j] = AST_LIN2A(k);
5024 } else {
5025 g->rxgain[j] = j;
5026 }
5027 }
5028 break;
5029 case DAHDI_LAW_MULAW:
5030 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5031 if (gain || drc) {
5032 k = AST_MULAW(j);
5033 if (drc) {
5034 k = drc_sample(k, drc);
5035 }
5036 k = (float)k * linear_gain;
5037 if (k > 32767) {
5038 k = 32767;
5039 } else if (k < -32768) {
5040 k = -32768;
5041 }
5042 g->rxgain[j] = AST_LIN2MU(k);
5043 } else {
5044 g->rxgain[j] = j;
5045 }
5046 }
5047 break;
5048 }
5049 }
5050
5051 static int set_actual_txgain(int fd, float gain, float drc, int law)
5052 {
5053 struct dahdi_gains g;
5054 int res;
5055
5056 memset(&g, 0, sizeof(g));
5057 res = ioctl(fd, DAHDI_GETGAINS, &g);
5058 if (res) {
5059 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5060 return res;
5061 }
5062
5063 fill_txgain(&g, gain, drc, law);
5064
5065 return ioctl(fd, DAHDI_SETGAINS, &g);
5066 }
5067
5068 static int set_actual_rxgain(int fd, float gain, float drc, int law)
5069 {
5070 struct dahdi_gains g;
5071 int res;
5072
5073 memset(&g, 0, sizeof(g));
5074 res = ioctl(fd, DAHDI_GETGAINS, &g);
5075 if (res) {
5076 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
5077 return res;
5078 }
5079
5080 fill_rxgain(&g, gain, drc, law);
5081
5082 return ioctl(fd, DAHDI_SETGAINS, &g);
5083 }
5084
5085 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
5086 {
5087 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5088 }
5089
5090 static int bump_gains(struct dahdi_pvt *p)
5091 {
5092 int res;
5093
5094 /* Bump receive gain by value stored in cid_rxgain */
5095 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5096 if (res) {
5097 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
5098 return -1;
5099 }
5100
5101 return 0;
5102 }
5103
5104 static int restore_gains(struct dahdi_pvt *p)
5105 {
5106 int res;
5107
5108 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5109 if (res) {
5110 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
5111 return -1;
5112 }
5113
5114 return 0;
5115 }
5116
5117 static inline int dahdi_set_hook(int fd, int hs)
5118 {
5119 int x, res;
5120
5121 x = hs;
5122 res = ioctl(fd, DAHDI_HOOK, &x);
5123
5124 if (res < 0) {
5125 if (errno == EINPROGRESS)
5126 return 0;
5127 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5128 /* will expectedly fail if phone is off hook during operation, such as during a restart */
5129 }
5130
5131 return res;
5132 }
5133
5134 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
5135 {
5136 int x, res;
5137
5138 x = muted;
5139 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5140 switch (p->sig) {
5141 #if defined(HAVE_PRI)
5142 case SIG_PRI_LIB_HANDLE_CASES:
5143 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5144 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
5145 break;
5146 }
5147 /* Fall through */
5148 #endif /* defined(HAVE_PRI) */
5149 #if defined(HAVE_SS7)
5150 case SIG_SS7:
5151 #endif /* defined(HAVE_SS7) */
5152 {
5153 int y = 1;
5154
5155 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5156 if (res)
5157 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
5158 p->channel, strerror(errno));
5159 }
5160 break;
5161 default:
5162 break;
5163 }
5164 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
5165 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5166 if (res < 0)
5167 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
5168 return res;
5169 }
5170
5171 static int save_conference(struct dahdi_pvt *p)
5172 {
5173 struct dahdi_confinfo c;
5174 int res;
5175 if (p->saveconf.confmode) {
5176 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
5177 return -1;
5178 }
5179 p->saveconf.chan = 0;
5180 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
5181 if (res) {
5182 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
5183 p->saveconf.confmode = 0;
5184 return -1;
5185 }
5186 memset(&c, 0, sizeof(c));
5187 c.confmode = DAHDI_CONF_NORMAL;
5188 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
5189 if (res) {
5190 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
5191 return -1;
5192 }
5193 ast_debug(1, "Disabled conferencing\n");
5194 return 0;
5195 }
5196
5197 static int restore_conference(struct dahdi_pvt *p)
5198 {
5199 int res;
5200 if (p->saveconf.confmode) {
5201 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5202 p->saveconf.confmode = 0;
5203 if (res) {
5204 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5205 return -1;
5206 }
5207 ast_debug(1, "Restored conferencing\n");
5208 }
5209 return 0;
5210 }
5211
5212 static int send_cwcidspill(struct dahdi_pvt *p)
5213 {
5214 p->callwaitcas = 0;
5215 p->cidcwexpire = 0;
5216 p->cid_suppress_expire = 0;
5217 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
5218 return -1;
5219 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
5220 /* Make sure we account for the end */
5221 p->cidlen += READ_SIZE * 4;
5222 p->cidpos = 0;
5223 send_callerid(p);
5224 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5225 return 0;
5226 }
5227
5228 static int has_voicemail(struct dahdi_pvt *p)
5229 {
5230 int new_msgs;
5231 RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5232
5233 mwi_message = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), p->mailbox);
5234 if (mwi_message) {
5235 struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5236 new_msgs = mwi_state->new_msgs;
5237 } else {
5238 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
5239 }
5240
5241 return new_msgs;
5242 }
5243
5244
5245
5246 static int send_callerid(struct dahdi_pvt *p)
5247 {
5248 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5249 int res;
5250 /* Take out of linear mode if necessary */
5251 if (p->subs[SUB_REAL].linear) {
5252 p->subs[SUB_REAL].linear = 0;
5253 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
5254 }
5255 while (p->cidpos < p->cidlen) {
5256 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5257 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5258 if (res < 0) {
5259 if (errno == EAGAIN)
5260 return 0;
5261 else {
5262 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5263 return -1;
5264 }
5265 }
5266 if (!res)
5267 return 0;
5268 p->cidpos += res;
5269 }
5270 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
5271 ast_free(p->cidspill);
5272 p->cidspill = NULL;
5273 if (p->callwaitcas) {
5274 /* Wait for CID/CW to expire */
5275 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
5276 p->cid_suppress_expire = p->cidcwexpire;
5277 } else
5278 restore_conference(p);
5279 return 0;
5280 }
5281
5282 static int dahdi_callwait(struct ast_channel *ast)
5283 {
5284 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5285
5286 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
5287 if (p->cidspill) {
5288 ast_log(LOG_WARNING, "Spill already exists?!?\n");
5289 ast_free(p->cidspill);
5290 }
5291
5292 /*
5293 * SAS: Subscriber Alert Signal, 440Hz for 300ms
5294 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5295 */
5296 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5297 return -1;
5298 save_conference(p);
5299 /* Silence */
5300 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5301 if (!p->callwaitrings && p->callwaitingcallerid) {
5302 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5303 p->callwaitcas = 1;
5304 p->cidlen = 2400 + 680 + READ_SIZE * 4;
5305 } else {
5306 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5307 p->callwaitcas = 0;
5308 p->cidlen = 2400 + READ_SIZE * 4;
5309 }
5310 p->cidpos = 0;
5311 send_callerid(p);
5312
5313 return 0;
5314 }
5315
5316 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
5317 {
5318 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5319 int x, res, mysig;
5320 char *dest;
5321 AST_DECLARE_APP_ARGS(args,
5322 AST_APP_ARG(group); /* channel/group token */
5323 AST_APP_ARG(ext); /* extension token */
5324 //AST_APP_ARG(opts); /* options token */
5325 AST_APP_ARG(other); /* Any remining unused arguments */
5326 );
5327
5328 ast_mutex_lock(&p->lock);
5329 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5330
5331 /* Split the dialstring */
5332 dest = ast_strdupa(rdest);
5333 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5334 if (!args.ext) {
5335 args.ext = "";
5336 }
5337
5338 #if defined(HAVE_PRI)
5339 if (dahdi_sig_pri_lib_handles(p->sig)) {
5340 char *subaddr;
5341
5342 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5343
5344 /* Remove any subaddress for uniformity with incoming calls. */
5345 subaddr = strchr(p->exten, ':');
5346 if (subaddr) {
5347 *subaddr = '\0';
5348 }
5349 } else
5350 #endif /* defined(HAVE_PRI) */
5351 {
5352 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5353 }
5354
5355 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5356 p->subs[SUB_REAL].needbusy = 1;
5357 ast_mutex_unlock(&p->lock);
5358 return 0;
5359 }
5360 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
5361 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5362 ast_mutex_unlock(&p->lock);
5363 return -1;
5364 }
5365 p->waitingfordt.tv_sec = 0;
5366 p->dialednone = 0;
5367 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5368 {
5369 /* Special pseudo -- automatically up */
5370 ast_setstate(ast, AST_STATE_UP);
5371 ast_mutex_unlock(&p->lock);
5372 return 0;
5373 }
5374 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5375 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5376 if (res)
5377 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5378 p->outgoing = 1;
5379
5380 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
5381 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5382 } else {
5383 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5384 }
5385
5386 #ifdef HAVE_PRI
5387 if (dahdi_sig_pri_lib_handles(p->sig)) {
5388 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5389 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5390 ast_mutex_unlock(&p->lock);
5391 return res;
5392 }
5393 #endif
5394
5395 #if defined(HAVE_SS7)
5396 if (p->sig == SIG_SS7) {
5397 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5398 ast_mutex_unlock(&p->lock);
5399 return res;
5400 }
5401 #endif /* defined(HAVE_SS7) */
5402
5403 /* If this is analog signalling we can exit here */
5404 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5405 p->callwaitrings = 0;
5406 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5407 ast_mutex_unlock(&p->lock);
5408 return res;
5409 }
5410
5411 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5412 switch (mysig) {
5413 case 0:
5414 /* Special pseudo -- automatically up*/
5415 ast_setstate(ast, AST_STATE_UP);
5416 break;
5417 case SIG_MFCR2:
5418 break;
5419 default:
5420 ast_debug(1, "not yet implemented\n");
5421 ast_mutex_unlock(&p->lock);
5422 return -1;
5423 }
5424
5425 #ifdef HAVE_OPENR2
5426 if (p->mfcr2) {
5427 openr2_calling_party_category_t chancat;
5428 int callres = 0;
5429 char *c, *l;
5430
5431 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5432 p->dialdest[0] = '\0';
5433
5434 c = args.ext;
5435 if (!p->hidecallerid) {
5436 l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
5437 } else {
5438 l = NULL;
5439 }
5440 if (strlen(c) < p->stripmsd) {
5441 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5442 ast_mutex_unlock(&p->lock);
5443 return -1;
5444 }
5445 p->dialing = 1;
5446 chancat = dahdi_r2_get_channel_category(ast);
5447 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5448 if (-1 == callres) {
5449 ast_mutex_unlock(&p->lock);
5450 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5451 return -1;
5452 }
5453 p->mfcr2_call_accepted = 0;
5454 p->mfcr2_progress_sent = 0;
5455 ast_setstate(ast, AST_STATE_DIALING);
5456 }
5457 #endif /* HAVE_OPENR2 */
5458 ast_mutex_unlock(&p->lock);
5459 return 0;
5460 }
5461
5462 /*!
5463 * \internal
5464 * \brief Insert the given chan_dahdi interface structure into the interface list.
5465 * \since 1.8
5466 *
5467 * \param pvt chan_dahdi private interface structure to insert.
5468 *
5469 * \details
5470 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5471 * Any duplicates are inserted after the existing entries.
5472 *
5473 * \note The new interface must not already be in the list.
5474 */
5475 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
5476 {
5477 struct dahdi_pvt *cur;
5478
5479 pvt->which_iflist = DAHDI_IFLIST_MAIN;
5480
5481 /* Find place in middle of list for the new interface. */
5482 for (cur = iflist; cur; cur = cur->next) {
5483 if (pvt->channel < cur->channel) {
5484 /* New interface goes before the current interface. */
5485 pvt->prev = cur->prev;
5486 pvt->next = cur;
5487 if (cur->prev) {
5488 /* Insert into the middle of the list. */
5489 cur->prev->next = pvt;
5490 } else {
5491 /* Insert at head of list. */
5492 iflist = pvt;
5493 }
5494 cur->prev = pvt;
5495 return;
5496 }
5497 }
5498
5499 /* New interface goes onto the end of the list */
5500 pvt->prev = ifend;
5501 pvt->next = NULL;
5502 if (ifend) {
5503 ifend->next = pvt;
5504 }
5505 ifend = pvt;
5506 if (!iflist) {
5507 /* List was empty */
5508 iflist = pvt;
5509 }
5510 }
5511
5512 /*!
5513 * \internal
5514 * \brief Extract the given chan_dahdi interface structure from the interface list.
5515 * \since 1.8
5516 *
5517 * \param pvt chan_dahdi private interface structure to extract.
5518 *
5519 * \note
5520 * The given interface structure can be either in the interface list or a stand alone
5521 * structure that has not been put in the list if the next and prev pointers are NULL.
5522 */
5523 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
5524 {
5525 /* Extract from the forward chain. */
5526 if (pvt->prev) {
5527 pvt->prev->next = pvt->next;
5528 } else if (iflist == pvt) {
5529 /* Node is at the head of the list. */
5530 iflist = pvt->next;
5531 }
5532
5533 /* Extract from the reverse chain. */
5534 if (pvt->next) {
5535 pvt->next->prev = pvt->prev;
5536 } else if (ifend == pvt) {
5537 /* Node is at the end of the list. */
5538 ifend = pvt->prev;
5539 }
5540
5541 /* Node is no longer in the list. */
5542 pvt->which_iflist = DAHDI_IFLIST_NONE;
5543 pvt->prev = NULL;
5544 pvt->next = NULL;
5545 }
5546
5547 #if defined(HAVE_PRI)
5548 /*!
5549 * \internal
5550 * \brief Insert the given chan_dahdi interface structure into the no B channel list.
5551 * \since 1.8
5552 *
5553 * \param pri sig_pri span control structure holding no B channel list.
5554 * \param pvt chan_dahdi private interface structure to insert.
5555 *
5556 * \details
5557 * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5558 * Any duplicates are inserted after the existing entries.
5559 *
5560 * \note The new interface must not already be in the list.
5561 */
5562 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5563 {
5564 struct dahdi_pvt *cur;
5565
5566 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
5567
5568 /* Find place in middle of list for the new interface. */
5569 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
5570 if (pvt->channel < cur->channel) {
5571 /* New interface goes before the current interface. */
5572 pvt->prev = cur->prev;
5573 pvt->next = cur;
5574 if (cur->prev) {
5575 /* Insert into the middle of the list. */
5576 cur->prev->next = pvt;
5577 } else {
5578 /* Insert at head of list. */
5579 pri->no_b_chan_iflist = pvt;
5580 }
5581 cur->prev = pvt;
5582 return;
5583 }
5584 }
5585
5586 /* New interface goes onto the end of the list */
5587 pvt->prev = pri->no_b_chan_end;
5588 pvt->next = NULL;
5589 if (pri->no_b_chan_end) {
5590 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
5591 }
5592 pri->no_b_chan_end = pvt;
5593 if (!pri->no_b_chan_iflist) {
5594 /* List was empty */
5595 pri->no_b_chan_iflist = pvt;
5596 }
5597 }
5598 #endif /* defined(HAVE_PRI) */
5599
5600 #if defined(HAVE_PRI)
5601 /*!
5602 * \internal
5603 * \brief Extract the given chan_dahdi interface structure from the no B channel list.
5604 * \since 1.8
5605 *
5606 * \param pri sig_pri span control structure holding no B channel list.
5607 * \param pvt chan_dahdi private interface structure to extract.
5608 *
5609 * \note
5610 * The given interface structure can be either in the interface list or a stand alone
5611 * structure that has not been put in the list if the next and prev pointers are NULL.
5612 */
5613 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5614 {
5615 /* Extract from the forward chain. */
5616 if (pvt->prev) {
5617 pvt->prev->next = pvt->next;
5618 } else if (pri->no_b_chan_iflist == pvt) {
5619 /* Node is at the head of the list. */
5620 pri->no_b_chan_iflist = pvt->next;
5621 }
5622
5623 /* Extract from the reverse chain. */
5624 if (pvt->next) {
5625 pvt->next->prev = pvt->prev;
5626 } else if (pri->no_b_chan_end == pvt) {
5627 /* Node is at the end of the list. */
5628 pri->no_b_chan_end = pvt->prev;
5629 }
5630
5631 /* Node is no longer in the list. */
5632 pvt->which_iflist = DAHDI_IFLIST_NONE;
5633 pvt->prev = NULL;
5634 pvt->next = NULL;
5635 }
5636 #endif /* defined(HAVE_PRI) */
5637
5638 #if defined(HAVE_PRI)
5639 /*!
5640 * \internal
5641 * \brief Unlink the channel interface from the PRI private pointer array.
5642 * \since 1.8
5643 *
5644 * \param pvt chan_dahdi private interface structure to unlink.
5645 */
5646 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
5647 {
5648 unsigned idx;
5649 struct sig_pri_span *pri;
5650
5651 pri = pvt->pri;
5652 if (!pri) {
5653 /* Not PRI signaling so cannot be in a PRI private pointer array. */
5654 return;
5655 }
5656 ast_mutex_lock(&pri->lock);
5657 for (idx = 0; idx < pri->numchans; ++idx) {
5658 if (pri->pvts[idx] == pvt->sig_pvt) {
5659 pri->pvts[idx] = NULL;
5660 ast_mutex_unlock(&pri->lock);
5661 return;
5662 }
5663 }
5664 ast_mutex_unlock(&pri->lock);
5665 }
5666 #endif /* defined(HAVE_PRI) */
5667
5668 #if defined(HAVE_SS7)
5669 /*!
5670 * \internal
5671 * \brief Unlink the channel interface from the SS7 private pointer array.
5672 * \since 1.8
5673 *
5674 * \param pvt chan_dahdi private interface structure to unlink.
5675 */
5676 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
5677 {
5678 unsigned idx;
5679 struct sig_ss7_linkset *ss7;
5680
5681 ss7 = pvt->ss7;
5682 if (!ss7) {
5683 /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
5684 return;
5685 }
5686 ast_mutex_lock(&ss7->lock);
5687 for (idx = 0; idx < ss7->numchans; ++idx) {
5688 if (ss7->pvts[idx] == pvt->sig_pvt) {
5689 ss7->pvts[idx] = NULL;
5690 ast_mutex_unlock(&ss7->lock);
5691 return;
5692 }
5693 }
5694 ast_mutex_unlock(&ss7->lock);
5695 }
5696 #endif /* defined(HAVE_SS7) */
5697
5698 #if defined(HAVE_OPENR2)
5699 /*!
5700 * \internal
5701 * \brief Unlink the channel interface from the MFC/R2 private pointer array.
5702 *
5703 * \param pvt chan_dahdi private interface structure to unlink.
5704 */
5705 static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)
5706 {
5707 unsigned idx;
5708 struct dahdi_mfcr2 *mfcr2;
5709 int should_destroy_link = 0;
5710
5711 ast_mutex_lock(&pvt->lock);
5712 if (pvt->r2chan) {
5713 ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);
5714 openr2_chan_disable_read(pvt->r2chan);
5715 }
5716 mfcr2 = pvt->mfcr2;
5717 if (mfcr2) {
5718 for (idx = 0; idx < mfcr2->numchans; ++idx) {
5719 if (mfcr2->pvts[idx] == pvt) {
5720 ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);
5721 mfcr2->pvts[idx] = NULL;
5722 mfcr2->live_chans--;
5723 break;
5724 }
5725 }
5726 if (!mfcr2->live_chans) {
5727 ast_debug(1, "MFC/R2 link is now empty\n");
5728 should_destroy_link = 1;
5729 }
5730 }
5731 ast_mutex_unlock(&pvt->lock);
5732 if (should_destroy_link) {
5733 ast_debug(1, "MFC/R2 link is now empty\n");
5734 mfcr2_queue_for_destruction(pvt);
5735 }
5736 }
5737 #endif /* defined(HAVE_OPENR2) */
5738
5739 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
5740 {
5741 if (cur->next && cur->next->span == cur->span) {
5742 return cur->next;
5743 } else if (cur->prev && cur->prev->span == cur->span) {
5744 return cur->prev;
5745 }
5746
5747 return NULL;
5748 }
5749
5750 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5751 {
5752 struct dahdi_pvt *p = pvt;
5753
5754 if (p->manages_span_alarms) {
5755 struct dahdi_pvt *next = find_next_iface_in_span(p);
5756 if (next) {
5757 next->manages_span_alarms = 1;
5758 }
5759 }
5760
5761 /* Remove channel from the list */
5762 #if defined(HAVE_PRI)
5763 dahdi_unlink_pri_pvt(p);
5764 #endif /* defined(HAVE_PRI) */
5765 #if defined(HAVE_SS7)
5766 dahdi_unlink_ss7_pvt(p);
5767 #endif /* defined(HAVE_SS7) */
5768 #if defined(HAVE_OPENR2)
5769 dahdi_unlink_mfcr2_pvt(p);
5770 #endif /* defined(HAVE_SS7) */
5771 switch (pvt->which_iflist) {
5772 case DAHDI_IFLIST_NONE:
5773 break;
5774 case DAHDI_IFLIST_MAIN:
5775 dahdi_iflist_extract(p);
5776 break;
5777 #if defined(HAVE_PRI)
5778 case DAHDI_IFLIST_NO_B_CHAN:
5779 if (p->pri) {
5780 dahdi_nobch_extract(p->pri, p);
5781 }
5782 break;
5783 #endif /* defined(HAVE_PRI) */
5784 }
5785
5786 if (p->sig_pvt) {
5787 if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5788 analog_delete(p->sig_pvt);
5789 }
5790 switch (p->sig) {
5791 #if defined(HAVE_PRI)
5792 case SIG_PRI_LIB_HANDLE_CASES:
5793 sig_pri_chan_delete(p->sig_pvt);
5794 break;
5795 #endif /* defined(HAVE_PRI) */
5796 #if defined(HAVE_SS7)
5797 case SIG_SS7:
5798 sig_ss7_chan_delete(p->sig_pvt);
5799 break;
5800 #endif /* defined(HAVE_SS7) */
5801 default:
5802 break;
5803 }
5804 }
5805 ast_free(p->cidspill);
5806 if (p->use_smdi) {
5807 ao2_cleanup(p->smdi_iface);
5808 }
5809 if (p->mwi_event_sub) {
5810 p->mwi_event_sub = ast_mwi_unsubscribe(p->mwi_event_sub);
5811 }
5812 if (p->vars) {
5813 ast_variables_destroy(p->vars);
5814 }
5815 if (p->cc_params) {
5816 ast_cc_config_params_destroy(p->cc_params);
5817 }
5818
5819 p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
5820 p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
5821
5822 ast_mutex_destroy(&p->lock);
5823 dahdi_close_sub(p, SUB_REAL);
5824 if (p->owner) {
5825 ast_channel_tech_pvt_set(p->owner, NULL);
5826 }
5827 ast_free(p);
5828 }
5829
5830 static void destroy_channel(struct dahdi_pvt *cur, int now)
5831 {
5832 int i;
5833
5834 if (!now) {
5835 /* Do not destroy the channel now if it is owned by someone. */
5836 if (cur->owner) {
5837 return;
5838 }
5839 for (i = 0; i < 3; i++) {
5840 if (cur->subs[i].owner) {
5841 return;
5842 }
5843 }
5844 }
5845 destroy_dahdi_pvt(cur);
5846 }
5847
5848 static void destroy_all_channels(void)
5849 {
5850 int chan;
5851 #if defined(HAVE_PRI)
5852 unsigned span;
5853 struct sig_pri_span *pri;
5854 #endif /* defined(HAVE_PRI) */
5855 struct dahdi_pvt *p;
5856
5857 while (num_restart_pending) {
5858 usleep(1);
5859 }
5860
5861 ast_mutex_lock(&iflock);
5862 /* Destroy all the interfaces and free their memory */
5863 while (iflist) {
5864 p = iflist;
5865
5866 chan = p->channel;
5867 #if defined(HAVE_PRI_SERVICE_MESSAGES)
5868 {
5869 char db_chan_name[20];
5870 char db_answer[5];
5871 char state;
5872 int why = -1;
5873
5874 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5875 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5876 sscanf(db_answer, "%1c:%30d", &state, &why);
5877 }
5878 if (!why) {
5879 /* SRVST persistence is not required */
5880 ast_db_del(db_chan_name, SRVST_DBKEY);
5881 }
5882 }
5883 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5884 /* Free associated memory */
5885 destroy_dahdi_pvt(p);
5886 ast_verb(3, "Unregistered channel %d\n", chan);
5887 }
5888 ifcount = 0;
5889 ast_mutex_unlock(&iflock);
5890
5891 #if defined(HAVE_PRI)
5892 /* Destroy all of the no B channel interface lists */
5893 for (span = 0; span < NUM_SPANS; ++span) {
5894 if (!pris[span].dchannels[0]) {
5895 break;
5896 }
5897 pri = &pris[span].pri;
5898 ast_mutex_lock(&pri->lock);
5899 while (pri->no_b_chan_iflist) {
5900 p = pri->no_b_chan_iflist;
5901
5902 /* Free associated memory */
5903 destroy_dahdi_pvt(p);
5904 }
5905 ast_mutex_unlock(&pri->lock);
5906 }
5907 #endif /* defined(HAVE_PRI) */
5908 }
5909
5910 #if defined(HAVE_PRI)
5911 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5912
5913 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
5914 {
5915 /* Data will be our digit string */
5916 struct dahdi_pvt *p;
5917
5918 if (ast_strlen_zero(digits)) {
5919 ast_debug(1, "No digit string sent to application!\n");
5920 return -1;
5921 }
5922
5923 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
5924
5925 if (!p) {
5926 ast_debug(1, "Unable to find technology private\n");
5927 return -1;
5928 }
5929
5930 pri_send_keypad_facility_exec(p->sig_pvt, digits);
5931
5932 return 0;
5933 }
5934 #endif /* defined(HAVE_PRI) */
5935
5936 #if defined(HAVE_PRI)
5937 #if defined(HAVE_PRI_PROG_W_CAUSE)
5938 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
5939
5940 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
5941 {
5942 /* Data will be our digit string */
5943 struct dahdi_pvt *pvt;
5944 char *parse;
5945 int res;
5946 AST_DECLARE_APP_ARGS(args,
5947 AST_APP_ARG(destination);
5948 AST_APP_ARG(original);
5949 AST_APP_ARG(reason);
5950 );
5951
5952 if (ast_strlen_zero(data)) {
5953 ast_debug(1, "No data sent to application!\n");
5954 return -1;
5955 }
5956 if (ast_channel_tech(chan) != &dahdi_tech) {
5957 ast_debug(1, "Only DAHDI technology accepted!\n");
5958 return -1;
5959 }
5960 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
5961 if (!pvt) {
5962 ast_debug(1, "Unable to find technology private\n");
5963 return -1;
5964 }
5965 switch (pvt->sig) {
5966 case SIG_PRI_LIB_HANDLE_CASES:
5967 break;
5968 default:
5969 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
5970 ast_channel_name(chan));
5971 return -1;
5972 }
5973
5974 parse = ast_strdupa(data);
5975 AST_STANDARD_APP_ARGS(args, parse);
5976
5977 if (ast_strlen_zero(args.destination)) {
5978 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
5979 return -1;
5980 }
5981
5982 if (ast_strlen_zero(args.original)) {
5983 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
5984 args.original = NULL;
5985 }
5986
5987 if (ast_strlen_zero(args.reason)) {
5988 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
5989 args.reason = NULL;
5990 }
5991
5992 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
5993 args.destination, args.original, args.reason);
5994 if (!res) {
5995 /*
5996 * Wait up to 5 seconds for a reply before hanging up this call
5997 * leg if the peer does not disconnect first.
5998 */
5999 ast_safe_sleep(chan, 5000);
6000 }
6001
6002 return -1;
6003 }
6004 #endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
6005 #endif /* defined(HAVE_PRI) */
6006
6007 #if defined(HAVE_OPENR2)
6008 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
6009
6010 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
6011 {
6012 /* data is whether to accept with charge or no charge */
6013 openr2_call_mode_t accept_mode;
6014 int res, timeout, maxloops;
6015 struct ast_frame *f;
6016 struct dahdi_pvt *p;
6017 char *parse;
6018 AST_DECLARE_APP_ARGS(args,
6019 AST_APP_ARG(charge);
6020 );
6021
6022 if (ast_strlen_zero(data)) {
6023 ast_debug(1, "No data sent to application!\n");
6024 return -1;
6025 }
6026
6027 if (ast_channel_tech(chan) != &dahdi_tech) {
6028 ast_debug(1, "Only DAHDI technology accepted!\n");
6029 return -1;
6030 }
6031
6032 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6033 if (!p) {
6034 ast_debug(1, "Unable to find technology private!\n");
6035 return -1;
6036 }
6037
6038 parse = ast_strdupa(data);
6039 AST_STANDARD_APP_ARGS(args, parse);
6040
6041 if (ast_strlen_zero(args.charge)) {
6042 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
6043 return -1;
6044 }
6045
6046 ast_mutex_lock(&p->lock);
6047 if (!p->mfcr2 || !p->mfcr2call) {
6048 ast_mutex_unlock(&p->lock);
6049 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
6050 return -1;
6051 }
6052
6053 if (p->mfcr2_call_accepted) {
6054 ast_mutex_unlock(&p->lock);
6055 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
6056 return 0;
6057 }
6058 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
6059 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
6060 ast_mutex_unlock(&p->lock);
6061 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6062 return -1;
6063 }
6064 ast_mutex_unlock(&p->lock);
6065
6066 res = 0;
6067 timeout = 100;
6068 maxloops = 50; /* wait up to 5 seconds */
6069 /* we need to read() until the call is accepted */
6070 while (maxloops > 0) {
6071 maxloops--;
6072 if (ast_check_hangup(chan)) {
6073 break;
6074 }
6075 res = ast_waitfor(chan, timeout);
6076 if (res < 0) {
6077 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
6078 res = -1;
6079 break;
6080 }
6081 if (res == 0) {
6082 continue;
6083 }
6084 res = 0;
6085 f = ast_read(chan);
6086 if (!f) {
6087 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
6088 res = -1;
6089 break;
6090 }
6091 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
6092 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
6093 ast_frfree(f);
6094 res = -1;
6095 break;
6096 }
6097 ast_frfree(f);
6098 ast_mutex_lock(&p->lock);
6099 if (p->mfcr2_call_accepted) {
6100 ast_mutex_unlock(&p->lock);
6101 ast_debug(1, "Accepted MFC/R2 call!\n");
6102 break;
6103 }
6104 ast_mutex_unlock(&p->lock);
6105 }
6106 if (res == -1) {
6107 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
6108 }
6109 return res;
6110 }
6111
6112 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
6113 {
6114 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
6115 switch (cause) {
6116 case AST_CAUSE_USER_BUSY:
6117 case AST_CAUSE_CALL_REJECTED:
6118 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
6119 r2cause = OR2_CAUSE_BUSY_NUMBER;
6120 break;
6121
6122 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
6123 case AST_CAUSE_SWITCH_CONGESTION:
6124 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6125 break;
6126
6127 case AST_CAUSE_UNALLOCATED:
6128 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6129 break;
6130
6131 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
6132 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
6133 r2cause = OR2_CAUSE_OUT_OF_ORDER;
6134 break;
6135
6136 case AST_CAUSE_NO_ANSWER:
6137 case AST_CAUSE_NO_USER_RESPONSE:
6138 r2cause = OR2_CAUSE_NO_ANSWER;
6139 break;
6140
6141 default:
6142 r2cause = OR2_CAUSE_NORMAL_CLEARING;
6143 break;
6144 }
6145 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
6146 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
6147 return r2cause;
6148 }
6149 #endif
6150
6151 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
6152 {
6153 if (p->bufferoverrideinuse) {
6154 /* faxbuffers are in use, revert them */
6155 struct dahdi_bufferinfo bi = {
6156 .txbufpolicy = p->buf_policy,
6157 .rxbufpolicy = p->buf_policy,
6158 .bufsize = p->bufsize,
6159 .numbufs = p->buf_no
6160 };
6161 int bpres;
6162
6163 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6164 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6165 }
6166 p->bufferoverrideinuse = 0;
6167 return bpres;
6168 }
6169
6170 return -1;
6171 }
6172
6173 static int dahdi_hangup(struct ast_channel *ast)
6174 {
6175 int res = 0;
6176 int idx,x;
6177 int law;
6178 /*static int restore_gains(struct dahdi_pvt *p);*/
6179 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6180 struct dahdi_params par;
6181
6182 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6183 if (!ast_channel_tech_pvt(ast)) {
6184 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6185 return 0;
6186 }
6187
6188 ast_mutex_lock(&p->lock);
6189 p->exten[0] = '\0';
6190 /* Always use sig_analog hangup handling for operator mode */
6191 if (dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6192 p->oprmode = 0;
6193 dahdi_confmute(p, 0);
6194 restore_gains(p);
6195 p->ignoredtmf = 0;
6196 p->waitingfordt.tv_sec = 0;
6197
6198 res = analog_hangup(p->sig_pvt, ast);
6199 revert_fax_buffers(p, ast);
6200
6201 goto hangup_out;
6202 } else {
6203 p->cid_num[0] = '\0';
6204 p->cid_name[0] = '\0';
6205 p->cid_subaddr[0] = '\0';
6206 }
6207
6208 #if defined(HAVE_PRI)
6209 if (dahdi_sig_pri_lib_handles(p->sig)) {
6210 x = 1;
6211 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6212
6213 dahdi_confmute(p, 0);
6214 p->muting = 0;
6215 restore_gains(p);
6216 if (p->dsp) {
6217 ast_dsp_free(p->dsp);
6218 p->dsp = NULL;
6219 }
6220 p->ignoredtmf = 0;
6221
6222 /* Real channel, do some fixup */
6223 p->subs[SUB_REAL].owner = NULL;
6224 p->subs[SUB_REAL].needbusy = 0;
6225 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6226
6227 p->owner = NULL;
6228 p->cid_tag[0] = '\0';
6229 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6230 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6231 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6232 p->outgoing = 0;
6233 p->digital = 0;
6234 p->faxhandled = 0;
6235 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6236
6237 revert_fax_buffers(p, ast);
6238
6239 p->law = p->law_default;
6240 law = p->law_default;
6241 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6242 if (res < 0) {
6243 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6244 p->channel, strerror(errno));
6245 }
6246
6247 sig_pri_hangup(p->sig_pvt, ast);
6248
6249 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6250 dahdi_ec_disable(p);
6251
6252 x = 0;
6253 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6254 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6255
6256 p->rdnis[0] = '\0';
6257 dahdi_conf_update(p);
6258 reset_conf(p);
6259
6260 /* Restore data mode */
6261 x = 0;
6262 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6263
6264 if (num_restart_pending == 0) {
6265 restart_monitor();
6266 }
6267 goto hangup_out;
6268 }
6269 #endif /* defined(HAVE_PRI) */
6270
6271 #if defined(HAVE_SS7)
6272 if (p->sig == SIG_SS7) {
6273 x = 1;
6274 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6275
6276 dahdi_confmute(p, 0);
6277 p->muting = 0;
6278 restore_gains(p);
6279 if (p->dsp) {
6280 ast_dsp_free(p->dsp);
6281 p->dsp = NULL;
6282 }
6283 p->ignoredtmf = 0;
6284
6285 /* Real channel, do some fixup */
6286 p->subs[SUB_REAL].owner = NULL;
6287 p->subs[SUB_REAL].needbusy = 0;
6288 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6289
6290 p->owner = NULL;
6291 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6292 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6293 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6294 p->outgoing = 0;
6295 p->digital = 0;
6296 p->faxhandled = 0;
6297 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6298
6299 revert_fax_buffers(p, ast);
6300
6301 p->law = p->law_default;
6302 law = p->law_default;
6303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6304 if (res < 0) {
6305 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6306 p->channel, strerror(errno));
6307 }
6308
6309 sig_ss7_hangup(p->sig_pvt, ast);
6310
6311 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6312 dahdi_ec_disable(p);
6313
6314 x = 0;
6315 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6316 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6317
6318 dahdi_conf_update(p);
6319 reset_conf(p);
6320
6321 /* Restore data mode */
6322 x = 0;
6323 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6324
6325 if (num_restart_pending == 0) {
6326 restart_monitor();
6327 }
6328 goto hangup_out;
6329 }
6330 #endif /* defined(HAVE_SS7) */
6331
6332 idx = dahdi_get_index(ast, p, 1);
6333
6334 dahdi_confmute(p, 0);
6335 p->muting = 0;
6336 restore_gains(p);
6337 if (p->origcid_num) {
6338 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6339 ast_free(p->origcid_num);
6340 p->origcid_num = NULL;
6341 }
6342 if (p->origcid_name) {
6343 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6344 ast_free(p->origcid_name);
6345 p->origcid_name = NULL;
6346 }
6347 if (p->dsp)
6348 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6349
6350 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6351 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6352 p->ignoredtmf = 0;
6353
6354 if (idx > -1) {
6355 /* Real channel, do some fixup */
6356 p->subs[idx].owner = NULL;
6357 p->subs[idx].needanswer = 0;
6358 p->subs[idx].needflash = 0;
6359 p->subs[idx].needringing = 0;
6360 p->subs[idx].needbusy = 0;
6361 p->subs[idx].needcongestion = 0;
6362 p->subs[idx].linear = 0;
6363 p->polarity = POLARITY_IDLE;
6364 dahdi_setlinear(p->subs[idx].dfd, 0);
6365 if (idx == SUB_REAL) {
6366 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6367 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6368 if (p->subs[SUB_CALLWAIT].inthreeway) {
6369 /* We had flipped over to answer a callwait and now it's gone */
6370 ast_debug(1, "We were flipped over to the callwait, moving back and not owning.\n");
6371 /* Move to the call-wait, but un-own us until they flip back. */
6372 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6373 unalloc_sub(p, SUB_CALLWAIT);
6374 p->owner = NULL;
6375 } else {
6376 /* The three way hung up, but we still have a call wait */
6377 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6378 swap_subs(p, SUB_THREEWAY, SUB_REAL);
6379 unalloc_sub(p, SUB_THREEWAY);
6380 if (p->subs[SUB_REAL].inthreeway) {
6381 /* This was part of a three way call. Immediately make way for
6382 another call */
6383 ast_debug(1, "Call was complete, setting owner to former third call\n");
6384 p->owner = p->subs[SUB_REAL].owner;
6385 } else {
6386 /* This call hasn't been completed yet... Set owner to NULL */
6387 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6388 p->owner = NULL;
6389 }
6390 p->subs[SUB_REAL].inthreeway = 0;
6391 }
6392 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6393 /* Move to the call-wait and switch back to them. */
6394 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
6395 unalloc_sub(p, SUB_CALLWAIT);
6396 p->owner = p->subs[SUB_REAL].owner;
6397 if (ast_channel_state(p->owner) != AST_STATE_UP)
6398 p->subs[SUB_REAL].needanswer = 1;
6399 ast_queue_unhold(p->subs[SUB_REAL].owner);
6400 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6401 swap_subs(p, SUB_THREEWAY, SUB_REAL);
6402 unalloc_sub(p, SUB_THREEWAY);
6403 if (p->subs[SUB_REAL].inthreeway) {
6404 /* This was part of a three way call. Immediately make way for
6405 another call */
6406 ast_debug(1, "Call was complete, setting owner to former third call\n");
6407 p->owner = p->subs[SUB_REAL].owner;
6408 } else {
6409 /* This call hasn't been completed yet... Set owner to NULL */
6410 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6411 p->owner = NULL;
6412 }
6413 p->subs[SUB_REAL].inthreeway = 0;
6414 }
6415 } else if (idx == SUB_CALLWAIT) {
6416 /* Ditch the holding callwait call, and immediately make it availabe */
6417 if (p->subs[SUB_CALLWAIT].inthreeway) {
6418 /* This is actually part of a three way, placed on hold. Place the third part
6419 on music on hold now */
6420 if (p->subs[SUB_THREEWAY].owner) {
6421 ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
6422 }
6423 p->subs[SUB_THREEWAY].inthreeway = 0;
6424 /* Make it the call wait now */
6425 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6426 unalloc_sub(p, SUB_THREEWAY);
6427 } else
6428 unalloc_sub(p, SUB_CALLWAIT);
6429 } else if (idx == SUB_THREEWAY) {
6430 if (p->subs[SUB_CALLWAIT].inthreeway) {
6431 /* The other party of the three way call is currently in a call-wait state.
6432 Start music on hold for them, and take the main guy out of the third call */
6433 if (p->subs[SUB_CALLWAIT].owner) {
6434 ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
6435 }
6436 p->subs[SUB_CALLWAIT].inthreeway = 0;
6437 }
6438 p->subs[SUB_REAL].inthreeway = 0;
6439 /* If this was part of a three way call index, let us make
6440 another three way call */
6441 unalloc_sub(p, SUB_THREEWAY);
6442 } else {
6443 /* This wasn't any sort of call, but how are we an index? */
6444 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6445 }
6446 }
6447
6448 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6449 p->owner = NULL;
6450 p->ringt = 0;
6451 p->distinctivering = 0;
6452 p->confirmanswer = 0;
6453 p->outgoing = 0;
6454 p->digital = 0;
6455 p->faxhandled = 0;
6456 p->pulsedial = 0;
6457 if (p->dsp) {
6458 ast_dsp_free(p->dsp);
6459 p->dsp = NULL;
6460 }
6461
6462 revert_fax_buffers(p, ast);
6463
6464 p->law = p->law_default;
6465 law = p->law_default;
6466 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6467 if (res < 0)
6468 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6469 /* Perform low level hangup if no owner left */
6470 #ifdef HAVE_OPENR2
6471 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6472 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6473 /* If it's an incoming call, check the mfcr2_forced_release setting */
6474 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6475 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6476 } else {
6477 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6478 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6479 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6480 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6481 dahdi_r2_disconnect_call(p, r2cause);
6482 }
6483 } else if (p->mfcr2call) {
6484 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6485 /* since ast_request() was called but not ast_call() we have not yet dialed
6486 and the openr2 stack will not call on_call_end callback, we need to unset
6487 the mfcr2call flag and bump the monitor count so the monitor thread can take
6488 care of this channel events from now on */
6489 p->mfcr2call = 0;
6490 }
6491 #endif
6492 switch (p->sig) {
6493 case SIG_SS7:
6494 case SIG_MFCR2:
6495 case SIG_PRI_LIB_HANDLE_CASES:
6496 case 0:
6497 break;
6498 default:
6499 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6500 break;
6501 }
6502 if (res < 0) {
6503 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6504 }
6505 switch (p->sig) {
6506 case SIG_FXOGS:
6507 case SIG_FXOLS:
6508 case SIG_FXOKS:
6509 memset(&par, 0, sizeof(par));
6510 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6511 if (!res) {
6512 struct analog_pvt *analog_p = p->sig_pvt;
6513 #if 0
6514 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6515 #endif
6516 /* If they're off hook, try playing congestion */
6517 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6518 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6519 else
6520 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6521 analog_p->fxsoffhookstate = par.rxisoffhook;
6522 }
6523 break;
6524 case SIG_FXSGS:
6525 case SIG_FXSLS:
6526 case SIG_FXSKS:
6527 /* Make sure we're not made available for at least two seconds assuming
6528 we were actually used for an inbound or outbound call. */
6529 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
6530 time(&p->guardtime);
6531 p->guardtime += 2;
6532 }
6533 break;
6534 default:
6535 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6536 break;
6537 }
6538 if (p->sig)
6539 dahdi_ec_disable(p);
6540 x = 0;
6541 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6542 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6543 p->didtdd = 0;
6544 p->callwaitcas = 0;
6545 p->callwaiting = p->permcallwaiting;
6546 p->hidecallerid = p->permhidecallerid;
6547 p->waitingfordt.tv_sec = 0;
6548 p->dialing = 0;
6549 p->rdnis[0] = '\0';
6550 dahdi_conf_update(p);
6551 reset_conf(p);
6552 /* Restore data mode */
6553 switch (p->sig) {
6554 case SIG_PRI_LIB_HANDLE_CASES:
6555 case SIG_SS7:
6556 x = 0;
6557 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6558 break;
6559 default:
6560 break;
6561 }
6562 if (num_restart_pending == 0)
6563 restart_monitor();
6564 }
6565
6566 p->callwaitingrepeat = 0;
6567 p->cidcwexpire = 0;
6568 p->cid_suppress_expire = 0;
6569 p->oprmode = 0;
6570 hangup_out:
6571 ast_channel_tech_pvt_set(ast, NULL);
6572 ast_free(p->cidspill);
6573 p->cidspill = NULL;
6574
6575 if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) {
6576 /* Automatic reorigination: if all calls towards a user have hung up,
6577 * give dial tone again, so user doesn't need to cycle the hook state manually. */
6578 if (my_is_off_hook(p) && !p->owner) {
6579 /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */
6580 ast_debug(1, "Queuing reorigination for channel %d\n", p->channel);
6581 my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */
6582 /* Must wait for the loop disconnect to end.
6583 * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h
6584 * Calling usleep on an active DAHDI channel is a no-no, but this is okay.
6585 */
6586 usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */
6587 /* If the line is still off-hook and ownerless, actually queue the reorigination.
6588 * do_monitor will actually go ahead and do it. */
6589 if (!p->owner && my_is_off_hook(p)) {
6590 p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */
6591 /* Note, my_off_hook will fail if called before the loop disconnect has finished
6592 * (important for FXOKS signaled channels). This is because DAHDI will reject
6593 * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL,
6594 * so we have to wait for that to finish (see comment above).
6595 * do_monitor itself cannot block, so make the blocking usleep call
6596 * here in the channel thread instead.
6597 */
6598 my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */
6599 } else {
6600 ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel);
6601 }
6602 }
6603 }
6604
6605 ast_mutex_unlock(&p->lock);
6606 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6607
6608 ast_mutex_lock(&iflock);
6609 if (p->restartpending) {
6610 num_restart_pending--;
6611 }
6612
6613 if (p->destroy) {
6614 destroy_channel(p, 0);
6615 }
6616 ast_mutex_unlock(&iflock);
6617
6618 ast_module_unref(ast_module_info->self);
6619 return 0;
6620 }
6621
6622 static int dahdi_answer(struct ast_channel *ast)
6623 {
6624 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6625 int res = 0;
6626 int idx;
6627 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6628 ast_mutex_lock(&p->lock);
6629 idx = dahdi_get_index(ast, p, 0);
6630 if (idx < 0)
6631 idx = SUB_REAL;
6632 /* nothing to do if a radio channel */
6633 if ((p->radio || (p->oprmode < 0))) {
6634 ast_mutex_unlock(&p->lock);
6635 return 0;
6636 }
6637
6638 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6639 res = analog_answer(p->sig_pvt, ast);
6640 ast_mutex_unlock(&p->lock);
6641 return res;
6642 }
6643
6644 switch (p->sig) {
6645 #if defined(HAVE_PRI)
6646 case SIG_PRI_LIB_HANDLE_CASES:
6647 res = sig_pri_answer(p->sig_pvt, ast);
6648 break;
6649 #endif /* defined(HAVE_PRI) */
6650 #if defined(HAVE_SS7)
6651 case SIG_SS7:
6652 res = sig_ss7_answer(p->sig_pvt, ast);
6653 break;
6654 #endif /* defined(HAVE_SS7) */
6655 #ifdef HAVE_OPENR2
6656 case SIG_MFCR2:
6657 if (!p->mfcr2_call_accepted) {
6658 /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6659 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6660 p->mfcr2_answer_pending = 1;
6661 if (p->mfcr2_charge_calls) {
6662 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6663 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6664 } else {
6665 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6666 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6667 }
6668 } else {
6669 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6670 dahdi_r2_answer(p);
6671 }
6672 break;
6673 #endif
6674 case 0:
6675 ast_mutex_unlock(&p->lock);
6676 return 0;
6677 default:
6678 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6679 res = -1;
6680 break;
6681 }
6682 ast_mutex_unlock(&p->lock);
6683 return res;
6684 }
6685
6686 void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
6687 {
6688 int val = 0;
6689
6690 p->ignoredtmf = 1;
6691
6692 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6693
6694 if (!p->hardwaredtmf && p->dsp) {
6695 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
6696 ast_dsp_set_features(p->dsp, p->dsp_features);
6697 }
6698 }
6699
6700 void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
6701 {
6702 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6703
6704 if (p->channel == CHAN_PSEUDO)
6705 return;
6706
6707 p->ignoredtmf = 0;
6708
6709 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6710
6711 if (!p->hardwaredtmf && p->dsp) {
6712 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
6713 ast_dsp_set_features(p->dsp, p->dsp_features);
6714 }
6715 }
6716
6717 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
6718 {
6719 char *cp;
6720 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6721
6722 /* all supported options require data */
6723 if (!p || !data || (*datalen < 1)) {
6724 errno = EINVAL;
6725 return -1;
6726 }
6727
6728 switch (option) {
6729 case AST_OPTION_TDD:
6730 cp = (char *) data;
6731 if (p->mate) {
6732 *cp = 2;
6733 } else {
6734 *cp = p->tdd ? 1 : 0;
6735 }
6736 break;
6737 case AST_OPTION_DIGIT_DETECT:
6738 cp = (char *) data;
6739 *cp = p->ignoredtmf ? 0 : 1;
6740 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6741 break;
6742 case AST_OPTION_FAX_DETECT:
6743 cp = (char *) data;
6744 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6745 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6746 break;
6747 case AST_OPTION_CC_AGENT_TYPE:
6748 #if defined(HAVE_PRI)
6749 #if defined(HAVE_PRI_CCSS)
6750 if (dahdi_sig_pri_lib_handles(p->sig)) {
6751 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6752 break;
6753 }
6754 #endif /* defined(HAVE_PRI_CCSS) */
6755 #endif /* defined(HAVE_PRI) */
6756 return -1;
6757 default:
6758 return -1;
6759 }
6760
6761 errno = 0;
6762
6763 return 0;
6764 }
6765
6766 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
6767 {
6768 char *cp;
6769 signed char *scp;
6770 int x;
6771 int idx;
6772 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6773 struct oprmode *oprmode;
6774
6775
6776 /* all supported options require data */
6777 if (!p || !data || (datalen < 1)) {
6778 errno = EINVAL;
6779 return -1;
6780 }
6781
6782 switch (option) {
6783 case AST_OPTION_TXGAIN:
6784 scp = (signed char *) data;
6785 idx = dahdi_get_index(chan, p, 0);
6786 if (idx < 0) {
6787 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6788 return -1;
6789 }
6790 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6791 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6792 case AST_OPTION_RXGAIN:
6793 scp = (signed char *) data;
6794 idx = dahdi_get_index(chan, p, 0);
6795 if (idx < 0) {
6796 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6797 return -1;
6798 }
6799 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6800 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6801 case AST_OPTION_TONE_VERIFY:
6802 if (!p->dsp)
6803 break;
6804 cp = (char *) data;
6805 switch (*cp) {
6806 case 1:
6807 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6808 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6809 break;
6810 case 2:
6811 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6812 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6813 break;
6814 default:
6815 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6816 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6817 break;
6818 }
6819 break;
6820 case AST_OPTION_TDD:
6821 /* turn on or off TDD */
6822 cp = (char *) data;
6823 p->mate = 0;
6824 if (!*cp) { /* turn it off */
6825 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6826 if (p->tdd)
6827 tdd_free(p->tdd);
6828 p->tdd = 0;
6829 break;
6830 }
6831 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6832 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6833 dahdi_ec_disable(p);
6834 /* otherwise, turn it on */
6835 if (!p->didtdd) { /* if havent done it yet */
6836 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6837 unsigned char *buf;
6838 int size, res, fd, len;
6839 struct pollfd fds[1];
6840
6841 buf = mybuf;
6842 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6843 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6844 len = 40000;
6845 idx = dahdi_get_index(chan, p, 0);
6846 if (idx < 0) {
6847 ast_log(LOG_WARNING, "No index in TDD?\n");
6848 return -1;
6849 }
6850 fd = p->subs[idx].dfd;
6851 while (len) {
6852 if (ast_check_hangup(chan))
6853 return -1;
6854 size = len;
6855 if (size > READ_SIZE)
6856 size = READ_SIZE;
6857 fds[0].fd = fd;
6858 fds[0].events = POLLPRI | POLLOUT;
6859 fds[0].revents = 0;
6860 res = poll(fds, 1, -1);
6861 if (!res) {
6862 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6863 continue;
6864 }
6865 /* if got exception */
6866 if (fds[0].revents & POLLPRI)
6867 return -1;
6868 if (!(fds[0].revents & POLLOUT)) {
6869 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6870 continue;
6871 }
6872 res = write(fd, buf, size);
6873 if (res != size) {
6874 if (res == -1) return -1;
6875 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6876 break;
6877 }
6878 len -= size;
6879 buf += size;
6880 }
6881 p->didtdd = 1; /* set to have done it now */
6882 }
6883 if (*cp == 2) { /* Mate mode */
6884 if (p->tdd)
6885 tdd_free(p->tdd);
6886 p->tdd = 0;
6887 p->mate = 1;
6888 break;
6889 }
6890 if (!p->tdd) { /* if we don't have one yet */
6891 p->tdd = tdd_new(); /* allocate one */
6892 }
6893 break;
6894 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6895 if (!p->dsp)
6896 break;
6897 cp = (char *) data;
6898 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6899 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6900 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
6901 break;
6902 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6903 #if defined(HAVE_PRI)
6904 if (dahdi_sig_pri_lib_handles(p->sig)
6905 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6906 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6907 break;
6908 }
6909 #endif /* defined(HAVE_PRI) */
6910
6911 cp = (char *) data;
6912 if (!*cp) {
6913 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6914 x = 0;
6915 dahdi_ec_disable(p);
6916 } else {
6917 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6918 x = 1;
6919 }
6920 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6921 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6922 break;
6923 case AST_OPTION_OPRMODE: /* Operator services mode */
6924 oprmode = (struct oprmode *) data;
6925 /* We don't support operator mode across technologies */
6926 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
6927 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
6928 ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
6929 errno = EINVAL;
6930 return -1;
6931 }
6932 pp = ast_channel_tech_pvt(oprmode->peer);
6933 p->oprmode = pp->oprmode = 0;
6934 /* setup peers */
6935 p->oprpeer = pp;
6936 pp->oprpeer = p;
6937 /* setup modes, if any */
6938 if (oprmode->mode)
6939 {
6940 pp->oprmode = oprmode->mode;
6941 p->oprmode = -oprmode->mode;
6942 }
6943 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
6944 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
6945 break;
6946 case AST_OPTION_ECHOCAN:
6947 cp = (char *) data;
6948 if (*cp) {
6949 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
6950 dahdi_ec_enable(p);
6951 } else {
6952 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
6953 dahdi_ec_disable(p);
6954 }
6955 break;
6956 case AST_OPTION_DIGIT_DETECT:
6957 cp = (char *) data;
6958 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6959 if (*cp) {
6960 dahdi_dtmf_detect_enable(p);
6961 } else {
6962 dahdi_dtmf_detect_disable(p);
6963 }
6964 break;
6965 case AST_OPTION_FAX_DETECT:
6966 cp = (char *) data;
6967 if (p->dsp) {
6968 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6969 if (*cp) {
6970 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
6971 } else {
6972 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
6973 }
6974 ast_dsp_set_features(p->dsp, p->dsp_features);
6975 }
6976 break;
6977 default:
6978 return -1;
6979 }
6980 errno = 0;
6981
6982 return 0;
6983 }
6984
6985 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
6986 {
6987 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6988 int res = 0;
6989
6990 if (!p) {
6991 /* No private structure! */
6992 *buf = '\0';
6993 return -1;
6994 }
6995
6996 if (!strcasecmp(data, "rxgain")) {
6997 ast_mutex_lock(&p->lock);
6998 snprintf(buf, len, "%f", p->rxgain);
6999 ast_mutex_unlock(&p->lock);
7000 } else if (!strcasecmp(data, "txgain")) {
7001 ast_mutex_lock(&p->lock);
7002 snprintf(buf, len, "%f", p->txgain);
7003 ast_mutex_unlock(&p->lock);
7004 } else if (!strcasecmp(data, "dahdi_channel")) {
7005 ast_mutex_lock(&p->lock);
7006 snprintf(buf, len, "%d", p->channel);
7007 ast_mutex_unlock(&p->lock);
7008 } else if (!strcasecmp(data, "dahdi_span")) {
7009 ast_mutex_lock(&p->lock);
7010 snprintf(buf, len, "%d", p->span);
7011 ast_mutex_unlock(&p->lock);
7012 } else if (!strcasecmp(data, "dahdi_group")) {
7013 ast_mutex_lock(&p->lock);
7014 snprintf(buf, len, "%llu", p->group);
7015 ast_mutex_unlock(&p->lock);
7016 } else if (!strcasecmp(data, "dahdi_type")) {
7017 ast_mutex_lock(&p->lock);
7018 switch (p->sig) {
7019 #if defined(HAVE_OPENR2)
7020 case SIG_MFCR2:
7021 ast_copy_string(buf, "mfc/r2", len);
7022 break;
7023 #endif /* defined(HAVE_OPENR2) */
7024 #if defined(HAVE_PRI)
7025 case SIG_PRI_LIB_HANDLE_CASES:
7026 ast_copy_string(buf, "pri", len);
7027 break;
7028 #endif /* defined(HAVE_PRI) */
7029 case 0:
7030 ast_copy_string(buf, "pseudo", len);
7031 break;
7032 #if defined(HAVE_SS7)
7033 case SIG_SS7:
7034 ast_copy_string(buf, "ss7", len);
7035 break;
7036 #endif /* defined(HAVE_SS7) */
7037 default:
7038 /* The only thing left is analog ports. */
7039 ast_copy_string(buf, "analog", len);
7040 break;
7041 }
7042 ast_mutex_unlock(&p->lock);
7043 #if defined(HAVE_PRI)
7044 #if defined(HAVE_PRI_REVERSE_CHARGE)
7045 } else if (!strcasecmp(data, "reversecharge")) {
7046 ast_mutex_lock(&p->lock);
7047 switch (p->sig) {
7048 case SIG_PRI_LIB_HANDLE_CASES:
7049 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7050 break;
7051 default:
7052 *buf = '\0';
7053 res = -1;
7054 break;
7055 }
7056 ast_mutex_unlock(&p->lock);
7057 #endif
7058 #if defined(HAVE_PRI_SETUP_KEYPAD)
7059 } else if (!strcasecmp(data, "keypad_digits")) {
7060 ast_mutex_lock(&p->lock);
7061 switch (p->sig) {
7062 case SIG_PRI_LIB_HANDLE_CASES:
7063 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
7064 len);
7065 break;
7066 default:
7067 *buf = '\0';
7068 res = -1;
7069 break;
7070 }
7071 ast_mutex_unlock(&p->lock);
7072 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
7073 } else if (!strcasecmp(data, "no_media_path")) {
7074 ast_mutex_lock(&p->lock);
7075 switch (p->sig) {
7076 case SIG_PRI_LIB_HANDLE_CASES:
7077 /*
7078 * TRUE if the call is on hold or is call waiting because
7079 * there is no media path available.
7080 */
7081 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7082 break;
7083 default:
7084 *buf = '\0';
7085 res = -1;
7086 break;
7087 }
7088 ast_mutex_unlock(&p->lock);
7089 #endif /* defined(HAVE_PRI) */
7090 } else if (!strcasecmp(data, "dialmode")) {
7091 struct analog_pvt *analog_p;
7092 ast_mutex_lock(&p->lock);
7093 analog_p = p->sig_pvt;
7094 /* Hardcode p->radio and p->oprmode as 0 since we're using this to check for analogness, not the handler */
7095 if (dahdi_analog_lib_handles(p->sig, 0, 0) && analog_p) {
7096 switch (analog_p->dialmode) {
7097 case ANALOG_DIALMODE_BOTH:
7098 ast_copy_string(buf, "both", len);
7099 break;
7100 case ANALOG_DIALMODE_PULSE:
7101 ast_copy_string(buf, "pulse", len);
7102 break;
7103 case ANALOG_DIALMODE_DTMF:
7104 ast_copy_string(buf, "dtmf", len);
7105 break;
7106 case ANALOG_DIALMODE_NONE:
7107 ast_copy_string(buf, "none", len);
7108 break;
7109 }
7110 } else {
7111 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7112 *buf = '\0';
7113 res = -1;
7114 }
7115 ast_mutex_unlock(&p->lock);
7116 } else {
7117 *buf = '\0';
7118 res = -1;
7119 }
7120
7121 return res;
7122 }
7123
7124
7125 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
7126 {
7127 int res;
7128 char policy_str[21] = "";
7129
7130 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
7131 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
7132 return 1;
7133 }
7134 if (*num_buffers < 0) {
7135 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
7136 return -1;
7137 }
7138 if (!strcasecmp(policy_str, "full")) {
7139 *policy = DAHDI_POLICY_WHEN_FULL;
7140 } else if (!strcasecmp(policy_str, "immediate")) {
7141 *policy = DAHDI_POLICY_IMMEDIATE;
7142 #if defined(HAVE_DAHDI_HALF_FULL)
7143 } else if (!strcasecmp(policy_str, "half")) {
7144 *policy = DAHDI_POLICY_HALF_FULL;
7145 #endif
7146 } else {
7147 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
7148 return -1;
7149 }
7150
7151 return 0;
7152 }
7153
7154 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
7155 {
7156 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7157 int res = 0;
7158
7159 if (!p) {
7160 /* No private structure! */
7161 return -1;
7162 }
7163
7164 if (!strcasecmp(data, "buffers")) {
7165 int num_bufs, policy;
7166
7167 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7168 struct dahdi_bufferinfo bi = {
7169 .txbufpolicy = policy,
7170 .rxbufpolicy = policy,
7171 .bufsize = p->bufsize,
7172 .numbufs = num_bufs,
7173 };
7174 int bpres;
7175
7176 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7177 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
7178 } else {
7179 p->bufferoverrideinuse = 1;
7180 }
7181 } else {
7182 res = -1;
7183 }
7184 } else if (!strcasecmp(data, "echocan_mode")) {
7185 if (!strcasecmp(value, "on")) {
7186 ast_mutex_lock(&p->lock);
7187 dahdi_ec_enable(p);
7188 ast_mutex_unlock(&p->lock);
7189 } else if (!strcasecmp(value, "off")) {
7190 ast_mutex_lock(&p->lock);
7191 dahdi_ec_disable(p);
7192 ast_mutex_unlock(&p->lock);
7193 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7194 } else if (!strcasecmp(value, "fax")) {
7195 int blah = 1;
7196
7197 ast_mutex_lock(&p->lock);
7198 if (!p->echocanon) {
7199 dahdi_ec_enable(p);
7200 }
7201 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7202 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
7203 }
7204 ast_mutex_unlock(&p->lock);
7205 } else if (!strcasecmp(value, "voice")) {
7206 int blah = 0;
7207
7208 ast_mutex_lock(&p->lock);
7209 if (!p->echocanon) {
7210 dahdi_ec_enable(p);
7211 }
7212 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7213 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
7214 }
7215 ast_mutex_unlock(&p->lock);
7216 #endif
7217 } else {
7218 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
7219 res = -1;
7220 }
7221 } else if (!strcasecmp(data, "dialmode")) {
7222 struct analog_pvt *analog_p;
7223
7224 ast_mutex_lock(&p->lock);
7225 analog_p = p->sig_pvt;
7226 if (!dahdi_analog_lib_handles(p->sig, 0, 0) || !analog_p) {
7227 ast_log(LOG_WARNING, "%s only supported on analog channels\n", data);
7228 ast_mutex_unlock(&p->lock);
7229 return -1;
7230 }
7231 /* analog pvt is used for pulse dialing, so update both */
7232 if (!strcasecmp(value, "pulse")) {
7233 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_PULSE;
7234 } else if (!strcasecmp(value, "dtmf") || !strcasecmp(value, "tone")) {
7235 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_DTMF;
7236 } else if (!strcasecmp(value, "none")) {
7237 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_NONE;
7238 } else if (!strcasecmp(value, "both")) {
7239 p->dialmode = analog_p->dialmode = ANALOG_DIALMODE_BOTH;
7240 } else {
7241 ast_log(LOG_WARNING, "'%s' is an invalid setting for %s\n", value, data);
7242 res = -1;
7243 }
7244 ast_mutex_unlock(&p->lock);
7245 } else {
7246 res = -1;
7247 }
7248
7249 return res;
7250 }
7251
7252 void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
7253 {
7254 /* Unlink a specific slave or all slaves/masters from a given master */
7255 int x;
7256 int hasslaves;
7257 if (!master)
7258 return;
7259 if (needlock) {
7260 ast_mutex_lock(&master->lock);
7261 if (slave) {
7262 while (ast_mutex_trylock(&slave->lock)) {
7263 DEADLOCK_AVOIDANCE(&master->lock);
7264 }
7265 }
7266 }
7267 hasslaves = 0;
7268 for (x = 0; x < MAX_SLAVES; x++) {
7269 if (master->slaves[x]) {
7270 if (!slave || (master->slaves[x] == slave)) {
7271 /* Take slave out of the conference */
7272 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7273 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7274 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7275 master->slaves[x]->master = NULL;
7276 master->slaves[x] = NULL;
7277 } else
7278 hasslaves = 1;
7279 }
7280 if (!hasslaves)
7281 master->inconference = 0;
7282 }
7283 if (!slave) {
7284 if (master->master) {
7285 /* Take master out of the conference */
7286 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7287 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7288 hasslaves = 0;
7289 for (x = 0; x < MAX_SLAVES; x++) {
7290 if (master->master->slaves[x] == master)
7291 master->master->slaves[x] = NULL;
7292 else if (master->master->slaves[x])
7293 hasslaves = 1;
7294 }
7295 if (!hasslaves)
7296 master->master->inconference = 0;
7297 }
7298 master->master = NULL;
7299 }
7300 dahdi_conf_update(master);
7301 if (needlock) {
7302 if (slave)
7303 ast_mutex_unlock(&slave->lock);
7304 ast_mutex_unlock(&master->lock);
7305 }
7306 }
7307
7308 void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
7309 {
7310 int x;
7311 if (!slave || !master) {
7312 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7313 return;
7314 }
7315 for (x = 0; x < MAX_SLAVES; x++) {
7316 if (!master->slaves[x]) {
7317 master->slaves[x] = slave;
7318 break;
7319 }
7320 }
7321 if (x >= MAX_SLAVES) {
7322 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7323 master->slaves[MAX_SLAVES - 1] = slave;
7324 }
7325 if (slave->master)
7326 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7327 slave->master = master;
7328
7329 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7330 }
7331
7332 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
7333 {
7334 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7335 int x;
7336
7337 ast_mutex_lock(&p->lock);
7338
7339 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7340 if (p->owner == oldchan) {
7341 p->owner = newchan;
7342 }
7343 for (x = 0; x < 3; x++) {
7344 if (p->subs[x].owner == oldchan) {
7345 if (!x) {
7346 dahdi_master_slave_unlink(NULL, p, 0);
7347 }
7348 p->subs[x].owner = newchan;
7349 }
7350 }
7351 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7352 analog_fixup(oldchan, newchan, p->sig_pvt);
7353 #if defined(HAVE_PRI)
7354 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7355 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7356 #endif /* defined(HAVE_PRI) */
7357 #if defined(HAVE_SS7)
7358 } else if (p->sig == SIG_SS7) {
7359 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7360 #endif /* defined(HAVE_SS7) */
7361 }
7362 dahdi_conf_update(p);
7363
7364 ast_mutex_unlock(&p->lock);
7365
7366 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7367 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
7368 }
7369 return 0;
7370 }
7371
7372 static int dahdi_ring_phone(struct dahdi_pvt *p)
7373 {
7374 int x;
7375 int res;
7376 /* Make sure our transmit state is on hook */
7377 x = 0;
7378 x = DAHDI_ONHOOK;
7379 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7380 do {
7381 x = DAHDI_RING;
7382 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7383 if (res) {
7384 switch (errno) {
7385 case EBUSY:
7386 case EINTR:
7387 /* Wait just in case */
7388 usleep(10000);
7389 continue;
7390 case EINPROGRESS:
7391 res = 0;
7392 break;
7393 default:
7394 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7395 res = 0;
7396 }
7397 }
7398 } while (res);
7399 return res;
7400 }
7401
7402 static void *analog_ss_thread(void *data);
7403
7404 /*!
7405 * \internal
7406 * \brief Attempt to transfer 3-way call.
7407 *
7408 * \param p DAHDI private structure.
7409 *
7410 * \note On entry these locks are held: real-call, private, 3-way call.
7411 * \note On exit these locks are held: real-call, private.
7412 *
7413 * \retval 0 on success.
7414 * \retval -1 on error.
7415 */
7416 static int attempt_transfer(struct dahdi_pvt *p)
7417 {
7418 struct ast_channel *owner_real;
7419 struct ast_channel *owner_3way;
7420 enum ast_transfer_result xfer_res;
7421 int res = 0;
7422
7423 owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7424 owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7425
7426 ast_verb(3, "TRANSFERRING %s to %s\n",
7427 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7428
7429 ast_channel_unlock(owner_real);
7430 ast_channel_unlock(owner_3way);
7431 ast_mutex_unlock(&p->lock);
7432
7433 xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7434 if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7435 ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7436 res = -1;
7437 }
7438
7439 /* Must leave with these locked. */
7440 ast_channel_lock(owner_real);
7441 ast_mutex_lock(&p->lock);
7442
7443 ast_channel_unref(owner_real);
7444 ast_channel_unref(owner_3way);
7445
7446 return res;
7447 }
7448
7449 static int check_for_conference(struct dahdi_pvt *p)
7450 {
7451 struct dahdi_confinfo ci;
7452 /* Fine if we already have a master, etc */
7453 if (p->master || (p->confno > -1))
7454 return 0;
7455 memset(&ci, 0, sizeof(ci));
7456 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7457 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7458 return 0;
7459 }
7460 /* If we have no master and don't have a confno, then
7461 if we're in a conference, it's probably a MeetMe room or
7462 some such, so don't let us 3-way out! */
7463 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7464 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7465 return 1;
7466 }
7467 return 0;
7468 }
7469
7470 /*! Checks channel for alarms
7471 * \param p a channel to check for alarms.
7472 * \returns the alarms on the span to which the channel belongs, or alarms on
7473 * the channel if no span alarms.
7474 */
7475 static int get_alarms(struct dahdi_pvt *p)
7476 {
7477 int res;
7478 struct dahdi_spaninfo zi;
7479 struct dahdi_params params;
7480
7481 memset(&zi, 0, sizeof(zi));
7482 zi.spanno = p->span;
7483
7484 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7485 if (zi.alarms != DAHDI_ALARM_NONE)
7486 return zi.alarms;
7487 } else {
7488 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7489 return 0;
7490 }
7491
7492 /* No alarms on the span. Check for channel alarms. */
7493 memset(&params, 0, sizeof(params));
7494 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7495 return params.chan_alarms;
7496
7497 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7498
7499 return DAHDI_ALARM_NONE;
7500 }
7501
7502 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
7503 {
7504 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7505 struct ast_frame *f = *dest;
7506
7507 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7508 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7509 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7510
7511 if (p->confirmanswer) {
7512 if (f->frametype == AST_FRAME_DTMF_END) {
7513 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7514 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7515 of a DTMF digit */
7516 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7517 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7518 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7519 p->confirmanswer = 0;
7520 } else {
7521 p->subs[idx].f.frametype = AST_FRAME_NULL;
7522 p->subs[idx].f.subclass.integer = 0;
7523 }
7524 *dest = &p->subs[idx].f;
7525 } else if (p->callwaitcas) {
7526 if (f->frametype == AST_FRAME_DTMF_END) {
7527 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7528 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7529 ast_free(p->cidspill);
7530 p->cidspill = NULL;
7531 send_cwcidspill(p);
7532 }
7533 p->callwaitcas = 0;
7534 }
7535 p->subs[idx].f.frametype = AST_FRAME_NULL;
7536 p->subs[idx].f.subclass.integer = 0;
7537 *dest = &p->subs[idx].f;
7538 } else if (f->subclass.integer == 'f') {
7539 if (f->frametype == AST_FRAME_DTMF_END) {
7540 /* Fax tone -- Handle and return NULL */
7541 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7542 /* If faxbuffers are configured, use them for the fax transmission */
7543 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7544 struct dahdi_bufferinfo bi = {
7545 .txbufpolicy = p->faxbuf_policy,
7546 .bufsize = p->bufsize,
7547 .numbufs = p->faxbuf_no
7548 };
7549 int res;
7550
7551 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7552 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7553 } else {
7554 p->bufferoverrideinuse = 1;
7555 }
7556 }
7557 p->faxhandled = 1;
7558 if (p->dsp) {
7559 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
7560 ast_dsp_set_features(p->dsp, p->dsp_features);
7561 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7562 }
7563 if (strcmp(ast_channel_exten(ast), "fax")) {
7564 const char *target_context = ast_channel_context(ast);
7565
7566 /*
7567 * We need to unlock 'ast' here because ast_exists_extension has the
7568 * potential to start autoservice on the channel. Such action is prone
7569 * to deadlock if the channel is locked.
7570 *
7571 * ast_async_goto() has its own restriction on not holding the
7572 * channel lock.
7573 */
7574 ast_mutex_unlock(&p->lock);
7575 ast_channel_unlock(ast);
7576 if (ast_exists_extension(ast, target_context, "fax", 1,
7577 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7578 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7579 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7580 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7581 if (ast_async_goto(ast, target_context, "fax", 1))
7582 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7583 } else {
7584 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7585 }
7586 ast_channel_lock(ast);
7587 ast_mutex_lock(&p->lock);
7588 } else {
7589 ast_debug(1, "Already in a fax extension, not redirecting\n");
7590 }
7591 } else {
7592 ast_debug(1, "Fax already handled\n");
7593 }
7594 dahdi_confmute(p, 0);
7595 }
7596 p->subs[idx].f.frametype = AST_FRAME_NULL;
7597 p->subs[idx].f.subclass.integer = 0;
7598 *dest = &p->subs[idx].f;
7599 }
7600 }
7601
7602 static void publish_span_alarm(int span, const char *alarm_txt)
7603 {
7604 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7605
7606 body = ast_json_pack("{s: i, s: s}",
7607 "Span", span,
7608 "Alarm", alarm_txt);
7609 if (!body) {
7610 return;
7611 }
7612
7613 ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7614 }
7615
7616 static void publish_channel_alarm(int channel, const char *alarm_txt)
7617 {
7618 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7619 RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7620 if (!dahdi_chan) {
7621 return;
7622 }
7623
7624 ast_str_set(&dahdi_chan, 0, "%d", channel);
7625 body = ast_json_pack("{s: s, s: s}",
7626 "DAHDIChannel", ast_str_buffer(dahdi_chan),
7627 "Alarm", alarm_txt);
7628 if (!body) {
7629 return;
7630 }
7631
7632 ast_manager_publish_event("Alarm", EVENT_FLAG_SYSTEM, body);
7633 }
7634
7635 static void handle_alarms(struct dahdi_pvt *p, int alms)
7636 {
7637 const char *alarm_str;
7638
7639 #if defined(HAVE_PRI)
7640 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
7641 return;
7642 }
7643 #endif /* defined(HAVE_PRI) */
7644
7645 alarm_str = alarm2str(alms);
7646 if (report_alarms & REPORT_CHANNEL_ALARMS) {
7647 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7648 publish_channel_alarm(p->channel, alarm_str);
7649 }
7650
7651 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
7652 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7653 publish_span_alarm(p->span, alarm_str);
7654 }
7655 }
7656
7657 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
7658 {
7659 int res, x;
7660 int idx, mysig;
7661 char *c;
7662 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7663 pthread_t threadid;
7664 struct ast_channel *chan;
7665 struct ast_frame *f;
7666
7667 idx = dahdi_get_index(ast, p, 0);
7668 if (idx < 0) {
7669 return &ast_null_frame;
7670 }
7671 mysig = p->sig;
7672 if (p->outsigmod > -1)
7673 mysig = p->outsigmod;
7674 p->subs[idx].f.frametype = AST_FRAME_NULL;
7675 p->subs[idx].f.subclass.integer = 0;
7676 p->subs[idx].f.datalen = 0;
7677 p->subs[idx].f.samples = 0;
7678 p->subs[idx].f.mallocd = 0;
7679 p->subs[idx].f.offset = 0;
7680 p->subs[idx].f.src = "dahdi_handle_event";
7681 p->subs[idx].f.data.ptr = NULL;
7682 f = &p->subs[idx].f;
7683
7684 if (p->fake_event) {
7685 res = p->fake_event;
7686 p->fake_event = 0;
7687 } else
7688 res = dahdi_get_event(p->subs[idx].dfd);
7689
7690 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7691
7692 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7693 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7694 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7695 #if defined(HAVE_PRI)
7696 if (dahdi_sig_pri_lib_handles(p->sig)
7697 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7698 && p->pri
7699 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7700 /* absorb event */
7701 } else
7702 #endif /* defined(HAVE_PRI) */
7703 {
7704 /* Unmute conference */
7705 dahdi_confmute(p, 0);
7706 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
7707 p->subs[idx].f.subclass.integer = res & 0xff;
7708 dahdi_handle_dtmf(ast, idx, &f);
7709 }
7710 return f;
7711 }
7712
7713 if (res & DAHDI_EVENT_DTMFDOWN) {
7714 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7715 #if defined(HAVE_PRI)
7716 if (dahdi_sig_pri_lib_handles(p->sig)
7717 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7718 && p->pri
7719 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7720 /* absorb event */
7721 } else
7722 #endif /* defined(HAVE_PRI) */
7723 {
7724 /* Mute conference */
7725 dahdi_confmute(p, 1);
7726 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
7727 p->subs[idx].f.subclass.integer = res & 0xff;
7728 dahdi_handle_dtmf(ast, idx, &f);
7729 }
7730 return &p->subs[idx].f;
7731 }
7732
7733 switch (res) {
7734 case DAHDI_EVENT_EC_DISABLED:
7735 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7736 p->echocanon = 0;
7737 break;
7738 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7739 case DAHDI_EVENT_TX_CED_DETECTED:
7740 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7741 break;
7742 case DAHDI_EVENT_RX_CED_DETECTED:
7743 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7744 break;
7745 case DAHDI_EVENT_EC_NLP_DISABLED:
7746 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7747 break;
7748 case DAHDI_EVENT_EC_NLP_ENABLED:
7749 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7750 break;
7751 #endif
7752 case DAHDI_EVENT_BITSCHANGED:
7753 #ifdef HAVE_OPENR2
7754 if (p->sig != SIG_MFCR2) {
7755 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7756 } else {
7757 ast_debug(1, "bits changed in chan %d\n", p->channel);
7758 openr2_chan_handle_cas(p->r2chan);
7759 }
7760 #else
7761 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7762 #endif
7763 break;
7764 case DAHDI_EVENT_PULSE_START:
7765 /* Stop tone if there's a pulse start and the PBX isn't started */
7766 if (!ast_channel_pbx(ast))
7767 tone_zone_play_tone(p->subs[idx].dfd, -1);
7768 break;
7769 case DAHDI_EVENT_DIALCOMPLETE:
7770 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7771 #if defined(HAVE_PRI)
7772 if (dahdi_sig_pri_lib_handles(p->sig)) {
7773 if (p->inalarm) {
7774 break;
7775 }
7776 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7777 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7778 ast_channel_name(ast), strerror(errno));
7779 return NULL;
7780 }
7781 if (x) {
7782 /* Still dialing in DAHDI driver */
7783 break;
7784 }
7785 /*
7786 * The ast channel is locked and the private may be locked more
7787 * than once.
7788 */
7789 sig_pri_dial_complete(p->sig_pvt, ast);
7790 break;
7791 }
7792 #endif /* defined(HAVE_PRI) */
7793 #ifdef HAVE_OPENR2
7794 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7795 /* we don't need to do anything for this event for R2 signaling
7796 if the call is being setup */
7797 break;
7798 }
7799 #endif
7800 if (p->inalarm) break;
7801 if ((p->radio || (p->oprmode < 0))) break;
7802 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7803 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7804 return NULL;
7805 }
7806 if (!x) { /* if not still dialing in driver */
7807 dahdi_ec_enable(p);
7808 if (p->echobreak) {
7809 dahdi_train_ec(p);
7810 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7811 p->dop.op = DAHDI_DIAL_OP_REPLACE;
7812 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7813 p->echobreak = 0;
7814 } else {
7815 p->dialing = 0;
7816 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7817 /* if thru with dialing after offhook */
7818 if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
7819 ast_setstate(ast, AST_STATE_UP);
7820 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7821 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7822 break;
7823 } else { /* if to state wait for offhook to dial rest */
7824 /* we now wait for off hook */
7825 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
7826 }
7827 }
7828 if (ast_channel_state(ast) == AST_STATE_DIALING) {
7829 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7830 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7831 } else if (p->confirmanswer || (!p->dialednone
7832 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7833 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7834 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7835 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7836 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7837 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7838 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7839 || (mysig == SIG_SF_FEATB)))) {
7840 ast_setstate(ast, AST_STATE_RINGING);
7841 } else if (!p->answeronpolarityswitch) {
7842 ast_setstate(ast, AST_STATE_UP);
7843 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7844 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
7845 /* If aops=0 and hops=1, this is necessary */
7846 p->polarity = POLARITY_REV;
7847 } else {
7848 /* Start clean, so we can catch the change to REV polarity when party answers */
7849 p->polarity = POLARITY_IDLE;
7850 }
7851 }
7852 }
7853 }
7854 break;
7855 case DAHDI_EVENT_ALARM:
7856 switch (p->sig) {
7857 #if defined(HAVE_PRI)
7858 case SIG_PRI_LIB_HANDLE_CASES:
7859 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
7860 break;
7861 #endif /* defined(HAVE_PRI) */
7862 #if defined(HAVE_SS7)
7863 case SIG_SS7:
7864 sig_ss7_set_alarm(p->sig_pvt, 1);
7865 break;
7866 #endif /* defined(HAVE_SS7) */
7867 default:
7868 p->inalarm = 1;
7869 break;
7870 }
7871 res = get_alarms(p);
7872 handle_alarms(p, res);
7873 #ifdef HAVE_PRI
7874 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7875 /* fall through intentionally */
7876 } else {
7877 break;
7878 }
7879 #endif
7880 #if defined(HAVE_SS7)
7881 if (p->sig == SIG_SS7)
7882 break;
7883 #endif /* defined(HAVE_SS7) */
7884 #ifdef HAVE_OPENR2
7885 if (p->sig == SIG_MFCR2)
7886 break;
7887 #endif
7888 case DAHDI_EVENT_ONHOOK:
7889 if (p->radio) {
7890 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7891 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
7892 break;
7893 }
7894 if (p->oprmode < 0)
7895 {
7896 if (p->oprmode != -1) { /* Operator flash recall */
7897 ast_verb(4, "Operator mode enabled on channel %d, holding line for channel %d\n", p->channel, p->oprpeer->channel);
7898 break;
7899 }
7900 /* Otherwise, immediate recall */
7901 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7902 {
7903 /* Make sure it starts ringing */
7904 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7905 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7906 save_conference(p->oprpeer);
7907 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
7908 ast_verb(4, "Operator recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
7909 }
7910 break;
7911 }
7912 switch (p->sig) {
7913 case SIG_FXOLS:
7914 case SIG_FXOGS:
7915 case SIG_FXOKS:
7916 /* Check for some special conditions regarding call waiting */
7917 if (idx == SUB_REAL) {
7918 /* The normal line was hung up */
7919 if (p->subs[SUB_CALLWAIT].owner) {
7920 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
7921 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
7922 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
7923 unalloc_sub(p, SUB_CALLWAIT);
7924 #if 0
7925 p->subs[idx].needanswer = 0;
7926 p->subs[idx].needringing = 0;
7927 #endif
7928 p->callwaitingrepeat = 0;
7929 p->cidcwexpire = 0;
7930 p->cid_suppress_expire = 0;
7931 p->owner = NULL;
7932 /* Don't start streaming audio yet if the incoming call isn't up yet */
7933 if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
7934 p->dialing = 1;
7935 dahdi_ring_phone(p);
7936 } else if (p->subs[SUB_THREEWAY].owner) {
7937 unsigned int mssinceflash;
7938 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
7939 the private structure -- not especially easy or clean */
7940 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
7941 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
7942 DLA_UNLOCK(&p->lock);
7943 CHANNEL_DEADLOCK_AVOIDANCE(ast);
7944 /* We can grab ast and p in that order, without worry. We should make sure
7945 nothing seriously bad has happened though like some sort of bizarre double
7946 masquerade! */
7947 DLA_LOCK(&p->lock);
7948 if (p->owner != ast) {
7949 ast_log(LOG_WARNING, "This isn't good...\n");
7950 return NULL;
7951 }
7952 }
7953 if (!p->subs[SUB_THREEWAY].owner) {
7954 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
7955 return NULL;
7956 }
7957 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
7958 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
7959 if (mssinceflash < MIN_MS_SINCE_FLASH) {
7960 /* It hasn't been long enough since the last flashook. This is probably a bounce on
7961 hanging up. Hangup both channels now */
7962 if (p->subs[SUB_THREEWAY].owner)
7963 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
7964 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
7965 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
7966 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7967 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
7968 if (p->transfer) {
7969 /* In any case this isn't a threeway call anymore */
7970 p->subs[SUB_REAL].inthreeway = 0;
7971 p->subs[SUB_THREEWAY].inthreeway = 0;
7972 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
7973 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
7974 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7975 /* Swap subs and dis-own channel */
7976 swap_subs(p, SUB_THREEWAY, SUB_REAL);
7977 p->owner = NULL;
7978 /* Ring the phone */
7979 dahdi_ring_phone(p);
7980 } else if (!attempt_transfer(p)) {
7981 /*
7982 * Transfer successful. Don't actually hang up at this point.
7983 * Let our channel legs of the calls die off as the transfer
7984 * percolates through the core.
7985 */
7986 break;
7987 }
7988 } else {
7989 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
7990 if (p->subs[SUB_THREEWAY].owner)
7991 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7992 }
7993 } else {
7994 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
7995 /* Swap subs and dis-own channel */
7996 swap_subs(p, SUB_THREEWAY, SUB_REAL);
7997 p->owner = NULL;
7998 /* Ring the phone */
7999 dahdi_ring_phone(p);
8000 }
8001 }
8002 } else {
8003 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
8004 }
8005 /* Fall through */
8006 default:
8007 dahdi_ec_disable(p);
8008 return NULL;
8009 }
8010 break;
8011 case DAHDI_EVENT_RINGOFFHOOK:
8012 if (p->inalarm) break;
8013 if (p->oprmode < 0)
8014 {
8015 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
8016 {
8017 /* Make sure it stops ringing */
8018 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8019 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
8020 restore_conference(p->oprpeer);
8021 ast_debug(1, "Operator recall by channel %d for channel %d complete\n", p->oprpeer->channel, p->channel);
8022 }
8023 break;
8024 }
8025 if (p->radio)
8026 {
8027 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8028 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
8029 break;
8030 }
8031 /* for E911, its supposed to wait for offhook then dial
8032 the second half of the dial string */
8033 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
8034 c = strchr(p->dialdest, '/');
8035 if (c)
8036 c++;
8037 else
8038 c = p->dialdest;
8039
8040 if (*c) {
8041 int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
8042 if (numchars >= sizeof(p->dop.dialstr)) {
8043 ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
8044 }
8045 } else {
8046 ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
8047 }
8048
8049 if (strlen(p->dop.dialstr) > 4) {
8050 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
8051 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
8052 p->echorest[sizeof(p->echorest) - 1] = '\0';
8053 p->echobreak = 1;
8054 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
8055 } else
8056 p->echobreak = 0;
8057 if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
8058 x = DAHDI_ONHOOK;
8059 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
8060 return NULL;
8061 }
8062 p->dialing = 1;
8063 return &p->subs[idx].f;
8064 }
8065 switch (p->sig) {
8066 case SIG_FXOLS:
8067 case SIG_FXOGS:
8068 case SIG_FXOKS:
8069 switch (ast_channel_state(ast)) {
8070 case AST_STATE_RINGING:
8071 dahdi_ec_enable(p);
8072 dahdi_train_ec(p);
8073 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8074 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8075 /* Make sure it stops ringing */
8076 p->subs[SUB_REAL].needringing = 0;
8077 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8078 ast_debug(1, "channel %d answered\n", p->channel);
8079
8080 /* Cancel any running CallerID spill */
8081 ast_free(p->cidspill);
8082 p->cidspill = NULL;
8083 restore_conference(p);
8084
8085 p->dialing = 0;
8086 p->callwaitcas = 0;
8087 if (p->confirmanswer) {
8088 /* Ignore answer if "confirm answer" is enabled */
8089 p->subs[idx].f.frametype = AST_FRAME_NULL;
8090 p->subs[idx].f.subclass.integer = 0;
8091 } else if (!ast_strlen_zero(p->dop.dialstr)) {
8092 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
8093 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8094 if (res) {
8095 p->dop.dialstr[0] = '\0';
8096 return NULL;
8097 } else {
8098 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
8099 p->subs[idx].f.frametype = AST_FRAME_NULL;
8100 p->subs[idx].f.subclass.integer = 0;
8101 p->dialing = 1;
8102 }
8103 p->dop.dialstr[0] = '\0';
8104 ast_setstate(ast, AST_STATE_DIALING);
8105 } else
8106 ast_setstate(ast, AST_STATE_UP);
8107 return &p->subs[idx].f;
8108 case AST_STATE_DOWN:
8109 ast_setstate(ast, AST_STATE_RING);
8110 ast_channel_rings_set(ast, 1);
8111 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8112 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
8113 ast_debug(1, "channel %d picked up\n", p->channel);
8114 return &p->subs[idx].f;
8115 case AST_STATE_UP:
8116 /* Make sure it stops ringing */
8117 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
8118 /* Okay -- probably call waiting*/
8119 ast_queue_unhold(p->owner);
8120 p->subs[idx].needunhold = 1;
8121 break;
8122 case AST_STATE_RESERVED:
8123 /* Start up dialtone */
8124 if (has_voicemail(p))
8125 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8126 else
8127 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8128 break;
8129 default:
8130 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
8131 }
8132 break;
8133 case SIG_FXSLS:
8134 case SIG_FXSGS:
8135 case SIG_FXSKS:
8136 if (ast_channel_state(ast) == AST_STATE_RING) {
8137 p->ringt = p->ringt_base;
8138 }
8139
8140 /* If we get a ring then we cannot be in
8141 * reversed polarity. So we reset to idle */
8142 ast_debug(1, "Setting IDLE polarity due "
8143 "to ring. Old polarity was %d\n",
8144 p->polarity);
8145 p->polarity = POLARITY_IDLE;
8146
8147 /* Fall through */
8148 case SIG_EM:
8149 case SIG_EM_E1:
8150 case SIG_EMWINK:
8151 case SIG_FEATD:
8152 case SIG_FEATDMF:
8153 case SIG_FEATDMF_TA:
8154 case SIG_E911:
8155 case SIG_FGC_CAMA:
8156 case SIG_FGC_CAMAMF:
8157 case SIG_FEATB:
8158 case SIG_SF:
8159 case SIG_SFWINK:
8160 case SIG_SF_FEATD:
8161 case SIG_SF_FEATDMF:
8162 case SIG_SF_FEATB:
8163 if (ast_channel_state(ast) == AST_STATE_PRERING)
8164 ast_setstate(ast, AST_STATE_RING);
8165 if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
8166 ast_debug(1, "Ring detected\n");
8167 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8168 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
8169 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
8170 ast_debug(1, "Line answered\n");
8171 if (p->confirmanswer) {
8172 p->subs[idx].f.frametype = AST_FRAME_NULL;
8173 p->subs[idx].f.subclass.integer = 0;
8174 } else {
8175 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8176 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8177 ast_setstate(ast, AST_STATE_UP);
8178 }
8179 } else if (ast_channel_state(ast) != AST_STATE_RING)
8180 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
8181 break;
8182 default:
8183 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8184 }
8185 break;
8186 case DAHDI_EVENT_RINGBEGIN:
8187 switch (p->sig) {
8188 case SIG_FXSLS:
8189 case SIG_FXSGS:
8190 case SIG_FXSKS:
8191 if (ast_channel_state(ast) == AST_STATE_RING) {
8192 p->ringt = p->ringt_base;
8193 }
8194 break;
8195 }
8196 break;
8197 case DAHDI_EVENT_RINGERON:
8198 break;
8199 case DAHDI_EVENT_NOALARM:
8200 switch (p->sig) {
8201 #if defined(HAVE_PRI)
8202 case SIG_PRI_LIB_HANDLE_CASES:
8203 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
8204 break;
8205 #endif /* defined(HAVE_PRI) */
8206 #if defined(HAVE_SS7)
8207 case SIG_SS7:
8208 sig_ss7_set_alarm(p->sig_pvt, 0);
8209 break;
8210 #endif /* defined(HAVE_SS7) */
8211 default:
8212 p->inalarm = 0;
8213 break;
8214 }
8215 handle_clear_alarms(p);
8216 break;
8217 case DAHDI_EVENT_WINKFLASH:
8218 if (p->inalarm) break;
8219 if (p->radio) break;
8220 if (p->oprmode < 0) break;
8221 if (p->oprmode > 1)
8222 {
8223 struct dahdi_params par;
8224
8225 memset(&par, 0, sizeof(par));
8226 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
8227 {
8228 if (!par.rxisoffhook)
8229 {
8230 /* Make sure it stops ringing */
8231 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
8232 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
8233 save_conference(p);
8234 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8235 ast_verb(4, "Operator flash recall, channel %d ringing back channel %d\n", p->oprpeer->channel, p->channel);
8236 }
8237 }
8238 break;
8239 }
8240 /* Remember last time we got a flash-hook */
8241 p->flashtime = ast_tvnow();
8242 switch (mysig) {
8243 case SIG_FXOLS:
8244 case SIG_FXOGS:
8245 case SIG_FXOKS:
8246 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8247 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
8248
8249 /* Cancel any running CallerID spill */
8250 ast_free(p->cidspill);
8251 p->cidspill = NULL;
8252 restore_conference(p);
8253 p->callwaitcas = 0;
8254
8255 if (idx != SUB_REAL) {
8256 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
8257 goto winkflashdone;
8258 }
8259
8260 if (p->subs[SUB_CALLWAIT].owner) {
8261 /* Swap to call-wait */
8262 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
8263 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
8264 p->owner = p->subs[SUB_REAL].owner;
8265 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
8266 if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
8267 ast_setstate(p->owner, AST_STATE_UP);
8268 p->subs[SUB_REAL].needanswer = 1;
8269 }
8270 p->callwaitingrepeat = 0;
8271 p->cidcwexpire = 0;
8272 p->cid_suppress_expire = 0;
8273 /* Start music on hold if appropriate */
8274 if (!p->subs[SUB_CALLWAIT].inthreeway) {
8275 ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
8276 }
8277 p->subs[SUB_CALLWAIT].needhold = 1;
8278 ast_queue_hold(p->subs[SUB_REAL].owner, p->mohsuggest);
8279 p->subs[SUB_REAL].needunhold = 1;
8280 } else if (!p->subs[SUB_THREEWAY].owner) {
8281 if (!p->threewaycalling) {
8282 /* Just send a flash if no 3-way calling */
8283 p->subs[SUB_REAL].needflash = 1;
8284 goto winkflashdone;
8285 } else if (!check_for_conference(p)) {
8286 ast_callid callid = 0;
8287 int callid_created;
8288 char cid_num[256];
8289 char cid_name[256];
8290
8291 cid_num[0] = 0;
8292 cid_name[0] = 0;
8293 if (p->dahditrcallerid && p->owner) {
8294 if (ast_channel_caller(p->owner)->id.number.valid
8295 && ast_channel_caller(p->owner)->id.number.str) {
8296 ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
8297 sizeof(cid_num));
8298 }
8299 if (ast_channel_caller(p->owner)->id.name.valid
8300 && ast_channel_caller(p->owner)->id.name.str) {
8301 ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
8302 sizeof(cid_name));
8303 }
8304 }
8305 /* XXX This section needs much more error checking!!! XXX */
8306 /* Start a 3-way call if feasible */
8307 if (!((ast_channel_pbx(ast)) ||
8308 (ast_channel_state(ast) == AST_STATE_UP) ||
8309 (ast_channel_state(ast) == AST_STATE_RING))) {
8310 ast_debug(1, "Flash when call not up or ringing\n");
8311 goto winkflashdone;
8312 }
8313 if (alloc_sub(p, SUB_THREEWAY)) {
8314 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8315 goto winkflashdone;
8316 }
8317 callid_created = ast_callid_threadstorage_auto(&callid);
8318 /*
8319 * Make new channel
8320 *
8321 * We cannot hold the p or ast locks while creating a new
8322 * channel.
8323 */
8324 ast_mutex_unlock(&p->lock);
8325 ast_channel_unlock(ast);
8326 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8327 ast_channel_lock(ast);
8328 ast_mutex_lock(&p->lock);
8329 if (p->dahditrcallerid) {
8330 if (!p->origcid_num)
8331 p->origcid_num = ast_strdup(p->cid_num);
8332 if (!p->origcid_name)
8333 p->origcid_name = ast_strdup(p->cid_name);
8334 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8335 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8336 }
8337 /* Swap things around between the three-way and real call */
8338 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8339 /* Disable echo canceller for better dialing */
8340 dahdi_ec_disable(p);
8341 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8342 if (res)
8343 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8344 p->owner = chan;
8345 if (!chan) {
8346 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8347 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8348 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8349 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8350 dahdi_ec_enable(p);
8351 ast_hangup(chan);
8352 } else {
8353 ast_verb(3, "Started three way call on channel %d\n", p->channel);
8354
8355 /* Start music on hold */
8356 ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
8357 p->subs[SUB_THREEWAY].needhold = 1;
8358 }
8359 ast_callid_threadstorage_auto_clean(callid, callid_created);
8360 }
8361 } else {
8362 /* Already have a 3 way call */
8363 if (p->subs[SUB_THREEWAY].inthreeway) {
8364 /* Call is already up, drop the last person */
8365 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8366 /* If the primary call isn't answered yet, use it */
8367 if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
8368 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8369 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8370 p->owner = p->subs[SUB_REAL].owner;
8371 }
8372 /* Drop the last call and stop the conference */
8373 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8374 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8375 p->subs[SUB_REAL].inthreeway = 0;
8376 p->subs[SUB_THREEWAY].inthreeway = 0;
8377 } else {
8378 /* Lets see what we're up to */
8379 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8380 (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
8381 int otherindex = SUB_THREEWAY;
8382
8383 ast_verb(3, "Building conference call with %s and %s\n",
8384 ast_channel_name(p->subs[SUB_THREEWAY].owner),
8385 ast_channel_name(p->subs[SUB_REAL].owner));
8386 /* Put them in the threeway, and flip */
8387 p->subs[SUB_THREEWAY].inthreeway = 1;
8388 p->subs[SUB_REAL].inthreeway = 1;
8389 if (ast_channel_state(ast) == AST_STATE_UP) {
8390 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8391 otherindex = SUB_REAL;
8392 }
8393 if (p->subs[otherindex].owner) {
8394 ast_queue_unhold(p->subs[otherindex].owner);
8395 }
8396 p->subs[otherindex].needunhold = 1;
8397 p->owner = p->subs[SUB_REAL].owner;
8398 } else {
8399 ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8400 swap_subs(p, SUB_THREEWAY, SUB_REAL);
8401 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
8402 p->owner = p->subs[SUB_REAL].owner;
8403 if (p->subs[SUB_REAL].owner) {
8404 ast_queue_unhold(p->subs[SUB_REAL].owner);
8405 }
8406 p->subs[SUB_REAL].needunhold = 1;
8407 dahdi_ec_enable(p);
8408 }
8409 }
8410 }
8411 winkflashdone:
8412 dahdi_conf_update(p);
8413 break;
8414 case SIG_EM:
8415 case SIG_EM_E1:
8416 case SIG_FEATD:
8417 case SIG_SF:
8418 case SIG_SFWINK:
8419 case SIG_SF_FEATD:
8420 case SIG_FXSLS:
8421 case SIG_FXSGS:
8422 if (p->dialing)
8423 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8424 else
8425 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8426 break;
8427 case SIG_FEATDMF_TA:
8428 switch (p->whichwink) {
8429 case 0:
8430 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8431 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8432 ast_channel_caller(p->owner)->ani.number.str, ""));
8433 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8434 ast_channel_caller(p->owner)->ani2,
8435 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
8436 ast_channel_caller(p->owner)->ani.number.str, ""));
8437 break;
8438 case 1:
8439 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8440 break;
8441 case 2:
8442 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8443 return NULL;
8444 }
8445 p->whichwink++;
8446 /* Fall through */
8447 case SIG_FEATDMF:
8448 case SIG_E911:
8449 case SIG_FGC_CAMAMF:
8450 case SIG_FGC_CAMA:
8451 case SIG_FEATB:
8452 case SIG_SF_FEATDMF:
8453 case SIG_SF_FEATB:
8454 case SIG_EMWINK:
8455 /* FGD MF and EMWINK *Must* wait for wink */
8456 if (!ast_strlen_zero(p->dop.dialstr)) {
8457 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8458 if (res) {
8459 p->dop.dialstr[0] = '\0';
8460 return NULL;
8461 } else
8462 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8463 }
8464 p->dop.dialstr[0] = '\0';
8465 break;
8466 default:
8467 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8468 }
8469 break;
8470 case DAHDI_EVENT_HOOKCOMPLETE:
8471 if (p->inalarm) break;
8472 if ((p->radio || (p->oprmode < 0))) break;
8473 if (p->waitingfordt.tv_sec) break;
8474 switch (mysig) {
8475 case SIG_FXSLS: /* only interesting for FXS */
8476 case SIG_FXSGS:
8477 case SIG_FXSKS:
8478 case SIG_EM:
8479 case SIG_EM_E1:
8480 case SIG_EMWINK:
8481 case SIG_FEATD:
8482 case SIG_SF:
8483 case SIG_SFWINK:
8484 case SIG_SF_FEATD:
8485 if (!ast_strlen_zero(p->dop.dialstr)) {
8486 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8487 if (res) {
8488 p->dop.dialstr[0] = '\0';
8489 return NULL;
8490 } else
8491 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8492 }
8493 p->dop.dialstr[0] = '\0';
8494 p->dop.op = DAHDI_DIAL_OP_REPLACE;
8495 break;
8496 case SIG_FEATDMF:
8497 case SIG_FEATDMF_TA:
8498 case SIG_E911:
8499 case SIG_FGC_CAMA:
8500 case SIG_FGC_CAMAMF:
8501 case SIG_FEATB:
8502 case SIG_SF_FEATDMF:
8503 case SIG_SF_FEATB:
8504 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8505 break;
8506 default:
8507 break;
8508 }
8509 break;
8510 case DAHDI_EVENT_POLARITY:
8511 /*
8512 * If we get a Polarity Switch event, check to see
8513 * if we should change the polarity state and
8514 * mark the channel as UP or if this is an indication
8515 * of remote end disconnect.
8516 */
8517 if (p->polarity == POLARITY_IDLE) {
8518 p->polarity = POLARITY_REV;
8519 if (p->answeronpolarityswitch &&
8520 ((ast_channel_state(ast) == AST_STATE_DIALING) ||
8521 (ast_channel_state(ast) == AST_STATE_RINGING))) {
8522 ast_debug(1, "Answering on polarity switch!\n");
8523 ast_setstate(p->owner, AST_STATE_UP);
8524 if (p->hanguponpolarityswitch) {
8525 p->polaritydelaytv = ast_tvnow();
8526 }
8527 } else
8528 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8529 }
8530 /* Removed else statement from here as it was preventing hangups from ever happening*/
8531 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8532 if (p->hanguponpolarityswitch &&
8533 (p->polarityonanswerdelay > 0) &&
8534 (p->polarity == POLARITY_REV) &&
8535 ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
8536 /* Added log_debug information below to provide a better indication of what is going on */
8537 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) );
8538
8539 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
8540 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8541 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
8542 p->polarity = POLARITY_IDLE;
8543 } else
8544 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));
8545
8546 } else {
8547 p->polarity = POLARITY_IDLE;
8548 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8549 }
8550 /* Added more log_debug information below to provide a better indication of what is going on */
8551 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) );
8552 break;
8553 default:
8554 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8555 }
8556 return &p->subs[idx].f;
8557 }
8558
8559 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
8560 {
8561 int res;
8562 int idx;
8563 struct ast_frame *f;
8564 int usedindex = -1;
8565 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8566
8567 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8568 idx = SUB_REAL;
8569 }
8570
8571 p->subs[idx].f.frametype = AST_FRAME_NULL;
8572 p->subs[idx].f.datalen = 0;
8573 p->subs[idx].f.samples = 0;
8574 p->subs[idx].f.mallocd = 0;
8575 p->subs[idx].f.offset = 0;
8576 p->subs[idx].f.subclass.integer = 0;
8577 p->subs[idx].f.delivery = ast_tv(0,0);
8578 p->subs[idx].f.src = "dahdi_exception";
8579 p->subs[idx].f.data.ptr = NULL;
8580
8581
8582 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8583 /* If nobody owns us, absorb the event appropriately, otherwise
8584 we loop indefinitely. This occurs when, during call waiting, the
8585 other end hangs up our channel so that it no longer exists, but we
8586 have neither FLASH'd nor ONHOOK'd to signify our desire to
8587 change to the other channel. */
8588 if (p->fake_event) {
8589 res = p->fake_event;
8590 p->fake_event = 0;
8591 } else
8592 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8593 /* Switch to real if there is one and this isn't something really silly... */
8594 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8595 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8596 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8597 p->owner = p->subs[SUB_REAL].owner;
8598 if (p->owner) {
8599 ast_queue_unhold(p->owner);
8600 }
8601 p->subs[SUB_REAL].needunhold = 1;
8602 }
8603 switch (res) {
8604 case DAHDI_EVENT_ONHOOK:
8605 dahdi_ec_disable(p);
8606 if (p->owner) {
8607 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8608 dahdi_ring_phone(p);
8609 p->callwaitingrepeat = 0;
8610 p->cidcwexpire = 0;
8611 p->cid_suppress_expire = 0;
8612 } else
8613 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8614 dahdi_conf_update(p);
8615 break;
8616 case DAHDI_EVENT_RINGOFFHOOK:
8617 dahdi_ec_enable(p);
8618 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8619 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8620 p->subs[SUB_REAL].needanswer = 1;
8621 p->dialing = 0;
8622 }
8623 break;
8624 case DAHDI_EVENT_HOOKCOMPLETE:
8625 case DAHDI_EVENT_RINGERON:
8626 case DAHDI_EVENT_RINGEROFF:
8627 /* Do nothing */
8628 break;
8629 case DAHDI_EVENT_WINKFLASH:
8630 p->flashtime = ast_tvnow();
8631 if (p->owner) {
8632 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8633 if (ast_channel_state(p->owner) != AST_STATE_UP) {
8634 /* Answer if necessary */
8635 usedindex = dahdi_get_index(p->owner, p, 0);
8636 if (usedindex > -1) {
8637 p->subs[usedindex].needanswer = 1;
8638 }
8639 ast_setstate(p->owner, AST_STATE_UP);
8640 }
8641 p->callwaitingrepeat = 0;
8642 p->cidcwexpire = 0;
8643 p->cid_suppress_expire = 0;
8644 ast_queue_unhold(p->owner);
8645 p->subs[SUB_REAL].needunhold = 1;
8646 } else
8647 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8648 dahdi_conf_update(p);
8649 break;
8650 default:
8651 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8652 }
8653 f = &p->subs[idx].f;
8654 return f;
8655 }
8656 if (!(p->radio || (p->oprmode < 0)))
8657 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8658 /* If it's not us, return NULL immediately */
8659 if (ast != p->owner) {
8660 if (p->owner) {
8661 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8662 }
8663 f = &p->subs[idx].f;
8664 return f;
8665 }
8666
8667 f = dahdi_handle_event(ast);
8668 if (!f) {
8669 const char *name = ast_strdupa(ast_channel_name(ast));
8670
8671 /* Tell the CDR this DAHDI device hung up */
8672 ast_mutex_unlock(&p->lock);
8673 ast_channel_unlock(ast);
8674 ast_set_hangupsource(ast, name, 0);
8675 ast_channel_lock(ast);
8676 ast_mutex_lock(&p->lock);
8677 }
8678 return f;
8679 }
8680
8681 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
8682 {
8683 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8684 struct ast_frame *f;
8685 ast_mutex_lock(&p->lock);
8686 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8687 struct analog_pvt *analog_p = p->sig_pvt;
8688 f = analog_exception(analog_p, ast);
8689 } else {
8690 f = __dahdi_exception(ast);
8691 }
8692 ast_mutex_unlock(&p->lock);
8693 return f;
8694 }
8695
8696 static struct ast_frame *dahdi_read(struct ast_channel *ast)
8697 {
8698 struct dahdi_pvt *p;
8699 int res;
8700 int idx;
8701 void *readbuf;
8702 struct ast_frame *f;
8703
8704 /*
8705 * For analog channels, we must do deadlock avoidance because
8706 * analog ports can have more than one Asterisk channel using
8707 * the same private structure.
8708 */
8709 p = ast_channel_tech_pvt(ast);
8710 while (ast_mutex_trylock(&p->lock)) {
8711 CHANNEL_DEADLOCK_AVOIDANCE(ast);
8712
8713 /*
8714 * Check to see if the channel is still associated with the same
8715 * private structure. While the Asterisk channel was unlocked
8716 * the following events may have occured:
8717 *
8718 * 1) A masquerade may have associated the channel with another
8719 * technology or private structure.
8720 *
8721 * 2) For PRI calls, call signaling could change the channel
8722 * association to another B channel (private structure).
8723 */
8724 if (ast_channel_tech_pvt(ast) != p) {
8725 /* The channel is no longer associated. Quit gracefully. */
8726 return &ast_null_frame;
8727 }
8728 }
8729
8730 idx = dahdi_get_index(ast, p, 0);
8731
8732 /* Hang up if we don't really exist */
8733 if (idx < 0) {
8734 ast_log(LOG_WARNING, "We don't exist?\n");
8735 ast_mutex_unlock(&p->lock);
8736 return NULL;
8737 }
8738
8739 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8740 ast_mutex_unlock(&p->lock);
8741 return NULL;
8742 }
8743
8744 p->subs[idx].f.frametype = AST_FRAME_NULL;
8745 p->subs[idx].f.datalen = 0;
8746 p->subs[idx].f.samples = 0;
8747 p->subs[idx].f.mallocd = 0;
8748 p->subs[idx].f.offset = 0;
8749 p->subs[idx].f.subclass.integer = 0;
8750 p->subs[idx].f.delivery = ast_tv(0,0);
8751 p->subs[idx].f.src = "dahdi_read";
8752 p->subs[idx].f.data.ptr = NULL;
8753
8754 /* make sure it sends initial key state as first frame */
8755 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8756 {
8757 struct dahdi_params ps;
8758
8759 memset(&ps, 0, sizeof(ps));
8760 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8761 ast_mutex_unlock(&p->lock);
8762 return NULL;
8763 }
8764 p->firstradio = 1;
8765 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8766 if (ps.rxisoffhook)
8767 {
8768 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
8769 }
8770 else
8771 {
8772 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
8773 }
8774 ast_mutex_unlock(&p->lock);
8775 return &p->subs[idx].f;
8776 }
8777 if (p->ringt > 0) {
8778 if (!(--p->ringt)) {
8779 ast_mutex_unlock(&p->lock);
8780 return NULL;
8781 }
8782 }
8783
8784 #ifdef HAVE_OPENR2
8785 if (p->mfcr2) {
8786 openr2_chan_process_event(p->r2chan);
8787 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8788 struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
8789 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8790 * now enqueue a progress frame to bridge the media up */
8791 if (p->mfcr2_call_accepted &&
8792 !p->mfcr2_progress_sent &&
8793 ast_channel_state(ast) == AST_STATE_RINGING) {
8794 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8795 ast_queue_frame(p->owner, &fr);
8796 p->mfcr2_progress_sent = 1;
8797 }
8798 }
8799 }
8800 #endif
8801
8802 if (p->subs[idx].needringing) {
8803 /* Send ringing frame if requested */
8804 p->subs[idx].needringing = 0;
8805 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8806 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
8807 ast_setstate(ast, AST_STATE_RINGING);
8808 ast_mutex_unlock(&p->lock);
8809 return &p->subs[idx].f;
8810 }
8811
8812 if (p->subs[idx].needbusy) {
8813 /* Send busy frame if requested */
8814 p->subs[idx].needbusy = 0;
8815 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8816 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
8817 ast_mutex_unlock(&p->lock);
8818 return &p->subs[idx].f;
8819 }
8820
8821 if (p->subs[idx].needcongestion) {
8822 /* Send congestion frame if requested */
8823 p->subs[idx].needcongestion = 0;
8824 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8825 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
8826 ast_mutex_unlock(&p->lock);
8827 return &p->subs[idx].f;
8828 }
8829
8830 if (p->subs[idx].needanswer) {
8831 /* Send answer frame if requested */
8832 p->subs[idx].needanswer = 0;
8833 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8834 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
8835 ast_mutex_unlock(&p->lock);
8836 return &p->subs[idx].f;
8837 }
8838 #ifdef HAVE_OPENR2
8839 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8840 /* openr2 took care of reading and handling any event
8841 (needanswer, needbusy etc), if we continue we will read()
8842 twice, lets just return a null frame. This should only
8843 happen when openr2 is dialing out */
8844 ast_mutex_unlock(&p->lock);
8845 return &ast_null_frame;
8846 }
8847 #endif
8848
8849 if (p->subs[idx].needflash) {
8850 /* Send answer frame if requested */
8851 p->subs[idx].needflash = 0;
8852 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8853 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
8854 ast_mutex_unlock(&p->lock);
8855 return &p->subs[idx].f;
8856 }
8857
8858 if (p->subs[idx].needhold) {
8859 /* Send answer frame if requested */
8860 p->subs[idx].needhold = 0;
8861 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8862 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
8863 ast_mutex_unlock(&p->lock);
8864 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8865 return &p->subs[idx].f;
8866 }
8867
8868 if (p->subs[idx].needunhold) {
8869 /* Send answer frame if requested */
8870 p->subs[idx].needunhold = 0;
8871 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8872 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
8873 ast_mutex_unlock(&p->lock);
8874 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8875 return &p->subs[idx].f;
8876 }
8877
8878 /*
8879 * If we have a fake_event, fake an exception to handle it only
8880 * if this channel owns the private.
8881 */
8882 if (p->fake_event && p->owner == ast) {
8883 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8884 struct analog_pvt *analog_p = p->sig_pvt;
8885
8886 f = analog_exception(analog_p, ast);
8887 } else {
8888 f = __dahdi_exception(ast);
8889 }
8890 ast_mutex_unlock(&p->lock);
8891 return f;
8892 }
8893
8894 if (ast_format_cmp(ast_channel_rawreadformat(ast), ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
8895 if (!p->subs[idx].linear) {
8896 p->subs[idx].linear = 1;
8897 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8898 if (res)
8899 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8900 }
8901 } else {
8902 if (p->subs[idx].linear) {
8903 p->subs[idx].linear = 0;
8904 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8905 if (res)
8906 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8907 }
8908 }
8909 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
8910 CHECK_BLOCKING(ast);
8911 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8912 ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
8913 /* Check for hangup */
8914 if (res < 0) {
8915 f = NULL;
8916 if (res == -1) {
8917 if (errno == EAGAIN) {
8918 /* Return "NULL" frame if there is nobody there */
8919 ast_mutex_unlock(&p->lock);
8920 return &p->subs[idx].f;
8921 } else if (errno == ELAST) {
8922 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8923 struct analog_pvt *analog_p = p->sig_pvt;
8924 f = analog_exception(analog_p, ast);
8925 } else {
8926 f = __dahdi_exception(ast);
8927 }
8928 } else
8929 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
8930 }
8931 ast_mutex_unlock(&p->lock);
8932 return f;
8933 }
8934 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
8935 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8936 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8937 struct analog_pvt *analog_p = p->sig_pvt;
8938 f = analog_exception(analog_p, ast);
8939 } else {
8940 f = __dahdi_exception(ast);
8941 }
8942 ast_mutex_unlock(&p->lock);
8943 return f;
8944 }
8945 if (p->tdd) { /* if in TDD mode, see if we receive that */
8946 int c;
8947
8948 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
8949 if (c < 0) {
8950 ast_debug(1,"tdd_feed failed\n");
8951 ast_mutex_unlock(&p->lock);
8952 return NULL;
8953 }
8954 if (c) { /* if a char to return */
8955 p->subs[idx].f.subclass.integer = 0;
8956 p->subs[idx].f.frametype = AST_FRAME_TEXT;
8957 p->subs[idx].f.mallocd = 0;
8958 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
8959 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
8960 p->subs[idx].f.datalen = 1;
8961 *((char *) p->subs[idx].f.data.ptr) = c;
8962 ast_mutex_unlock(&p->lock);
8963 return &p->subs[idx].f;
8964 }
8965 }
8966 if (idx == SUB_REAL) {
8967 /* Ensure the CW timers decrement only on a single subchannel */
8968 if (p->cidcwexpire) {
8969 if (!--p->cidcwexpire) {
8970 /* Expired CID/CW */
8971 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
8972 restore_conference(p);
8973 }
8974 }
8975 if (p->cid_suppress_expire) {
8976 --p->cid_suppress_expire;
8977 }
8978 if (p->callwaitingrepeat) {
8979 if (!--p->callwaitingrepeat) {
8980 /* Expired, Repeat callwaiting tone */
8981 ++p->callwaitrings;
8982 dahdi_callwait(ast);
8983 }
8984 }
8985 }
8986 if (p->subs[idx].linear) {
8987 p->subs[idx].f.datalen = READ_SIZE * 2;
8988 } else
8989 p->subs[idx].f.datalen = READ_SIZE;
8990
8991 /* Handle CallerID Transmission */
8992 if ((p->owner == ast) && p->cidspill) {
8993 send_callerid(p);
8994 }
8995
8996 p->subs[idx].f.frametype = AST_FRAME_VOICE;
8997 p->subs[idx].f.subclass.format = ast_channel_rawreadformat(ast);
8998 p->subs[idx].f.samples = READ_SIZE;
8999 p->subs[idx].f.mallocd = 0;
9000 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
9001 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
9002 #if 0
9003 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
9004 #endif
9005 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
9006 (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
9007 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
9008 ) {
9009 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
9010 don't send anything */
9011 p->subs[idx].f.frametype = AST_FRAME_NULL;
9012 p->subs[idx].f.subclass.integer = 0;
9013 p->subs[idx].f.samples = 0;
9014 p->subs[idx].f.mallocd = 0;
9015 p->subs[idx].f.offset = 0;
9016 p->subs[idx].f.data.ptr = NULL;
9017 p->subs[idx].f.datalen= 0;
9018 }
9019 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
9020 /* Perform busy detection etc on the dahdi line */
9021 int mute;
9022
9023 if ((p->dsp_features & DSP_FEATURE_FAX_DETECT)
9024 && p->faxdetect_timeout
9025 && p->faxdetect_timeout <= ast_channel_get_up_time(ast)) {
9026 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
9027 ast_dsp_set_features(p->dsp, p->dsp_features);
9028 ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
9029 ast_channel_name(ast));
9030 }
9031
9032 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
9033
9034 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
9035 mute = ast_dsp_was_muted(p->dsp);
9036 if (p->muting != mute) {
9037 p->muting = mute;
9038 dahdi_confmute(p, mute);
9039 }
9040
9041 if (f) {
9042 if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
9043 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
9044 if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
9045 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9046 ast_dsp_set_features(p->dsp, p->dsp_features);
9047 }
9048 }
9049 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
9050 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
9051 /*
9052 * Treat this as a "hangup" instead of a "busy" on the
9053 * assumption that a busy means the incoming call went away.
9054 */
9055 ast_frfree(f);
9056 f = NULL;
9057 }
9058 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
9059 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
9060 /* Dialtone detected on inbound call; hangup the channel */
9061 ast_frfree(f);
9062 f = NULL;
9063 }
9064 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
9065 || f->frametype == AST_FRAME_DTMF_END) {
9066 #ifdef HAVE_PRI
9067 if (dahdi_sig_pri_lib_handles(p->sig)
9068 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
9069 && p->pri
9070 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
9071 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
9072 /* Don't accept in-band DTMF when in overlap dial mode */
9073 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9074 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
9075 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
9076
9077 f->frametype = AST_FRAME_NULL;
9078 f->subclass.integer = 0;
9079 }
9080 #endif
9081 /* DSP clears us of being pulse */
9082 p->pulsedial = 0;
9083 } else if (p->waitingfordt.tv_sec) {
9084 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
9085 p->waitingfordt.tv_sec = 0;
9086 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
9087 ast_frfree(f);
9088 f = NULL;
9089 } else if (f->frametype == AST_FRAME_VOICE) {
9090 f->frametype = AST_FRAME_NULL;
9091 f->subclass.integer = 0;
9092 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
9093 p->waitingfordt.tv_sec = 0;
9094 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
9095 ast_dsp_set_features(p->dsp, p->dsp_features);
9096 ast_debug(1, "Got 10 samples of dialtone!\n");
9097 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
9098 res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
9099 if (res) {
9100 p->dop.dialstr[0] = '\0';
9101 ast_mutex_unlock(&p->lock);
9102 ast_frfree(f);
9103 return NULL;
9104 } else {
9105 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
9106 p->dialing = 1;
9107 p->dop.dialstr[0] = '\0';
9108 p->dop.op = DAHDI_DIAL_OP_REPLACE;
9109 ast_setstate(ast, AST_STATE_DIALING);
9110 }
9111 }
9112 }
9113 }
9114 }
9115 }
9116 } else
9117 f = &p->subs[idx].f;
9118
9119 if (f) {
9120 switch (f->frametype) {
9121 case AST_FRAME_DTMF_BEGIN:
9122 case AST_FRAME_DTMF_END:
9123 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
9124 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9125 } else {
9126 dahdi_handle_dtmf(ast, idx, &f);
9127 }
9128 if (!(p->dialmode == ANALOG_DIALMODE_BOTH || p->dialmode == ANALOG_DIALMODE_DTMF)) {
9129 if (f->frametype == AST_FRAME_DTMF_END) { /* only show this message when the key is let go of */
9130 ast_debug(1, "Dropping DTMF digit '%c' because tone dialing is disabled\n", f->subclass.integer);
9131 }
9132 f->frametype = AST_FRAME_NULL;
9133 f->subclass.integer = 0;
9134 }
9135 break;
9136 case AST_FRAME_VOICE:
9137 if (p->cidspill || p->cid_suppress_expire) {
9138 /* We are/were sending a caller id spill. Suppress any echo. */
9139 p->subs[idx].f.frametype = AST_FRAME_NULL;
9140 p->subs[idx].f.subclass.integer = 0;
9141 p->subs[idx].f.samples = 0;
9142 p->subs[idx].f.mallocd = 0;
9143 p->subs[idx].f.offset = 0;
9144 p->subs[idx].f.data.ptr = NULL;
9145 p->subs[idx].f.datalen= 0;
9146 }
9147 break;
9148 default:
9149 break;
9150 }
9151 }
9152
9153 ast_mutex_unlock(&p->lock);
9154 return f;
9155 }
9156
9157 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
9158 {
9159 int sent=0;
9160 int size;
9161 int res;
9162 int fd;
9163 fd = p->subs[idx].dfd;
9164 while (len) {
9165 size = len;
9166 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9167 size = (linear ? READ_SIZE * 2 : READ_SIZE);
9168 res = write(fd, buf, size);
9169 if (res != size) {
9170 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
9171 return sent;
9172 }
9173 len -= size;
9174 buf += size;
9175 }
9176 return sent;
9177 }
9178
9179 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
9180 {
9181 struct dahdi_pvt *p;
9182 int res;
9183 int idx;
9184
9185 /* Write a frame of (presumably voice) data */
9186 if (frame->frametype != AST_FRAME_VOICE) {
9187 if (frame->frametype != AST_FRAME_IMAGE) {
9188 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
9189 frame->frametype);
9190 }
9191 return 0;
9192 }
9193
9194 /* Return if it's not valid data */
9195 if (!frame->data.ptr || !frame->datalen) {
9196 return 0;
9197 }
9198
9199 p = ast_channel_tech_pvt(ast);
9200 ast_mutex_lock(&p->lock);
9201
9202 idx = dahdi_get_index(ast, p, 0);
9203 if (idx < 0) {
9204 ast_mutex_unlock(&p->lock);
9205 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
9206 return -1;
9207 }
9208
9209 if (p->dialing) {
9210 ast_mutex_unlock(&p->lock);
9211 ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
9212 ast_channel_name(ast));
9213 return 0;
9214 }
9215 if (!p->owner) {
9216 ast_mutex_unlock(&p->lock);
9217 ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
9218 ast_channel_name(ast));
9219 return 0;
9220 }
9221 if (p->cidspill) {
9222 ast_mutex_unlock(&p->lock);
9223 ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
9224 ast_channel_name(ast));
9225 return 0;
9226 }
9227
9228 if (ast_format_cmp(frame->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
9229 if (!p->subs[idx].linear) {
9230 p->subs[idx].linear = 1;
9231 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9232 if (res)
9233 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
9234 }
9235 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
9236 } else if (ast_format_cmp(frame->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL
9237 || ast_format_cmp(frame->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
9238 /* x-law already */
9239 if (p->subs[idx].linear) {
9240 p->subs[idx].linear = 0;
9241 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
9242 if (res)
9243 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
9244 }
9245 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
9246 } else {
9247 ast_mutex_unlock(&p->lock);
9248 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
9249 ast_format_get_name(frame->subclass.format));
9250 return -1;
9251 }
9252 ast_mutex_unlock(&p->lock);
9253 if (res < 0) {
9254 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
9255 return -1;
9256 }
9257 return 0;
9258 }
9259
9260 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
9261 {
9262 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9263 int res=-1;
9264 int idx;
9265 int func = DAHDI_FLASH;
9266
9267 ast_mutex_lock(&p->lock);
9268 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9269 switch (p->sig) {
9270 #if defined(HAVE_PRI)
9271 case SIG_PRI_LIB_HANDLE_CASES:
9272 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9273 ast_mutex_unlock(&p->lock);
9274 return res;
9275 #endif /* defined(HAVE_PRI) */
9276 #if defined(HAVE_SS7)
9277 case SIG_SS7:
9278 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9279 ast_mutex_unlock(&p->lock);
9280 return res;
9281 #endif /* defined(HAVE_SS7) */
9282 default:
9283 break;
9284 }
9285 #ifdef HAVE_OPENR2
9286 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9287 ast_mutex_unlock(&p->lock);
9288 /* if this is an R2 call and the call is not yet accepted, we don't want the
9289 tone indications to mess up with the MF tones */
9290 return 0;
9291 }
9292 #endif
9293 idx = dahdi_get_index(chan, p, 0);
9294 if (idx == SUB_REAL) {
9295 switch (condition) {
9296 case AST_CONTROL_BUSY:
9297 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9298 break;
9299 case AST_CONTROL_RINGING:
9300 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9301
9302 if (ast_channel_state(chan) != AST_STATE_UP) {
9303 if ((ast_channel_state(chan) != AST_STATE_RING) ||
9304 ((p->sig != SIG_FXSKS) &&
9305 (p->sig != SIG_FXSLS) &&
9306 (p->sig != SIG_FXSGS)))
9307 ast_setstate(chan, AST_STATE_RINGING);
9308 }
9309 break;
9310 case AST_CONTROL_INCOMPLETE:
9311 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9312 /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9313 res = 0;
9314 break;
9315 case AST_CONTROL_PROCEEDING:
9316 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9317 /* don't continue in ast_indicate */
9318 res = 0;
9319 break;
9320 case AST_CONTROL_PROGRESS:
9321 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9322 /* don't continue in ast_indicate */
9323 res = 0;
9324 break;
9325 case AST_CONTROL_CONGESTION:
9326 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9327 switch (ast_channel_hangupcause(chan)) {
9328 case AST_CAUSE_USER_BUSY:
9329 case AST_CAUSE_NORMAL_CLEARING:
9330 case 0:/* Cause has not been set. */
9331 /* Supply a more appropriate cause. */
9332 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
9333 break;
9334 default:
9335 break;
9336 }
9337 break;
9338 case AST_CONTROL_HOLD:
9339 ast_moh_start(chan, data, p->mohinterpret);
9340 break;
9341 case AST_CONTROL_UNHOLD:
9342 ast_moh_stop(chan);
9343 break;
9344 case AST_CONTROL_RADIO_KEY:
9345 if (p->radio)
9346 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9347 res = 0;
9348 break;
9349 case AST_CONTROL_RADIO_UNKEY:
9350 if (p->radio)
9351 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9352 res = 0;
9353 break;
9354 case AST_CONTROL_FLASH:
9355 /* flash hookswitch */
9356 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9357 /* Clear out the dial buffer */
9358 p->dop.dialstr[0] = '\0';
9359 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9360 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9361 ast_channel_name(chan), strerror(errno));
9362 } else
9363 res = 0;
9364 } else
9365 res = 0;
9366 break;
9367 case AST_CONTROL_SRCUPDATE:
9368 res = 0;
9369 break;
9370 case -1:
9371 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9372 break;
9373 }
9374 } else {
9375 res = 0;
9376 }
9377 ast_mutex_unlock(&p->lock);
9378 return res;
9379 }
9380
9381 #if defined(HAVE_PRI)
9382 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9383 #else
9384 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
9385 #endif /* defined(HAVE_PRI) */
9386 {
9387 struct ast_str *chan_name;
9388 int x, y;
9389
9390 /* Create the new channel name tail. */
9391 if (!(chan_name = ast_str_create(32))) {
9392 return NULL;
9393 }
9394 if (i->channel == CHAN_PSEUDO) {
9395 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9396 #if defined(HAVE_PRI)
9397 } else if (i->pri) {
9398 ast_mutex_lock(&i->pri->lock);
9399 y = ++i->pri->new_chan_seq;
9400 if (is_outgoing) {
9401 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9402 address[0] = '\0';
9403 } else if (ast_strlen_zero(i->cid_subaddr)) {
9404 /* Put in caller-id number only since there is no subaddress. */
9405 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9406 } else {
9407 /* Put in caller-id number and subaddress. */
9408 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9409 i->cid_subaddr, (unsigned)y);
9410 }
9411 ast_mutex_unlock(&i->pri->lock);
9412 #endif /* defined(HAVE_PRI) */
9413 } else {
9414 y = 1;
9415 do {
9416 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9417 for (x = 0; x < 3; ++x) {
9418 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9419 ast_channel_name(i->subs[x].owner) + 6)) {
9420 break;
9421 }
9422 }
9423 ++y;
9424 } while (x < 3);
9425 }
9426 return chan_name;
9427 }
9428
9429 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)
9430 {
9431 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9432
9433 ast_callid_threadstorage_auto_clean(callid, callid_created);
9434
9435 return new_channel;
9436 }
9437
9438 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)
9439 {
9440 struct ast_channel *tmp;
9441 struct ast_format_cap *caps;
9442 struct ast_format *deflaw;
9443 int x;
9444 int features;
9445 struct ast_str *chan_name;
9446 struct ast_variable *v;
9447 char *dashptr;
9448 char device_name[AST_CHANNEL_NAME];
9449
9450 if (i->subs[idx].owner) {
9451 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9452 return NULL;
9453 }
9454
9455 #if defined(HAVE_PRI)
9456 /*
9457 * The dnid has been stuffed with the called-number[:subaddress]
9458 * by dahdi_request() for outgoing calls.
9459 */
9460 chan_name = create_channel_name(i, i->outgoing, i->dnid);
9461 #else
9462 chan_name = create_channel_name(i);
9463 #endif /* defined(HAVE_PRI) */
9464 if (!chan_name) {
9465 return NULL;
9466 }
9467
9468 caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
9469 if (!caps) {
9470 ast_free(chan_name);
9471 return NULL;
9472 }
9473
9474 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));
9475 ast_free(chan_name);
9476 if (!tmp) {
9477 ao2_ref(caps, -1);
9478 return NULL;
9479 }
9480
9481 ast_channel_stage_snapshot(tmp);
9482
9483 if (callid) {
9484 ast_channel_callid_set(tmp, callid);
9485 }
9486
9487 ast_channel_tech_set(tmp, &dahdi_tech);
9488 #if defined(HAVE_PRI)
9489 if (i->pri) {
9490 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
9491 }
9492 #endif /* defined(HAVE_PRI) */
9493 ast_channel_cc_params_init(tmp, i->cc_params);
9494 if (law) {
9495 i->law = law;
9496 if (law == DAHDI_LAW_ALAW) {
9497 deflaw = ast_format_alaw;
9498 } else {
9499 deflaw = ast_format_ulaw;
9500 }
9501 } else {
9502 switch (i->sig) {
9503 case SIG_PRI_LIB_HANDLE_CASES:
9504 /* Make sure companding law is known. */
9505 i->law = (i->law_default == DAHDI_LAW_ALAW)
9506 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9507 break;
9508 default:
9509 i->law = i->law_default;
9510 break;
9511 }
9512 if (i->law_default == DAHDI_LAW_ALAW) {
9513 deflaw = ast_format_alaw;
9514 } else {
9515 deflaw = ast_format_ulaw;
9516 }
9517 }
9518 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9519 ast_format_cap_append(caps, deflaw, 0);
9520 ast_channel_nativeformats_set(tmp, caps);
9521 ao2_ref(caps, -1);
9522 /* Start out assuming ulaw since it's smaller :) */
9523 ast_channel_set_rawreadformat(tmp, deflaw);
9524 ast_channel_set_readformat(tmp, deflaw);
9525 ast_channel_set_rawwriteformat(tmp, deflaw);
9526 ast_channel_set_writeformat(tmp, deflaw);
9527 i->subs[idx].linear = 0;
9528 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9529 features = 0;
9530 if (idx == SUB_REAL) {
9531 if (i->busydetect && CANBUSYDETECT(i))
9532 features |= DSP_FEATURE_BUSY_DETECT;
9533 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
9534 features |= DSP_FEATURE_CALL_PROGRESS;
9535 if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
9536 features |= DSP_FEATURE_WAITDIALTONE;
9537 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9538 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
9539 features |= DSP_FEATURE_FAX_DETECT;
9540 }
9541 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9542 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9543 i->hardwaredtmf = 0;
9544 features |= DSP_FEATURE_DIGIT_DETECT;
9545 } else if (NEED_MFDETECT(i)) {
9546 i->hardwaredtmf = 1;
9547 features |= DSP_FEATURE_DIGIT_DETECT;
9548 }
9549 }
9550 if (features) {
9551 if (i->dsp) {
9552 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9553 } else {
9554 if (i->channel != CHAN_PSEUDO)
9555 i->dsp = ast_dsp_new();
9556 else
9557 i->dsp = NULL;
9558 if (i->dsp) {
9559 i->dsp_features = features;
9560 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9561 /* We cannot do progress detection until receive PROGRESS message */
9562 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9563 /* Remember requested DSP features, don't treat
9564 talking as ANSWER */
9565 i->dsp_features = features & ~DSP_PROGRESS_TALK;
9566 features = 0;
9567 }
9568 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9569 ast_dsp_set_features(i->dsp, features);
9570 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
9571 if (!ast_strlen_zero(progzone))
9572 ast_dsp_set_call_progress_zone(i->dsp, progzone);
9573 if (i->busydetect && CANBUSYDETECT(i)) {
9574 ast_dsp_set_busy_count(i->dsp, i->busycount);
9575 ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
9576 }
9577 }
9578 }
9579 }
9580
9581 i->dialtone_scanning_time_elapsed = 0;
9582
9583 if (state == AST_STATE_RING)
9584 ast_channel_rings_set(tmp, 1);
9585 ast_channel_tech_pvt_set(tmp, i);
9586 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9587 /* Only FXO signalled stuff can be picked up */
9588 ast_channel_callgroup_set(tmp, i->callgroup);
9589 ast_channel_pickupgroup_set(tmp, i->pickupgroup);
9590 ast_channel_named_callgroups_set(tmp, i->named_callgroups);
9591 ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
9592 }
9593 if (!ast_strlen_zero(i->parkinglot))
9594 ast_channel_parkinglot_set(tmp, i->parkinglot);
9595 if (!ast_strlen_zero(i->language))
9596 ast_channel_language_set(tmp, i->language);
9597 if (!i->owner)
9598 i->owner = tmp;
9599 if (!ast_strlen_zero(i->accountcode))
9600 ast_channel_accountcode_set(tmp, i->accountcode);
9601 if (i->amaflags)
9602 ast_channel_amaflags_set(tmp, i->amaflags);
9603 i->subs[idx].owner = tmp;
9604 ast_channel_context_set(tmp, i->context);
9605 if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9606 ast_channel_call_forward_set(tmp, i->call_forward);
9607 }
9608 /* If we've been told "no ADSI" then enforce it */
9609 if (!i->adsi)
9610 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
9611 if (!ast_strlen_zero(i->exten))
9612 ast_channel_exten_set(tmp, i->exten);
9613 if (!ast_strlen_zero(i->rdnis)) {
9614 ast_channel_redirecting(tmp)->from.number.valid = 1;
9615 ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
9616 }
9617 if (!ast_strlen_zero(i->dnid)) {
9618 ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
9619 }
9620
9621 /* Don't use ast_set_callerid() here because it will
9622 * generate a needless NewCallerID event */
9623 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9624 if (!ast_strlen_zero(i->cid_ani)) {
9625 ast_channel_caller(tmp)->ani.number.valid = 1;
9626 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9627 } else if (!ast_strlen_zero(i->cid_num)) {
9628 ast_channel_caller(tmp)->ani.number.valid = 1;
9629 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9630 }
9631 #else
9632 if (!ast_strlen_zero(i->cid_num)) {
9633 ast_channel_caller(tmp)->ani.number.valid = 1;
9634 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
9635 }
9636 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9637 ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
9638 ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
9639 ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
9640 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9641 ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
9642 /* clear the fake event in case we posted one before we had ast_channel */
9643 i->fake_event = 0;
9644 /* Assure there is no confmute on this channel */
9645 dahdi_confmute(i, 0);
9646 i->muting = 0;
9647 /* Configure the new channel jb */
9648 ast_jb_configure(tmp, &global_jbconf);
9649
9650 /* Set initial device state */
9651 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9652 dashptr = strrchr(device_name, '-');
9653 if (dashptr) {
9654 *dashptr = '\0';
9655 }
9656 ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
9657 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
9658
9659 for (v = i->vars ; v ; v = v->next)
9660 pbx_builtin_setvar_helper(tmp, v->name, v->value);
9661
9662 ast_channel_stage_snapshot_done(tmp);
9663
9664 ast_channel_unlock(tmp);
9665
9666 ast_module_ref(ast_module_info->self);
9667
9668 dahdi_ami_channel_event(i, tmp);
9669 if (startpbx) {
9670 #ifdef HAVE_OPENR2
9671 if (i->mfcr2call) {
9672 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9673 }
9674 #endif
9675 if (ast_pbx_start(tmp)) {
9676 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9677 ast_hangup(tmp);
9678 return NULL;
9679 }
9680 }
9681 return tmp;
9682 }
9683
9684
9685 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
9686 {
9687 char c;
9688
9689 *str = 0; /* start with empty output buffer */
9690 for (;;)
9691 {
9692 /* Wait for the first digit (up to specified ms). */
9693 c = ast_waitfordigit(chan, ms);
9694 /* if timeout, hangup or error, return as such */
9695 if (c < 1)
9696 return c;
9697 *str++ = c;
9698 *str = 0;
9699 if (strchr(term, c))
9700 return 1;
9701 }
9702 }
9703
9704 static int dahdi_wink(struct dahdi_pvt *p, int idx)
9705 {
9706 int j;
9707 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9708 for (;;)
9709 {
9710 /* set bits of interest */
9711 j = DAHDI_IOMUX_SIGEVENT;
9712 /* wait for some happening */
9713 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9714 /* exit loop if we have it */
9715 if (j & DAHDI_IOMUX_SIGEVENT) break;
9716 }
9717 /* get the event info */
9718 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9719 return 0;
9720 }
9721
9722 static void publish_dnd_state(int channel, const char *status)
9723 {
9724 RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9725 RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9726 if (!dahdichan) {
9727 return;
9728 }
9729
9730 ast_str_set(&dahdichan, 0, "%d", channel);
9731
9732 body = ast_json_pack("{s: s, s: s}",
9733 "DAHDIChannel", ast_str_buffer(dahdichan),
9734 "Status", status);
9735 if (!body) {
9736 return;
9737 }
9738
9739 ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body);
9740 }
9741
9742 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
9743 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
9744 * \param flag on 1 to enable, 0 to disable, -1 return dnd value
9745 *
9746 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
9747 * DAHDI channel). Use this to enable or disable it.
9748 *
9749 * \bug the use of the word "channel" for those dahdichans is really confusing.
9750 */
9751 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
9752 {
9753 if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9754 return analog_dnd(dahdichan->sig_pvt, flag);
9755 }
9756
9757 if (flag == -1) {
9758 return dahdichan->dnd;
9759 }
9760
9761 /* Do not disturb */
9762 dahdichan->dnd = flag;
9763 ast_verb(3, "%s DND on channel %d\n",
9764 flag? "Enabled" : "Disabled",
9765 dahdichan->channel);
9766 publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9767 return 0;
9768 }
9769
9770 static int canmatch_featurecode(const char *pickupexten, const char *exten)
9771 {
9772 int extlen = strlen(exten);
9773
9774 if (!extlen) {
9775 return 1;
9776 }
9777
9778 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9779 return 1;
9780 }
9781 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9782 if (exten[0] == '*' && extlen < 3) {
9783 if (extlen == 1) {
9784 return 1;
9785 }
9786 /* "*0" should be processed before it gets here */
9787 switch (exten[1]) {
9788 case '6':
9789 case '7':
9790 case '8':
9791 return 1;
9792 }
9793 }
9794 return 0;
9795 }
9796
9797 static void *analog_ss_thread(void *data)
9798 {
9799 struct ast_channel *chan = data;
9800 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9801 char exten[AST_MAX_EXTENSION] = "";
9802 char exten2[AST_MAX_EXTENSION] = "";
9803 unsigned char buf[256];
9804 char dtmfcid[300];
9805 char dtmfbuf[300];
9806 struct callerid_state *cs = NULL;
9807 char *name = NULL, *number = NULL;
9808 int distMatches;
9809 int curRingData[3];
9810 int receivedRingT;
9811 int counter1;
9812 int counter;
9813 int samples = 0;
9814 struct ast_smdi_md_message *smdi_msg = NULL;
9815 int flags = 0;
9816 int i;
9817 int timeout;
9818 int getforward = 0;
9819 char *s1, *s2;
9820 int len = 0;
9821 int res;
9822 int idx;
9823 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9824 const char *pickupexten;
9825
9826 ast_mutex_lock(&ss_thread_lock);
9827 ss_thread_count++;
9828 ast_mutex_unlock(&ss_thread_lock);
9829 /* in the bizarre case where the channel has become a zombie before we
9830 even get started here, abort safely
9831 */
9832 if (!p) {
9833 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9834 ast_hangup(chan);
9835 goto quit;
9836 }
9837 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9838 idx = dahdi_get_index(chan, p, 1);
9839 if (idx < 0) {
9840 ast_log(LOG_WARNING, "Huh?\n");
9841 ast_hangup(chan);
9842 goto quit;
9843 }
9844
9845 ast_channel_lock(chan);
9846 pickup_cfg = ast_get_chan_features_pickup_config(chan);
9847 if (!pickup_cfg) {
9848 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9849 pickupexten = "";
9850 } else {
9851 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9852 }
9853 ast_channel_unlock(chan);
9854
9855 if (p->dsp)
9856 ast_dsp_digitreset(p->dsp);
9857 switch (p->sig) {
9858 case SIG_FEATD:
9859 case SIG_FEATDMF:
9860 case SIG_FEATDMF_TA:
9861 case SIG_E911:
9862 case SIG_FGC_CAMAMF:
9863 case SIG_FEATB:
9864 case SIG_EMWINK:
9865 case SIG_SF_FEATD:
9866 case SIG_SF_FEATDMF:
9867 case SIG_SF_FEATB:
9868 case SIG_SFWINK:
9869 if (dahdi_wink(p, idx))
9870 goto quit;
9871 /* Fall through */
9872 case SIG_EM:
9873 case SIG_EM_E1:
9874 case SIG_SF:
9875 case SIG_FGC_CAMA:
9876 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9877 if (p->dsp)
9878 ast_dsp_digitreset(p->dsp);
9879 /* set digit mode appropriately */
9880 if (p->dsp) {
9881 if (NEED_MFDETECT(p))
9882 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
9883 else
9884 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
9885 }
9886 memset(dtmfbuf, 0, sizeof(dtmfbuf));
9887 /* Wait for the first digit only if immediate=no */
9888 if (!p->immediate)
9889 /* Wait for the first digit (up to 5 seconds). */
9890 res = ast_waitfordigit(chan, 5000);
9891 else
9892 res = 0;
9893 if (res > 0) {
9894 /* save first char */
9895 dtmfbuf[0] = res;
9896 switch (p->sig) {
9897 case SIG_FEATD:
9898 case SIG_SF_FEATD:
9899 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9900 if (res > 0)
9901 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9902 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9903 break;
9904 case SIG_FEATDMF_TA:
9905 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9906 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9907 if (dahdi_wink(p, idx)) goto quit;
9908 dtmfbuf[0] = 0;
9909 /* Wait for the first digit (up to 5 seconds). */
9910 res = ast_waitfordigit(chan, 5000);
9911 if (res <= 0) break;
9912 dtmfbuf[0] = res;
9913 /* fall through intentionally */
9914 case SIG_FEATDMF:
9915 case SIG_E911:
9916 case SIG_FGC_CAMAMF:
9917 case SIG_SF_FEATDMF:
9918 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9919 /* if international caca, do it again to get real ANO */
9920 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
9921 {
9922 if (dahdi_wink(p, idx)) goto quit;
9923 dtmfbuf[0] = 0;
9924 /* Wait for the first digit (up to 5 seconds). */
9925 res = ast_waitfordigit(chan, 5000);
9926 if (res <= 0) break;
9927 dtmfbuf[0] = res;
9928 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9929 }
9930 if (res > 0) {
9931 /* if E911, take off hook */
9932 if (p->sig == SIG_E911)
9933 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9934 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
9935 }
9936 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9937 break;
9938 case SIG_FEATB:
9939 case SIG_SF_FEATB:
9940 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9941 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9942 break;
9943 case SIG_EMWINK:
9944 /* if we received a '*', we are actually receiving Feature Group D
9945 dial syntax, so use that mode; otherwise, fall through to normal
9946 mode
9947 */
9948 if (res == '*') {
9949 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9950 if (res > 0)
9951 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9952 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9953 break;
9954 }
9955 default:
9956 /* If we got the first digit, get the rest */
9957 len = 1;
9958 dtmfbuf[len] = '\0';
9959 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9960 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9961 timeout = p->matchdigit_timeout;
9962 } else {
9963 timeout = p->interdigit_timeout;
9964 }
9965 res = ast_waitfordigit(chan, timeout);
9966 if (res < 0) {
9967 ast_debug(1, "waitfordigit returned < 0...\n");
9968 ast_hangup(chan);
9969 goto quit;
9970 } else if (res) {
9971 dtmfbuf[len++] = res;
9972 dtmfbuf[len] = '\0';
9973 } else {
9974 break;
9975 }
9976 }
9977 break;
9978 }
9979 }
9980 if (res == -1) {
9981 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
9982 ast_hangup(chan);
9983 goto quit;
9984 } else if (res < 0) {
9985 ast_debug(1, "Got hung up before digits finished\n");
9986 ast_hangup(chan);
9987 goto quit;
9988 }
9989
9990 if (p->sig == SIG_FGC_CAMA) {
9991 char anibuf[100];
9992
9993 if (ast_safe_sleep(chan,1000) == -1) {
9994 ast_hangup(chan);
9995 goto quit;
9996 }
9997 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9998 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
9999 res = my_getsigstr(chan, anibuf, "#", 10000);
10000 if ((res > 0) && (strlen(anibuf) > 2)) {
10001 if (anibuf[strlen(anibuf) - 1] == '#')
10002 anibuf[strlen(anibuf) - 1] = 0;
10003 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10004 }
10005 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10006 }
10007
10008 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10009 if (ast_strlen_zero(exten))
10010 ast_copy_string(exten, "s", sizeof(exten));
10011 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10012 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10013 if (exten[0] == '*') {
10014 char *stringp=NULL;
10015 ast_copy_string(exten2, exten, sizeof(exten2));
10016 /* Parse out extension and callerid */
10017 stringp=exten2 +1;
10018 s1 = strsep(&stringp, "*");
10019 s2 = strsep(&stringp, "*");
10020 if (s2) {
10021 if (!ast_strlen_zero(p->cid_num))
10022 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10023 else
10024 ast_set_callerid(chan, s1, NULL, s1);
10025 ast_copy_string(exten, s2, sizeof(exten));
10026 } else
10027 ast_copy_string(exten, s1, sizeof(exten));
10028 } else if (p->sig == SIG_FEATD)
10029 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10030 }
10031 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10032 if (exten[0] == '*') {
10033 char *stringp=NULL;
10034 ast_copy_string(exten2, exten, sizeof(exten2));
10035 /* Parse out extension and callerid */
10036 stringp=exten2 +1;
10037 s1 = strsep(&stringp, "#");
10038 s2 = strsep(&stringp, "#");
10039 if (s2) {
10040 if (!ast_strlen_zero(p->cid_num))
10041 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10042 else
10043 if (*(s1 + 2))
10044 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10045 ast_copy_string(exten, s2 + 1, sizeof(exten));
10046 } else
10047 ast_copy_string(exten, s1 + 2, sizeof(exten));
10048 } else
10049 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10050 }
10051 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10052 if (exten[0] == '*') {
10053 char *stringp=NULL;
10054 ast_copy_string(exten2, exten, sizeof(exten2));
10055 /* Parse out extension and callerid */
10056 stringp=exten2 +1;
10057 s1 = strsep(&stringp, "#");
10058 s2 = strsep(&stringp, "#");
10059 if (s2 && (*(s2 + 1) == '0')) {
10060 if (*(s2 + 2))
10061 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10062 }
10063 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10064 else ast_copy_string(exten, "911", sizeof(exten));
10065 } else
10066 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10067 }
10068 if (p->sig == SIG_FEATB) {
10069 if (exten[0] == '*') {
10070 char *stringp=NULL;
10071 ast_copy_string(exten2, exten, sizeof(exten2));
10072 /* Parse out extension and callerid */
10073 stringp=exten2 +1;
10074 s1 = strsep(&stringp, "#");
10075 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10076 } else
10077 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10078 }
10079 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10080 dahdi_wink(p, idx);
10081 /* some switches require a minimum guard time between
10082 the last FGD wink and something that answers
10083 immediately. This ensures it */
10084 if (ast_safe_sleep(chan, 100)) {
10085 ast_hangup(chan);
10086 goto quit;
10087 }
10088 }
10089 dahdi_ec_enable(p);
10090 if (NEED_MFDETECT(p)) {
10091 if (p->dsp) {
10092 if (!p->hardwaredtmf)
10093 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10094 else {
10095 ast_dsp_free(p->dsp);
10096 p->dsp = NULL;
10097 }
10098 }
10099 }
10100
10101 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10102 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10103 ast_channel_exten_set(chan, exten);
10104 if (p->dsp) ast_dsp_digitreset(p->dsp);
10105 res = ast_pbx_run(chan);
10106 if (res) {
10107 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10108 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10109 }
10110 goto quit;
10111 } else {
10112 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10113 sleep(2);
10114 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10115 if (res < 0)
10116 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10117 else
10118 sleep(1);
10119 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10120 if (res >= 0)
10121 ast_waitstream(chan, "");
10122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10123 ast_hangup(chan);
10124 goto quit;
10125 }
10126 break;
10127 case SIG_FXOLS:
10128 case SIG_FXOGS:
10129 case SIG_FXOKS:
10130 /* Read the first digit */
10131 timeout = p->firstdigit_timeout;
10132 /* If starting a threeway call, never timeout on the first digit so someone
10133 can use flash-hook as a "hold" feature */
10134 if (p->subs[SUB_THREEWAY].owner)
10135 timeout = INT_MAX;
10136 while (len < AST_MAX_EXTENSION-1) {
10137 int is_exten_parking = 0;
10138
10139 /* Read digit unless it's supposed to be immediate, in which case the
10140 only answer is 's' */
10141 if (p->immediate)
10142 res = 's';
10143 else
10144 res = ast_waitfordigit(chan, timeout);
10145 timeout = 0;
10146 if (res < 0) {
10147 ast_debug(1, "waitfordigit returned < 0...\n");
10148 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10149 ast_hangup(chan);
10150 goto quit;
10151 } else if (res) {
10152 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10153 exten[len++]=res;
10154 exten[len] = '\0';
10155 }
10156 if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
10157 tone_zone_play_tone(p->subs[idx].dfd, -1);
10158 } else {
10159 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10160 }
10161 if (ast_parking_provider_registered()) {
10162 is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
10163 }
10164 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
10165 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10166 if (getforward) {
10167 /* Record this as the forwarding extension */
10168 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10169 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10170 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10171 if (res)
10172 break;
10173 usleep(500000);
10174 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10175 sleep(1);
10176 memset(exten, 0, sizeof(exten));
10177 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10178 len = 0;
10179 getforward = 0;
10180 } else {
10181 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10182 ast_channel_lock(chan);
10183 ast_channel_exten_set(chan, exten);
10184 if (!ast_strlen_zero(p->cid_num)) {
10185 if (!p->hidecallerid)
10186 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10187 else
10188 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10189 }
10190 if (!ast_strlen_zero(p->cid_name)) {
10191 if (!p->hidecallerid)
10192 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10193 }
10194 ast_setstate(chan, AST_STATE_RING);
10195 ast_channel_unlock(chan);
10196 dahdi_ec_enable(p);
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 }
10204 } else {
10205 /* It's a match, but they just typed a digit, and there is an ambiguous match,
10206 so just set the timeout to matchdigit_timeout and wait some more */
10207 timeout = p->matchdigit_timeout;
10208 }
10209 } else if (res == 0) {
10210 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10211 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10212 dahdi_wait_event(p->subs[idx].dfd);
10213 ast_hangup(chan);
10214 goto quit;
10215 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10216 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10217 /* Disable call waiting if enabled */
10218 p->callwaiting = 0;
10219 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10220 if (res) {
10221 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10222 ast_channel_name(chan), strerror(errno));
10223 }
10224 len = 0;
10225 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10226 memset(exten, 0, sizeof(exten));
10227 timeout = p->firstdigit_timeout;
10228
10229 } else if (!strcmp(exten, pickupexten)) {
10230 /* Scan all channels and see if there are any
10231 * ringing channels that have call groups
10232 * that equal this channels pickup group
10233 */
10234 if (idx == SUB_REAL) {
10235 /* Switch us from Third call to Call Wait */
10236 if (p->subs[SUB_THREEWAY].owner) {
10237 /* If you make a threeway call and the *8# a call, it should actually
10238 look like a callwait */
10239 alloc_sub(p, SUB_CALLWAIT);
10240 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10241 unalloc_sub(p, SUB_THREEWAY);
10242 }
10243 dahdi_ec_enable(p);
10244 if (ast_pickup_call(chan)) {
10245 ast_debug(1, "No call pickup possible...\n");
10246 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10247 dahdi_wait_event(p->subs[idx].dfd);
10248 }
10249 ast_hangup(chan);
10250 goto quit;
10251 } else {
10252 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10253 ast_hangup(chan);
10254 goto quit;
10255 }
10256
10257 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10258 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10259 /* Disable Caller*ID if enabled */
10260 p->hidecallerid = 1;
10261 ast_party_number_free(&ast_channel_caller(chan)->id.number);
10262 ast_party_number_init(&ast_channel_caller(chan)->id.number);
10263 ast_party_name_free(&ast_channel_caller(chan)->id.name);
10264 ast_party_name_init(&ast_channel_caller(chan)->id.name);
10265 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10266 if (res) {
10267 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10268 ast_channel_name(chan), strerror(errno));
10269 }
10270 len = 0;
10271 memset(exten, 0, sizeof(exten));
10272 timeout = p->firstdigit_timeout;
10273 } else if (p->callreturn && !strcmp(exten, "*69")) {
10274 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10275 break;
10276 } else if (!strcmp(exten, "*78")) {
10277 dahdi_dnd(p, 1);
10278 /* Do not disturb */
10279 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10280 getforward = 0;
10281 memset(exten, 0, sizeof(exten));
10282 len = 0;
10283 } else if (!strcmp(exten, "*79")) {
10284 dahdi_dnd(p, 0);
10285 /* Do not disturb */
10286 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10287 getforward = 0;
10288 memset(exten, 0, sizeof(exten));
10289 len = 0;
10290 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10291 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10292 getforward = 1;
10293 memset(exten, 0, sizeof(exten));
10294 len = 0;
10295 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10296 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10297 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10298 memset(p->call_forward, 0, sizeof(p->call_forward));
10299 getforward = 0;
10300 memset(exten, 0, sizeof(exten));
10301 len = 0;
10302 } else if ((p->transfer || p->canpark) && is_exten_parking
10303 && p->subs[SUB_THREEWAY].owner) {
10304 struct ast_bridge_channel *bridge_channel;
10305
10306 /*
10307 * This is a three way call, the main call being a real channel,
10308 * and we're parking the first call.
10309 */
10310 ast_channel_lock(p->subs[SUB_THREEWAY].owner);
10311 bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
10312 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
10313 if (bridge_channel) {
10314 if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10315 /*
10316 * Swap things around between the three-way and real call so we
10317 * can hear where the channel got parked.
10318 */
10319 ast_mutex_lock(&p->lock);
10320 p->owner = p->subs[SUB_THREEWAY].owner;
10321 swap_subs(p, SUB_THREEWAY, SUB_REAL);
10322 ast_mutex_unlock(&p->lock);
10323
10324 ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10325 ast_hangup(chan);
10326 ao2_ref(bridge_channel, -1);
10327 goto quit;
10328 }
10329 ao2_ref(bridge_channel, -1);
10330 }
10331 break;
10332 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10333 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10334 /* Enable Caller*ID if enabled */
10335 p->hidecallerid = 0;
10336 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10337 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10338 if (res) {
10339 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10340 ast_channel_name(chan), strerror(errno));
10341 }
10342 len = 0;
10343 memset(exten, 0, sizeof(exten));
10344 timeout = p->firstdigit_timeout;
10345 } else if (!strcmp(exten, "*0")) {
10346 struct ast_channel *nbridge =
10347 p->subs[SUB_THREEWAY].owner;
10348 struct dahdi_pvt *pbridge = NULL;
10349 RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10350
10351 /* set up the private struct of the bridged one, if any */
10352 if (nbridge && bridged) {
10353 pbridge = ast_channel_tech_pvt(bridged);
10354 }
10355 if (nbridge && pbridge &&
10356 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10357 (ast_channel_tech(bridged) == &dahdi_tech) &&
10358 ISTRUNK(pbridge)) {
10359 int func = DAHDI_FLASH;
10360 /* Clear out the dial buffer */
10361 p->dop.dialstr[0] = '\0';
10362 /* flash hookswitch */
10363 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10364 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10365 ast_channel_name(nbridge), strerror(errno));
10366 }
10367 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10368 unalloc_sub(p, SUB_THREEWAY);
10369 p->owner = p->subs[SUB_REAL].owner;
10370 ast_queue_unhold(p->subs[SUB_REAL].owner);
10371 ast_hangup(chan);
10372 goto quit;
10373 } else {
10374 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10375 dahdi_wait_event(p->subs[idx].dfd);
10376 tone_zone_play_tone(p->subs[idx].dfd, -1);
10377 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10378 unalloc_sub(p, SUB_THREEWAY);
10379 p->owner = p->subs[SUB_REAL].owner;
10380 ast_hangup(chan);
10381 goto quit;
10382 }
10383 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10384 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10385 && !canmatch_featurecode(pickupexten, exten)) {
10386 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10387 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10388 ast_channel_context(chan));
10389 break;
10390 }
10391 if (!timeout)
10392 timeout = p->interdigit_timeout;
10393 if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10394 tone_zone_play_tone(p->subs[idx].dfd, -1);
10395 }
10396 break;
10397 case SIG_FXSLS:
10398 case SIG_FXSGS:
10399 case SIG_FXSKS:
10400 /* check for SMDI messages */
10401 if (p->use_smdi && p->smdi_iface) {
10402 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10403
10404 if (smdi_msg != NULL) {
10405 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10406
10407 if (smdi_msg->type == 'B')
10408 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10409 else if (smdi_msg->type == 'N')
10410 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10411
10412 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10413 } else {
10414 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10415 }
10416 }
10417
10418 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10419 number = smdi_msg->calling_st;
10420
10421 /* If we want caller id, we're in a prering state due to a polarity reversal
10422 * and we're set to use a polarity reversal to trigger the start of caller id,
10423 * grab the caller id and wait for ringing to start... */
10424 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10425 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10426 /* If set to use DTMF CID signalling, listen for DTMF */
10427 if (p->cid_signalling == CID_SIG_DTMF) {
10428 int k = 0;
10429 int off_ms;
10430 struct timeval start = ast_tvnow();
10431 int ms;
10432 cs = NULL;
10433 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10434 dahdi_setlinear(p->subs[idx].dfd, 0);
10435 /*
10436 * We are the only party interested in the Rx stream since
10437 * we have not answered yet. We don't need or even want DTMF
10438 * emulation. The DTMF digits can come so fast that emulation
10439 * can drop some of them.
10440 */
10441 ast_channel_lock(chan);
10442 ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10443 ast_channel_unlock(chan);
10444 off_ms = 4000;/* This is a typical OFF time between rings. */
10445 for (;;) {
10446 struct ast_frame *f;
10447
10448 ms = ast_remaining_ms(start, off_ms);
10449 res = ast_waitfor(chan, ms);
10450 if (res <= 0) {
10451 /*
10452 * We do not need to restore the dahdi_setlinear()
10453 * or AST_FLAG_END_DTMF_ONLY flag settings since we
10454 * are hanging up the channel.
10455 */
10456 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10457 "Exiting simple switch\n");
10458 ast_hangup(chan);
10459 goto quit;
10460 }
10461 f = ast_read(chan);
10462 if (!f)
10463 break;
10464 if (f->frametype == AST_FRAME_DTMF) {
10465 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10466 dtmfbuf[k++] = f->subclass.integer;
10467 }
10468 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10469 start = ast_tvnow();
10470 }
10471 ast_frfree(f);
10472 if (ast_channel_state(chan) == AST_STATE_RING ||
10473 ast_channel_state(chan) == AST_STATE_RINGING)
10474 break; /* Got ring */
10475 }
10476 ast_channel_lock(chan);
10477 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10478 ast_channel_unlock(chan);
10479 dtmfbuf[k] = '\0';
10480 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10481 /* Got cid and ring. */
10482 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10483 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10484 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10485 /* If first byte is NULL, we have no cid */
10486 if (!ast_strlen_zero(dtmfcid))
10487 number = dtmfcid;
10488 else
10489 number = NULL;
10490 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10491 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10492 cs = callerid_new(p->cid_signalling);
10493 if (cs) {
10494 int off_ms;
10495 struct timeval start;
10496 int ms;
10497 samples = 0;
10498 #if 1
10499 bump_gains(p);
10500 #endif
10501 /* Take out of linear mode for Caller*ID processing */
10502 dahdi_setlinear(p->subs[idx].dfd, 0);
10503
10504 /* First we wait and listen for the Caller*ID */
10505 for (;;) {
10506 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10507 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10508 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10509 callerid_free(cs);
10510 ast_hangup(chan);
10511 goto quit;
10512 }
10513 if (i & DAHDI_IOMUX_SIGEVENT) {
10514 res = dahdi_get_event(p->subs[idx].dfd);
10515 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10516 if (res == DAHDI_EVENT_NOALARM) {
10517 p->inalarm = 0;
10518 }
10519
10520 if (p->cid_signalling == CID_SIG_V23_JP) {
10521 if (res == DAHDI_EVENT_RINGBEGIN) {
10522 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10523 usleep(1);
10524 }
10525 } else {
10526 res = 0;
10527 break;
10528 }
10529 } else if (i & DAHDI_IOMUX_READ) {
10530 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10531 if (res < 0) {
10532 if (errno != ELAST) {
10533 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10534 callerid_free(cs);
10535 ast_hangup(chan);
10536 goto quit;
10537 }
10538 break;
10539 }
10540 samples += res;
10541
10542 if (p->cid_signalling == CID_SIG_V23_JP) {
10543 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10544 } else {
10545 res = callerid_feed(cs, buf, res, AST_LAW(p));
10546 }
10547 if (res < 0) {
10548 /*
10549 * The previous diagnostic message output likely
10550 * explains why it failed.
10551 */
10552 ast_log(LOG_WARNING,
10553 "Failed to decode CallerID on channel '%s'\n",
10554 ast_channel_name(chan));
10555 break;
10556 } else if (res)
10557 break;
10558 else if (samples > (8000 * 10))
10559 break;
10560 }
10561 }
10562 if (res == 1) {
10563 callerid_get(cs, &name, &number, &flags);
10564 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10565 }
10566
10567 if (p->cid_signalling == CID_SIG_V23_JP) {
10568 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10569 usleep(1);
10570 }
10571
10572 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10573 start = ast_tvnow();
10574 off_ms = 4000;/* This is a typical OFF time between rings. */
10575 for (;;) {
10576 struct ast_frame *f;
10577
10578 ms = ast_remaining_ms(start, off_ms);
10579 res = ast_waitfor(chan, ms);
10580 if (res <= 0) {
10581 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10582 "Exiting simple switch\n");
10583 ast_hangup(chan);
10584 goto quit;
10585 }
10586 if (!(f = ast_read(chan))) {
10587 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10588 ast_hangup(chan);
10589 goto quit;
10590 }
10591 ast_frfree(f);
10592 if (ast_channel_state(chan) == AST_STATE_RING ||
10593 ast_channel_state(chan) == AST_STATE_RINGING)
10594 break; /* Got ring */
10595 }
10596
10597 /* We must have a ring by now, so, if configured, lets try to listen for
10598 * distinctive ringing */
10599 if (p->usedistinctiveringdetection) {
10600 len = 0;
10601 distMatches = 0;
10602 /* Clear the current ring data array so we don't have old data in it. */
10603 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10604 curRingData[receivedRingT] = 0;
10605 receivedRingT = 0;
10606 counter = 0;
10607 counter1 = 0;
10608 /* Check to see if context is what it should be, if not set to be. */
10609 if (strcmp(p->context,p->defcontext) != 0) {
10610 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10611 ast_channel_context_set(chan, p->defcontext);
10612 }
10613
10614 for (;;) {
10615 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10616 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10617 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10618 callerid_free(cs);
10619 ast_hangup(chan);
10620 goto quit;
10621 }
10622 if (i & DAHDI_IOMUX_SIGEVENT) {
10623 res = dahdi_get_event(p->subs[idx].dfd);
10624 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10625 if (res == DAHDI_EVENT_NOALARM) {
10626 p->inalarm = 0;
10627 }
10628 res = 0;
10629 /* Let us detect distinctive ring */
10630
10631 curRingData[receivedRingT] = p->ringt;
10632
10633 if (p->ringt < p->ringt_base/2)
10634 break;
10635 /* Increment the ringT counter so we can match it against
10636 values in chan_dahdi.conf for distinctive ring */
10637 if (++receivedRingT == ARRAY_LEN(curRingData))
10638 break;
10639 } else if (i & DAHDI_IOMUX_READ) {
10640 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10641 if (res < 0) {
10642 if (errno != ELAST) {
10643 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10644 callerid_free(cs);
10645 ast_hangup(chan);
10646 goto quit;
10647 }
10648 break;
10649 }
10650 if (p->ringt > 0) {
10651 if (!(--p->ringt)) {
10652 res = -1;
10653 break;
10654 }
10655 }
10656 }
10657 }
10658 /* this only shows up if you have n of the dring patterns filled in */
10659 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10660 for (counter = 0; counter < 3; counter++) {
10661 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10662 channel */
10663 distMatches = 0;
10664 for (counter1 = 0; counter1 < 3; counter1++) {
10665 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10666 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10667 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10668 curRingData[counter1]);
10669 distMatches++;
10670 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10671 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10672 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10673 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10674 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10675 distMatches++;
10676 }
10677 }
10678
10679 if (distMatches == 3) {
10680 /* The ring matches, set the context to whatever is for distinctive ring.. */
10681 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10682 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
10683 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10684 break;
10685 }
10686 }
10687 }
10688 /* Restore linear mode (if appropriate) for Caller*ID processing */
10689 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10690 #if 1
10691 restore_gains(p);
10692 #endif
10693 } else
10694 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10695 } else {
10696 ast_log(LOG_WARNING, "Channel %s in prering "
10697 "state, but I have nothing to do. "
10698 "Terminating simple switch, should be "
10699 "restarted by the actual ring.\n",
10700 ast_channel_name(chan));
10701 ast_hangup(chan);
10702 goto quit;
10703 }
10704 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10705 if (p->cid_signalling == CID_SIG_DTMF) {
10706 int k = 0;
10707 int off_ms;
10708 struct timeval start;
10709 int ms;
10710 cs = NULL;
10711 dahdi_setlinear(p->subs[idx].dfd, 0);
10712 off_ms = 2000;
10713 start = ast_tvnow();
10714 for (;;) {
10715 struct ast_frame *f;
10716
10717 ms = ast_remaining_ms(start, off_ms);
10718 res = ast_waitfor(chan, ms);
10719 if (res <= 0) {
10720 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10721 "Exiting simple switch\n");
10722 ast_hangup(chan);
10723 goto quit;
10724 }
10725 f = ast_read(chan);
10726 if (!f) {
10727 /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10728 ast_hangup(chan);
10729 goto quit;
10730 }
10731 if (f->frametype == AST_FRAME_DTMF) {
10732 dtmfbuf[k++] = f->subclass.integer;
10733 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10734 start = ast_tvnow();
10735 }
10736 ast_frfree(f);
10737
10738 if (p->ringt_base == p->ringt)
10739 break;
10740 }
10741 dtmfbuf[k] = '\0';
10742 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10743 /* Got cid and ring. */
10744 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10745 ast_debug(1, "CID is '%s', flags %d\n",
10746 dtmfcid, flags);
10747 /* If first byte is NULL, we have no cid */
10748 if (!ast_strlen_zero(dtmfcid))
10749 number = dtmfcid;
10750 else
10751 number = NULL;
10752 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10753 } else {
10754 /* FSK Bell202 callerID */
10755 cs = callerid_new(p->cid_signalling);
10756 if (cs) {
10757 #if 1
10758 bump_gains(p);
10759 #endif
10760 samples = 0;
10761 len = 0;
10762 distMatches = 0;
10763 /* Clear the current ring data array so we don't have old data in it. */
10764 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10765 curRingData[receivedRingT] = 0;
10766 receivedRingT = 0;
10767 counter = 0;
10768 counter1 = 0;
10769 /* Check to see if context is what it should be, if not set to be. */
10770 if (strcmp(p->context,p->defcontext) != 0) {
10771 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10772 ast_channel_context_set(chan, p->defcontext);
10773 }
10774
10775 /* Take out of linear mode for Caller*ID processing */
10776 dahdi_setlinear(p->subs[idx].dfd, 0);
10777 for (;;) {
10778 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10779 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10780 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10781 callerid_free(cs);
10782 ast_hangup(chan);
10783 goto quit;
10784 }
10785 if (i & DAHDI_IOMUX_SIGEVENT) {
10786 res = dahdi_get_event(p->subs[idx].dfd);
10787 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10788 if (res == DAHDI_EVENT_NOALARM) {
10789 p->inalarm = 0;
10790 }
10791 /* If we get a PR event, they hung up while processing calerid */
10792 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10793 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10794 p->polarity = POLARITY_IDLE;
10795 callerid_free(cs);
10796 ast_hangup(chan);
10797 goto quit;
10798 }
10799 res = 0;
10800 /* Let us detect callerid when the telco uses distinctive ring */
10801
10802 curRingData[receivedRingT] = p->ringt;
10803
10804 if (p->ringt < p->ringt_base/2)
10805 break;
10806 /* Increment the ringT counter so we can match it against
10807 values in chan_dahdi.conf for distinctive ring */
10808 if (++receivedRingT == ARRAY_LEN(curRingData))
10809 break;
10810 } else if (i & DAHDI_IOMUX_READ) {
10811 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10812 if (res < 0) {
10813 if (errno != ELAST) {
10814 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10815 callerid_free(cs);
10816 ast_hangup(chan);
10817 goto quit;
10818 }
10819 break;
10820 }
10821 if (p->ringt > 0) {
10822 if (!(--p->ringt)) {
10823 res = -1;
10824 break;
10825 }
10826 }
10827 samples += res;
10828 res = callerid_feed(cs, buf, res, AST_LAW(p));
10829 if (res < 0) {
10830 /*
10831 * The previous diagnostic message output likely
10832 * explains why it failed.
10833 */
10834 ast_log(LOG_WARNING,
10835 "Failed to decode CallerID on channel '%s'\n",
10836 ast_channel_name(chan));
10837 break;
10838 } else if (res)
10839 break;
10840 else if (samples > (8000 * 10))
10841 break;
10842 }
10843 }
10844 if (res == 1) {
10845 callerid_get(cs, &name, &number, &flags);
10846 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10847 }
10848 if (distinctiveringaftercid == 1) {
10849 /* Clear the current ring data array so we don't have old data in it. */
10850 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10851 curRingData[receivedRingT] = 0;
10852 }
10853 receivedRingT = 0;
10854 ast_verb(3, "Detecting post-CID distinctive ring\n");
10855 for (;;) {
10856 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10857 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10858 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10859 callerid_free(cs);
10860 ast_hangup(chan);
10861 goto quit;
10862 }
10863 if (i & DAHDI_IOMUX_SIGEVENT) {
10864 res = dahdi_get_event(p->subs[idx].dfd);
10865 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10866 if (res == DAHDI_EVENT_NOALARM) {
10867 p->inalarm = 0;
10868 }
10869 res = 0;
10870 /* Let us detect callerid when the telco uses distinctive ring */
10871
10872 curRingData[receivedRingT] = p->ringt;
10873
10874 if (p->ringt < p->ringt_base/2)
10875 break;
10876 /* Increment the ringT counter so we can match it against
10877 values in chan_dahdi.conf for distinctive ring */
10878 if (++receivedRingT == ARRAY_LEN(curRingData))
10879 break;
10880 } else if (i & DAHDI_IOMUX_READ) {
10881 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10882 if (res < 0) {
10883 if (errno != ELAST) {
10884 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10885 callerid_free(cs);
10886 ast_hangup(chan);
10887 goto quit;
10888 }
10889 break;
10890 }
10891 if (p->ringt > 0) {
10892 if (!(--p->ringt)) {
10893 res = -1;
10894 break;
10895 }
10896 }
10897 }
10898 }
10899 }
10900 if (p->usedistinctiveringdetection) {
10901 /* this only shows up if you have n of the dring patterns filled in */
10902 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10903
10904 for (counter = 0; counter < 3; counter++) {
10905 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10906 channel */
10907 /* this only shows up if you have n of the dring patterns filled in */
10908 ast_verb(3, "Checking %d,%d,%d\n",
10909 p->drings.ringnum[counter].ring[0],
10910 p->drings.ringnum[counter].ring[1],
10911 p->drings.ringnum[counter].ring[2]);
10912 distMatches = 0;
10913 for (counter1 = 0; counter1 < 3; counter1++) {
10914 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10915 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10916 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10917 curRingData[counter1]);
10918 distMatches++;
10919 }
10920 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10921 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10922 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10923 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10924 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10925 distMatches++;
10926 }
10927 }
10928 if (distMatches == 3) {
10929 /* The ring matches, set the context to whatever is for distinctive ring.. */
10930 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10931 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
10932 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10933 break;
10934 }
10935 }
10936 }
10937 /* Restore linear mode (if appropriate) for Caller*ID processing */
10938 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10939 #if 1
10940 restore_gains(p);
10941 #endif
10942 if (res < 0) {
10943 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
10944 }
10945 } else
10946 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10947 }
10948 } else
10949 cs = NULL;
10950
10951 if (number)
10952 ast_shrink_phone_number(number);
10953 ast_set_callerid(chan, number, name, number);
10954
10955 ao2_cleanup(smdi_msg);
10956
10957 if (cs)
10958 callerid_free(cs);
10959
10960 my_handle_notify_message(chan, p, flags, -1);
10961
10962 ast_channel_lock(chan);
10963 ast_setstate(chan, AST_STATE_RING);
10964 ast_channel_rings_set(chan, 1);
10965 ast_channel_unlock(chan);
10966 p->ringt = p->ringt_base;
10967 res = ast_pbx_run(chan);
10968 if (res) {
10969 ast_hangup(chan);
10970 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10971 }
10972 goto quit;
10973 default:
10974 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10975 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10976 if (res < 0)
10977 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10978 }
10979 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10980 if (res < 0)
10981 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10982 ast_hangup(chan);
10983 quit:
10984 ast_mutex_lock(&ss_thread_lock);
10985 ss_thread_count--;
10986 ast_cond_signal(&ss_thread_complete);
10987 ast_mutex_unlock(&ss_thread_lock);
10988 return NULL;
10989 }
10990
10991 struct mwi_thread_data {
10992 struct dahdi_pvt *pvt;
10993 unsigned char buf[READ_SIZE];
10994 size_t len;
10995 };
10996
10997 static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
10998 {
10999 int x;
11000 int sum = 0;
11001
11002 if (!len)
11003 return 0;
11004
11005 for (x = 0; x < len; x++)
11006 sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11007
11008 return sum / len;
11009 }
11010
11011 static void *mwi_thread(void *data)
11012 {
11013 struct mwi_thread_data *mtd = data;
11014 struct callerid_state *cs;
11015 pthread_t threadid;
11016 int samples = 0;
11017 char *name, *number;
11018 int flags;
11019 int i, res;
11020 unsigned int spill_done = 0;
11021 int spill_result = -1;
11022
11023 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11024 goto quit_no_clean;
11025 }
11026
11027 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11028
11029 bump_gains(mtd->pvt);
11030
11031 for (;;) {
11032 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11033 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11034 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11035 goto quit;
11036 }
11037
11038 if (i & DAHDI_IOMUX_SIGEVENT) {
11039 struct ast_channel *chan;
11040 ast_callid callid = 0;
11041 int callid_created;
11042
11043 /* If we get an event, screen out events that we do not act on.
11044 * Otherwise, cancel and go to the simple switch to let it deal with it.
11045 */
11046 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11047
11048 switch (res) {
11049 case DAHDI_EVENT_NEONMWI_ACTIVE:
11050 case DAHDI_EVENT_NEONMWI_INACTIVE:
11051 case DAHDI_EVENT_NONE:
11052 case DAHDI_EVENT_BITSCHANGED:
11053 break;
11054 case DAHDI_EVENT_NOALARM:
11055 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11056 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11057
11058 analog_p->inalarm = 0;
11059 }
11060 mtd->pvt->inalarm = 0;
11061 handle_clear_alarms(mtd->pvt);
11062 break;
11063 case DAHDI_EVENT_ALARM:
11064 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11065 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11066
11067 analog_p->inalarm = 1;
11068 }
11069 mtd->pvt->inalarm = 1;
11070 res = get_alarms(mtd->pvt);
11071 handle_alarms(mtd->pvt, res);
11072 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11073 default:
11074 callid_created = ast_callid_threadstorage_auto(&callid);
11075 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11076 callerid_free(cs);
11077
11078 restore_gains(mtd->pvt);
11079 mtd->pvt->ringt = mtd->pvt->ringt_base;
11080
11081 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
11082 int result;
11083
11084 if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11085 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11086 } else {
11087 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11088 }
11089 if (result) {
11090 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11091 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11092 if (res < 0)
11093 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11094 ast_hangup(chan);
11095 }
11096 } else {
11097 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11098 }
11099
11100 ast_callid_threadstorage_auto_clean(callid, callid_created);
11101 goto quit_no_clean;
11102 }
11103 } else if (i & DAHDI_IOMUX_READ) {
11104 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11105 if (errno != ELAST) {
11106 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11107 goto quit;
11108 }
11109 break;
11110 }
11111 samples += res;
11112 if (!spill_done) {
11113 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11114 /*
11115 * The previous diagnostic message output likely
11116 * explains why it failed.
11117 */
11118 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11119 break;
11120 } else if (spill_result) {
11121 spill_done = 1;
11122 }
11123 } else {
11124 /* keep reading data until the energy level drops below the threshold
11125 so we don't get another 'trigger' on the remaining carrier signal
11126 */
11127 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11128 break;
11129 }
11130 if (samples > (8000 * 4)) /*Termination case - time to give up*/
11131 break;
11132 }
11133 }
11134
11135 if (spill_result == 1) {
11136 callerid_get(cs, &name, &number, &flags);
11137 if (flags & CID_MSGWAITING) {
11138 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11139 notify_message(mtd->pvt->mailbox, 1);
11140 } else if (flags & CID_NOMSGWAITING) {
11141 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11142 notify_message(mtd->pvt->mailbox, 0);
11143 } else {
11144 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11145 }
11146 }
11147
11148
11149 quit:
11150 callerid_free(cs);
11151
11152 restore_gains(mtd->pvt);
11153
11154 quit_no_clean:
11155 mtd->pvt->mwimonitoractive = 0;
11156 ast_free(mtd);
11157
11158 return NULL;
11159 }
11160
11161 /*
11162 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11163 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11164 * that are sent out via FXS port on voicemail state change. The execution of
11165 * the mwi send is state driven and can either generate a ring pulse prior to
11166 * sending the fsk spill or simply send an fsk spill.
11167 */
11168 static int mwi_send_init(struct dahdi_pvt * pvt)
11169 {
11170 int x;
11171
11172 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11173 /* Determine how this spill is to be sent */
11174 if (pvt->mwisend_rpas) {
11175 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11176 pvt->mwisendactive = 1;
11177 } else if (pvt->mwisend_fsk) {
11178 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11179 pvt->mwisendactive = 1;
11180 } else {
11181 pvt->mwisendactive = 0;
11182 return 0;
11183 }
11184 #else
11185 if (mwisend_rpas) {
11186 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11187 } else {
11188 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11189 }
11190 pvt->mwisendactive = 1;
11191 #endif
11192
11193 if (pvt->cidspill) {
11194 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11195 ast_free(pvt->cidspill);
11196 pvt->cidspill = NULL;
11197 pvt->cidpos = 0;
11198 pvt->cidlen = 0;
11199 }
11200 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11201 if (!pvt->cidspill) {
11202 pvt->mwisendactive = 0;
11203 return -1;
11204 }
11205 x = DAHDI_FLUSH_BOTH;
11206 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11207 x = 3000;
11208 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11209 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11210 if (pvt->mwisend_fsk) {
11211 #endif
11212 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt),
11213 CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11214 pvt->cidpos = 0;
11215 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11216 }
11217 #endif
11218 return 0;
11219 }
11220
11221 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11222 {
11223 struct timeval now;
11224 int res;
11225
11226 /* sanity check to catch if this had been interrupted previously
11227 * i.e. state says there is more to do but there is no spill allocated
11228 */
11229 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11230 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11231 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11232 /* Normal processing -- Perform mwi send action */
11233 switch ( pvt->mwisend_data.mwisend_current) {
11234 case MWI_SEND_SA:
11235 /* Send the Ring Pulse Signal Alert */
11236 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11237 if (res) {
11238 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11239 goto quit;
11240 }
11241 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11242 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11243 break;
11244 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
11245 break;
11246 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
11247 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11248 if (pvt->mwisend_fsk) {
11249 #endif
11250 gettimeofday(&now, NULL);
11251 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11252 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11253 }
11254 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11255 } else { /* support for mwisendtype=nofsk */
11256 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11257 }
11258 #endif
11259 break;
11260 case MWI_SEND_SPILL:
11261 /* We read some number of bytes. Write an equal amount of data */
11262 if (0 < num_read) {
11263 if (num_read > pvt->cidlen - pvt->cidpos) {
11264 num_read = pvt->cidlen - pvt->cidpos;
11265 }
11266 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11267 if (res > 0) {
11268 pvt->cidpos += res;
11269 if (pvt->cidpos >= pvt->cidlen) {
11270 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11271 }
11272 } else {
11273 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11274 goto quit;
11275 }
11276 }
11277 break;
11278 case MWI_SEND_CLEANUP:
11279 /* For now, do nothing */
11280 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11281 break;
11282 default:
11283 /* Should not get here, punt*/
11284 goto quit;
11285 }
11286 }
11287
11288 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11289 if (pvt->cidspill) {
11290 ast_free(pvt->cidspill);
11291 pvt->cidspill = NULL;
11292 pvt->cidpos = 0;
11293 pvt->cidlen = 0;
11294 }
11295 pvt->mwisendactive = 0;
11296 }
11297 return 0;
11298 quit:
11299 if (pvt->cidspill) {
11300 ast_free(pvt->cidspill);
11301 pvt->cidspill = NULL;
11302 pvt->cidpos = 0;
11303 pvt->cidlen = 0;
11304 }
11305 pvt->mwisendactive = 0;
11306 return -1;
11307 }
11308
11309 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11310 {
11311 int handled = 0;
11312
11313 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11314 switch (event) {
11315 case DAHDI_EVENT_RINGEROFF:
11316 if (pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11317 handled = 1;
11318
11319 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11320 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11321 ast_free(pvt->cidspill);
11322 pvt->cidspill = NULL;
11323 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11324 pvt->mwisendactive = 0;
11325 } else {
11326 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11327 gettimeofday(&pvt->mwisend_data.pause, NULL);
11328 }
11329 }
11330 break;
11331 /* Going off hook, I need to punt this spill */
11332 case DAHDI_EVENT_RINGOFFHOOK:
11333 if (pvt->cidspill) {
11334 ast_free(pvt->cidspill);
11335 pvt->cidspill = NULL;
11336 pvt->cidpos = 0;
11337 pvt->cidlen = 0;
11338 }
11339 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11340 pvt->mwisendactive = 0;
11341 break;
11342 case DAHDI_EVENT_RINGERON:
11343 case DAHDI_EVENT_HOOKCOMPLETE:
11344 break;
11345 default:
11346 break;
11347 }
11348 }
11349 return handled;
11350 }
11351
11352 /* destroy a range DAHDI channels, identified by their number */
11353 static void dahdi_destroy_channel_range(int start, int end)
11354 {
11355 struct dahdi_pvt *cur;
11356 struct dahdi_pvt *next;
11357 int destroyed_first = 0;
11358 int destroyed_last = 0;
11359
11360 ast_mutex_lock(&iflock);
11361 ast_debug(1, "range: %d-%d\n", start, end);
11362 for (cur = iflist; cur; cur = next) {
11363 next = cur->next;
11364 if (cur->channel >= start && cur->channel <= end) {
11365 int x = DAHDI_FLASH;
11366
11367 if (cur->channel > destroyed_last) {
11368 destroyed_last = cur->channel;
11369 }
11370 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11371 destroyed_first = cur->channel;
11372 }
11373 ast_debug(3, "Destroying %d\n", cur->channel);
11374 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11375 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11376
11377 destroy_channel(cur, 1);
11378 ast_module_unref(ast_module_info->self);
11379 }
11380 }
11381 ast_mutex_unlock(&iflock);
11382 if (destroyed_first > start || destroyed_last < end) {
11383 ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11384 start, end, destroyed_first, destroyed_last);
11385 }
11386 }
11387
11388 #ifdef HAVE_OPENR2
11389 static void dahdi_r2_destroy_nodev(void)
11390 {
11391 struct r2link_entry *cur;
11392 AST_LIST_LOCK(&nodev_r2links);
11393 AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {
11394 int i;
11395 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11396 ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11397 for (i = 0; i < r2->numchans; i++) {
11398 int channel;
11399 struct dahdi_pvt *pvt = r2->pvts[i];
11400 if (!pvt) {
11401 continue;
11402 }
11403 channel = pvt->channel;
11404 ast_debug(3, "About to destroy B-channel %d.\n", channel);
11405 dahdi_destroy_channel_range(channel, channel);
11406 }
11407 ast_debug(3, "Destroying R2 link\n");
11408 AST_LIST_REMOVE(&nodev_r2links, cur, list);
11409 if (r2->r2master != AST_PTHREADT_NULL) {
11410 pthread_cancel(r2->r2master);
11411 pthread_join(r2->r2master, NULL);
11412 r2->r2master = AST_PTHREADT_NULL;
11413 openr2_context_delete(r2->protocol_context);
11414 }
11415 ast_free(cur);
11416 }
11417 AST_LIST_TRAVERSE_SAFE_END;
11418 AST_LIST_UNLOCK(&nodev_r2links);
11419 }
11420 #endif
11421
11422 static int setup_dahdi(int reload);
11423 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
11424
11425 /*!
11426 * \internal
11427 * \brief create a range of new DAHDI channels
11428 *
11429 * \param start first channel in the range
11430 * \param end last channel in the range
11431 *
11432 * \retval RESULT_SUCCESS on success.
11433 * \retval RESULT_FAILURE on error.
11434 */
11435 static int dahdi_create_channel_range(int start, int end)
11436 {
11437 struct dahdi_pvt *cur;
11438 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11439 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11440 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11441 int ret = RESULT_FAILURE; /* be pessimistic */
11442
11443 ast_debug(1, "channel range caps: %d - %d\n", start, end);
11444 ast_mutex_lock(&iflock);
11445 for (cur = iflist; cur; cur = cur->next) {
11446 if (cur->channel >= start && cur->channel <= end) {
11447 ast_log(LOG_ERROR,
11448 "channel range %d-%d is occupied\n",
11449 start, end);
11450 goto out;
11451 }
11452 }
11453 #ifdef HAVE_PRI
11454 {
11455 int i, x;
11456 for (x = 0; x < NUM_SPANS; x++) {
11457 struct dahdi_pri *pri = pris + x;
11458
11459 if (!pris[x].pri.pvts[0]) {
11460 break;
11461 }
11462 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11463 int channo = pri->dchannels[i];
11464
11465 if (!channo) {
11466 break;
11467 }
11468 if (!pri->pri.fds[i]) {
11469 break;
11470 }
11471 if (channo >= start && channo <= end) {
11472 ast_log(LOG_ERROR,
11473 "channel range %d-%d is occupied by span %d\n",
11474 start, end, x + 1);
11475 goto out;
11476 }
11477 }
11478 }
11479 }
11480 #endif
11481 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11482 !conf.chan.cc_params) {
11483 goto out;
11484 }
11485 default_conf.wanted_channels_start = start;
11486 base_conf.wanted_channels_start = start;
11487 conf.wanted_channels_start = start;
11488 default_conf.wanted_channels_end = end;
11489 base_conf.wanted_channels_end = end;
11490 conf.wanted_channels_end = end;
11491 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11492 ret = RESULT_SUCCESS;
11493 }
11494 out:
11495 ast_cc_config_params_destroy(default_conf.chan.cc_params);
11496 ast_cc_config_params_destroy(base_conf.chan.cc_params);
11497 ast_cc_config_params_destroy(conf.chan.cc_params);
11498 ast_mutex_unlock(&iflock);
11499 return ret;
11500 }
11501
11502
11503 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11504 {
11505 int res;
11506 pthread_t threadid;
11507 struct ast_channel *chan;
11508 ast_callid callid = 0;
11509 int callid_created;
11510
11511 /* Handle an event on a given channel for the monitor thread. */
11512
11513 switch (event) {
11514 case DAHDI_EVENT_NONE:
11515 case DAHDI_EVENT_BITSCHANGED:
11516 break;
11517 case DAHDI_EVENT_WINKFLASH:
11518 case DAHDI_EVENT_RINGOFFHOOK:
11519 if (i->inalarm) break;
11520 if (i->radio) break;
11521 /* Got a ring/answer. What kind of channel are we? */
11522 switch (i->sig) {
11523 case SIG_FXOLS:
11524 case SIG_FXOGS:
11525 case SIG_FXOKS:
11526 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11527 if (res && (errno == EBUSY)) {
11528 break;
11529 }
11530
11531 callid_created = ast_callid_threadstorage_auto(&callid);
11532
11533 /* Cancel VMWI spill */
11534 ast_free(i->cidspill);
11535 i->cidspill = NULL;
11536 restore_conference(i);
11537
11538 if (i->immediate) {
11539 dahdi_ec_enable(i);
11540 /* The channel is immediately up. Start right away */
11541 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11542 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11543 if (!chan) {
11544 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11545 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11546 if (res < 0)
11547 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11548 }
11549 } else {
11550 /* Check for callerid, digits, etc */
11551 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11552 if (chan) {
11553 if (has_voicemail(i))
11554 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11555 else
11556 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11557 if (res < 0)
11558 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11559 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11560 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11562 if (res < 0)
11563 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11564 ast_hangup(chan);
11565 }
11566 } else
11567 ast_log(LOG_WARNING, "Unable to create channel\n");
11568 }
11569
11570 ast_callid_threadstorage_auto_clean(callid, callid_created);
11571 break;
11572 case SIG_FXSLS:
11573 case SIG_FXSGS:
11574 case SIG_FXSKS:
11575 i->ringt = i->ringt_base;
11576 /* Fall through */
11577 case SIG_EMWINK:
11578 case SIG_FEATD:
11579 case SIG_FEATDMF:
11580 case SIG_FEATDMF_TA:
11581 case SIG_E911:
11582 case SIG_FGC_CAMA:
11583 case SIG_FGC_CAMAMF:
11584 case SIG_FEATB:
11585 case SIG_EM:
11586 case SIG_EM_E1:
11587 case SIG_SFWINK:
11588 case SIG_SF_FEATD:
11589 case SIG_SF_FEATDMF:
11590 case SIG_SF_FEATB:
11591 case SIG_SF:
11592 /* Check for callerid, digits, etc */
11593 callid_created = ast_callid_threadstorage_auto(&callid);
11594 if (i->cid_start == CID_START_POLARITY_IN) {
11595 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11596 } else {
11597 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11598 }
11599
11600 if (!chan) {
11601 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11602 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11603 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11604 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11605 if (res < 0) {
11606 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11607 }
11608 ast_hangup(chan);
11609 }
11610
11611 ast_callid_threadstorage_auto_clean(callid, callid_created);
11612 break;
11613 default:
11614 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11615 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11616 if (res < 0)
11617 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11618 return NULL;
11619 }
11620 break;
11621 case DAHDI_EVENT_NOALARM:
11622 switch (i->sig) {
11623 #if defined(HAVE_PRI)
11624 case SIG_PRI_LIB_HANDLE_CASES:
11625 ast_mutex_lock(&i->lock);
11626 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11627 ast_mutex_unlock(&i->lock);
11628 break;
11629 #endif /* defined(HAVE_PRI) */
11630 #if defined(HAVE_SS7)
11631 case SIG_SS7:
11632 sig_ss7_set_alarm(i->sig_pvt, 0);
11633 break;
11634 #endif /* defined(HAVE_SS7) */
11635 default:
11636 i->inalarm = 0;
11637 break;
11638 }
11639 handle_clear_alarms(i);
11640 break;
11641 case DAHDI_EVENT_ALARM:
11642 switch (i->sig) {
11643 #if defined(HAVE_PRI)
11644 case SIG_PRI_LIB_HANDLE_CASES:
11645 ast_mutex_lock(&i->lock);
11646 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11647 ast_mutex_unlock(&i->lock);
11648 break;
11649 #endif /* defined(HAVE_PRI) */
11650 #if defined(HAVE_SS7)
11651 case SIG_SS7:
11652 sig_ss7_set_alarm(i->sig_pvt, 1);
11653 break;
11654 #endif /* defined(HAVE_SS7) */
11655 default:
11656 i->inalarm = 1;
11657 break;
11658 }
11659 res = get_alarms(i);
11660 handle_alarms(i, res);
11661 /* fall thru intentionally */
11662 case DAHDI_EVENT_ONHOOK:
11663 if (i->radio)
11664 break;
11665 /* Back on hook. Hang up. */
11666 switch (i->sig) {
11667 case SIG_FXOLS:
11668 case SIG_FXOGS:
11669 case SIG_FEATD:
11670 case SIG_FEATDMF:
11671 case SIG_FEATDMF_TA:
11672 case SIG_E911:
11673 case SIG_FGC_CAMA:
11674 case SIG_FGC_CAMAMF:
11675 case SIG_FEATB:
11676 case SIG_EM:
11677 case SIG_EM_E1:
11678 case SIG_EMWINK:
11679 case SIG_SF_FEATD:
11680 case SIG_SF_FEATDMF:
11681 case SIG_SF_FEATB:
11682 case SIG_SF:
11683 case SIG_SFWINK:
11684 case SIG_FXSLS:
11685 case SIG_FXSGS:
11686 case SIG_FXSKS:
11687 case SIG_FXOKS:
11688 dahdi_ec_disable(i);
11689 /* Diddle the battery for the zhone */
11690 #ifdef ZHONE_HACK
11691 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11692 usleep(1);
11693 #endif
11694 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11695 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11696 break;
11697 case SIG_SS7:
11698 case SIG_PRI_LIB_HANDLE_CASES:
11699 dahdi_ec_disable(i);
11700 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11701 break;
11702 default:
11703 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11704 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11705 return NULL;
11706 }
11707 break;
11708 case DAHDI_EVENT_POLARITY:
11709 switch (i->sig) {
11710 case SIG_FXSLS:
11711 case SIG_FXSKS:
11712 case SIG_FXSGS:
11713 /* We have already got a PR before the channel was
11714 created, but it wasn't handled. We need polarity
11715 to be REV for remote hangup detection to work.
11716 At least in Spain */
11717 callid_created = ast_callid_threadstorage_auto(&callid);
11718 if (i->hanguponpolarityswitch)
11719 i->polarity = POLARITY_REV;
11720 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11721 i->polarity = POLARITY_REV;
11722 ast_verb(2, "Starting post polarity "
11723 "CID detection on channel %d\n",
11724 i->channel);
11725 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11726 if (!chan) {
11727 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11728 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11729 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11730 ast_hangup(chan);
11731 }
11732 }
11733 ast_callid_threadstorage_auto_clean(callid, callid_created);
11734 break;
11735 default:
11736 ast_log(LOG_WARNING, "handle_init_event detected "
11737 "polarity reversal on non-FXO (SIG_FXS) "
11738 "interface %d\n", i->channel);
11739 }
11740 break;
11741 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11742 ast_log(LOG_NOTICE,
11743 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11744 i->channel);
11745 return i;
11746 case DAHDI_EVENT_NEONMWI_ACTIVE:
11747 if (i->mwimonitor_neon) {
11748 notify_message(i->mailbox, 1);
11749 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11750 }
11751 break;
11752 case DAHDI_EVENT_NEONMWI_INACTIVE:
11753 if (i->mwimonitor_neon) {
11754 notify_message(i->mailbox, 0);
11755 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11756 }
11757 break;
11758 }
11759 return NULL;
11760 }
11761
11762 static void monitor_pfds_clean(void *arg) {
11763 struct pollfd **pfds = arg;
11764 ast_free(*pfds);
11765 }
11766
11767 static void *do_monitor(void *data)
11768 {
11769 int count, res, res2, spoint, pollres=0;
11770 struct dahdi_pvt *i;
11771 struct dahdi_pvt *last = NULL;
11772 struct dahdi_pvt *doomed;
11773 time_t thispass = 0, lastpass = 0;
11774 int found;
11775 char buf[1024];
11776 struct pollfd *pfds=NULL;
11777 int lastalloc = -1;
11778 /* This thread monitors all the frame relay interfaces which are not yet in use
11779 (and thus do not have a separate thread) indefinitely */
11780 /* From here on out, we die whenever asked */
11781 #if 0
11782 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11783 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11784 return NULL;
11785 }
11786 ast_debug(1, "Monitor starting...\n");
11787 #endif
11788 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11789
11790 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11791 for (;;) {
11792 /* Lock the interface list */
11793 ast_mutex_lock(&iflock);
11794 if (!pfds || (lastalloc != ifcount)) {
11795 if (pfds) {
11796 ast_free(pfds);
11797 pfds = NULL;
11798 }
11799 if (ifcount) {
11800 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11801 ast_mutex_unlock(&iflock);
11802 return NULL;
11803 }
11804 }
11805 lastalloc = ifcount;
11806 }
11807 /* Build the stuff we're going to poll on, that is the socket of every
11808 dahdi_pvt that does not have an associated owner channel */
11809 count = 0;
11810 for (i = iflist; i; i = i->next) {
11811 ast_mutex_lock(&i->lock);
11812 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11813 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11814 struct analog_pvt *p = i->sig_pvt;
11815
11816 if (!p) {
11817 ast_log(LOG_ERROR, "No sig_pvt?\n");
11818 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11819 /* This needs to be watched, as it lacks an owner */
11820 pfds[count].fd = i->subs[SUB_REAL].dfd;
11821 pfds[count].events = POLLPRI;
11822 pfds[count].revents = 0;
11823 /* Message waiting or r2 channels also get watched for reading */
11824 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11825 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11826 pfds[count].events |= POLLIN;
11827 }
11828 count++;
11829 }
11830 } else {
11831 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11832 /* This needs to be watched, as it lacks an owner */
11833 pfds[count].fd = i->subs[SUB_REAL].dfd;
11834 pfds[count].events = POLLPRI;
11835 pfds[count].revents = 0;
11836 /* If we are monitoring for VMWI or sending CID, we need to
11837 read from the channel as well */
11838 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11839 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11840 pfds[count].events |= POLLIN;
11841 }
11842 count++;
11843 }
11844 }
11845 }
11846 ast_mutex_unlock(&i->lock);
11847 }
11848 /* Okay, now that we know what to do, release the interface lock */
11849 ast_mutex_unlock(&iflock);
11850
11851 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11852 pthread_testcancel();
11853 /* Wait at least a second for something to happen */
11854 res = poll(pfds, count, 1000);
11855 pthread_testcancel();
11856 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11857
11858 /* Okay, poll has finished. Let's see what happened. */
11859 if (res < 0) {
11860 if ((errno != EAGAIN) && (errno != EINTR))
11861 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11862 continue;
11863 }
11864 /* Alright, lock the interface list again, and let's look and see what has
11865 happened */
11866 ast_mutex_lock(&iflock);
11867 found = 0;
11868 spoint = 0;
11869 lastpass = thispass;
11870 thispass = time(NULL);
11871 doomed = NULL;
11872 for (i = iflist;; i = i->next) {
11873 if (doomed) {
11874 dahdi_destroy_channel_range(doomed->channel, doomed->channel);
11875 doomed = NULL;
11876 }
11877 if (!i) {
11878 break;
11879 }
11880
11881 if (thispass != lastpass) {
11882 if (!found && ((i == last) || ((i == iflist) && !last))) {
11883 last = i;
11884 if (last) {
11885 struct analog_pvt *analog_p = last->sig_pvt;
11886 /* Only allow MWI to be initiated on a quiescent fxs port */
11887 if (analog_p
11888 && !last->mwisendactive
11889 && (last->sig & __DAHDI_SIG_FXO)
11890 && !analog_p->fxsoffhookstate
11891 && !last->owner
11892 && !ast_strlen_zero(last->mailbox)
11893 && !analog_p->subs[SUB_REAL].owner /* could be a recall ring from a flash hook hold */
11894 && (thispass - analog_p->onhooktime > 3)) {
11895 res = has_voicemail(last);
11896 if (analog_p->msgstate != res) {
11897 /* Set driver resources for signalling VMWI */
11898 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11899 if (res2) {
11900 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11901 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11902 }
11903 /* If enabled for FSK spill then initiate it */
11904 if (mwi_send_init(last)) {
11905 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11906 }
11907 analog_p->msgstate = res;
11908 found ++;
11909 }
11910 }
11911 last = last->next;
11912 }
11913 }
11914 }
11915 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11916 if (i->radio && !i->owner)
11917 {
11918 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11919 if (res)
11920 {
11921 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11922 /* Don't hold iflock while handling init events */
11923 ast_mutex_unlock(&iflock);
11924 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
11925 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11926 else
11927 doomed = handle_init_event(i, res);
11928 ast_mutex_lock(&iflock);
11929 }
11930 continue;
11931 }
11932 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11933 if (pollres & POLLIN) {
11934 if (i->owner || i->subs[SUB_REAL].owner) {
11935 #ifdef HAVE_PRI
11936 if (!i->pri)
11937 #endif
11938 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11939 continue;
11940 }
11941 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11942 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11943 continue;
11944 }
11945 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11946 if (res > 0) {
11947 if (i->mwimonitor_fsk) {
11948 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11949 pthread_attr_t attr;
11950 pthread_t threadid;
11951 struct mwi_thread_data *mtd;
11952
11953 pthread_attr_init(&attr);
11954 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11955
11956 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
11957 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11958 mtd->pvt = i;
11959 memcpy(mtd->buf, buf, res);
11960 mtd->len = res;
11961 i->mwimonitoractive = 1;
11962 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11963 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11964 i->mwimonitoractive = 0;
11965 ast_free(mtd);
11966 }
11967 }
11968 }
11969 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11970 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11971 int energy;
11972 struct timeval now;
11973 /* State machine dtmfcid_holdoff_state allows for the line to settle
11974 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
11975 */
11976 if (1 == i->dtmfcid_holdoff_state) {
11977 gettimeofday(&i->dtmfcid_delay, NULL);
11978 i->dtmfcid_holdoff_state = 2;
11979 } else if (2 == i->dtmfcid_holdoff_state) {
11980 gettimeofday(&now, NULL);
11981 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11982 i->dtmfcid_holdoff_state = 0;
11983 }
11984 } else {
11985 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11986 if (!i->mwisendactive && energy > dtmfcid_level) {
11987 pthread_t threadid;
11988 struct ast_channel *chan;
11989 ast_mutex_unlock(&iflock);
11990 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11991 /* just in case this event changes or somehow destroys a channel, set doomed here too */
11992 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11993 i->dtmfcid_holdoff_state = 1;
11994 } else {
11995 ast_callid callid = 0;
11996 int callid_created = ast_callid_threadstorage_auto(&callid);
11997 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11998 if (!chan) {
11999 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12000 } else {
12001 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12002 if (res) {
12003 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12004 ast_hangup(chan);
12005 } else {
12006 i->dtmfcid_holdoff_state = 1;
12007 }
12008 }
12009 ast_callid_threadstorage_auto_clean(callid, callid_created);
12010 }
12011 ast_mutex_lock(&iflock);
12012 }
12013 }
12014 }
12015 if (i->mwisendactive) {
12016 mwi_send_process_buffer(i, res);
12017 }
12018 } else {
12019 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12020 }
12021 }
12022 if (pollres & POLLPRI) {
12023 if (i->owner || i->subs[SUB_REAL].owner) {
12024 #ifdef HAVE_PRI
12025 if (!i->pri)
12026 #endif
12027 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12028 continue;
12029 }
12030 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12031 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12032 /* Don't hold iflock while handling init events */
12033 ast_mutex_unlock(&iflock);
12034 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12035 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
12036 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12037 else
12038 doomed = handle_init_event(i, res);
12039 }
12040 if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) {
12041 /* Actually automatically reoriginate this FXS line, if directed to.
12042 * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect
12043 * doing its thing (one reason why this is for FXOKS only: FXOLS
12044 * hangups don't give us any DAHDI events to piggyback off of)*/
12045 i->doreoriginate = 0;
12046 /* Double check the channel is still off-hook. There's only about a millisecond
12047 * between when doreoriginate is set high and we see that here, but just to be safe. */
12048 if (!my_is_off_hook(i)) {
12049 ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel);
12050 } else {
12051 ast_verb(3, "Automatic reorigination on channel %d\n", i->channel);
12052 res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */
12053 if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12054 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12055 } else {
12056 doomed = handle_init_event(i, res);
12057 }
12058 }
12059 }
12060 ast_mutex_lock(&iflock);
12061 }
12062 }
12063 }
12064 ast_mutex_unlock(&iflock);
12065 release_doomed_pris();
12066 #ifdef HAVE_OPENR2
12067 dahdi_r2_destroy_nodev();
12068 #endif
12069 }
12070 /* Never reached */
12071 pthread_cleanup_pop(1);
12072 return NULL;
12073
12074 }
12075
12076 static int restart_monitor(void)
12077 {
12078 /* If we're supposed to be stopped -- stay stopped */
12079 if (monitor_thread == AST_PTHREADT_STOP)
12080 return 0;
12081 ast_mutex_lock(&monlock);
12082 if (monitor_thread == pthread_self()) {
12083 ast_mutex_unlock(&monlock);
12084 ast_log(LOG_WARNING, "Cannot kill myself\n");
12085 return -1;
12086 }
12087 if (monitor_thread != AST_PTHREADT_NULL) {
12088 /* Wake up the thread */
12089 pthread_kill(monitor_thread, SIGURG);
12090 } else {
12091 /* Start a new monitor */
12092 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12093 ast_mutex_unlock(&monlock);
12094 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12095 return -1;
12096 }
12097 }
12098 ast_mutex_unlock(&monlock);
12099 return 0;
12100 }
12101
12102 #if defined(HAVE_PRI)
12103 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12104 {
12105 int x;
12106 int trunkgroup;
12107 /* Get appropriate trunk group if there is one */
12108 trunkgroup = pris[*span].mastertrunkgroup;
12109 if (trunkgroup) {
12110 /* Select a specific trunk group */
12111 for (x = 0; x < NUM_SPANS; x++) {
12112 if (pris[x].pri.trunkgroup == trunkgroup) {
12113 *span = x;
12114 return 0;
12115 }
12116 }
12117 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12118 *span = -1;
12119 } else {
12120 if (pris[*span].pri.trunkgroup) {
12121 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);
12122 *span = -1;
12123 } else if (pris[*span].mastertrunkgroup) {
12124 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12125 *span = -1;
12126 } else {
12127 if (si->totalchans == 31) {
12128 /* E1 */
12129 pris[*span].dchannels[0] = 16 + offset;
12130 } else if (si->totalchans == 24) {
12131 /* T1 or J1 */
12132 pris[*span].dchannels[0] = 24 + offset;
12133 } else if (si->totalchans == 3) {
12134 /* BRI */
12135 pris[*span].dchannels[0] = 3 + offset;
12136 } else {
12137 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);
12138 *span = -1;
12139 return 0;
12140 }
12141 pris[*span].pri.span = *span + 1;
12142 }
12143 }
12144 return 0;
12145 }
12146 #endif /* defined(HAVE_PRI) */
12147
12148 #if defined(HAVE_PRI)
12149 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12150 {
12151 struct dahdi_spaninfo si;
12152 struct dahdi_params p;
12153 int fd;
12154 int span;
12155 int ospan=0;
12156 int x,y;
12157 for (x = 0; x < NUM_SPANS; x++) {
12158 if (pris[x].pri.trunkgroup == trunkgroup) {
12159 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12160 return -1;
12161 }
12162 }
12163 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12164 if (!channels[y])
12165 break;
12166 memset(&si, 0, sizeof(si));
12167 memset(&p, 0, sizeof(p));
12168 fd = open("/dev/dahdi/channel", O_RDWR);
12169 if (fd < 0) {
12170 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12171 return -1;
12172 }
12173 x = channels[y];
12174 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12175 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12176 close(fd);
12177 return -1;
12178 }
12179 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12180 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12181 close(fd);
12182 return -1;
12183 }
12184 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12185 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12186 close(fd);
12187 return -1;
12188 }
12189 span = p.spanno - 1;
12190 if (pris[span].pri.trunkgroup) {
12191 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12192 close(fd);
12193 return -1;
12194 }
12195 if (pris[span].pri.pvts[0]) {
12196 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12197 close(fd);
12198 return -1;
12199 }
12200 if (!y) {
12201 pris[span].pri.trunkgroup = trunkgroup;
12202 ospan = span;
12203 }
12204 pris[ospan].dchannels[y] = channels[y];
12205 pris[span].pri.span = span + 1;
12206 close(fd);
12207 }
12208 return 0;
12209 }
12210 #endif /* defined(HAVE_PRI) */
12211
12212 #if defined(HAVE_PRI)
12213 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12214 {
12215 if (pris[span].mastertrunkgroup) {
12216 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);
12217 return -1;
12218 }
12219 pris[span].mastertrunkgroup = trunkgroup;
12220 pris[span].prilogicalspan = logicalspan;
12221 return 0;
12222 }
12223 #endif /* defined(HAVE_PRI) */
12224
12225 #if defined(HAVE_SS7)
12226 static unsigned int parse_pointcode(const char *pcstring)
12227 {
12228 unsigned int code1, code2, code3;
12229 int numvals;
12230
12231 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12232 if (numvals == 1)
12233 return code1;
12234 if (numvals == 3)
12235 return (code1 << 16) | (code2 << 8) | code3;
12236
12237 return 0;
12238 }
12239 #endif /* defined(HAVE_SS7) */
12240
12241 #if defined(HAVE_SS7)
12242 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12243 {
12244 if ((linkset < 0) || (linkset >= NUM_SPANS))
12245 return NULL;
12246 else
12247 return &linksets[linkset - 1];
12248 }
12249 #endif /* defined(HAVE_SS7) */
12250
12251 #ifdef HAVE_OPENR2
12252 static void dahdi_r2_destroy_links(void)
12253 {
12254 struct r2link_entry *cur;
12255
12256 /* Queue everything for removal */
12257 AST_LIST_LOCK(&r2links);
12258 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
12259 ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
12260 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
12261 }
12262 AST_LIST_TRAVERSE_SAFE_END;
12263 AST_LIST_UNLOCK(&r2links);
12264 /* Now destroy properly */
12265 dahdi_r2_destroy_nodev();
12266 }
12267
12268 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12269 #define R2_LINK_CAPACITY 30
12270 static struct r2link_entry *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12271 {
12272 struct r2link_entry *cur = NULL;
12273 /* Only create a new R2 link if
12274 1. This is the first link requested
12275 2. Configuration changed
12276 3. We got more channels than supported per link */
12277 AST_LIST_LOCK(&r2links);
12278 if (! AST_LIST_EMPTY(&r2links)) {
12279 cur = AST_LIST_LAST(&r2links);
12280 if (memcmp(&conf->mfcr2, &cur->mfcr2.conf, sizeof(conf->mfcr2))) {
12281 ast_debug(3, "Need new R2 link because of: Configuration change\n");
12282 cur = NULL;
12283 } else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
12284 ast_debug(3, "Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
12285 cur = NULL;
12286 }
12287 }
12288 if (!cur) {
12289 struct r2link_entry *tmp = NULL;
12290 int new_idx = r2links_count + 1;
12291 int i;
12292 for (i = 1; i <= r2links_count; i++) {
12293 int i_unused = 1;
12294 AST_LIST_TRAVERSE(&r2links, tmp, list) {
12295 if (i == tmp->mfcr2.index) {
12296 i_unused = 0;
12297 break;
12298 }
12299 }
12300 if (i_unused) {
12301 new_idx = i;
12302 break;
12303 }
12304 }
12305 cur = ast_calloc(1, sizeof(*cur));
12306 if (!cur) {
12307 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12308 return NULL;
12309 }
12310 cur->mfcr2.index = new_idx;
12311 cur->mfcr2.r2master = AST_PTHREADT_NULL;
12312 r2links_count++;
12313 ast_debug(3, "Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12314 AST_LIST_INSERT_TAIL(&r2links, cur, list);
12315 }
12316 AST_LIST_UNLOCK(&r2links);
12317 return cur;
12318 }
12319
12320 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12321 {
12322 char tmplogdir[] = "/tmp";
12323 char logdir[OR2_MAX_PATH];
12324 int threshold = 0;
12325 int snres = 0;
12326 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12327 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12328 conf->mfcr2.max_dnis);
12329 if (!r2_link->protocol_context) {
12330 return -1;
12331 }
12332 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12333 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12334 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12335 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12336 #endif
12337 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12338 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12339 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12340 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12341 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12342 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12343 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12344 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12345 #endif
12346 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12347 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12348 #endif
12349 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12350 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12351 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12352 }
12353 } else {
12354 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12355 if (snres >= sizeof(logdir)) {
12356 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12357 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12358 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12359 }
12360 } else {
12361 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12362 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12363 }
12364 }
12365 }
12366 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12367 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12368 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12369 }
12370 }
12371 /* Save the configuration used to setup this link */
12372 memcpy(&r2_link->conf, &conf->mfcr2, sizeof(r2_link->conf));
12373 return 0;
12374 }
12375 #endif
12376
12377 /* converts a DAHDI sigtype to signalling as can be configured from
12378 * chan_dahdi.conf.
12379 * While both have basically the same values, this will later be the
12380 * place to add filters and sanity checks
12381 */
12382 static int sigtype_to_signalling(int sigtype)
12383 {
12384 return sigtype;
12385 }
12386
12387 /*!
12388 * \internal
12389 * \brief Initialize/create a channel interface.
12390 *
12391 * \param channel Channel interface number to initialize/create.
12392 * \param conf Configuration parameters to initialize interface with.
12393 * \param reloading What we are doing now:
12394 * 0 - initial module load,
12395 * 1 - module reload,
12396 * 2 - module restart
12397 *
12398 * \retval Interface-pointer initialized/created
12399 * \retval NULL if error
12400 */
12401 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12402 {
12403 /* Make a dahdi_pvt structure for this interface */
12404 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12405 char fn[80];
12406 struct dahdi_bufferinfo bi;
12407
12408 int res;
12409 #if defined(HAVE_PRI)
12410 int span = 0;
12411 #endif /* defined(HAVE_PRI) */
12412 int here = 0;/*!< TRUE if the channel interface already exists. */
12413 int x;
12414 struct analog_pvt *analog_p = NULL;
12415 struct dahdi_params p;
12416 #if defined(HAVE_PRI)
12417 struct dahdi_spaninfo si;
12418 struct sig_pri_chan *pri_chan = NULL;
12419 #endif /* defined(HAVE_PRI) */
12420 #if defined(HAVE_SS7)
12421 struct sig_ss7_chan *ss7_chan = NULL;
12422 #endif /* defined(HAVE_SS7) */
12423
12424 /* Search channel interface list to see if it already exists. */
12425 for (tmp = iflist; tmp; tmp = tmp->next) {
12426 if (!tmp->destroy) {
12427 if (tmp->channel == channel) {
12428 /* The channel interface already exists. */
12429 here = 1;
12430 break;
12431 }
12432 if (tmp->channel > channel) {
12433 /* No way it can be in the sorted list. */
12434 tmp = NULL;
12435 break;
12436 }
12437 }
12438 }
12439
12440 if (!here && reloading != 1) {
12441 tmp = ast_calloc(1, sizeof(*tmp));
12442 if (!tmp) {
12443 return NULL;
12444 }
12445 tmp->cc_params = ast_cc_config_params_init();
12446 if (!tmp->cc_params) {
12447 ast_free(tmp);
12448 return NULL;
12449 }
12450 ast_mutex_init(&tmp->lock);
12451 ifcount++;
12452 for (x = 0; x < 3; x++)
12453 tmp->subs[x].dfd = -1;
12454 tmp->channel = channel;
12455 tmp->priindication_oob = conf->chan.priindication_oob;
12456 }
12457
12458 if (tmp) {
12459 int chan_sig = conf->chan.sig;
12460
12461 /* If there are variables in tmp before it is updated to match the new config, clear them */
12462 if (reloading && tmp->vars) {
12463 ast_variables_destroy(tmp->vars);
12464 tmp->vars = NULL;
12465 }
12466
12467 if (!here) {
12468 /* Can only get here if this is a new channel interface being created. */
12469 if ((channel != CHAN_PSEUDO)) {
12470 int count = 0;
12471
12472 snprintf(fn, sizeof(fn), "%d", channel);
12473 /* Open non-blocking */
12474 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12475 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12476 usleep(1);
12477 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12478 count++;
12479 }
12480 /* Allocate a DAHDI structure */
12481 if (tmp->subs[SUB_REAL].dfd < 0) {
12482 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);
12483 destroy_dahdi_pvt(tmp);
12484 return NULL;
12485 }
12486 memset(&p, 0, sizeof(p));
12487 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12488 if (res < 0) {
12489 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12490 destroy_dahdi_pvt(tmp);
12491 return NULL;
12492 }
12493 if (conf->is_sig_auto)
12494 chan_sig = sigtype_to_signalling(p.sigtype);
12495 if (p.sigtype != (chan_sig & 0x3ffff)) {
12496 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));
12497 destroy_dahdi_pvt(tmp);
12498 return NULL;
12499 }
12500 tmp->law_default = p.curlaw;
12501 tmp->law = p.curlaw;
12502 tmp->span = p.spanno;
12503 #if defined(HAVE_PRI)
12504 span = p.spanno - 1;
12505 #endif /* defined(HAVE_PRI) */
12506 } else {
12507 chan_sig = 0;
12508 }
12509 tmp->sig = chan_sig;
12510 tmp->outsigmod = conf->chan.outsigmod;
12511
12512 if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12513 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12514 if (!analog_p) {
12515 destroy_dahdi_pvt(tmp);
12516 return NULL;
12517 }
12518 tmp->sig_pvt = analog_p;
12519 }
12520 #if defined(HAVE_SS7)
12521 if (chan_sig == SIG_SS7) {
12522 struct dahdi_ss7 *ss7;
12523 int clear = 0;
12524
12525 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12526 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12527 destroy_dahdi_pvt(tmp);
12528 return NULL;
12529 }
12530
12531 ss7 = ss7_resolve_linkset(cur_linkset);
12532 if (!ss7) {
12533 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12534 destroy_dahdi_pvt(tmp);
12535 return NULL;
12536 }
12537 ss7->ss7.span = cur_linkset;
12538 if (cur_cicbeginswith < 0) {
12539 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12540 destroy_dahdi_pvt(tmp);
12541 return NULL;
12542 }
12543 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12544 if (!ss7_chan) {
12545 destroy_dahdi_pvt(tmp);
12546 return NULL;
12547 }
12548 tmp->sig_pvt = ss7_chan;
12549 tmp->ss7 = &ss7->ss7;
12550
12551 ss7_chan->channel = tmp->channel;
12552 ss7_chan->cic = cur_cicbeginswith++;
12553
12554 /* DB: Add CIC's DPC information */
12555 ss7_chan->dpc = cur_defaultdpc;
12556
12557 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12558
12559 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12560 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12561 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12562 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12563 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12564
12565 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12566 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12567 }
12568 #endif /* defined(HAVE_SS7) */
12569 #ifdef HAVE_OPENR2
12570 if (chan_sig == SIG_MFCR2) {
12571 struct dahdi_mfcr2 *r2_link;
12572 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12573 r2_link = &r2_le->mfcr2;
12574 if (!r2_link) {
12575 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12576 destroy_dahdi_pvt(tmp);
12577 return NULL;
12578 }
12579 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12580 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12581 destroy_dahdi_pvt(tmp);
12582 return NULL;
12583 }
12584 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12585 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12586 destroy_dahdi_pvt(tmp);
12587 return NULL;
12588 }
12589 r2_link->pvts[r2_link->numchans++] = tmp;
12590 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12591 tmp->subs[SUB_REAL].dfd,
12592 NULL, NULL);
12593 if (!tmp->r2chan) {
12594 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12595 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12596 destroy_dahdi_pvt(tmp);
12597 return NULL;
12598 }
12599 r2_link->live_chans++;
12600 tmp->mfcr2 = r2_link;
12601 if (conf->mfcr2.call_files) {
12602 openr2_chan_enable_call_files(tmp->r2chan);
12603 }
12604 openr2_chan_set_client_data(tmp->r2chan, tmp);
12605 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12606 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12607 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12608 tmp->mfcr2_category = conf->mfcr2.category;
12609 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12610 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12611 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12612 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12613 tmp->mfcr2call = 0;
12614 tmp->mfcr2_dnis_index = 0;
12615 tmp->mfcr2_ani_index = 0;
12616 }
12617 #endif
12618 #ifdef HAVE_PRI
12619 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12620 int offset;
12621 int matchesdchan;
12622 int x,y;
12623 int myswitchtype = 0;
12624
12625 offset = 0;
12626 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12627 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12628 destroy_dahdi_pvt(tmp);
12629 return NULL;
12630 }
12631 if (span >= NUM_SPANS) {
12632 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12633 destroy_dahdi_pvt(tmp);
12634 return NULL;
12635 } else {
12636 si.spanno = 0;
12637 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12638 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12639 destroy_dahdi_pvt(tmp);
12640 return NULL;
12641 }
12642 /* Store the logical span first based upon the real span */
12643 tmp->logicalspan = pris[span].prilogicalspan;
12644 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12645 if (span < 0) {
12646 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12647 destroy_dahdi_pvt(tmp);
12648 return NULL;
12649 }
12650 myswitchtype = conf->pri.pri.switchtype;
12651 /* Make sure this isn't a d-channel */
12652 matchesdchan=0;
12653 for (x = 0; x < NUM_SPANS; x++) {
12654 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12655 if (pris[x].dchannels[y] == tmp->channel) {
12656 matchesdchan = 1;
12657 break;
12658 }
12659 }
12660 }
12661 if (!matchesdchan) {
12662 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12663 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12664 destroy_dahdi_pvt(tmp);
12665 return NULL;
12666 }
12667 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12668 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12669 destroy_dahdi_pvt(tmp);
12670 return NULL;
12671 }
12672 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12673 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));
12674 destroy_dahdi_pvt(tmp);
12675 return NULL;
12676 }
12677 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12678 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12679 destroy_dahdi_pvt(tmp);
12680 return NULL;
12681 }
12682 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12683 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12684 destroy_dahdi_pvt(tmp);
12685 return NULL;
12686 }
12687 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12688 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12689 destroy_dahdi_pvt(tmp);
12690 return NULL;
12691 }
12692 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12693 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12694 destroy_dahdi_pvt(tmp);
12695 return NULL;
12696 }
12697 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12698 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12699 pris[span].pri.trunkgroup);
12700 destroy_dahdi_pvt(tmp);
12701 return NULL;
12702 }
12703
12704 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12705 if (!pri_chan) {
12706 destroy_dahdi_pvt(tmp);
12707 return NULL;
12708 }
12709 tmp->sig_pvt = pri_chan;
12710 tmp->pri = &pris[span].pri;
12711
12712 tmp->priexclusive = conf->chan.priexclusive;
12713
12714 if (!tmp->pri->cc_params) {
12715 tmp->pri->cc_params = ast_cc_config_params_init();
12716 if (!tmp->pri->cc_params) {
12717 destroy_dahdi_pvt(tmp);
12718 return NULL;
12719 }
12720 }
12721 ast_cc_copy_config_params(tmp->pri->cc_params,
12722 conf->chan.cc_params);
12723
12724 pris[span].pri.sig = chan_sig;
12725 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12726 pris[span].pri.switchtype = myswitchtype;
12727 pris[span].pri.nsf = conf->pri.pri.nsf;
12728 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12729 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12730 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12731 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12732 pris[span].pri.minunused = conf->pri.pri.minunused;
12733 pris[span].pri.minidle = conf->pri.pri.minidle;
12734 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12735 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12736 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12737 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12738 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12739 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12740 #ifdef HAVE_PRI_INBANDDISCONNECT
12741 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12742 #endif
12743 #if defined(HAVE_PRI_CALL_HOLD)
12744 pris[span].pri.hold_disconnect_transfer =
12745 conf->pri.pri.hold_disconnect_transfer;
12746 #endif /* defined(HAVE_PRI_CALL_HOLD) */
12747 #if defined(HAVE_PRI_CCSS)
12748 pris[span].pri.cc_ptmp_recall_mode =
12749 conf->pri.pri.cc_ptmp_recall_mode;
12750 pris[span].pri.cc_qsig_signaling_link_req =
12751 conf->pri.pri.cc_qsig_signaling_link_req;
12752 pris[span].pri.cc_qsig_signaling_link_rsp =
12753 conf->pri.pri.cc_qsig_signaling_link_rsp;
12754 #endif /* defined(HAVE_PRI_CCSS) */
12755 #if defined(HAVE_PRI_CALL_WAITING)
12756 pris[span].pri.max_call_waiting_calls =
12757 conf->pri.pri.max_call_waiting_calls;
12758 pris[span].pri.allow_call_waiting_calls =
12759 conf->pri.pri.allow_call_waiting_calls;
12760 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12761 pris[span].pri.transfer = conf->chan.transfer;
12762 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12763 #if defined(HAVE_PRI_L2_PERSISTENCE)
12764 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12765 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12766 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12767 #if defined(HAVE_PRI_AOC_EVENTS)
12768 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12769 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12770 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
12771 if (chan_sig == SIG_BRI_PTMP) {
12772 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12773 } else {
12774 /* Option does not apply to this line type. */
12775 pris[span].pri.layer1_ignored = 0;
12776 }
12777 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12778 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12779 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12780 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12781 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12782 #if defined(HAVE_PRI_MWI)
12783 ast_copy_string(pris[span].pri.mwi_mailboxes,
12784 conf->pri.pri.mwi_mailboxes,
12785 sizeof(pris[span].pri.mwi_mailboxes));
12786 ast_copy_string(pris[span].pri.mwi_vm_boxes,
12787 conf->pri.pri.mwi_vm_boxes,
12788 sizeof(pris[span].pri.mwi_vm_boxes));
12789 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12790 conf->pri.pri.mwi_vm_numbers,
12791 sizeof(pris[span].pri.mwi_vm_numbers));
12792 #endif /* defined(HAVE_PRI_MWI) */
12793 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12794 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12795 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12796 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12797 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12798 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12799 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12800 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12801 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12802 #if defined(HAVE_PRI_DISPLAY_TEXT)
12803 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12804 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12805 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12806 #if defined(HAVE_PRI_MCID)
12807 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12808 #endif /* defined(HAVE_PRI_MCID) */
12809 pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
12810 #if defined(HAVE_PRI_DATETIME_SEND)
12811 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12812 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
12813
12814 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12815 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12816 }
12817
12818 #if defined(HAVE_PRI_CALL_WAITING)
12819 /* Channel initial config parameters. */
12820 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12821 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12822 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12823 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12824 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12825 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12826 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12827 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12828 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12829 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12830 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12831 } else {
12832 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12833 destroy_dahdi_pvt(tmp);
12834 return NULL;
12835 }
12836 }
12837 }
12838 #endif
12839 } else {
12840 /* already exists in interface list */
12841 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));
12842 chan_sig = tmp->sig;
12843 if (tmp->subs[SUB_REAL].dfd > -1) {
12844 memset(&p, 0, sizeof(p));
12845 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12846 }
12847 }
12848 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12849 switch (chan_sig) {
12850 case SIG_FXSKS:
12851 case SIG_FXSLS:
12852 case SIG_EM:
12853 case SIG_EM_E1:
12854 case SIG_EMWINK:
12855 case SIG_FEATD:
12856 case SIG_FEATDMF:
12857 case SIG_FEATDMF_TA:
12858 case SIG_FEATB:
12859 case SIG_E911:
12860 case SIG_SF:
12861 case SIG_SFWINK:
12862 case SIG_FGC_CAMA:
12863 case SIG_FGC_CAMAMF:
12864 case SIG_SF_FEATD:
12865 case SIG_SF_FEATDMF:
12866 case SIG_SF_FEATB:
12867 p.starttime = 250;
12868 break;
12869 }
12870
12871 if (tmp->radio) {
12872 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12873 p.channo = channel;
12874 p.rxwinktime = 1;
12875 p.rxflashtime = 1;
12876 p.starttime = 1;
12877 p.debouncetime = 5;
12878 } else {
12879 p.channo = channel;
12880 /* Override timing settings based on config file */
12881 if (conf->timing.prewinktime >= 0)
12882 p.prewinktime = conf->timing.prewinktime;
12883 if (conf->timing.preflashtime >= 0)
12884 p.preflashtime = conf->timing.preflashtime;
12885 if (conf->timing.winktime >= 0)
12886 p.winktime = conf->timing.winktime;
12887 if (conf->timing.flashtime >= 0)
12888 p.flashtime = conf->timing.flashtime;
12889 if (conf->timing.starttime >= 0)
12890 p.starttime = conf->timing.starttime;
12891 if (conf->timing.rxwinktime >= 0)
12892 p.rxwinktime = conf->timing.rxwinktime;
12893 if (conf->timing.rxflashtime >= 0)
12894 p.rxflashtime = conf->timing.rxflashtime;
12895 if (conf->timing.debouncetime >= 0)
12896 p.debouncetime = conf->timing.debouncetime;
12897 }
12898
12899 /* don't set parms on a pseudo-channel */
12900 if (tmp->subs[SUB_REAL].dfd >= 0)
12901 {
12902 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12903 if (res < 0) {
12904 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12905 destroy_dahdi_pvt(tmp);
12906 return NULL;
12907 }
12908 }
12909 #if 1
12910 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12911 memset(&bi, 0, sizeof(bi));
12912 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12913 if (!res) {
12914 bi.txbufpolicy = conf->chan.buf_policy;
12915 bi.rxbufpolicy = conf->chan.buf_policy;
12916 bi.numbufs = conf->chan.buf_no;
12917 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12918 if (res < 0) {
12919 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12920 }
12921 } else {
12922 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12923 }
12924 tmp->buf_policy = conf->chan.buf_policy;
12925 tmp->buf_no = conf->chan.buf_no;
12926 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12927 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12928 tmp->faxbuf_no = conf->chan.faxbuf_no;
12929 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
12930 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12931 * The reason the ioctl call above failed should to be determined before worrying about the
12932 * faxbuffer-related ioctl calls */
12933 tmp->bufsize = bi.bufsize;
12934 }
12935 #endif
12936 tmp->immediate = conf->chan.immediate;
12937 tmp->immediatering = conf->chan.immediatering;
12938 tmp->transfertobusy = conf->chan.transfertobusy;
12939 tmp->dialmode = conf->chan.dialmode;
12940 if (chan_sig & __DAHDI_SIG_FXS) {
12941 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12942 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12943 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12944 }
12945 tmp->ringt_base = ringt_base;
12946 tmp->firstradio = 0;
12947 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12948 tmp->permcallwaiting = conf->chan.callwaiting;
12949 else
12950 tmp->permcallwaiting = 0;
12951 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
12952 tmp->destroy = 0;
12953 tmp->drings = conf->chan.drings;
12954
12955 /* 10 is a nice default. */
12956 if (tmp->drings.ringnum[0].range == 0)
12957 tmp->drings.ringnum[0].range = 10;
12958 if (tmp->drings.ringnum[1].range == 0)
12959 tmp->drings.ringnum[1].range = 10;
12960 if (tmp->drings.ringnum[2].range == 0)
12961 tmp->drings.ringnum[2].range = 10;
12962
12963 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12964 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12965 tmp->threewaycalling = conf->chan.threewaycalling;
12966 tmp->threewaysilenthold = conf->chan.threewaysilenthold;
12967 tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
12968 tmp->adsi = conf->chan.adsi;
12969 tmp->use_smdi = conf->chan.use_smdi;
12970 tmp->permhidecallerid = conf->chan.hidecallerid;
12971 tmp->hidecalleridname = conf->chan.hidecalleridname;
12972 tmp->callreturn = conf->chan.callreturn;
12973 tmp->echocancel = conf->chan.echocancel;
12974 tmp->echotraining = conf->chan.echotraining;
12975 tmp->pulse = conf->chan.pulse;
12976 if (tmp->echocancel.head.tap_length) {
12977 tmp->echocanbridged = conf->chan.echocanbridged;
12978 } else {
12979 if (conf->chan.echocanbridged)
12980 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12981 tmp->echocanbridged = 0;
12982 }
12983 tmp->busydetect = conf->chan.busydetect;
12984 tmp->busycount = conf->chan.busycount;
12985 tmp->busy_cadence = conf->chan.busy_cadence;
12986 tmp->callprogress = conf->chan.callprogress;
12987 tmp->waitfordialtone = conf->chan.waitfordialtone;
12988 tmp->dialtone_detect = conf->chan.dialtone_detect;
12989 tmp->faxdetect_timeout = conf->chan.faxdetect_timeout;
12990 tmp->firstdigit_timeout = conf->chan.firstdigit_timeout;
12991 tmp->interdigit_timeout = conf->chan.interdigit_timeout;
12992 tmp->matchdigit_timeout = conf->chan.matchdigit_timeout;
12993 tmp->cancallforward = conf->chan.cancallforward;
12994 tmp->dtmfrelax = conf->chan.dtmfrelax;
12995 tmp->callwaiting = tmp->permcallwaiting;
12996 tmp->hidecallerid = tmp->permhidecallerid;
12997 tmp->channel = channel;
12998 tmp->stripmsd = conf->chan.stripmsd;
12999 tmp->use_callerid = conf->chan.use_callerid;
13000 tmp->cid_signalling = conf->chan.cid_signalling;
13001 tmp->cid_start = conf->chan.cid_start;
13002 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13003 tmp->restrictcid = conf->chan.restrictcid;
13004 tmp->use_callingpres = conf->chan.use_callingpres;
13005 if (tmp->usedistinctiveringdetection) {
13006 if (!tmp->use_callerid) {
13007 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13008 tmp->use_callerid = 1;
13009 }
13010 }
13011
13012 if (tmp->cid_signalling == CID_SIG_SMDI) {
13013 if (!tmp->use_smdi) {
13014 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13015 tmp->use_smdi = 1;
13016 }
13017 }
13018 if (tmp->use_smdi) {
13019 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13020 if (!(tmp->smdi_iface)) {
13021 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13022 tmp->use_smdi = 0;
13023 }
13024 }
13025
13026 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13027 tmp->amaflags = conf->chan.amaflags;
13028 if (!here) {
13029 tmp->confno = -1;
13030 tmp->propconfno = -1;
13031 }
13032 tmp->canpark = conf->chan.canpark;
13033 tmp->transfer = conf->chan.transfer;
13034 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13035 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13036 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13037 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13038 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13039 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13040 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13041 tmp->cid_ton = 0;
13042 if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13043 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13044 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13045 } else {
13046 tmp->cid_num[0] = '\0';
13047 tmp->cid_name[0] = '\0';
13048 }
13049 #if defined(HAVE_PRI)
13050 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13051 tmp->cid_tag[0] = '\0';
13052 } else
13053 #endif /* defined(HAVE_PRI) */
13054 {
13055 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13056 }
13057 tmp->cid_subaddr[0] = '\0';
13058 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13059 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13060 /* This module does not handle MWI in an event-based manner. However, it
13061 * subscribes to MWI for each mailbox that is configured so that the core
13062 * knows that we care about it. Then, chan_dahdi will get the MWI from the
13063 * event cache instead of checking the mailbox directly. */
13064 tmp->mwi_event_sub = ast_mwi_subscribe_pool(tmp->mailbox, stasis_subscription_cb_noop, NULL);
13065 }
13066 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13067 tmp->mwisend_setting = conf->chan.mwisend_setting;
13068 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13069 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13070 #endif
13071
13072 tmp->group = conf->chan.group;
13073 tmp->callgroup = conf->chan.callgroup;
13074 tmp->pickupgroup= conf->chan.pickupgroup;
13075 ast_unref_namedgroups(tmp->named_callgroups);
13076 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13077 ast_unref_namedgroups(tmp->named_pickupgroups);
13078 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13079 if (conf->chan.vars) {
13080 struct ast_variable *v, *tmpvar;
13081 for (v = conf->chan.vars ; v ; v = v->next) {
13082 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13083 if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
13084 tmpvar->next = tmp->vars;
13085 tmp->vars = tmpvar;
13086 }
13087 }
13088 }
13089 }
13090 tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
13091 tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
13092 tmp->hwrxgain = conf->chan.hwrxgain;
13093 tmp->hwtxgain = conf->chan.hwtxgain;
13094 tmp->cid_rxgain = conf->chan.cid_rxgain;
13095 tmp->rxgain = conf->chan.rxgain;
13096 tmp->txgain = conf->chan.txgain;
13097 tmp->txdrc = conf->chan.txdrc;
13098 tmp->rxdrc = conf->chan.rxdrc;
13099 tmp->tonezone = conf->chan.tonezone;
13100 if (tmp->subs[SUB_REAL].dfd > -1) {
13101 if (tmp->hwrxgain_enabled) {
13102 tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
13103 }
13104 if (tmp->hwtxgain_enabled) {
13105 tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
13106 }
13107 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13108 if (tmp->dsp)
13109 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13110 dahdi_conf_update(tmp);
13111 if (!here) {
13112 switch (chan_sig) {
13113 case SIG_PRI_LIB_HANDLE_CASES:
13114 case SIG_SS7:
13115 case SIG_MFCR2:
13116 break;
13117 default:
13118 /* Hang it up to be sure it's good */
13119 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13120 break;
13121 }
13122 }
13123 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13124 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13125 /* the dchannel is down so put the channel in alarm */
13126 switch (tmp->sig) {
13127 #ifdef HAVE_PRI
13128 case SIG_PRI_LIB_HANDLE_CASES:
13129 sig_pri_set_alarm(tmp->sig_pvt, 1);
13130 break;
13131 #endif
13132 #if defined(HAVE_SS7)
13133 case SIG_SS7:
13134 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13135 break;
13136 #endif /* defined(HAVE_SS7) */
13137 default:
13138 /* The only sig submodule left should be sig_analog. */
13139 analog_p = tmp->sig_pvt;
13140 if (analog_p) {
13141 analog_p->inalarm = 1;
13142 }
13143 tmp->inalarm = 1;
13144 break;
13145 }
13146 handle_alarms(tmp, res);
13147 }
13148 }
13149
13150 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13151 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13152 tmp->ani_info_digits = conf->chan.ani_info_digits;
13153 tmp->ani_wink_time = conf->chan.ani_wink_time;
13154 tmp->ani_timeout = conf->chan.ani_timeout;
13155 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13156 tmp->reoriginate = conf->chan.reoriginate;
13157 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13158 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13159
13160 if (!here) {
13161 tmp->locallyblocked = 0;
13162 tmp->remotelyblocked = 0;
13163 switch (tmp->sig) {
13164 #if defined(HAVE_PRI)
13165 case SIG_PRI_LIB_HANDLE_CASES:
13166 tmp->inservice = 1;/* Inservice until actually implemented. */
13167 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13168 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13169 if (chan_sig == SIG_PRI) {
13170 char db_chan_name[20];
13171 char db_answer[5];
13172
13173 /*
13174 * Initialize the active out-of-service status
13175 * and delete any record if the feature is not enabled.
13176 */
13177 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13178 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13179 unsigned *why;
13180
13181 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13182 if (tmp->pri->enable_service_message_support) {
13183 char state;
13184
13185 sscanf(db_answer, "%1c:%30u", &state, why);
13186
13187 /* Ensure that only the implemented bits could be set.*/
13188 *why &= (SRVST_NEAREND | SRVST_FAREND);
13189 }
13190 if (!*why) {
13191 ast_db_del(db_chan_name, SRVST_DBKEY);
13192 }
13193 }
13194 }
13195 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13196 break;
13197 #endif /* defined(HAVE_PRI) */
13198 #if defined(HAVE_SS7)
13199 case SIG_SS7:
13200 tmp->inservice = 0;
13201 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13202 tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
13203 }
13204 break;
13205 #endif /* defined(HAVE_SS7) */
13206 default:
13207 /* We default to in service on protocols that don't have a reset */
13208 tmp->inservice = 1;
13209 break;
13210 }
13211 }
13212
13213 switch (tmp->sig) {
13214 #if defined(HAVE_PRI)
13215 case SIG_PRI_LIB_HANDLE_CASES:
13216 if (pri_chan) {
13217 pri_chan->channel = tmp->channel;
13218 pri_chan->hidecallerid = tmp->hidecallerid;
13219 pri_chan->hidecalleridname = tmp->hidecalleridname;
13220 pri_chan->immediate = tmp->immediate;
13221 pri_chan->inalarm = tmp->inalarm;
13222 pri_chan->priexclusive = tmp->priexclusive;
13223 pri_chan->priindication_oob = tmp->priindication_oob;
13224 pri_chan->use_callerid = tmp->use_callerid;
13225 pri_chan->use_callingpres = tmp->use_callingpres;
13226 ast_copy_string(pri_chan->context, tmp->context,
13227 sizeof(pri_chan->context));
13228 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13229 sizeof(pri_chan->mohinterpret));
13230 pri_chan->stripmsd = tmp->stripmsd;
13231 }
13232 break;
13233 #endif /* defined(HAVE_PRI) */
13234 #if defined(HAVE_SS7)
13235 case SIG_SS7:
13236 if (ss7_chan) {
13237 ss7_chan->inalarm = tmp->inalarm;
13238 ss7_chan->inservice = tmp->inservice;
13239
13240 ss7_chan->stripmsd = tmp->stripmsd;
13241 ss7_chan->hidecallerid = tmp->hidecallerid;
13242 ss7_chan->use_callerid = tmp->use_callerid;
13243 ss7_chan->use_callingpres = tmp->use_callingpres;
13244 ss7_chan->immediate = tmp->immediate;
13245 ss7_chan->locallyblocked = tmp->locallyblocked;
13246 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13247 ast_copy_string(ss7_chan->context, tmp->context,
13248 sizeof(ss7_chan->context));
13249 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13250 sizeof(ss7_chan->mohinterpret));
13251 }
13252 break;
13253 #endif /* defined(HAVE_SS7) */
13254 default:
13255 /* The only sig submodule left should be sig_analog. */
13256 analog_p = tmp->sig_pvt;
13257 if (analog_p) {
13258 analog_p->channel = tmp->channel;
13259 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13260 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13261 analog_p->ani_info_digits = conf->chan.ani_info_digits;
13262 analog_p->ani_timeout = conf->chan.ani_timeout;
13263 analog_p->ani_wink_time = conf->chan.ani_wink_time;
13264 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13265 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13266 analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actually used in analog pvt, not DAHDI pvt */
13267 analog_p->callreturn = conf->chan.callreturn;
13268 analog_p->cancallforward = conf->chan.cancallforward;
13269 analog_p->canpark = conf->chan.canpark;
13270 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13271 analog_p->immediate = conf->chan.immediate;
13272 analog_p->immediatering = conf->chan.immediatering;
13273 analog_p->permhidecallerid = conf->chan.hidecallerid; /* hidecallerid is the config setting, not permhidecallerid (~permcallwaiting above) */
13274 /* It's not necessary to set analog_p->hidecallerid here, sig_analog will set hidecallerid=permhidecaller before each call */
13275 analog_p->pulse = conf->chan.pulse;
13276 analog_p->threewaycalling = conf->chan.threewaycalling;
13277 analog_p->transfer = conf->chan.transfer;
13278 analog_p->transfertobusy = conf->chan.transfertobusy;
13279 analog_p->dialmode = conf->chan.dialmode;
13280 analog_p->use_callerid = tmp->use_callerid;
13281 analog_p->usedistinctiveringdetection = tmp->usedistinctiveringdetection;
13282 analog_p->use_smdi = tmp->use_smdi;
13283 analog_p->smdi_iface = tmp->smdi_iface;
13284 analog_p->outsigmod = ANALOG_SIG_NONE;
13285 analog_p->echotraining = conf->chan.echotraining;
13286 analog_p->cid_signalling = conf->chan.cid_signalling;
13287 analog_p->stripmsd = conf->chan.stripmsd;
13288 switch (conf->chan.cid_start) {
13289 case CID_START_POLARITY:
13290 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13291 break;
13292 case CID_START_POLARITY_IN:
13293 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13294 break;
13295 case CID_START_DTMF_NOALERT:
13296 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13297 break;
13298 default:
13299 analog_p->cid_start = ANALOG_CID_START_RING;
13300 break;
13301 }
13302 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13303 analog_p->ringt = conf->chan.ringt;
13304 analog_p->ringt_base = ringt_base;
13305 analog_p->onhooktime = time(NULL);
13306 if (chan_sig & __DAHDI_SIG_FXO) {
13307 memset(&p, 0, sizeof(p));
13308 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13309 if (!res) {
13310 analog_p->fxsoffhookstate = p.rxisoffhook;
13311 }
13312 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13313 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13314 #endif
13315 }
13316 analog_p->msgstate = -1;
13317
13318 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13319 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13320 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13321
13322 analog_config_complete(analog_p);
13323 }
13324 break;
13325 }
13326 #if defined(HAVE_PRI)
13327 if (tmp->channel == CHAN_PSEUDO) {
13328 /*
13329 * Save off pseudo channel buffer policy values for dynamic creation of
13330 * no B channel interfaces.
13331 */
13332 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13333 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13334 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13335 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13336 }
13337 #endif /* defined(HAVE_PRI) */
13338 }
13339 if (tmp && !here) {
13340 /* Add the new channel interface to the sorted channel interface list. */
13341 dahdi_iflist_insert(tmp);
13342 }
13343 return tmp;
13344 }
13345
13346 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13347 {
13348 #if defined(HAVE_PRI)
13349 if (0 < span) {
13350 /* The channel must be on the specified PRI span. */
13351 if (!p->pri || p->pri->span != span) {
13352 return 0;
13353 }
13354 if (!groupmatch && channelmatch == -1) {
13355 /* Match any group since it only needs to be on the PRI span. */
13356 *groupmatched = 1;
13357 return 1;
13358 }
13359 }
13360 #endif /* defined(HAVE_PRI) */
13361 /* check group matching */
13362 if (groupmatch) {
13363 if ((p->group & groupmatch) != groupmatch)
13364 /* Doesn't match the specified group, try the next one */
13365 return 0;
13366 *groupmatched = 1;
13367 }
13368 /* Check to see if we have a channel match */
13369 if (channelmatch != -1) {
13370 if (p->channel != channelmatch)
13371 /* Doesn't match the specified channel, try the next one */
13372 return 0;
13373 *channelmatched = 1;
13374 }
13375
13376 return 1;
13377 }
13378
13379 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13380 {
13381 struct dahdi_pvt *p = *pvt;
13382
13383 if (p->inalarm)
13384 return 0;
13385
13386 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13387 return analog_available(p->sig_pvt);
13388
13389 switch (p->sig) {
13390 #if defined(HAVE_PRI)
13391 case SIG_PRI_LIB_HANDLE_CASES:
13392 {
13393 struct sig_pri_chan *pvt_chan;
13394 int res;
13395
13396 pvt_chan = p->sig_pvt;
13397 res = sig_pri_available(&pvt_chan, is_specific_channel);
13398 *pvt = pvt_chan->chan_pvt;
13399 return res;
13400 }
13401 #endif /* defined(HAVE_PRI) */
13402 #if defined(HAVE_SS7)
13403 case SIG_SS7:
13404 return sig_ss7_available(p->sig_pvt);
13405 #endif /* defined(HAVE_SS7) */
13406 default:
13407 break;
13408 }
13409
13410 if (p->locallyblocked || p->remotelyblocked) {
13411 return 0;
13412 }
13413
13414 /* If no owner definitely available */
13415 if (!p->owner) {
13416 #ifdef HAVE_OPENR2
13417 /* Trust MFC/R2 */
13418 if (p->mfcr2) {
13419 if (p->mfcr2call) {
13420 return 0;
13421 } else {
13422 return 1;
13423 }
13424 }
13425 #endif
13426 return 1;
13427 }
13428
13429 return 0;
13430 }
13431
13432 #if defined(HAVE_PRI)
13433 #if defined(HAVE_PRI_CALL_WAITING)
13434 /*!
13435 * \internal
13436 * \brief Init the private channel configuration using the span controller.
13437 * \since 1.8
13438 *
13439 * \param priv Channel to init the configuration.
13440 * \param pri sig_pri PRI control structure.
13441 *
13442 * \note Assumes the pri->lock is already obtained.
13443 */
13444 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13445 {
13446 struct dahdi_pvt *pvt = priv;
13447
13448 pvt->stripmsd = pri->ch_cfg.stripmsd;
13449 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13450 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13451 pvt->immediate = pri->ch_cfg.immediate;
13452 pvt->priexclusive = pri->ch_cfg.priexclusive;
13453 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13454 pvt->use_callerid = pri->ch_cfg.use_callerid;
13455 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13456 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13457 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13458 }
13459 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13460 #endif /* defined(HAVE_PRI) */
13461
13462 #if defined(HAVE_PRI)
13463 /*!
13464 * \internal
13465 * \brief Create a no B channel interface.
13466 * \since 1.8
13467 *
13468 * \param pri sig_pri span controller to add interface.
13469 *
13470 * \note Assumes the pri->lock is already obtained.
13471 *
13472 * \retval array-index into private pointer array on success.
13473 * \retval -1 on error.
13474 */
13475 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13476 {
13477 int pvt_idx;
13478 int res;
13479 unsigned idx;
13480 struct dahdi_pvt *pvt;
13481 struct sig_pri_chan *chan;
13482 struct dahdi_bufferinfo bi;
13483
13484 static int nobch_channel = CHAN_PSEUDO;
13485
13486 /* Find spot in the private pointer array for new interface. */
13487 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13488 if (!pri->pvts[pvt_idx]) {
13489 break;
13490 }
13491 }
13492 if (pri->numchans == pvt_idx) {
13493 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13494 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13495 return -1;
13496 }
13497
13498 /* Add new spot to the private pointer array. */
13499 pri->pvts[pvt_idx] = NULL;
13500 ++pri->numchans;
13501 }
13502
13503 pvt = ast_calloc(1, sizeof(*pvt));
13504 if (!pvt) {
13505 return -1;
13506 }
13507 pvt->cc_params = ast_cc_config_params_init();
13508 if (!pvt->cc_params) {
13509 ast_free(pvt);
13510 return -1;
13511 }
13512 ast_mutex_init(&pvt->lock);
13513 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13514 pvt->subs[idx].dfd = -1;
13515 }
13516 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13517 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13518 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13519 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13520
13521 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13522 if (!chan) {
13523 destroy_dahdi_pvt(pvt);
13524 return -1;
13525 }
13526 chan->no_b_channel = 1;
13527
13528 /*
13529 * Pseudo channel companding law.
13530 * Needed for outgoing call waiting calls.
13531 * XXX May need to make this determined by switchtype or user option.
13532 */
13533 pvt->law_default = DAHDI_LAW_ALAW;
13534
13535 pvt->sig = pri->sig;
13536 pvt->outsigmod = -1;
13537 pvt->pri = pri;
13538 pvt->sig_pvt = chan;
13539 pri->pvts[pvt_idx] = chan;
13540
13541 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13542 if (pvt->subs[SUB_REAL].dfd < 0) {
13543 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13544 strerror(errno));
13545 destroy_dahdi_pvt(pvt);
13546 return -1;
13547 }
13548 memset(&bi, 0, sizeof(bi));
13549 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13550 if (!res) {
13551 pvt->bufsize = bi.bufsize;
13552 bi.txbufpolicy = pvt->buf_policy;
13553 bi.rxbufpolicy = pvt->buf_policy;
13554 bi.numbufs = pvt->buf_no;
13555 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13556 if (res < 0) {
13557 ast_log(LOG_WARNING,
13558 "Unable to set buffer policy on no B channel interface: %s\n",
13559 strerror(errno));
13560 }
13561 } else
13562 ast_log(LOG_WARNING,
13563 "Unable to check buffer policy on no B channel interface: %s\n",
13564 strerror(errno));
13565
13566 --nobch_channel;
13567 if (CHAN_PSEUDO < nobch_channel) {
13568 nobch_channel = CHAN_PSEUDO - 1;
13569 }
13570 pvt->channel = nobch_channel;
13571 pvt->span = pri->span;
13572 chan->channel = pvt->channel;
13573
13574 dahdi_nobch_insert(pri, pvt);
13575
13576 return pvt_idx;
13577 }
13578 #endif /* defined(HAVE_PRI) */
13579
13580 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13581 structures; it makes no attempt to safely copy regular channel private
13582 structures that might contain reference-counted object pointers and other
13583 scary bits
13584 */
13585 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13586 {
13587 struct dahdi_pvt *p;
13588 struct dahdi_bufferinfo bi;
13589 int res;
13590
13591 p = ast_malloc(sizeof(*p));
13592 if (!p) {
13593 return NULL;
13594 }
13595 *p = *src;
13596
13597 /* Must deep copy the cc_params. */
13598 p->cc_params = ast_cc_config_params_init();
13599 if (!p->cc_params) {
13600 ast_free(p);
13601 return NULL;
13602 }
13603 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13604
13605 p->which_iflist = DAHDI_IFLIST_NONE;
13606 p->next = NULL;
13607 p->prev = NULL;
13608 ast_mutex_init(&p->lock);
13609 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13610 if (p->subs[SUB_REAL].dfd < 0) {
13611 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13612 destroy_dahdi_pvt(p);
13613 return NULL;
13614 }
13615 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13616 if (!res) {
13617 bi.txbufpolicy = src->buf_policy;
13618 bi.rxbufpolicy = src->buf_policy;
13619 bi.numbufs = src->buf_no;
13620 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13621 if (res < 0) {
13622 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13623 }
13624 } else
13625 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13626 p->destroy = 1;
13627 dahdi_iflist_insert(p);
13628 return p;
13629 }
13630
13631 struct dahdi_starting_point {
13632 /*! Group matching mask. Zero if not specified. */
13633 ast_group_t groupmatch;
13634 /*! DAHDI channel to match with. -1 if not specified. */
13635 int channelmatch;
13636 /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13637 int rr_starting_point;
13638 /*! ISDN span where channels can be picked (Zero if not specified) */
13639 int span;
13640 /*! Analog channel distinctive ring cadence index. */
13641 int cadence;
13642 /*! Dialing option. c/r/d if present and valid. */
13643 char opt;
13644 /*! TRUE if to search the channel list backwards. */
13645 char backwards;
13646 /*! TRUE if search is done with round robin sequence. */
13647 char roundrobin;
13648 };
13649 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13650 {
13651 char *dest;
13652 char *s;
13653 int x;
13654 int res = 0;
13655 struct dahdi_pvt *p;
13656 char *subdir = NULL;
13657 AST_DECLARE_APP_ARGS(args,
13658 AST_APP_ARG(group); /* channel/group token */
13659 //AST_APP_ARG(ext); /* extension token */
13660 //AST_APP_ARG(opts); /* options token */
13661 AST_APP_ARG(other); /* Any remining unused arguments */
13662 );
13663
13664 /*
13665 * data is ---v
13666 * Dial(DAHDI/pseudo[/extension[/options]])
13667 * Dial(DAHDI/<channel#>[c|r<cadence#>|d][/extension[/options]])
13668 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadence#>|d][/extension[/options]])
13669 * Dial(DAHDI/i<span>[/extension[/options]])
13670 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadence#>|d][/extension[/options]])
13671 *
13672 * i - ISDN span channel restriction.
13673 * Used by CC to ensure that the CC recall goes out the same span.
13674 * Also to make ISDN channel names dialable when the sequence number
13675 * is stripped off. (Used by DTMF attended transfer feature.)
13676 *
13677 * g - channel group allocation search forward
13678 * G - channel group allocation search backward
13679 * r - channel group allocation round robin search forward
13680 * R - channel group allocation round robin search backward
13681 *
13682 * c - Wait for DTMF digit to confirm answer
13683 * r<cadence#> - Set distinctive ring cadence number
13684 * d - Force bearer capability for ISDN/SS7 call to digital.
13685 */
13686
13687 if (data) {
13688 dest = ast_strdupa(data);
13689 } else {
13690 ast_log(LOG_WARNING, "Channel requested with no data\n");
13691 return NULL;
13692 }
13693 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13694 if (!args.argc || ast_strlen_zero(args.group)) {
13695 ast_log(LOG_WARNING, "No channel/group specified\n");
13696 return NULL;
13697 }
13698
13699 /* Initialize the output parameters */
13700 memset(param, 0, sizeof(*param));
13701 param->channelmatch = -1;
13702
13703 if (strchr(args.group, '!') != NULL) {
13704 char *prev = args.group;
13705 while ((s = strchr(prev, '!')) != NULL) {
13706 *s++ = '/';
13707 prev = s;
13708 }
13709 *(prev - 1) = '\0';
13710 subdir = args.group;
13711 args.group = prev;
13712 } else if (args.group[0] == 'i') {
13713 /* Extract the ISDN span channel restriction specifier. */
13714 res = sscanf(args.group + 1, "%30d", &x);
13715 if (res < 1) {
13716 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13717 return NULL;
13718 }
13719 param->span = x;
13720
13721 /* Remove the ISDN span channel restriction specifier. */
13722 s = strchr(args.group, '-');
13723 if (!s) {
13724 /* Search all groups since we are ISDN span restricted. */
13725 return iflist;
13726 }
13727 args.group = s + 1;
13728 res = 0;
13729 }
13730 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13731 /* Retrieve the group number */
13732 s = args.group + 1;
13733 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13734 if (res < 1) {
13735 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13736 return NULL;
13737 }
13738 param->groupmatch = ((ast_group_t) 1 << x);
13739
13740 if (toupper(args.group[0]) == 'G') {
13741 if (args.group[0] == 'G') {
13742 param->backwards = 1;
13743 p = ifend;
13744 } else
13745 p = iflist;
13746 } else {
13747 if (ARRAY_LEN(round_robin) <= x) {
13748 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13749 x, data);
13750 return NULL;
13751 }
13752 if (args.group[0] == 'R') {
13753 param->backwards = 1;
13754 p = round_robin[x] ? round_robin[x]->prev : ifend;
13755 if (!p)
13756 p = ifend;
13757 } else {
13758 p = round_robin[x] ? round_robin[x]->next : iflist;
13759 if (!p)
13760 p = iflist;
13761 }
13762 param->roundrobin = 1;
13763 param->rr_starting_point = x;
13764 }
13765 } else {
13766 s = args.group;
13767 if (!strcasecmp(s, "pseudo")) {
13768 /* Special case for pseudo */
13769 x = CHAN_PSEUDO;
13770 param->channelmatch = x;
13771 } else {
13772 res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadence);
13773 if (res < 1) {
13774 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13775 return NULL;
13776 } else {
13777 param->channelmatch = x;
13778 }
13779 }
13780 if (subdir) {
13781 char path[PATH_MAX];
13782 struct stat stbuf;
13783
13784 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13785 subdir, param->channelmatch);
13786 if (stat(path, &stbuf) < 0) {
13787 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13788 path, strerror(errno));
13789 return NULL;
13790 }
13791 if (!S_ISCHR(stbuf.st_mode)) {
13792 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13793 path);
13794 return NULL;
13795 }
13796 param->channelmatch = minor(stbuf.st_rdev);
13797 }
13798
13799 p = iflist;
13800 }
13801
13802 if (param->opt == 'r' && res < 3) {
13803 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13804 param->opt = '\0';
13805 }
13806
13807 return p;
13808 }
13809
13810 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
13811 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
13812 const char *data, int *cause)
13813 {
13814 int callwait = 0;
13815 struct dahdi_pvt *p;
13816 struct ast_channel *tmp = NULL;
13817 struct dahdi_pvt *exitpvt;
13818 int channelmatched = 0;
13819 int foundowner = 0;
13820 int groupmatched = 0;
13821 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13822 int transcapdigital = 0;
13823 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13824 struct dahdi_starting_point start;
13825 ast_callid callid = 0;
13826 int callid_created = ast_callid_threadstorage_auto(&callid);
13827
13828 ast_mutex_lock(&iflock);
13829 p = determine_starting_point(data, &start);
13830 if (!p) {
13831 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13832 ast_mutex_unlock(&iflock);
13833 ast_callid_threadstorage_auto_clean(callid, callid_created);
13834 return NULL;
13835 }
13836
13837 /* Search for an unowned channel */
13838 exitpvt = p;
13839 while (p && !tmp) {
13840 if (start.roundrobin)
13841 round_robin[start.rr_starting_point] = p;
13842
13843 if (p->owner) {
13844 foundowner++;
13845 }
13846
13847 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13848 && available(&p, channelmatched)) {
13849 ast_debug(1, "Using channel %d\n", p->channel);
13850
13851 callwait = (p->owner != NULL);
13852 #ifdef HAVE_OPENR2
13853 if (p->mfcr2) {
13854 ast_mutex_lock(&p->lock);
13855 if (p->mfcr2call) {
13856 ast_mutex_unlock(&p->lock);
13857 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13858 goto next;
13859 }
13860 p->mfcr2call = 1;
13861 ast_mutex_unlock(&p->lock);
13862 }
13863 #endif
13864 if (p->channel == CHAN_PSEUDO) {
13865 p = duplicate_pseudo(p);
13866 if (!p) {
13867 break;
13868 }
13869 }
13870
13871 p->distinctivering = 0;
13872 /* Make special notes */
13873 switch (start.opt) {
13874 case '\0':
13875 /* No option present. */
13876 break;
13877 case 'c':
13878 /* Confirm answer */
13879 p->confirmanswer = 1;
13880 break;
13881 case 'r':
13882 /* Distinctive ring */
13883 p->distinctivering = start.cadence;
13884 break;
13885 case 'd':
13886 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13887 /* If this is an ISDN call, make it digital */
13888 transcapdigital = AST_TRANS_CAP_DIGITAL;
13889 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13890 break;
13891 default:
13892 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13893 break;
13894 }
13895
13896 p->outgoing = 1;
13897 if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13898 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13899 #ifdef HAVE_PRI
13900 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13901 /*
13902 * We already have the B channel reserved for this call. We
13903 * just need to make sure that dahdi_hangup() has completed
13904 * cleaning up before continuing.
13905 */
13906 ast_mutex_lock(&p->lock);
13907 ast_mutex_unlock(&p->lock);
13908
13909 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13910 sizeof(p->dnid));
13911 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
13912 #endif
13913 #if defined(HAVE_SS7)
13914 } else if (p->sig == SIG_SS7) {
13915 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
13916 #endif /* defined(HAVE_SS7) */
13917 } else {
13918 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
13919 }
13920 if (!tmp) {
13921 p->outgoing = 0;
13922 #if defined(HAVE_PRI)
13923 switch (p->sig) {
13924 case SIG_PRI_LIB_HANDLE_CASES:
13925 #if defined(HAVE_PRI_CALL_WAITING)
13926 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13927 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13928 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13929 }
13930 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13931 /*
13932 * This should be the last thing to clear when we are done with
13933 * the channel.
13934 */
13935 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13936 break;
13937 default:
13938 break;
13939 }
13940 #endif /* defined(HAVE_PRI) */
13941 } else {
13942 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
13943 }
13944 break;
13945 }
13946 #ifdef HAVE_OPENR2
13947 next:
13948 #endif
13949 if (start.backwards) {
13950 p = p->prev;
13951 if (!p)
13952 p = ifend;
13953 } else {
13954 p = p->next;
13955 if (!p)
13956 p = iflist;
13957 }
13958 /* stop when you roll to the one that we started from */
13959 if (p == exitpvt)
13960 break;
13961 }
13962 ast_mutex_unlock(&iflock);
13963 restart_monitor();
13964 if (cause && !tmp) {
13965 if (callwait || (channelmatched && foundowner)) {
13966 *cause = AST_CAUSE_BUSY;
13967 } else if (groupmatched) {
13968 *cause = AST_CAUSE_CONGESTION;
13969 } else {
13970 /*
13971 * We did not match any channel requested.
13972 * Dialplan error requesting non-existant channel?
13973 */
13974 }
13975 }
13976
13977 ast_callid_threadstorage_auto_clean(callid, callid_created);
13978 return tmp;
13979 }
13980
13981 /*!
13982 * \internal
13983 * \brief Determine the device state for a given DAHDI device if we can.
13984 * \since 1.8
13985 *
13986 * \param data DAHDI device name after "DAHDI/".
13987 *
13988 * \retval device_state enum ast_device_state value.
13989 * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13990 */
13991 static int dahdi_devicestate(const char *data)
13992 {
13993 #if defined(HAVE_PRI)
13994 const char *device;
13995 unsigned span;
13996 int res;
13997
13998 device = data;
13999
14000 if (*device != 'I') {
14001 /* The request is not for an ISDN span device. */
14002 return AST_DEVICE_UNKNOWN;
14003 }
14004 res = sscanf(device, "I%30u", &span);
14005 if (res != 1 || !span || NUM_SPANS < span) {
14006 /* Bad format for ISDN span device name. */
14007 return AST_DEVICE_UNKNOWN;
14008 }
14009 device = strchr(device, '/');
14010 if (!device) {
14011 /* Bad format for ISDN span device name. */
14012 return AST_DEVICE_UNKNOWN;
14013 }
14014
14015 /*
14016 * Since there are currently no other span devstate's defined,
14017 * it must be congestion.
14018 */
14019 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14020 ++device;
14021 if (!strcmp(device, "congestion"))
14022 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14023 {
14024 return pris[span - 1].pri.congestion_devstate;
14025 }
14026 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14027 else if (!strcmp(device, "threshold")) {
14028 return pris[span - 1].pri.threshold_devstate;
14029 }
14030 return AST_DEVICE_UNKNOWN;
14031 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14032 #else
14033 return AST_DEVICE_UNKNOWN;
14034 #endif /* defined(HAVE_PRI) */
14035 }
14036
14037 /*!
14038 * \brief Callback made when dial failed to get a channel out of dahdi_request().
14039 * \since 1.8
14040 *
14041 * \param inbound Incoming asterisk channel.
14042 * \param dest Same dial string passed to dahdi_request().
14043 * \param callback Callback into CC core to announce a busy channel available for CC.
14044 *
14045 * \details
14046 * This callback acts like a forked dial with all prongs of the fork busy.
14047 * Essentially, for each channel that could have taken the call, indicate that
14048 * it is busy.
14049 *
14050 * \retval 0 on success.
14051 * \retval -1 on error.
14052 */
14053 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14054 {
14055 struct dahdi_pvt *p;
14056 struct dahdi_pvt *exitpvt;
14057 struct dahdi_starting_point start;
14058 int groupmatched = 0;
14059 int channelmatched = 0;
14060
14061 ast_mutex_lock(&iflock);
14062 p = determine_starting_point(dest, &start);
14063 if (!p) {
14064 ast_mutex_unlock(&iflock);
14065 return -1;
14066 }
14067 exitpvt = p;
14068 for (;;) {
14069 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14070 /* We found a potential match. call the callback */
14071 struct ast_str *device_name;
14072 char *dash;
14073 const char *monitor_type;
14074 char dialstring[AST_CHANNEL_NAME];
14075 char full_device_name[AST_CHANNEL_NAME];
14076
14077 switch (ast_get_cc_monitor_policy(p->cc_params)) {
14078 case AST_CC_MONITOR_NEVER:
14079 break;
14080 case AST_CC_MONITOR_NATIVE:
14081 case AST_CC_MONITOR_ALWAYS:
14082 case AST_CC_MONITOR_GENERIC:
14083 #if defined(HAVE_PRI)
14084 if (dahdi_sig_pri_lib_handles(p->sig)) {
14085 /*
14086 * ISDN is in a trunk busy condition so we need to monitor
14087 * the span congestion device state.
14088 */
14089 snprintf(full_device_name, sizeof(full_device_name),
14090 "DAHDI/I%d/congestion", p->pri->span);
14091 } else
14092 #endif /* defined(HAVE_PRI) */
14093 {
14094 #if defined(HAVE_PRI)
14095 device_name = create_channel_name(p, 1, "");
14096 #else
14097 device_name = create_channel_name(p);
14098 #endif /* defined(HAVE_PRI) */
14099 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14100 device_name ? ast_str_buffer(device_name) : "");
14101 ast_free(device_name);
14102 /*
14103 * The portion after the '-' in the channel name is either a random
14104 * number, a sequence number, or a subchannel number. None are
14105 * necessary so strip them off.
14106 */
14107 dash = strrchr(full_device_name, '-');
14108 if (dash) {
14109 *dash = '\0';
14110 }
14111 }
14112 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14113
14114 /*
14115 * Analog can only do generic monitoring.
14116 * ISDN is in a trunk busy condition and any "device" is going
14117 * to be busy until a B channel becomes available. The generic
14118 * monitor can do this task.
14119 */
14120 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14121 callback(inbound,
14122 #if defined(HAVE_PRI)
14123 p->pri ? p->pri->cc_params : p->cc_params,
14124 #else
14125 p->cc_params,
14126 #endif /* defined(HAVE_PRI) */
14127 monitor_type, full_device_name, dialstring, NULL);
14128 break;
14129 }
14130 }
14131 p = start.backwards ? p->prev : p->next;
14132 if (!p) {
14133 p = start.backwards ? ifend : iflist;
14134 }
14135 if (p == exitpvt) {
14136 break;
14137 }
14138 }
14139 ast_mutex_unlock(&iflock);
14140 return 0;
14141 }
14142
14143 #if defined(HAVE_SS7)
14144 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14145 {
14146 int i;
14147
14148 if (ss7) {
14149 for (i = 0; i < NUM_SPANS; i++) {
14150 if (linksets[i].ss7.ss7 == ss7) {
14151 ast_verbose_callid(0, "[%d] %s", i + 1, s);
14152 return;
14153 }
14154 }
14155 }
14156 ast_verbose_callid(0, "%s", s);
14157 }
14158 #endif /* defined(HAVE_SS7) */
14159
14160 #if defined(HAVE_SS7)
14161 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14162 {
14163 int i;
14164
14165 if (ss7) {
14166 for (i = 0; i < NUM_SPANS; i++) {
14167 if (linksets[i].ss7.ss7 == ss7) {
14168 ast_log_callid(LOG_ERROR, 0, "[%d] %s", i + 1, s);
14169 return;
14170 }
14171 }
14172 }
14173 ast_log_callid(LOG_ERROR, 0, "%s", s);
14174 }
14175 #endif /* defined(HAVE_SS7) */
14176
14177 #if defined(HAVE_OPENR2)
14178 static void *mfcr2_monitor(void *data)
14179 {
14180 struct dahdi_mfcr2 *mfcr2 = data;
14181 struct dahdi_pvt *pvt;
14182
14183 /* we should be using pthread_key_create
14184 and allocate pollers dynamically.
14185 I think do_monitor() could be leaking, since it
14186 could be cancelled at any time and is not
14187 using thread keys, why?, */
14188 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14189 int res = 0;
14190 int i = 0;
14191 int oldstate = 0;
14192 int quit_loop = 0;
14193 int maxsleep = 20;
14194 int was_idle = 0;
14195 int pollsize = 0;
14196 /* now that we're ready to get calls, unblock our side and
14197 get current line state */
14198 for (i = 0; i < mfcr2->numchans; i++) {
14199 pvt = mfcr2->pvts[i];
14200 if (!pvt) {
14201 continue;
14202 }
14203 openr2_chan_set_idle(pvt->r2chan);
14204 openr2_chan_handle_cas(pvt->r2chan);
14205 }
14206 while (1) {
14207 /* we trust here that the mfcr2 channel list will not ever change once
14208 the module is loaded */
14209 pollsize = 0;
14210 for (i = 0; i < mfcr2->numchans; i++) {
14211 pollers[i].revents = 0;
14212 pollers[i].events = 0;
14213 pvt = mfcr2->pvts[i];
14214 if (!pvt) {
14215 continue;
14216 }
14217 if (pvt->owner) {
14218 continue;
14219 }
14220 if (mfcr2->nodev) {
14221 continue;
14222 }
14223 if (!pvt->r2chan) {
14224 ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);
14225 quit_loop = 1;
14226 break;
14227 }
14228 openr2_chan_enable_read(pvt->r2chan);
14229 pollers[i].events = POLLIN | POLLPRI;
14230 pollers[i].fd = pvt->subs[SUB_REAL].dfd;
14231 pollsize++;
14232 }
14233 if (quit_loop) {
14234 break;
14235 }
14236 if (pollsize == 0) {
14237 if (!was_idle) {
14238 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14239 was_idle = 1;
14240 }
14241 poll(NULL, 0, maxsleep);
14242 continue;
14243 }
14244 was_idle = 0;
14245 /* probably poll() is a valid cancel point, lets just be on the safe side
14246 by calling pthread_testcancel */
14247 pthread_testcancel();
14248 res = poll(pollers, mfcr2->numchans, maxsleep);
14249 pthread_testcancel();
14250 if ((res < 0) && (errno != EINTR)) {
14251 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14252 break;
14253 }
14254 /* do we want to allow to cancel while processing events? */
14255 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14256 for (i = 0; i < mfcr2->numchans; i++) {
14257 pvt = mfcr2->pvts[i];
14258 if (!pvt) {
14259 continue;
14260 }
14261 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14262 openr2_chan_process_event(pvt->r2chan);
14263 }
14264 }
14265 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14266 }
14267 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14268 return 0;
14269 }
14270 #endif /* HAVE_OPENR2 */
14271
14272 #if defined(HAVE_PRI)
14273 static void dahdi_pri_message(struct pri *pri, char *s)
14274 {
14275 int x;
14276 int y;
14277 int dchan = -1;
14278 int span = -1;
14279 int dchancount = 0;
14280
14281 if (pri) {
14282 for (x = 0; x < NUM_SPANS; x++) {
14283 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14284 if (pris[x].pri.dchans[y]) {
14285 dchancount++;
14286 }
14287
14288 if (pris[x].pri.dchans[y] == pri) {
14289 dchan = y;
14290 }
14291 }
14292 if (dchan >= 0) {
14293 span = x;
14294 break;
14295 }
14296 dchancount = 0;
14297 }
14298 if (-1 < span) {
14299 if (1 < dchancount) {
14300 ast_verbose_callid(0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14301 } else {
14302 ast_verbose_callid(0, "PRI Span: %d %s", span + 1, s);
14303 }
14304 } else {
14305 ast_verbose_callid(0, "PRI Span: ? %s", s);
14306 }
14307 } else {
14308 ast_verbose_callid(0, "PRI Span: ? %s", s);
14309 }
14310
14311 ast_mutex_lock(&pridebugfdlock);
14312
14313 if (pridebugfd >= 0) {
14314 if (write(pridebugfd, s, strlen(s)) < 0) {
14315 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14316 }
14317 }
14318
14319 ast_mutex_unlock(&pridebugfdlock);
14320 }
14321 #endif /* defined(HAVE_PRI) */
14322
14323 #if defined(HAVE_PRI)
14324 static void dahdi_pri_error(struct pri *pri, char *s)
14325 {
14326 int x;
14327 int y;
14328 int dchan = -1;
14329 int span = -1;
14330 int dchancount = 0;
14331
14332 if (pri) {
14333 for (x = 0; x < NUM_SPANS; x++) {
14334 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14335 if (pris[x].pri.dchans[y]) {
14336 dchancount++;
14337 }
14338
14339 if (pris[x].pri.dchans[y] == pri) {
14340 dchan = y;
14341 }
14342 }
14343 if (dchan >= 0) {
14344 span = x;
14345 break;
14346 }
14347 dchancount = 0;
14348 }
14349 if (-1 < span) {
14350 if (1 < dchancount) {
14351 ast_log_callid(LOG_ERROR, 0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14352 } else {
14353 ast_log_callid(LOG_ERROR, 0, "PRI Span: %d %s", span + 1, s);
14354 }
14355 } else {
14356 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14357 }
14358 } else {
14359 ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14360 }
14361
14362 ast_mutex_lock(&pridebugfdlock);
14363
14364 if (pridebugfd >= 0) {
14365 if (write(pridebugfd, s, strlen(s)) < 0) {
14366 ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14367 }
14368 }
14369
14370 ast_mutex_unlock(&pridebugfdlock);
14371 }
14372 #endif /* defined(HAVE_PRI) */
14373
14374 #if defined(HAVE_PRI)
14375 static int prepare_pri(struct dahdi_pri *pri)
14376 {
14377 int i, res, x;
14378 struct dahdi_params p;
14379 struct dahdi_bufferinfo bi;
14380 struct dahdi_spaninfo si;
14381
14382 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14383 if (!pri->dchannels[i])
14384 break;
14385 if (pri->pri.fds[i] >= 0) {
14386 /* A partial range addition. Not a complete setup. */
14387 break;
14388 }
14389 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14390 if ((pri->pri.fds[i] < 0)) {
14391 ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
14392 pri->pri.fds[i], strerror(errno));
14393 return -1;
14394 }
14395 x = pri->dchannels[i];
14396 res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
14397 if (res) {
14398 dahdi_close_pri_fd(pri, i);
14399 ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14400 return -1;
14401 }
14402 memset(&p, 0, sizeof(p));
14403 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14404 if (res) {
14405 dahdi_close_pri_fd(pri, i);
14406 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14407 return -1;
14408 }
14409 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14410 dahdi_close_pri_fd(pri, i);
14411 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14412 return -1;
14413 }
14414 memset(&si, 0, sizeof(si));
14415 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14416 if (res) {
14417 dahdi_close_pri_fd(pri, i);
14418 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14419 }
14420 if (!si.alarms) {
14421 pri_event_noalarm(&pri->pri, i, 1);
14422 } else {
14423 pri_event_alarm(&pri->pri, i, 1);
14424 }
14425 memset(&bi, 0, sizeof(bi));
14426 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14427 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14428 bi.numbufs = 32;
14429 bi.bufsize = 1024;
14430 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14431 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14432 dahdi_close_pri_fd(pri, i);
14433 return -1;
14434 }
14435 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14436 }
14437 return 0;
14438 }
14439 #endif /* defined(HAVE_PRI) */
14440
14441 #if defined(HAVE_PRI)
14442 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14443 {
14444 int which, span;
14445 char *ret = NULL;
14446
14447 if (pos != rpos)
14448 return ret;
14449
14450 for (which = span = 0; span < NUM_SPANS; span++) {
14451 if (pris[span].pri.pri && ++which > state) {
14452 if (ast_asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14453 ret = NULL;
14454 }
14455 break;
14456 }
14457 }
14458 return ret;
14459 }
14460 #endif /* defined(HAVE_PRI) */
14461
14462 #if defined(HAVE_PRI)
14463 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14464 {
14465 return complete_span_helper(line,word,pos,state,3);
14466 }
14467 #endif /* defined(HAVE_PRI) */
14468
14469 #if defined(HAVE_PRI)
14470 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14471 {
14472 int myfd;
14473 switch (cmd) {
14474 case CLI_INIT:
14475 e->command = "pri set debug file";
14476 e->usage = "Usage: pri set debug file [output-file]\n"
14477 " Sends PRI debug output to the specified output file\n";
14478 return NULL;
14479 case CLI_GENERATE:
14480 return NULL;
14481 }
14482 if (a->argc < 5)
14483 return CLI_SHOWUSAGE;
14484
14485 if (ast_strlen_zero(a->argv[4]))
14486 return CLI_SHOWUSAGE;
14487
14488 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14489 if (myfd < 0) {
14490 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14491 return CLI_SUCCESS;
14492 }
14493
14494 ast_mutex_lock(&pridebugfdlock);
14495
14496 if (pridebugfd >= 0)
14497 close(pridebugfd);
14498
14499 pridebugfd = myfd;
14500 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14501 ast_mutex_unlock(&pridebugfdlock);
14502 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14503 return CLI_SUCCESS;
14504 }
14505 #endif /* defined(HAVE_PRI) */
14506
14507 #if defined(HAVE_PRI)
14508 static int action_pri_debug_file_set(struct mansession *s, const struct message *m)
14509 {
14510 const char *output_file = astman_get_header(m, "File");
14511 int myfd;
14512
14513 if (ast_strlen_zero(output_file)) {
14514 astman_send_error(s, m, "Action must define a 'File'");
14515 }
14516
14517 myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14518 if (myfd < 0) {
14519 astman_send_error(s, m, "Unable to open requested file for writing");
14520 return 0;
14521 }
14522
14523 ast_mutex_lock(&pridebugfdlock);
14524
14525 if (pridebugfd >= 0) {
14526 close(pridebugfd);
14527 }
14528
14529 pridebugfd = myfd;
14530 ast_copy_string(pridebugfilename, output_file, sizeof(pridebugfilename));
14531 ast_mutex_unlock(&pridebugfdlock);
14532 astman_send_ack(s, m, "PRI debug output will now be sent to requested file.");
14533
14534 return 0;
14535 }
14536 #endif /* defined(HAVE_PRI) */
14537
14538 #if defined(HAVE_PRI)
14539 static int action_pri_debug_file_unset(struct mansession *s, const struct message *m)
14540 {
14541 ast_mutex_lock(&pridebugfdlock);
14542
14543 if (pridebugfd >= 0) {
14544 close(pridebugfd);
14545 }
14546
14547 pridebugfd = -1;
14548
14549 ast_mutex_unlock(&pridebugfdlock);
14550
14551 astman_send_ack(s, m, "PRI Debug output to file disabled");
14552 return 0;
14553 }
14554 #endif /* defined(HAVE_PRI) */
14555
14556 #if defined(HAVE_PRI)
14557 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14558 {
14559 int span;
14560 int x;
14561 int debugmask = 0;
14562 int level = 0;
14563 switch (cmd) {
14564 case CLI_INIT:
14565 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";
14566 e->usage =
14567 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14568 " Enables debugging on a given PRI span\n"
14569 " Level is a bitmap of the following values:\n"
14570 " 1 General debugging incl. state changes\n"
14571 " 2 Decoded Q.931 messages\n"
14572 " 4 Decoded Q.921 messages\n"
14573 " 8 Raw hex dumps of Q.921 frames\n"
14574 " on - equivalent to 3\n"
14575 " hex - equivalent to 8\n"
14576 " intense - equivalent to 15\n";
14577 return NULL;
14578 case CLI_GENERATE:
14579 return complete_span_4(a->line, a->word, a->pos, a->n);
14580 }
14581 if (a->argc < 6) {
14582 return CLI_SHOWUSAGE;
14583 }
14584
14585 if (!strcasecmp(a->argv[3], "on")) {
14586 level = 3;
14587 } else if (!strcasecmp(a->argv[3], "off")) {
14588 level = 0;
14589 } else if (!strcasecmp(a->argv[3], "intense")) {
14590 level = 15;
14591 } else if (!strcasecmp(a->argv[3], "hex")) {
14592 level = 8;
14593 } else {
14594 level = atoi(a->argv[3]);
14595 }
14596 span = atoi(a->argv[5]);
14597 if ((span < 1) || (span > NUM_SPANS)) {
14598 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14599 return CLI_SUCCESS;
14600 }
14601 if (!pris[span-1].pri.pri) {
14602 ast_cli(a->fd, "No PRI running on span %d\n", span);
14603 return CLI_SUCCESS;
14604 }
14605
14606 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14607 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14608 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14609 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14610
14611 /* Set debug level in libpri */
14612 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14613 if (pris[span - 1].pri.dchans[x]) {
14614 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14615 }
14616 }
14617 if (level == 0) {
14618 /* Close the debugging file if it's set */
14619 ast_mutex_lock(&pridebugfdlock);
14620 if (0 <= pridebugfd) {
14621 close(pridebugfd);
14622 pridebugfd = -1;
14623 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14624 pridebugfilename);
14625 }
14626 ast_mutex_unlock(&pridebugfdlock);
14627 }
14628 pris[span - 1].pri.debug = (level) ? 1 : 0;
14629 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14630 return CLI_SUCCESS;
14631 }
14632 #endif /* defined(HAVE_PRI) */
14633
14634 #if defined(HAVE_PRI)
14635 static int action_pri_debug_set(struct mansession *s, const struct message *m)
14636 {
14637 const char *level = astman_get_header(m, "Level");
14638 const char *span = astman_get_header(m, "Span");
14639 int level_val;
14640 int span_val;
14641 int x;
14642 int debugmask = 0;
14643
14644 if (ast_strlen_zero(level)) {
14645 astman_send_error(s, m, "'Level' was not specified");
14646 return 0;
14647 }
14648
14649 if (ast_strlen_zero(span)) {
14650 astman_send_error(s, m, "'Span' was not specified");
14651 return 0;
14652 }
14653
14654 if (!strcasecmp(level, "on")) {
14655 level_val = 3;
14656 } else if (!strcasecmp(level, "off")) {
14657 level_val = 0;
14658 } else if (!strcasecmp(level, "intense")) {
14659 level_val = 15;
14660 } else if (!strcasecmp(level, "hex")) {
14661 level_val = 8;
14662 } else {
14663 if (sscanf(level, "%30d", &level_val) != 1) {
14664 astman_send_error(s, m, "Invalid value for 'Level'");
14665 return 0;
14666 }
14667 }
14668
14669 if (sscanf(span, "%30d", &span_val) != 1) {
14670 astman_send_error(s, m, "Invalid value for 'Span'");
14671 }
14672
14673 if ((span_val < 1) || (span_val > NUM_SPANS)) {
14674 const char *id = astman_get_header(m, "ActionID");
14675 char id_text[256] = "";
14676
14677 if (!ast_strlen_zero(id)) {
14678 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
14679 }
14680
14681 astman_append(s, "Response: Error\r\n"
14682 "%s" /* id_text */
14683 "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14684 "\r\n",
14685 id_text,
14686 span, NUM_SPANS);
14687
14688 return 0;
14689 }
14690
14691 if (!pris[span_val-1].pri.pri) {
14692 astman_send_error(s, m, "No PRI running on requested span");
14693 return 0;
14694 }
14695
14696 if (level_val & 1) {
14697 debugmask |= SIG_PRI_DEBUG_NORMAL;
14698 }
14699 if (level_val & 2) {
14700 debugmask |= PRI_DEBUG_Q931_DUMP;
14701 }
14702 if (level_val & 4) {
14703 debugmask |= PRI_DEBUG_Q921_DUMP;
14704 }
14705 if (level_val & 8) {
14706 debugmask |= PRI_DEBUG_Q921_RAW;
14707 }
14708
14709 /* Set debug level in libpri */
14710 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14711 if (pris[span_val - 1].pri.dchans[x]) {
14712 pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14713 }
14714 }
14715
14716 pris[span_val - 1].pri.debug = (level_val) ? 1 : 0;
14717 astman_send_ack(s, m, "Debug level set for requested span");
14718
14719 return 0;
14720 }
14721 #endif /* defined(HAVE_PRI) */
14722
14723 #if defined(HAVE_PRI)
14724 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14725 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14726 {
14727 unsigned *why;
14728 int channel;
14729 int trunkgroup;
14730 int x, y, fd = a->fd;
14731 int interfaceid = 0;
14732 char db_chan_name[20], db_answer[15];
14733 struct dahdi_pvt *tmp;
14734 struct dahdi_pri *pri;
14735
14736 if (a->argc < 5 || a->argc > 6)
14737 return CLI_SHOWUSAGE;
14738 if (strchr(a->argv[4], ':')) {
14739 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14740 return CLI_SHOWUSAGE;
14741 if ((trunkgroup < 1) || (channel < 1))
14742 return CLI_SHOWUSAGE;
14743 pri = NULL;
14744 for (x=0;x<NUM_SPANS;x++) {
14745 if (pris[x].pri.trunkgroup == trunkgroup) {
14746 pri = pris + x;
14747 break;
14748 }
14749 }
14750 if (!pri) {
14751 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14752 return CLI_FAILURE;
14753 }
14754 } else
14755 channel = atoi(a->argv[4]);
14756
14757 if (a->argc == 6)
14758 interfaceid = atoi(a->argv[5]);
14759
14760 /* either servicing a D-Channel */
14761 for (x = 0; x < NUM_SPANS; x++) {
14762 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14763 if (pris[x].dchannels[y] == channel) {
14764 pri = pris + x;
14765 if (pri->pri.enable_service_message_support) {
14766 ast_mutex_lock(&pri->pri.lock);
14767 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14768 ast_mutex_unlock(&pri->pri.lock);
14769 } else {
14770 ast_cli(fd,
14771 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14772 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14773 }
14774 return CLI_SUCCESS;
14775 }
14776 }
14777 }
14778
14779 /* or servicing a B-Channel */
14780 ast_mutex_lock(&iflock);
14781 for (tmp = iflist; tmp; tmp = tmp->next) {
14782 if (tmp->pri && tmp->channel == channel) {
14783 ast_mutex_unlock(&iflock);
14784 ast_mutex_lock(&tmp->pri->lock);
14785 if (!tmp->pri->enable_service_message_support) {
14786 ast_mutex_unlock(&tmp->pri->lock);
14787 ast_cli(fd,
14788 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14789 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14790 return CLI_SUCCESS;
14791 }
14792 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14793 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14794 switch(changestatus) {
14795 case 0: /* enable */
14796 /* Near end wants to be in service now. */
14797 ast_db_del(db_chan_name, SRVST_DBKEY);
14798 *why &= ~SRVST_NEAREND;
14799 if (*why) {
14800 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14801 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14802 } else {
14803 dahdi_pri_update_span_devstate(tmp->pri);
14804 }
14805 break;
14806 /* case 1: -- loop */
14807 case 2: /* disable */
14808 /* Near end wants to be out-of-service now. */
14809 ast_db_del(db_chan_name, SRVST_DBKEY);
14810 *why |= SRVST_NEAREND;
14811 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14812 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14813 dahdi_pri_update_span_devstate(tmp->pri);
14814 break;
14815 /* case 3: -- continuity */
14816 /* case 4: -- shutdown */
14817 default:
14818 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14819 break;
14820 }
14821 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14822 ast_mutex_unlock(&tmp->pri->lock);
14823 return CLI_SUCCESS;
14824 }
14825 }
14826 ast_mutex_unlock(&iflock);
14827
14828 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14829 return CLI_FAILURE;
14830 }
14831
14832 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14833 {
14834 switch (cmd) {
14835 case CLI_INIT:
14836 e->command = "pri service enable channel";
14837 e->usage =
14838 "Usage: pri service enable channel <channel> [<interface id>]\n"
14839 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14840 " to restore a channel to service, with optional interface id\n"
14841 " as agreed upon with remote switch operator\n";
14842 return NULL;
14843 case CLI_GENERATE:
14844 return NULL;
14845 }
14846 return handle_pri_service_generic(e, cmd, a, 0);
14847 }
14848
14849 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14850 {
14851 switch (cmd) {
14852 case CLI_INIT:
14853 e->command = "pri service disable channel";
14854 e->usage =
14855 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14856 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14857 " to remove a channel from service, with optional interface id\n"
14858 " as agreed upon with remote switch operator\n";
14859 return NULL;
14860 case CLI_GENERATE:
14861 return NULL;
14862 }
14863 return handle_pri_service_generic(e, cmd, a, 2);
14864 }
14865 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14866 #endif /* defined(HAVE_PRI) */
14867
14868 #if defined(HAVE_PRI)
14869 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14870 {
14871 int span;
14872
14873 switch (cmd) {
14874 case CLI_INIT:
14875 e->command = "pri show channels";
14876 e->usage =
14877 "Usage: pri show channels\n"
14878 " Displays PRI channel information such as the current mapping\n"
14879 " of DAHDI B channels to Asterisk channel names and which calls\n"
14880 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14881 " are not associated with any B channel.\n";
14882 return NULL;
14883 case CLI_GENERATE:
14884 return NULL;
14885 }
14886
14887 if (a->argc != 3)
14888 return CLI_SHOWUSAGE;
14889
14890 sig_pri_cli_show_channels_header(a->fd);
14891 for (span = 0; span < NUM_SPANS; ++span) {
14892 if (pris[span].pri.pri) {
14893 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14894 }
14895 }
14896 return CLI_SUCCESS;
14897 }
14898 #endif /* defined(HAVE_PRI) */
14899
14900 #if defined(HAVE_PRI)
14901 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14902 {
14903 int span;
14904
14905 switch (cmd) {
14906 case CLI_INIT:
14907 e->command = "pri show spans";
14908 e->usage =
14909 "Usage: pri show spans\n"
14910 " Displays PRI span information\n";
14911 return NULL;
14912 case CLI_GENERATE:
14913 return NULL;
14914 }
14915
14916 if (a->argc != 3)
14917 return CLI_SHOWUSAGE;
14918
14919 for (span = 0; span < NUM_SPANS; span++) {
14920 if (pris[span].pri.pri) {
14921 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14922 }
14923 }
14924 return CLI_SUCCESS;
14925 }
14926 #endif /* defined(HAVE_PRI) */
14927
14928 #if defined(HAVE_PRI)
14929 #define container_of(ptr, type, member) \
14930 ((type *)((char *)(ptr) - offsetof(type, member)))
14931 /*!
14932 * \internal
14933 * \brief Destroy a D-Channel of a PRI span
14934 * \since 12
14935 *
14936 * \param pri the pri span
14937 *
14938 * Shuts down a span and destroys its D-Channel. Further destruction
14939 * of the B-channels using dahdi_destroy_channel() would probably be required
14940 * for the B-Channels.
14941 */
14942 static void pri_destroy_span(struct sig_pri_span *pri)
14943 {
14944 int i;
14945 int res;
14946 int cancel_code;
14947 struct dahdi_pri* dahdi_pri;
14948 pthread_t master = pri->master;
14949
14950 if (!master || (master == AST_PTHREADT_NULL)) {
14951 return;
14952 }
14953 ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
14954 for (i = 0; i < pri->numchans; i++) {
14955 int channel;
14956 struct sig_pri_chan *pvt = pri->pvts[i];
14957
14958 if (!pvt) {
14959 continue;
14960 }
14961 channel = pvt->channel;
14962 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14963 dahdi_destroy_channel_range(channel, channel);
14964 }
14965
14966 cancel_code = pthread_cancel(master);
14967 pthread_kill(master, SIGURG);
14968 ast_debug(4,
14969 "Waiting to join thread of span %d "
14970 "with pid=%p cancel_code=%d\n",
14971 pri->span, (void *)master, cancel_code);
14972 res = pthread_join(master, NULL);
14973 if (res != 0) {
14974 ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
14975 }
14976 pri->master = AST_PTHREADT_NULL;
14977
14978 /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14979 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14980 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14981 ast_debug(4, "closing pri_fd %d\n", i);
14982 dahdi_close_pri_fd(dahdi_pri, i);
14983 dahdi_pri->dchannels[i] = 0;
14984 }
14985 sig_pri_init_pri(pri);
14986 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14987 }
14988
14989 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14990 struct ast_cli_args *a)
14991 {
14992 int span;
14993 int res;
14994 struct sig_pri_span *pri;
14995
14996 switch (cmd) {
14997 case CLI_INIT:
14998 e->command = "pri destroy span";
14999 e->usage =
15000 "Usage: pri destroy span <span>\n"
15001 " Destorys D-channel of span and its B-channels.\n"
15002 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15003 return NULL;
15004 case CLI_GENERATE:
15005 return complete_span_4(a->line, a->word, a->pos, a->n);
15006 }
15007
15008 if (a->argc < 4) {
15009 return CLI_SHOWUSAGE;
15010 }
15011 res = sscanf(a->argv[3], "%30d", &span);
15012 if ((res != 1) || span < 1 || span > NUM_SPANS) {
15013 ast_cli(a->fd,
15014 "Invalid span '%s'. Should be a number from %d to %d\n",
15015 a->argv[3], 1, NUM_SPANS);
15016 return CLI_SUCCESS;
15017 }
15018 pri = &pris[span - 1].pri;
15019 if (!pri->pri) {
15020 ast_cli(a->fd, "No PRI running on span %d\n", span);
15021 return CLI_SUCCESS;
15022 }
15023
15024 pri_destroy_span(pri);
15025 return CLI_SUCCESS;
15026 }
15027
15028 #endif /* defined(HAVE_PRI) */
15029
15030 #if defined(HAVE_PRI)
15031 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15032 {
15033 int span;
15034
15035 switch (cmd) {
15036 case CLI_INIT:
15037 e->command = "pri show span";
15038 e->usage =
15039 "Usage: pri show span <span>\n"
15040 " Displays PRI Information on a given PRI span\n";
15041 return NULL;
15042 case CLI_GENERATE:
15043 return complete_span_4(a->line, a->word, a->pos, a->n);
15044 }
15045
15046 if (a->argc < 4)
15047 return CLI_SHOWUSAGE;
15048 span = atoi(a->argv[3]);
15049 if ((span < 1) || (span > NUM_SPANS)) {
15050 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15051 return CLI_SUCCESS;
15052 }
15053 if (!pris[span-1].pri.pri) {
15054 ast_cli(a->fd, "No PRI running on span %d\n", span);
15055 return CLI_SUCCESS;
15056 }
15057
15058 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15059
15060 return CLI_SUCCESS;
15061 }
15062 #endif /* defined(HAVE_PRI) */
15063
15064 #if defined(HAVE_PRI)
15065 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15066 {
15067 int x;
15068 int span;
15069 int count=0;
15070 int debug;
15071
15072 switch (cmd) {
15073 case CLI_INIT:
15074 e->command = "pri show debug";
15075 e->usage =
15076 "Usage: pri show debug\n"
15077 " Show the debug state of pri spans\n";
15078 return NULL;
15079 case CLI_GENERATE:
15080 return NULL;
15081 }
15082
15083 for (span = 0; span < NUM_SPANS; span++) {
15084 if (pris[span].pri.pri) {
15085 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15086 if (pris[span].pri.dchans[x]) {
15087 debug = pri_get_debug(pris[span].pri.dchans[x]);
15088 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" );
15089 count++;
15090 }
15091 }
15092 }
15093
15094 }
15095 ast_mutex_lock(&pridebugfdlock);
15096 if (pridebugfd >= 0)
15097 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15098 ast_mutex_unlock(&pridebugfdlock);
15099
15100 if (!count)
15101 ast_cli(a->fd, "No PRI running\n");
15102 return CLI_SUCCESS;
15103 }
15104 #endif /* defined(HAVE_PRI) */
15105
15106 #if defined(HAVE_PRI)
15107 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15108 {
15109 switch (cmd) {
15110 case CLI_INIT:
15111 e->command = "pri show version";
15112 e->usage =
15113 "Usage: pri show version\n"
15114 "Show libpri version information\n";
15115 return NULL;
15116 case CLI_GENERATE:
15117 return NULL;
15118 }
15119
15120 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15121
15122 return CLI_SUCCESS;
15123 }
15124 #endif /* defined(HAVE_PRI) */
15125
15126 #if defined(HAVE_PRI)
15127 static struct ast_cli_entry dahdi_pri_cli[] = {
15128 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15129 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15130 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15131 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15132 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15133 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15134 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15135 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15136 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15137 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15138 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15139 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15140 };
15141 #endif /* defined(HAVE_PRI) */
15142
15143 #ifdef HAVE_OPENR2
15144
15145 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15146 {
15147 switch (cmd) {
15148 case CLI_INIT:
15149 e->command = "mfcr2 show version";
15150 e->usage =
15151 "Usage: mfcr2 show version\n"
15152 " Shows the version of the OpenR2 library being used.\n";
15153 return NULL;
15154 case CLI_GENERATE:
15155 return NULL;
15156 }
15157 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15158 return CLI_SUCCESS;
15159 }
15160
15161 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15162 {
15163 #define FORMAT "%4s %40s\n"
15164 int i = 0;
15165 int numvariants = 0;
15166 const openr2_variant_entry_t *variants;
15167 switch (cmd) {
15168 case CLI_INIT:
15169 e->command = "mfcr2 show variants";
15170 e->usage =
15171 "Usage: mfcr2 show variants\n"
15172 " Shows the list of MFC/R2 variants supported.\n";
15173 return NULL;
15174 case CLI_GENERATE:
15175 return NULL;
15176 }
15177 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15178 ast_cli(a->fd, "Failed to get list of variants.\n");
15179 return CLI_FAILURE;
15180 }
15181 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15182 for (i = 0; i < numvariants; i++) {
15183 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15184 }
15185 return CLI_SUCCESS;
15186 #undef FORMAT
15187 }
15188
15189 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15190 {
15191 #define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15192 int filtertype = 0;
15193 int targetnum = 0;
15194 char channo[5];
15195 char linkno[5];
15196 char anino[5];
15197 char dnisno[5];
15198 struct dahdi_pvt *p;
15199 openr2_context_t *r2context;
15200 openr2_variant_t r2variant;
15201 switch (cmd) {
15202 case CLI_INIT:
15203 e->command = "mfcr2 show channels [group|context]";
15204 e->usage =
15205 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15206 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15207 return NULL;
15208 case CLI_GENERATE:
15209 return NULL;
15210 }
15211 if (!((a->argc == 3) || (a->argc == 5))) {
15212 return CLI_SHOWUSAGE;
15213 }
15214 if (a->argc == 5) {
15215 if (!strcasecmp(a->argv[3], "group")) {
15216 targetnum = atoi(a->argv[4]);
15217 if ((targetnum < 0) || (targetnum > 63))
15218 return CLI_SHOWUSAGE;
15219 targetnum = 1 << targetnum;
15220 filtertype = 1;
15221 } else if (!strcasecmp(a->argv[3], "context")) {
15222 filtertype = 2;
15223 } else {
15224 return CLI_SHOWUSAGE;
15225 }
15226 }
15227 ast_cli(a->fd, FORMAT, "Chan", "Link#", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15228 ast_mutex_lock(&iflock);
15229 for (p = iflist; p; p = p->next) {
15230 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15231 continue;
15232 }
15233 if (filtertype) {
15234 switch(filtertype) {
15235 case 1: /* mfcr2 show channels group <group> */
15236 if (p->group != targetnum) {
15237 continue;
15238 }
15239 break;
15240 case 2: /* mfcr2 show channels context <context> */
15241 if (strcasecmp(p->context, a->argv[4])) {
15242 continue;
15243 }
15244 break;
15245 default:
15246 ;
15247 }
15248 }
15249 r2context = openr2_chan_get_context(p->r2chan);
15250 r2variant = openr2_context_get_variant(r2context);
15251 snprintf(channo, sizeof(channo), "%d", p->channel);
15252 snprintf(linkno, sizeof(linkno), "%d", p->mfcr2->index);
15253 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15254 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15255 ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
15256 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15257 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15258 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15259 }
15260 ast_mutex_unlock(&iflock);
15261 return CLI_SUCCESS;
15262 #undef FORMAT
15263 }
15264
15265 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15266 {
15267 struct dahdi_pvt *p = NULL;
15268 int channo = 0;
15269 char *toklevel = NULL;
15270 char *saveptr = NULL;
15271 char *logval = NULL;
15272 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15273 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15274 switch (cmd) {
15275 case CLI_INIT:
15276 e->command = "mfcr2 set debug";
15277 e->usage =
15278 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15279 " Set a new logging level for the specified channel.\n"
15280 " If no channel is specified the logging level will be applied to all channels.\n";
15281 return NULL;
15282 case CLI_GENERATE:
15283 return NULL;
15284 }
15285 if (a->argc < 4) {
15286 return CLI_SHOWUSAGE;
15287 }
15288 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15289 logval = ast_strdupa(a->argv[3]);
15290 toklevel = strtok_r(logval, ",", &saveptr);
15291 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15292 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15293 return CLI_FAILURE;
15294 } else if (OR2_LOG_NOTHING == tmplevel) {
15295 loglevel = tmplevel;
15296 } else {
15297 loglevel |= tmplevel;
15298 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15299 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15300 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15301 continue;
15302 }
15303 loglevel |= tmplevel;
15304 }
15305 }
15306 ast_mutex_lock(&iflock);
15307 for (p = iflist; p; p = p->next) {
15308 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15309 continue;
15310 }
15311 if ((channo != -1) && (p->channel != channo )) {
15312 continue;
15313 }
15314 openr2_chan_set_log_level(p->r2chan, loglevel);
15315 if (channo != -1) {
15316 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15317 break;
15318 }
15319 }
15320 if ((channo != -1) && !p) {
15321 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15322 }
15323 if (channo == -1) {
15324 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15325 }
15326 ast_mutex_unlock(&iflock);
15327 return CLI_SUCCESS;
15328 }
15329
15330 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15331 {
15332 struct dahdi_pvt *p = NULL;
15333 int channo = 0;
15334 switch (cmd) {
15335 case CLI_INIT:
15336 e->command = "mfcr2 call files [on|off]";
15337 e->usage =
15338 "Usage: mfcr2 call files [on|off] <channel>\n"
15339 " Enable call files creation on the specified channel.\n"
15340 " If no channel is specified call files creation policy will be applied to all channels.\n";
15341 return NULL;
15342 case CLI_GENERATE:
15343 return NULL;
15344 }
15345 if (a->argc < 4) {
15346 return CLI_SHOWUSAGE;
15347 }
15348 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15349 ast_mutex_lock(&iflock);
15350 for (p = iflist; p; p = p->next) {
15351 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15352 continue;
15353 }
15354 if ((channo != -1) && (p->channel != channo )) {
15355 continue;
15356 }
15357 if (ast_true(a->argv[3])) {
15358 openr2_chan_enable_call_files(p->r2chan);
15359 } else {
15360 openr2_chan_disable_call_files(p->r2chan);
15361 }
15362 if (channo != -1) {
15363 if (ast_true(a->argv[3])) {
15364 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15365 } else {
15366 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15367 }
15368 break;
15369 }
15370 }
15371 if ((channo != -1) && !p) {
15372 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15373 }
15374 if (channo == -1) {
15375 if (ast_true(a->argv[3])) {
15376 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15377 } else {
15378 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15379 }
15380 }
15381 ast_mutex_unlock(&iflock);
15382 return CLI_SUCCESS;
15383 }
15384
15385 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15386 {
15387 struct dahdi_pvt *p = NULL;
15388 int channo = 0;
15389 switch (cmd) {
15390 case CLI_INIT:
15391 e->command = "mfcr2 set idle";
15392 e->usage =
15393 "Usage: mfcr2 set idle <channel>\n"
15394 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15395 " Force the given channel into IDLE state.\n"
15396 " If no channel is specified, all channels will be set to IDLE.\n";
15397 return NULL;
15398 case CLI_GENERATE:
15399 return NULL;
15400 }
15401 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15402 ast_mutex_lock(&iflock);
15403 for (p = iflist; p; p = p->next) {
15404 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15405 continue;
15406 }
15407 if ((channo != -1) && (p->channel != channo )) {
15408 continue;
15409 }
15410 openr2_chan_set_idle(p->r2chan);
15411 ast_mutex_lock(&p->lock);
15412 p->locallyblocked = 0;
15413 p->mfcr2call = 0;
15414 ast_mutex_unlock(&p->lock);
15415 if (channo != -1) {
15416 break;
15417 }
15418 }
15419 if ((channo != -1) && !p) {
15420 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15421 }
15422 ast_mutex_unlock(&iflock);
15423 return CLI_SUCCESS;
15424 }
15425
15426 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15427 {
15428 struct dahdi_pvt *p = NULL;
15429 int channo = 0;
15430 switch (cmd) {
15431 case CLI_INIT:
15432 e->command = "mfcr2 set blocked";
15433 e->usage =
15434 "Usage: mfcr2 set blocked <channel>\n"
15435 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15436 " Force the given channel into BLOCKED state.\n"
15437 " If no channel is specified, all channels will be set to BLOCKED.\n";
15438 return NULL;
15439 case CLI_GENERATE:
15440 return NULL;
15441 }
15442 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15443 ast_mutex_lock(&iflock);
15444 for (p = iflist; p; p = p->next) {
15445 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15446 continue;
15447 }
15448 if ((channo != -1) && (p->channel != channo )) {
15449 continue;
15450 }
15451 openr2_chan_set_blocked(p->r2chan);
15452 ast_mutex_lock(&p->lock);
15453 p->locallyblocked = 1;
15454 ast_mutex_unlock(&p->lock);
15455 if (channo != -1) {
15456 break;
15457 }
15458 }
15459 if ((channo != -1) && !p) {
15460 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15461 }
15462 ast_mutex_unlock(&iflock);
15463 return CLI_SUCCESS;
15464 }
15465
15466 static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_head, const char *title)
15467 {
15468 #define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15469 AST_LIST_LOCK(list_head);
15470 if (! AST_LIST_EMPTY(list_head)) {
15471 int x = 0;
15472 char index[5];
15473 char live_chans_str[5];
15474 char channel_list[R2_LINK_CAPACITY * 4];
15475 struct r2link_entry *cur;
15476 ast_cli(a->fd, "%s\n", title);
15477 ast_cli(a->fd, FORMAT, "Index", "Thread", "Dahdi-Device", "Channels", "Channel-List");
15478 AST_LIST_TRAVERSE(list_head, cur, list) {
15479 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15480 const char *thread_status = NULL;
15481 int i;
15482 int len;
15483 int inside_range;
15484 int channo;
15485 int prev_channo;
15486 x++;
15487 if (mfcr2->r2master == 0L) {
15488 thread_status = "zero";
15489 } else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15490 thread_status = "none";
15491 } else {
15492 thread_status = "created";
15493 }
15494 snprintf(index, sizeof(index), "%d", mfcr2->index);
15495 snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
15496 channo = 0;
15497 prev_channo = 0;
15498 inside_range = 0;
15499 len = 0;
15500 /* Prepare nice string in channel_list[] */
15501 for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
15502 struct dahdi_pvt *p = mfcr2->pvts[i];
15503 if (!p) {
15504 continue;
15505 }
15506 channo = p->channel;
15507 /* Don't show a range until we know the last channel number */
15508 if (prev_channo && prev_channo == channo - 1) {
15509 prev_channo = channo;
15510 inside_range = 1;
15511 continue;
15512 }
15513 if (inside_range) {
15514 /* Close range */
15515 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d,%d", prev_channo, channo);
15516 inside_range = 0;
15517 } else if (prev_channo) {
15518 /* Non-sequential channel numbers */
15519 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15520 } else {
15521 /* First channel number */
15522 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "%d", channo);
15523 }
15524 prev_channo = channo;
15525 }
15526 /* Handle leftover channels */
15527 if (inside_range) {
15528 /* Close range */
15529 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d", channo);
15530 inside_range = 0;
15531 } else if (prev_channo) {
15532 /* Non-sequential channel numbers */
15533 len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15534 }
15535 // channel_list[len] = '\0';
15536 ast_cli(a->fd, FORMAT,
15537 index,
15538 thread_status,
15539 (mfcr2->nodev) ? "MISSING" : "OK",
15540 live_chans_str,
15541 channel_list);
15542 }
15543 }
15544 AST_LIST_UNLOCK(list_head);
15545 #undef FORMAT
15546 }
15547
15548 static char *handle_mfcr2_show_links(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15549 {
15550 switch (cmd) {
15551 case CLI_INIT:
15552 e->command = "mfcr2 show links";
15553 e->usage =
15554 "Usage: mfcr2 show links\n"
15555 " Shows the DAHDI MFC/R2 links.\n";
15556 return NULL;
15557 case CLI_GENERATE:
15558 return NULL;
15559 }
15560 if (a->argc != 3) {
15561 return CLI_SHOWUSAGE;
15562 }
15563 mfcr2_show_links_of(a, &r2links, "Live links\n");
15564 mfcr2_show_links_of(a, &nodev_r2links, "Links to be removed (device missing)\n");
15565 return CLI_SUCCESS;
15566 }
15567
15568 static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15569 {
15570 int res;
15571 int wanted_link_index;
15572 int found_link = 0;
15573 struct r2link_entry *cur = NULL;
15574
15575 switch (cmd) {
15576 case CLI_INIT:
15577 e->command = "mfcr2 destroy link";
15578 e->usage =
15579 "Usage: mfcr2 destroy link <index-number>\n"
15580 " Destorys D-channel of link and its B-channels.\n"
15581 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15582 return NULL;
15583 case CLI_GENERATE:
15584 return NULL;
15585 }
15586 if (a->argc < 4) {
15587 return CLI_SHOWUSAGE;
15588 }
15589 res = sscanf(a->argv[3], "%30d", &wanted_link_index);
15590 if ((res != 1) || wanted_link_index < 1) {
15591 ast_cli(a->fd,
15592 "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15593 return CLI_SUCCESS;
15594 }
15595 AST_LIST_LOCK(&r2links);
15596 AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
15597 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15598 if (wanted_link_index == mfcr2->index) {
15599 AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
15600 r2links_count--;
15601 break;
15602 }
15603 }
15604 AST_LIST_TRAVERSE_SAFE_END;
15605 AST_LIST_UNLOCK(&r2links);
15606 if (! found_link) {
15607 ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);
15608 return CLI_FAILURE;
15609 }
15610 return CLI_SUCCESS;
15611 }
15612
15613 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15614 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15615 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15616 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15617 AST_CLI_DEFINE(handle_mfcr2_show_links, "Show MFC/R2 links"),
15618 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15619 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15620 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15621 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15622 AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),
15623 };
15624
15625 #endif /* HAVE_OPENR2 */
15626
15627 static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15628 {
15629 int start;
15630 int end;
15631 switch (cmd) {
15632 case CLI_INIT:
15633 e->command = "dahdi destroy channels";
15634 e->usage =
15635 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15636 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15637 return NULL;
15638 case CLI_GENERATE:
15639 return NULL;
15640 }
15641 if ((a->argc < 4) || a->argc > 5) {
15642 return CLI_SHOWUSAGE;
15643 }
15644 start = atoi(a->argv[3]);
15645 if (start < 1) {
15646 ast_cli(a->fd, "Invalid starting channel number %s.\n",
15647 a->argv[4]);
15648 return CLI_FAILURE;
15649 }
15650 if (a->argc == 5) {
15651 end = atoi(a->argv[4]);
15652 if (end < 1) {
15653 ast_cli(a->fd, "Invalid ending channel number %s.\n",
15654 a->argv[4]);
15655 return CLI_FAILURE;
15656 }
15657 } else {
15658 end = start;
15659 }
15660
15661 if (end < start) {
15662 ast_cli(a->fd,
15663 "range end (%d) is smaller than range start (%d)\n",
15664 end, start);
15665 return CLI_FAILURE;
15666 }
15667 dahdi_destroy_channel_range(start, end);
15668 return CLI_SUCCESS;
15669 }
15670
15671 static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15672 {
15673 int start;
15674 int end;
15675 int ret;
15676
15677 switch (cmd) {
15678 case CLI_INIT:
15679 e->command = "dahdi create channels";
15680 e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15681 " dahdi create channels new - add channels not yet created\n"
15682 "For ISDN and SS7 the range should include complete spans.\n";
15683 return NULL;
15684 case CLI_GENERATE:
15685 return NULL;
15686 }
15687 if ((a->argc < 4) || a->argc > 5) {
15688 return CLI_SHOWUSAGE;
15689 }
15690 if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15691 ret = dahdi_create_channel_range(0, 0);
15692 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15693 }
15694 start = atoi(a->argv[3]);
15695 if (start <= 0) {
15696 ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15697 a->argv[3]);
15698 return CLI_FAILURE;
15699 }
15700 if (a->argc == 5) {
15701 end = atoi(a->argv[4]);
15702 if (end <= 0) {
15703 ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15704 a->argv[4]);
15705 return CLI_FAILURE;
15706 }
15707 } else {
15708 end = start;
15709 }
15710 if (end < start) {
15711 ast_cli(a->fd,
15712 "range end (%d) is smaller than range start (%d)\n",
15713 end, start);
15714 return CLI_FAILURE;
15715 }
15716 ret = dahdi_create_channel_range(start, end);
15717 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15718 }
15719
15720 static void dahdi_softhangup_all(void)
15721 {
15722 struct dahdi_pvt *p;
15723 retry:
15724 ast_mutex_lock(&iflock);
15725 for (p = iflist; p; p = p->next) {
15726 ast_mutex_lock(&p->lock);
15727 if (p->owner && !p->restartpending) {
15728 if (ast_channel_trylock(p->owner)) {
15729 if (DEBUG_ATLEAST(3))
15730 ast_verbose("Avoiding deadlock\n");
15731 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15732 ast_mutex_unlock(&p->lock);
15733 ast_mutex_unlock(&iflock);
15734 goto retry;
15735 }
15736 if (DEBUG_ATLEAST(3))
15737 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15738 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15739 p->restartpending = 1;
15740 num_restart_pending++;
15741 ast_channel_unlock(p->owner);
15742 }
15743 ast_mutex_unlock(&p->lock);
15744 }
15745 ast_mutex_unlock(&iflock);
15746 }
15747
15748 static int dahdi_restart(void)
15749 {
15750 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15751 int i, j;
15752 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15753 int cancel_code;
15754 struct dahdi_pvt *p;
15755
15756 ast_mutex_lock(&restart_lock);
15757 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15758 dahdi_softhangup_all();
15759 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15760 #ifdef HAVE_OPENR2
15761 dahdi_r2_destroy_links();
15762 #endif
15763
15764 #if defined(HAVE_PRI)
15765 for (i = 0; i < NUM_SPANS; i++) {
15766 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15767 cancel_code = pthread_cancel(pris[i].pri.master);
15768 pthread_kill(pris[i].pri.master, SIGURG);
15769 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);
15770 pthread_join(pris[i].pri.master, NULL);
15771 ast_debug(4, "Joined thread of span %d\n", i);
15772 }
15773 }
15774 #endif
15775
15776 #if defined(HAVE_SS7)
15777 for (i = 0; i < NUM_SPANS; i++) {
15778 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15779 cancel_code = pthread_cancel(linksets[i].ss7.master);
15780 pthread_kill(linksets[i].ss7.master, SIGURG);
15781 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);
15782 pthread_join(linksets[i].ss7.master, NULL);
15783 ast_debug(4, "Joined thread of span %d\n", i);
15784 }
15785 }
15786 #endif /* defined(HAVE_SS7) */
15787
15788 ast_mutex_lock(&monlock);
15789 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15790 cancel_code = pthread_cancel(monitor_thread);
15791 pthread_kill(monitor_thread, SIGURG);
15792 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15793 pthread_join(monitor_thread, NULL);
15794 ast_debug(4, "Joined monitor thread\n");
15795 }
15796 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15797
15798 ast_mutex_lock(&ss_thread_lock);
15799 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15800 int x = DAHDI_FLASH;
15801 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15802
15803 ast_mutex_lock(&iflock);
15804 for (p = iflist; p; p = p->next) {
15805 if (p->owner) {
15806 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15807 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15808 }
15809 }
15810 ast_mutex_unlock(&iflock);
15811 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15812 }
15813
15814 /* ensure any created channels before monitor threads were stopped are hungup */
15815 dahdi_softhangup_all();
15816 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15817 destroy_all_channels();
15818 memset(round_robin, 0, sizeof(round_robin));
15819 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15820
15821 ast_mutex_unlock(&monlock);
15822
15823 #ifdef HAVE_PRI
15824 for (i = 0; i < NUM_SPANS; i++) {
15825 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15826 dahdi_close_pri_fd(&(pris[i]), j);
15827 }
15828
15829 memset(pris, 0, sizeof(pris));
15830 for (i = 0; i < NUM_SPANS; i++) {
15831 sig_pri_init_pri(&pris[i].pri);
15832 }
15833 pri_set_error(dahdi_pri_error);
15834 pri_set_message(dahdi_pri_message);
15835 #endif
15836 #if defined(HAVE_SS7)
15837 for (i = 0; i < NUM_SPANS; i++) {
15838 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15839 dahdi_close_ss7_fd(&(linksets[i]), j);
15840 }
15841
15842 memset(linksets, 0, sizeof(linksets));
15843 for (i = 0; i < NUM_SPANS; i++) {
15844 sig_ss7_init_linkset(&linksets[i].ss7);
15845 }
15846 ss7_set_error(dahdi_ss7_error);
15847 ss7_set_message(dahdi_ss7_message);
15848 ss7_set_hangup(sig_ss7_cb_hangup);
15849 ss7_set_notinservice(sig_ss7_cb_notinservice);
15850 ss7_set_call_null(sig_ss7_cb_call_null);
15851 #endif /* defined(HAVE_SS7) */
15852
15853 if (setup_dahdi(2) != 0) {
15854 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15855 ast_mutex_unlock(&ss_thread_lock);
15856 return 1;
15857 }
15858 ast_mutex_unlock(&ss_thread_lock);
15859 ast_mutex_unlock(&restart_lock);
15860 return 0;
15861 }
15862
15863 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15864 {
15865 switch (cmd) {
15866 case CLI_INIT:
15867 e->command = "dahdi restart";
15868 e->usage =
15869 "Usage: dahdi restart\n"
15870 " Restarts the DAHDI channels: destroys them all and then\n"
15871 " re-reads them from chan_dahdi.conf.\n"
15872 " Note that this will STOP any running CALL on DAHDI channels.\n"
15873 "";
15874 return NULL;
15875 case CLI_GENERATE:
15876 return NULL;
15877 }
15878 if (a->argc != 2)
15879 return CLI_SHOWUSAGE;
15880
15881 if (dahdi_restart() != 0)
15882 return CLI_FAILURE;
15883 return CLI_SUCCESS;
15884 }
15885
15886 static int action_dahdirestart(struct mansession *s, const struct message *m)
15887 {
15888 if (dahdi_restart() != 0) {
15889 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15890 return 1;
15891 }
15892 astman_send_ack(s, m, "DAHDIRestart: Success");
15893 return 0;
15894 }
15895
15896 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15897 {
15898 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15899 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15900 ast_group_t targetnum = 0;
15901 int filtertype = 0;
15902 struct dahdi_pvt *tmp = NULL;
15903 char tmps[20];
15904 char blockstr[20];
15905
15906 switch (cmd) {
15907 case CLI_INIT:
15908 e->command = "dahdi show channels [group|context]";
15909 e->usage =
15910 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15911 " Shows a list of available channels with optional filtering\n"
15912 " <group> must be a number between 0 and 63\n";
15913 return NULL;
15914 case CLI_GENERATE:
15915 return NULL;
15916 }
15917
15918 /* syntax: dahdi show channels [ group <group> | context <context> ] */
15919
15920 if (!((a->argc == 3) || (a->argc == 5))) {
15921 return CLI_SHOWUSAGE;
15922 }
15923
15924 if (a->argc == 5) {
15925 if (!strcasecmp(a->argv[3], "group")) {
15926 targetnum = atoi(a->argv[4]);
15927 if (63 < targetnum) {
15928 return CLI_SHOWUSAGE;
15929 }
15930 targetnum = ((ast_group_t) 1) << targetnum;
15931 filtertype = 1;
15932 } else if (!strcasecmp(a->argv[3], "context")) {
15933 filtertype = 2;
15934 }
15935 }
15936
15937 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Description");
15938 ast_mutex_lock(&iflock);
15939 for (tmp = iflist; tmp; tmp = tmp->next) {
15940 if (filtertype) {
15941 switch(filtertype) {
15942 case 1: /* dahdi show channels group <group> */
15943 if (!(tmp->group & targetnum)) {
15944 continue;
15945 }
15946 break;
15947 case 2: /* dahdi show channels context <context> */
15948 if (strcasecmp(tmp->context, a->argv[4])) {
15949 continue;
15950 }
15951 break;
15952 default:
15953 break;
15954 }
15955 }
15956 if (tmp->channel > 0) {
15957 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15958 } else {
15959 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15960 }
15961
15962 blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
15963 blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
15964 blockstr[2] = '\0';
15965
15966 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No", tmp->description);
15967 }
15968 ast_mutex_unlock(&iflock);
15969 return CLI_SUCCESS;
15970 #undef FORMAT
15971 #undef FORMAT2
15972 }
15973
15974 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15975 {
15976 int channel;
15977 struct dahdi_pvt *tmp = NULL;
15978 struct dahdi_confinfo ci;
15979 struct dahdi_params ps;
15980 int x;
15981 char hwrxgain[15];
15982 char hwtxgain[15];
15983
15984 switch (cmd) {
15985 case CLI_INIT:
15986 e->command = "dahdi show channel";
15987 e->usage =
15988 "Usage: dahdi show channel <chan num>\n"
15989 " Detailed information about a given channel\n";
15990 return NULL;
15991 case CLI_GENERATE:
15992 return NULL;
15993 }
15994
15995 if (a->argc != 4)
15996 return CLI_SHOWUSAGE;
15997
15998 channel = atoi(a->argv[3]);
15999
16000 ast_mutex_lock(&iflock);
16001 for (tmp = iflist; tmp; tmp = tmp->next) {
16002 if (tmp->channel == channel) {
16003 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
16004 ast_cli(a->fd, "Description: %s\n", tmp->description);
16005 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
16006 ast_cli(a->fd, "Span: %d\n", tmp->span);
16007 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
16008 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
16009 ast_cli(a->fd, "Context: %s\n", tmp->context);
16010 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
16011 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
16012 #if defined(HAVE_PRI)
16013 #if defined(HAVE_PRI_SUBADDR)
16014 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
16015 #endif /* defined(HAVE_PRI_SUBADDR) */
16016 #endif /* defined(HAVE_PRI) */
16017 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
16018 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
16019 if (tmp->vars) {
16020 struct ast_variable *v;
16021 ast_cli(a->fd, "Variables:\n");
16022 for (v = tmp->vars ; v ; v = v->next)
16023 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
16024 }
16025 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
16026 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
16027 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
16028 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
16029 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
16030 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)" : "");
16031 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)" : "");
16032 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)" : "");
16033 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
16034 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
16035 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
16036 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
16037 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
16038 if (tmp->busydetect) {
16039 #if defined(BUSYDETECT_TONEONLY)
16040 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16041 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16042 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16043 #endif
16044 #ifdef BUSYDETECT_DEBUG
16045 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
16046 #endif
16047 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
16048 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);
16049 }
16050 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
16051 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
16052 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
16053 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
16054 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
16055 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
16056 if (tmp->hwrxgain_enabled) {
16057 snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
16058 } else {
16059 ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
16060 }
16061 if (tmp->hwtxgain_enabled) {
16062 snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
16063 } else {
16064 ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
16065 }
16066 ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16067 ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
16068 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
16069 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
16070 ast_cli(a->fd, "Echo Cancellation:\n");
16071
16072 if (tmp->echocancel.head.tap_length) {
16073 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
16074 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
16075 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
16076 }
16077 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
16078 } else {
16079 ast_cli(a->fd, "\tnone\n");
16080 }
16081 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
16082 if (tmp->master)
16083 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
16084 for (x = 0; x < MAX_SLAVES; x++) {
16085 if (tmp->slaves[x])
16086 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
16087 }
16088 #ifdef HAVE_OPENR2
16089 if (tmp->mfcr2) {
16090 char calldir[OR2_MAX_PATH];
16091 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16092 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16093 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16094 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16095 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16096 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16097 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
16098 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16099 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16100 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16101 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16102 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
16103 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
16104 #endif
16105 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
16106 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16107 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
16108 #endif
16109 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
16110 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
16111 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
16112 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
16113 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
16114 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16115 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16116 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16117 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16118 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16119 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16120 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
16121 }
16122 #endif
16123 #if defined(HAVE_SS7)
16124 if (tmp->ss7) {
16125 struct sig_ss7_chan *chan = tmp->sig_pvt;
16126
16127 ast_cli(a->fd, "CIC: %d\n", chan->cic);
16128 }
16129 #endif /* defined(HAVE_SS7) */
16130 #ifdef HAVE_PRI
16131 if (tmp->pri) {
16132 struct sig_pri_chan *chan = tmp->sig_pvt;
16133
16134 ast_cli(a->fd, "PRI Flags: ");
16135 if (chan->resetting != SIG_PRI_RESET_IDLE) {
16136 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
16137 }
16138 if (chan->call)
16139 ast_cli(a->fd, "Call ");
16140 if (chan->allocated) {
16141 ast_cli(a->fd, "Allocated ");
16142 }
16143 ast_cli(a->fd, "\n");
16144 if (tmp->logicalspan)
16145 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
16146 else
16147 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
16148 }
16149 #endif
16150 memset(&ci, 0, sizeof(ci));
16151 ps.channo = tmp->channel;
16152 if (tmp->subs[SUB_REAL].dfd > -1) {
16153 memset(&ci, 0, sizeof(ci));
16154 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16155 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
16156 }
16157 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16158 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
16159 }
16160 memset(&ps, 0, sizeof(ps));
16161 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16162 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
16163 } else {
16164 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
16165 }
16166 }
16167 ast_mutex_unlock(&iflock);
16168 return CLI_SUCCESS;
16169 }
16170 }
16171 ast_mutex_unlock(&iflock);
16172
16173 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16174 return CLI_FAILURE;
16175 }
16176
16177 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16178 {
16179 int i, j;
16180 switch (cmd) {
16181 case CLI_INIT:
16182 e->command = "dahdi show cadences";
16183 e->usage =
16184 "Usage: dahdi show cadences\n"
16185 " Shows all cadences currently defined\n";
16186 return NULL;
16187 case CLI_GENERATE:
16188 return NULL;
16189 }
16190 for (i = 0; i < num_cadence; i++) {
16191 char output[1024];
16192 char tmp[16], tmp2[64];
16193 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
16194 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
16195
16196 for (j = 0; j < 16; j++) {
16197 if (cadences[i].ringcadence[j] == 0)
16198 break;
16199 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
16200 if (cidrings[i] * 2 - 1 == j)
16201 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
16202 else
16203 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
16204 if (j != 0)
16205 strncat(output, ",", sizeof(output) - strlen(output) - 1);
16206 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
16207 }
16208 ast_cli(a->fd,"%s\n",output);
16209 }
16210 return CLI_SUCCESS;
16211 }
16212
16213 /* Based on irqmiss.c */
16214 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16215 {
16216 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16217 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16218 int span;
16219 int res;
16220 char alarmstr[50];
16221
16222 int ctl;
16223 struct dahdi_spaninfo s;
16224
16225 switch (cmd) {
16226 case CLI_INIT:
16227 e->command = "dahdi show status";
16228 e->usage =
16229 "Usage: dahdi show status\n"
16230 " Shows a list of DAHDI cards with status\n";
16231 return NULL;
16232 case CLI_GENERATE:
16233 return NULL;
16234 }
16235 ctl = open("/dev/dahdi/ctl", O_RDWR);
16236 if (ctl < 0) {
16237 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16238 return CLI_FAILURE;
16239 }
16240 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
16241
16242 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16243 s.spanno = span;
16244 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16245 if (res) {
16246 continue;
16247 }
16248 alarmstr[0] = '\0';
16249 if (s.alarms > 0) {
16250 if (s.alarms & DAHDI_ALARM_BLUE)
16251 strcat(alarmstr, "BLU/");
16252 if (s.alarms & DAHDI_ALARM_YELLOW)
16253 strcat(alarmstr, "YEL/");
16254 if (s.alarms & DAHDI_ALARM_RED)
16255 strcat(alarmstr, "RED/");
16256 if (s.alarms & DAHDI_ALARM_LOOPBACK)
16257 strcat(alarmstr, "LB/");
16258 if (s.alarms & DAHDI_ALARM_RECOVER)
16259 strcat(alarmstr, "REC/");
16260 if (s.alarms & DAHDI_ALARM_NOTOPEN)
16261 strcat(alarmstr, "NOP/");
16262 if (!strlen(alarmstr))
16263 strcat(alarmstr, "UUU/");
16264 if (strlen(alarmstr)) {
16265 /* Strip trailing / */
16266 alarmstr[strlen(alarmstr) - 1] = '\0';
16267 }
16268 } else {
16269 if (s.numchans)
16270 strcpy(alarmstr, "OK");
16271 else
16272 strcpy(alarmstr, "UNCONFIGURED");
16273 }
16274
16275 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16276 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16277 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16278 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16279 "CAS",
16280 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16281 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16282 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16283 "Unk",
16284 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16285 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16286 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16287 lbostr[s.lbo]
16288 );
16289 }
16290 close(ctl);
16291
16292 return CLI_SUCCESS;
16293 #undef FORMAT
16294 #undef FORMAT2
16295 }
16296
16297 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16298 {
16299 int pseudo_fd = -1;
16300 struct dahdi_versioninfo vi;
16301
16302 switch (cmd) {
16303 case CLI_INIT:
16304 e->command = "dahdi show version";
16305 e->usage =
16306 "Usage: dahdi show version\n"
16307 " Shows the DAHDI version in use\n";
16308 return NULL;
16309 case CLI_GENERATE:
16310 return NULL;
16311 }
16312 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16313 ast_cli(a->fd, "Failed to open control file to get version.\n");
16314 return CLI_SUCCESS;
16315 }
16316
16317 strcpy(vi.version, "Unknown");
16318 strcpy(vi.echo_canceller, "Unknown");
16319
16320 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16321 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16322 else
16323 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16324
16325 close(pseudo_fd);
16326
16327 return CLI_SUCCESS;
16328 }
16329
16330 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16331 {
16332 int channel;
16333 float gain;
16334 int tx;
16335 struct dahdi_pvt *tmp = NULL;
16336
16337 switch (cmd) {
16338 case CLI_INIT:
16339 e->command = "dahdi set hwgain {rx|tx}";
16340 e->usage =
16341 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16342 " Sets the hardware gain on a given channel and overrides the\n"
16343 " value provided at module loadtime. Changes take effect\n"
16344 " immediately whether the channel is in use or not.\n"
16345 "\n"
16346 " <rx|tx> which direction do you want to change (relative to our module)\n"
16347 " <chan num> is the channel number relative to the device\n"
16348 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16349 "\n"
16350 " Please note:\n"
16351 " * hwgain is only supportable by hardware with analog ports because\n"
16352 " hwgain works on the analog side of an analog-digital conversion.\n";
16353 return NULL;
16354 case CLI_GENERATE:
16355 return NULL;
16356 }
16357
16358 if (a->argc != 6)
16359 return CLI_SHOWUSAGE;
16360
16361 if (!strcasecmp("rx", a->argv[3]))
16362 tx = 0; /* rx */
16363 else if (!strcasecmp("tx", a->argv[3]))
16364 tx = 1; /* tx */
16365 else
16366 return CLI_SHOWUSAGE;
16367
16368 channel = atoi(a->argv[4]);
16369 gain = atof(a->argv[5]);
16370
16371 ast_mutex_lock(&iflock);
16372
16373 for (tmp = iflist; tmp; tmp = tmp->next) {
16374
16375 if (tmp->channel != channel)
16376 continue;
16377
16378 if (tmp->subs[SUB_REAL].dfd == -1)
16379 break;
16380
16381 if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16382 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16383 ast_mutex_unlock(&iflock);
16384 return CLI_FAILURE;
16385 }
16386 ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16387 tx ? "tx" : "rx", gain, channel);
16388
16389 if (tx) {
16390 tmp->hwtxgain_enabled = 1;
16391 tmp->hwtxgain = gain;
16392 } else {
16393 tmp->hwrxgain_enabled = 1;
16394 tmp->hwrxgain = gain;
16395 }
16396 break;
16397 }
16398
16399 ast_mutex_unlock(&iflock);
16400
16401 if (tmp)
16402 return CLI_SUCCESS;
16403
16404 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16405 return CLI_FAILURE;
16406
16407 }
16408
16409 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16410 {
16411 int channel;
16412 float gain;
16413 int tx;
16414 int res;
16415 struct dahdi_pvt *tmp = NULL;
16416
16417 switch (cmd) {
16418 case CLI_INIT:
16419 e->command = "dahdi set swgain {rx|tx}";
16420 e->usage =
16421 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16422 " Sets the software gain on a given channel and overrides the\n"
16423 " value provided at module loadtime. Changes take effect\n"
16424 " immediately whether the channel is in use or not.\n"
16425 "\n"
16426 " <rx|tx> which direction do you want to change (relative to our module)\n"
16427 " <chan num> is the channel number relative to the device\n"
16428 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16429 return NULL;
16430 case CLI_GENERATE:
16431 return NULL;
16432 }
16433
16434 if (a->argc != 6)
16435 return CLI_SHOWUSAGE;
16436
16437 if (!strcasecmp("rx", a->argv[3]))
16438 tx = 0; /* rx */
16439 else if (!strcasecmp("tx", a->argv[3]))
16440 tx = 1; /* tx */
16441 else
16442 return CLI_SHOWUSAGE;
16443
16444 channel = atoi(a->argv[4]);
16445 gain = atof(a->argv[5]);
16446
16447 ast_mutex_lock(&iflock);
16448 for (tmp = iflist; tmp; tmp = tmp->next) {
16449
16450 if (tmp->channel != channel)
16451 continue;
16452
16453 if (tmp->subs[SUB_REAL].dfd == -1)
16454 break;
16455
16456 if (tx)
16457 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16458 else
16459 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16460
16461 if (res) {
16462 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16463 ast_mutex_unlock(&iflock);
16464 return CLI_FAILURE;
16465 }
16466
16467 ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16468 tx ? "tx" : "rx", gain, channel);
16469
16470 if (tx) {
16471 tmp->txgain = gain;
16472 } else {
16473 tmp->rxgain = gain;
16474 }
16475 break;
16476 }
16477 ast_mutex_unlock(&iflock);
16478
16479 if (tmp)
16480 return CLI_SUCCESS;
16481
16482 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16483 return CLI_FAILURE;
16484
16485 }
16486
16487 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16488 {
16489 int channel;
16490 int on;
16491 struct dahdi_pvt *dahdi_chan = NULL;
16492
16493 switch (cmd) {
16494 case CLI_INIT:
16495 e->command = "dahdi set dnd";
16496 e->usage =
16497 "Usage: dahdi set dnd <chan#> <on|off>\n"
16498 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16499 " Changes take effect immediately.\n"
16500 " <chan num> is the channel number\n"
16501 " <on|off> Enable or disable DND mode?\n"
16502 ;
16503 return NULL;
16504 case CLI_GENERATE:
16505 return NULL;
16506 }
16507
16508 if (a->argc != 5)
16509 return CLI_SHOWUSAGE;
16510
16511 if ((channel = atoi(a->argv[3])) <= 0) {
16512 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16513 return CLI_SHOWUSAGE;
16514 }
16515
16516 if (ast_true(a->argv[4]))
16517 on = 1;
16518 else if (ast_false(a->argv[4]))
16519 on = 0;
16520 else {
16521 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16522 return CLI_SHOWUSAGE;
16523 }
16524
16525 ast_mutex_lock(&iflock);
16526 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16527 if (dahdi_chan->channel != channel)
16528 continue;
16529
16530 /* Found the channel. Actually set it */
16531 dahdi_dnd(dahdi_chan, on);
16532 break;
16533 }
16534 ast_mutex_unlock(&iflock);
16535
16536 if (!dahdi_chan) {
16537 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16538 return CLI_FAILURE;
16539 }
16540
16541 return CLI_SUCCESS;
16542 }
16543
16544 static struct ast_cli_entry dahdi_cli[] = {
16545 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16546 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16547 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16548 AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16549 AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16550 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16551 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16552 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16553 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16554 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16555 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16556 };
16557
16558 #define TRANSFER 0
16559 #define HANGUP 1
16560
16561 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16562 {
16563 if (p) {
16564 switch (mode) {
16565 case TRANSFER:
16566 p->fake_event = DAHDI_EVENT_WINKFLASH;
16567 break;
16568 case HANGUP:
16569 p->fake_event = DAHDI_EVENT_ONHOOK;
16570 break;
16571 default:
16572 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));
16573 }
16574 }
16575 return 0;
16576 }
16577 static struct dahdi_pvt *find_channel(int channel)
16578 {
16579 struct dahdi_pvt *p;
16580
16581 ast_mutex_lock(&iflock);
16582 for (p = iflist; p; p = p->next) {
16583 if (p->channel == channel) {
16584 break;
16585 }
16586 }
16587 ast_mutex_unlock(&iflock);
16588 return p;
16589 }
16590
16591 /*!
16592 * \internal
16593 * \brief Get private struct using given numeric channel string.
16594 *
16595 * \param channel Numeric channel number string get private struct.
16596 *
16597 * \retval pvt on success.
16598 * \retval NULL on error.
16599 */
16600 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16601 {
16602 int chan_num;
16603
16604 if (sscanf(channel, "%30d", &chan_num) != 1) {
16605 /* Not numeric string. */
16606 return NULL;
16607 }
16608
16609 return find_channel(chan_num);
16610 }
16611
16612 static int action_dahdidndon(struct mansession *s, const struct message *m)
16613 {
16614 struct dahdi_pvt *p;
16615 const char *channel = astman_get_header(m, "DAHDIChannel");
16616
16617 if (ast_strlen_zero(channel)) {
16618 astman_send_error(s, m, "No channel specified");
16619 return 0;
16620 }
16621 p = find_channel_from_str(channel);
16622 if (!p) {
16623 astman_send_error(s, m, "No such channel");
16624 return 0;
16625 }
16626 dahdi_dnd(p, 1);
16627 astman_send_ack(s, m, "DND Enabled");
16628 return 0;
16629 }
16630
16631 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16632 {
16633 struct dahdi_pvt *p;
16634 const char *channel = astman_get_header(m, "DAHDIChannel");
16635
16636 if (ast_strlen_zero(channel)) {
16637 astman_send_error(s, m, "No channel specified");
16638 return 0;
16639 }
16640 p = find_channel_from_str(channel);
16641 if (!p) {
16642 astman_send_error(s, m, "No such channel");
16643 return 0;
16644 }
16645 dahdi_dnd(p, 0);
16646 astman_send_ack(s, m, "DND Disabled");
16647 return 0;
16648 }
16649
16650 static int action_transfer(struct mansession *s, const struct message *m)
16651 {
16652 struct dahdi_pvt *p;
16653 const char *channel = astman_get_header(m, "DAHDIChannel");
16654
16655 if (ast_strlen_zero(channel)) {
16656 astman_send_error(s, m, "No channel specified");
16657 return 0;
16658 }
16659 p = find_channel_from_str(channel);
16660 if (!p) {
16661 astman_send_error(s, m, "No such channel");
16662 return 0;
16663 }
16664 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16665 astman_send_error(s, m, "Channel signaling is not analog");
16666 return 0;
16667 }
16668 dahdi_fake_event(p,TRANSFER);
16669 astman_send_ack(s, m, "DAHDITransfer");
16670 return 0;
16671 }
16672
16673 static int action_transferhangup(struct mansession *s, const struct message *m)
16674 {
16675 struct dahdi_pvt *p;
16676 const char *channel = astman_get_header(m, "DAHDIChannel");
16677
16678 if (ast_strlen_zero(channel)) {
16679 astman_send_error(s, m, "No channel specified");
16680 return 0;
16681 }
16682 p = find_channel_from_str(channel);
16683 if (!p) {
16684 astman_send_error(s, m, "No such channel");
16685 return 0;
16686 }
16687 if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16688 astman_send_error(s, m, "Channel signaling is not analog");
16689 return 0;
16690 }
16691 dahdi_fake_event(p,HANGUP);
16692 astman_send_ack(s, m, "DAHDIHangup");
16693 return 0;
16694 }
16695
16696 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16697 {
16698 struct dahdi_pvt *p;
16699 const char *channel = astman_get_header(m, "DAHDIChannel");
16700 const char *number = astman_get_header(m, "Number");
16701 int i;
16702
16703 if (ast_strlen_zero(channel)) {
16704 astman_send_error(s, m, "No channel specified");
16705 return 0;
16706 }
16707 if (ast_strlen_zero(number)) {
16708 astman_send_error(s, m, "No number specified");
16709 return 0;
16710 }
16711 p = find_channel_from_str(channel);
16712 if (!p) {
16713 astman_send_error(s, m, "No such channel");
16714 return 0;
16715 }
16716 if (!p->owner) {
16717 astman_send_error(s, m, "Channel does not have it's owner");
16718 return 0;
16719 }
16720 for (i = 0; i < strlen(number); i++) {
16721 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16722 dahdi_queue_frame(p, &f);
16723 }
16724 astman_send_ack(s, m, "DAHDIDialOffhook");
16725 return 0;
16726 }
16727
16728 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16729 {
16730 struct dahdi_pvt *tmp = NULL;
16731 const char *id = astman_get_header(m, "ActionID");
16732 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16733 char idText[256];
16734 int channels = 0;
16735 int dahdichanquery;
16736
16737 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16738 /* Not numeric string. */
16739 dahdichanquery = -1;
16740 }
16741
16742 idText[0] = '\0';
16743 if (!ast_strlen_zero(id)) {
16744 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16745 }
16746
16747 astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16748
16749 ast_mutex_lock(&iflock);
16750
16751 for (tmp = iflist; tmp; tmp = tmp->next) {
16752 if (tmp->channel > 0) {
16753 int alm;
16754
16755 /* If a specific channel is queried for, only deliver status for that channel */
16756 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16757 continue;
16758
16759 alm = get_alarms(tmp);
16760 channels++;
16761 if (tmp->owner) {
16762 /* Add data if we have a current call */
16763 astman_append(s,
16764 "Event: DAHDIShowChannels\r\n"
16765 "DAHDIChannel: %d\r\n"
16766 "Channel: %s\r\n"
16767 "Uniqueid: %s\r\n"
16768 "AccountCode: %s\r\n"
16769 "Signalling: %s\r\n"
16770 "SignallingCode: %d\r\n"
16771 "Context: %s\r\n"
16772 "DND: %s\r\n"
16773 "Alarm: %s\r\n"
16774 "Description: %s\r\n"
16775 "%s"
16776 "\r\n",
16777 tmp->channel,
16778 ast_channel_name(tmp->owner),
16779 ast_channel_uniqueid(tmp->owner),
16780 ast_channel_accountcode(tmp->owner),
16781 sig2str(tmp->sig),
16782 tmp->sig,
16783 tmp->context,
16784 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16785 alarm2str(alm),
16786 tmp->description, idText);
16787 } else {
16788 astman_append(s,
16789 "Event: DAHDIShowChannels\r\n"
16790 "DAHDIChannel: %d\r\n"
16791 "Signalling: %s\r\n"
16792 "SignallingCode: %d\r\n"
16793 "Context: %s\r\n"
16794 "DND: %s\r\n"
16795 "Alarm: %s\r\n"
16796 "Description: %s\r\n"
16797 "%s"
16798 "\r\n",
16799 tmp->channel, sig2str(tmp->sig), tmp->sig,
16800 tmp->context,
16801 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16802 alarm2str(alm),
16803 tmp->description, idText);
16804 }
16805 }
16806 }
16807
16808 ast_mutex_unlock(&iflock);
16809
16810 astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16811 astman_append(s, "Items: %d\r\n", channels);
16812 astman_send_list_complete_end(s);
16813 return 0;
16814 }
16815
16816 #if defined(HAVE_PRI)
16817 static int action_prishowspans(struct mansession *s, const struct message *m)
16818 {
16819 int count;
16820 int idx;
16821 int span_query;
16822 struct dahdi_pri *dspan;
16823 const char *id = astman_get_header(m, "ActionID");
16824 const char *span_str = astman_get_header(m, "Span");
16825 char action_id[256];
16826 const char *show_cmd = "PRIShowSpans";
16827
16828 /* NOTE: Asking for span 0 gets all spans. */
16829 if (!ast_strlen_zero(span_str)) {
16830 span_query = atoi(span_str);
16831 } else {
16832 span_query = 0;
16833 }
16834
16835 if (!ast_strlen_zero(id)) {
16836 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16837 } else {
16838 action_id[0] = '\0';
16839 }
16840
16841 astman_send_listack(s, m, "Span status will follow", "start");
16842
16843 count = 0;
16844 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16845 dspan = &pris[idx];
16846
16847 /* If a specific span is asked for, only deliver status for that span. */
16848 if (0 < span_query && dspan->pri.span != span_query) {
16849 continue;
16850 }
16851
16852 if (dspan->pri.pri) {
16853 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16854 action_id);
16855 }
16856 }
16857
16858 astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
16859 astman_append(s, "Items: %d\r\n", count);
16860 astman_send_list_complete_end(s);
16861 return 0;
16862 }
16863 #endif /* defined(HAVE_PRI) */
16864
16865 #if defined(HAVE_SS7)
16866 static int linkset_addsigchan(int sigchan)
16867 {
16868 struct dahdi_ss7 *link;
16869 int res;
16870 int curfd;
16871 struct dahdi_params params;
16872 struct dahdi_bufferinfo bi;
16873 struct dahdi_spaninfo si;
16874
16875 if (sigchan < 0) {
16876 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16877 return -1;
16878 }
16879 if (cur_ss7type < 0) {
16880 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16881 return -1;
16882 }
16883 if (cur_pointcode < 0) {
16884 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16885 return -1;
16886 }
16887 if (cur_adjpointcode < 0) {
16888 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16889 return -1;
16890 }
16891 if (cur_defaultdpc < 0) {
16892 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16893 return -1;
16894 }
16895 if (cur_networkindicator < 0) {
16896 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16897 return -1;
16898 }
16899 link = ss7_resolve_linkset(cur_linkset);
16900 if (!link) {
16901 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16902 return -1;
16903 }
16904 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16905 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16906 return -1;
16907 }
16908
16909 curfd = link->ss7.numsigchans;
16910
16911 /* Open signaling channel */
16912 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16913 if (link->ss7.fds[curfd] < 0) {
16914 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16915 strerror(errno));
16916 return -1;
16917 }
16918 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16919 dahdi_close_ss7_fd(link, curfd);
16920 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16921 strerror(errno));
16922 return -1;
16923 }
16924
16925 /* Get signaling channel parameters */
16926 memset(&params, 0, sizeof(params));
16927 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16928 if (res) {
16929 dahdi_close_ss7_fd(link, curfd);
16930 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16931 strerror(errno));
16932 return -1;
16933 }
16934 if (params.sigtype != DAHDI_SIG_HDLCFCS
16935 && params.sigtype != DAHDI_SIG_HARDHDLC
16936 && params.sigtype != DAHDI_SIG_MTP2) {
16937 dahdi_close_ss7_fd(link, curfd);
16938 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16939 return -1;
16940 }
16941
16942 /* Set signaling channel buffer policy. */
16943 memset(&bi, 0, sizeof(bi));
16944 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16945 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16946 bi.numbufs = 32;
16947 bi.bufsize = 512;
16948 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16949 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16950 sigchan, strerror(errno));
16951 dahdi_close_ss7_fd(link, curfd);
16952 return -1;
16953 }
16954
16955 /* Get current signaling channel alarm status. */
16956 memset(&si, 0, sizeof(si));
16957 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16958 if (res) {
16959 dahdi_close_ss7_fd(link, curfd);
16960 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16961 strerror(errno));
16962 }
16963
16964 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16965 (params.sigtype == DAHDI_SIG_MTP2)
16966 ? SS7_TRANSPORT_DAHDIMTP2
16967 : SS7_TRANSPORT_DAHDIDCHAN,
16968 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
16969 if (res) {
16970 dahdi_close_ss7_fd(link, curfd);
16971 return -1;
16972 }
16973
16974 ++link->ss7.numsigchans;
16975
16976 return 0;
16977 }
16978 #endif /* defined(HAVE_SS7) */
16979
16980 #if defined(HAVE_SS7)
16981 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16982 {
16983 int span;
16984 switch (cmd) {
16985 case CLI_INIT:
16986 e->command = "ss7 set debug {on|off} linkset";
16987 e->usage =
16988 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16989 " Enables debugging on a given SS7 linkset\n";
16990 return NULL;
16991 case CLI_GENERATE:
16992 return NULL;
16993 }
16994
16995 if (a->argc < 6) {
16996 return CLI_SHOWUSAGE;
16997 }
16998
16999 span = atoi(a->argv[5]);
17000 if ((span < 1) || (span > NUM_SPANS)) {
17001 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
17002 return CLI_SUCCESS;
17003 }
17004 if (!linksets[span-1].ss7.ss7) {
17005 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
17006 } else {
17007 if (!strcasecmp(a->argv[3], "on")) {
17008 linksets[span - 1].ss7.debug = 1;
17009 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
17010 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
17011 } else {
17012 linksets[span - 1].ss7.debug = 0;
17013 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
17014 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
17015 }
17016 }
17017
17018 return CLI_SUCCESS;
17019 }
17020 #endif /* defined(HAVE_SS7) */
17021
17022 #if defined(HAVE_SS7)
17023 static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17024 {
17025 int linkset, cic;
17026 int blocked, i;
17027 int do_block = 0;
17028 unsigned int dpc;
17029
17030 switch (cmd) {
17031 case CLI_INIT:
17032 e->command = "ss7 {block|unblock} cic";
17033 e->usage =
17034 "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
17035 " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
17036 return NULL;
17037 case CLI_GENERATE:
17038 return NULL;
17039 }
17040
17041 if (a->argc == 6) {
17042 linkset = atoi(a->argv[3]);
17043 } else {
17044 return CLI_SHOWUSAGE;
17045 }
17046
17047 if (!strcasecmp(a->argv[1], "block")) {
17048 do_block = 1;
17049 } else if (strcasecmp(a->argv[1], "unblock")) {
17050 return CLI_SHOWUSAGE;
17051 }
17052
17053 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17054 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17055 return CLI_SUCCESS;
17056 }
17057
17058 if (!linksets[linkset-1].ss7.ss7) {
17059 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17060 return CLI_SUCCESS;
17061 }
17062
17063 cic = atoi(a->argv[5]);
17064 if (cic < 1) {
17065 ast_cli(a->fd, "Invalid CIC specified!\n");
17066 return CLI_SUCCESS;
17067 }
17068
17069 dpc = atoi(a->argv[4]);
17070 if (dpc < 1) {
17071 ast_cli(a->fd, "Invalid DPC specified!\n");
17072 return CLI_SUCCESS;
17073 }
17074
17075 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
17076 if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
17077 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
17078 if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
17079 if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
17080 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17081 } else {
17082 ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
17083 }
17084 } else if (!do_block && blocked) {
17085 ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
17086 } else {
17087 ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
17088 }
17089 return CLI_SUCCESS;
17090 }
17091 }
17092
17093 ast_cli(a->fd, "Invalid CIC specified!\n");
17094 return CLI_SUCCESS;
17095 }
17096 #endif /* defined(HAVE_SS7) */
17097
17098 #if defined(HAVE_SS7)
17099 static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17100 {
17101 int linkset, i;
17102 enum {
17103 DO_BLOCK,
17104 DO_UNBLOCK,
17105 DO_RESET,
17106 } do_what;
17107
17108 switch (cmd) {
17109 case CLI_INIT:
17110 e->command = "ss7 {reset|block|unblock} linkset";
17111 e->usage =
17112 "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
17113 " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
17114 return NULL;
17115 case CLI_GENERATE:
17116 return NULL;
17117 }
17118
17119 if (a->argc == 4) {
17120 linkset = atoi(a->argv[3]);
17121 } else {
17122 return CLI_SHOWUSAGE;
17123 }
17124
17125 if (!strcasecmp(a->argv[1], "block")) {
17126 do_what = DO_BLOCK;
17127 } else if (!strcasecmp(a->argv[1], "unblock")) {
17128 do_what = DO_UNBLOCK;
17129 } else if (!strcasecmp(a->argv[1], "reset")) {
17130 do_what = DO_RESET;
17131 } else {
17132 return CLI_SHOWUSAGE;
17133 }
17134
17135 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17136 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17137 return CLI_SUCCESS;
17138 }
17139
17140 if (!linksets[linkset - 1].ss7.ss7) {
17141 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17142 return CLI_SUCCESS;
17143 }
17144
17145 for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
17146 /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
17147 if (linksets[linkset - 1].ss7.pvts[i]) {
17148 switch (do_what) {
17149 case DO_BLOCK:
17150 case DO_UNBLOCK:
17151 if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
17152 ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
17153 (do_what == DO_BLOCK) ? "blocking" : "unblocking",
17154 linksets[linkset - 1].ss7.pvts[i]->cic);
17155 }
17156 break;
17157 case DO_RESET:
17158 if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
17159 linksets[linkset - 1].ss7.pvts[i]->cic,
17160 linksets[linkset - 1].ss7.pvts[i]->dpc)) {
17161 ast_cli(a->fd, "Sent reset request on CIC %d\n",
17162 linksets[linkset - 1].ss7.pvts[i]->cic);
17163 }
17164 break;
17165 }
17166 }
17167 }
17168
17169 return CLI_SUCCESS;
17170 }
17171 #endif /* defined(HAVE_SS7) */
17172
17173 #if defined(HAVE_SS7)
17174 static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17175 {
17176 int linkset, cic, range, chanpos;
17177 int i, dpc, orient = 0;
17178 int do_block = 0;
17179 unsigned char state[255];
17180
17181 switch (cmd) {
17182 case CLI_INIT:
17183 e->command = "ss7 {block|unblock} group";
17184 e->usage =
17185 "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
17186 " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
17187 return NULL;
17188 case CLI_GENERATE:
17189 return NULL;
17190 }
17191
17192 if (a->argc == 7 || a->argc == 8) {
17193 linkset = atoi(a->argv[3]);
17194 } else {
17195 return CLI_SHOWUSAGE;
17196 }
17197
17198 if (!strcasecmp(a->argv[1], "block")) {
17199 do_block = 1;
17200 } else if (strcasecmp(a->argv[1], "unblock")) {
17201 return CLI_SHOWUSAGE;
17202 }
17203
17204 if (a->argc == 8) {
17205 if (!strcasecmp(a->argv[7], "H")) {
17206 orient = 1;
17207 } else {
17208 return CLI_SHOWUSAGE;
17209 }
17210 }
17211
17212 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17213 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17214 return CLI_SUCCESS;
17215 }
17216
17217 if (!linksets[linkset-1].ss7.ss7) {
17218 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17219 return CLI_SUCCESS;
17220 }
17221
17222 cic = atoi(a->argv[5]);
17223 if (cic < 1) {
17224 ast_cli(a->fd, "Invalid CIC specified!\n");
17225 return CLI_SUCCESS;
17226 }
17227
17228 range = atoi(a->argv[6]);
17229 /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
17230 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17231 ast_cli(a->fd, "Invalid range specified!\n");
17232 return CLI_SUCCESS;
17233 }
17234
17235 dpc = atoi(a->argv[4]);
17236 if (dpc < 1) {
17237 ast_cli(a->fd, "Invalid DPC specified!\n");
17238 return CLI_SUCCESS;
17239 }
17240
17241 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17242 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17243 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17244 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17245 return CLI_SHOWUSAGE;
17246 }
17247
17248 memset(state, 0, sizeof(state));
17249 for (i = 0; i <= range; ++i) {
17250 state[i] = 1;
17251 }
17252
17253 /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
17254 chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
17255 if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
17256 ast_cli(a->fd, "Unable allocate new ss7call\n");
17257 } else {
17258 ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
17259 orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
17260 }
17261
17262 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17263
17264 /* Break poll on the linkset so it sends our messages */
17265 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17266 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17267 }
17268 return CLI_SUCCESS;
17269 }
17270 #endif /* defined(HAVE_SS7) */
17271
17272 #if defined(HAVE_SS7)
17273 static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17274 {
17275 int linkset, cic, range;
17276 unsigned int dpc;
17277
17278 switch (cmd) {
17279 case CLI_INIT:
17280 e->command = "ss7 reset group";
17281 e->usage =
17282 "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
17283 " Send a GRS for the given CIC range on the specified linkset\n";
17284 return NULL;
17285 case CLI_GENERATE:
17286 return NULL;
17287 }
17288
17289 if (a->argc == 7) {
17290 linkset = atoi(a->argv[3]);
17291 } else {
17292 return CLI_SHOWUSAGE;
17293 }
17294
17295 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17296 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17297 return CLI_SUCCESS;
17298 }
17299
17300 if (!linksets[linkset-1].ss7.ss7) {
17301 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17302 return CLI_SUCCESS;
17303 }
17304
17305 cic = atoi(a->argv[5]);
17306
17307 if (cic < 1) {
17308 ast_cli(a->fd, "Invalid CIC specified!\n");
17309 return CLI_SUCCESS;
17310 }
17311
17312 range = atoi(a->argv[6]);
17313 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17314 ast_cli(a->fd, "Invalid range specified!\n");
17315 return CLI_SUCCESS;
17316 }
17317
17318 dpc = atoi(a->argv[4]);
17319 if (dpc < 1) {
17320 ast_cli(a->fd, "Invalid DPC specified!\n");
17321 return CLI_SUCCESS;
17322 }
17323
17324 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17325 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17326 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17327 ast_cli(a->fd, "Invalid CIC/RANGE\n");
17328 return CLI_SHOWUSAGE;
17329 }
17330
17331 if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17332 ast_cli(a->fd, "Unable to allocate new ss7call\n");
17333 } else {
17334 ast_cli(a->fd, "GRS sent ... \n");
17335 }
17336
17337 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17338
17339 /* Break poll on the linkset so it sends our messages */
17340 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17341 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17342 }
17343 return CLI_SUCCESS;
17344 }
17345 #endif /* defined(HAVE_SS7) */
17346
17347 #if defined(HAVE_SS7)
17348 static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17349 {
17350 int linkset;
17351
17352 switch (cmd) {
17353 case CLI_INIT:
17354 e->command = "ss7 show calls";
17355 e->usage =
17356 "Usage: ss7 show calls <linkset>\n"
17357 " Show SS7 calls on the specified linkset\n";
17358 return NULL;
17359 case CLI_GENERATE:
17360 return NULL;
17361 }
17362
17363 if (a->argc == 4) {
17364 linkset = atoi(a->argv[3]);
17365 } else {
17366 return CLI_SHOWUSAGE;
17367 }
17368
17369 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17370 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17371 return CLI_SUCCESS;
17372 }
17373
17374 if (!linksets[linkset-1].ss7.ss7) {
17375 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17376 return CLI_SUCCESS;
17377 }
17378
17379 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17380 isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17381 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17382
17383 return CLI_SUCCESS;
17384 }
17385 #endif /* defined(HAVE_SS7) */
17386
17387 #if defined(HAVE_SS7)
17388 static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17389 {
17390 int linkset, cic, res;
17391 unsigned int dpc;
17392
17393 switch (cmd) {
17394 case CLI_INIT:
17395 e->command = "ss7 reset cic";
17396 e->usage =
17397 "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17398 " Send a RSC for the given CIC on the specified linkset\n";
17399 return NULL;
17400 case CLI_GENERATE:
17401 return NULL;
17402 }
17403
17404 if (a->argc == 6) {
17405 linkset = atoi(a->argv[3]);
17406 } else {
17407 return CLI_SHOWUSAGE;
17408 }
17409
17410 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17411 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17412 return CLI_SUCCESS;
17413 }
17414
17415 if (!linksets[linkset-1].ss7.ss7) {
17416 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17417 return CLI_SUCCESS;
17418 }
17419
17420 cic = atoi(a->argv[5]);
17421
17422 if (cic < 1) {
17423 ast_cli(a->fd, "Invalid CIC specified!\n");
17424 return CLI_SUCCESS;
17425 }
17426
17427 dpc = atoi(a->argv[4]);
17428 if (dpc < 1) {
17429 ast_cli(a->fd, "Invalid DPC specified!\n");
17430 return CLI_SUCCESS;
17431 }
17432
17433 res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17434
17435 ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
17436
17437 return CLI_SUCCESS;
17438 }
17439 #endif /* defined(HAVE_SS7) */
17440
17441 #if defined(HAVE_SS7)
17442 static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17443 {
17444 int linkset;
17445 unsigned int slc;
17446 unsigned int arg = 0;
17447 const char *res;
17448
17449 switch (cmd) {
17450 case CLI_INIT:
17451 e->command = "ss7 mtp3";
17452 e->usage =
17453 "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17454 " Send a NET MNG message\n"
17455 " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17456 return NULL;
17457 case CLI_GENERATE:
17458 return NULL;
17459 }
17460
17461 if (a->argc < 5) {
17462 return CLI_SHOWUSAGE;
17463 }
17464
17465 linkset = atoi(a->argv[2]);
17466 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17467 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17468 return CLI_SUCCESS;
17469 }
17470 if (!linksets[linkset-1].ss7.ss7) {
17471 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17472 return CLI_SUCCESS;
17473 }
17474
17475 slc = atoi(a->argv[3]);
17476
17477 if (a->argc == 6) {
17478 arg = atoi(a->argv[5]);
17479 }
17480
17481 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17482 res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17483 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17484
17485 /* Break poll on the linkset so it sends our messages */
17486 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17487 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17488 }
17489
17490 ast_cli(a->fd, "%s", res);
17491
17492 return CLI_SUCCESS;
17493 }
17494 #endif /* defined(HAVE_SS7) */
17495
17496 #if defined(HAVE_SS7)
17497 static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17498 {
17499 int linkset;
17500 unsigned int slc = 0;
17501
17502 switch (cmd) {
17503 case CLI_INIT:
17504 e->command = "ss7 restart mtp3";
17505 e->usage =
17506 "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17507 " Restart link\n";
17508 return NULL;
17509 case CLI_GENERATE:
17510 return NULL;
17511 }
17512
17513 if (a->argc < 5) {
17514 return CLI_SHOWUSAGE;
17515 }
17516
17517 linkset = atoi(a->argv[3]);
17518 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17519 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17520 return CLI_SUCCESS;
17521 }
17522 if (!linksets[linkset-1].ss7.ss7) {
17523 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17524 return CLI_SUCCESS;
17525 }
17526
17527 slc = atoi(a->argv[4]);
17528
17529 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17530 mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17531 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17532
17533 /* Break poll on the linkset so it sends our messages */
17534 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17535 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17536 }
17537
17538 return CLI_SUCCESS;
17539 }
17540 #endif /* defined(HAVE_SS7) */
17541
17542 #if defined(HAVE_SS7)
17543 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17544 {
17545 int linkset;
17546 struct sig_ss7_linkset *ss7;
17547 switch (cmd) {
17548 case CLI_INIT:
17549 e->command = "ss7 show linkset";
17550 e->usage =
17551 "Usage: ss7 show linkset <span>\n"
17552 " Shows the status of an SS7 linkset.\n";
17553 return NULL;
17554 case CLI_GENERATE:
17555 return NULL;
17556 }
17557
17558 if (a->argc < 4) {
17559 return CLI_SHOWUSAGE;
17560 }
17561
17562 linkset = atoi(a->argv[3]);
17563 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17564 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17565 return CLI_SUCCESS;
17566 }
17567 ss7 = &linksets[linkset - 1].ss7;
17568 if (!ss7->ss7) {
17569 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17570 return CLI_SUCCESS;
17571 }
17572
17573 ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
17574 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17575 ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
17576 ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
17577 ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
17578 ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
17579 ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
17580 ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17581 ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
17582 ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17583
17584 return CLI_SUCCESS;
17585 }
17586 #endif /* defined(HAVE_SS7) */
17587
17588 #if defined(HAVE_SS7)
17589 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17590 {
17591 int linkset;
17592
17593 switch (cmd) {
17594 case CLI_INIT:
17595 e->command = "ss7 show channels";
17596 e->usage =
17597 "Usage: ss7 show channels\n"
17598 " Displays SS7 channel information at a glance.\n";
17599 return NULL;
17600 case CLI_GENERATE:
17601 return NULL;
17602 }
17603
17604 if (a->argc != 3) {
17605 return CLI_SHOWUSAGE;
17606 }
17607
17608 sig_ss7_cli_show_channels_header(a->fd);
17609 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17610 if (linksets[linkset].ss7.ss7) {
17611 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17612 }
17613 }
17614 return CLI_SUCCESS;
17615 }
17616 #endif /* defined(HAVE_SS7) */
17617
17618 #if defined(HAVE_SS7)
17619 static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17620 {
17621 #define FORMAT "%5s %5s %6s %12s %-12s\n"
17622 #define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17623 int i, linkset, dpc = 0;
17624 struct sig_ss7_linkset *ss7;
17625 char *state;
17626 char blocking[12];
17627
17628 switch (cmd) {
17629 case CLI_INIT:
17630 e->command = "ss7 show cics";
17631 e->usage =
17632 "Usage: ss7 show cics <linkset> [dpc]\n"
17633 " Shows the cics of an SS7 linkset.\n";
17634 return NULL;
17635 case CLI_GENERATE:
17636 return NULL;
17637 }
17638
17639 if (a->argc < 4 || a->argc > 5) {
17640 return CLI_SHOWUSAGE;
17641 }
17642
17643 linkset = atoi(a->argv[3]);
17644
17645 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17646 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17647 return CLI_SUCCESS;
17648 }
17649
17650 if (!linksets[linkset-1].ss7.ss7) {
17651 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17652 return CLI_SUCCESS;
17653 }
17654 ss7 = &linksets[linkset-1].ss7;
17655
17656 if (a->argc == 5) {
17657 dpc = atoi(a->argv[4]);
17658 if (dpc < 1) {
17659 ast_cli(a->fd, "Invalid DPC specified!\n");
17660 return CLI_SUCCESS;
17661 }
17662 }
17663
17664 ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
17665
17666 for (i = 0; i < ss7->numchans; i++) {
17667 if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
17668 struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
17669
17670 if (ss7->pvts[i]->owner) {
17671 state = "Used";
17672 } else if (ss7->pvts[i]->ss7call) {
17673 state = "Pending";
17674 } else if (!p->inservice) {
17675 state = "NotInServ";
17676 } else {
17677 state = "Idle";
17678 }
17679
17680 if (p->locallyblocked) {
17681 strcpy(blocking, "L:");
17682 if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
17683 strcat(blocking, "M");
17684 } else {
17685 strcat(blocking, " ");
17686 }
17687
17688 if (p->locallyblocked & SS7_BLOCKED_HARDWARE) {
17689 strcat(blocking, "H");
17690 } else {
17691 strcat(blocking, " ");
17692 }
17693 } else {
17694 strcpy(blocking, " ");
17695 }
17696
17697 if (p->remotelyblocked) {
17698 strcat(blocking, " R:");
17699 if (p->remotelyblocked & SS7_BLOCKED_MAINTENANCE) {
17700 strcat(blocking, "M");
17701 } else {
17702 strcat(blocking, " ");
17703 }
17704
17705 if (p->remotelyblocked & SS7_BLOCKED_HARDWARE) {
17706 strcat(blocking, "H");
17707 } else {
17708 strcat(blocking, " ");
17709 }
17710 }
17711
17712 ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
17713 }
17714 }
17715
17716 return CLI_SUCCESS;
17717 #undef FORMAT
17718 #undef FORMAT2
17719 }
17720 #endif /* defined(HAVE_SS7) */
17721
17722 #if defined(HAVE_SS7)
17723 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17724 {
17725 switch (cmd) {
17726 case CLI_INIT:
17727 e->command = "ss7 show version";
17728 e->usage =
17729 "Usage: ss7 show version\n"
17730 " Show the libss7 version\n";
17731 return NULL;
17732 case CLI_GENERATE:
17733 return NULL;
17734 }
17735
17736 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17737
17738 return CLI_SUCCESS;
17739 }
17740 #endif /* defined(HAVE_SS7) */
17741
17742 #if defined(HAVE_SS7)
17743 static struct ast_cli_entry dahdi_ss7_cli[] = {
17744 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17745 AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
17746 AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
17747 AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
17748 AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
17749 AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
17750 AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
17751 AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
17752 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17753 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17754 AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
17755 AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
17756 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17757 };
17758 #endif /* defined(HAVE_SS7) */
17759
17760 #if defined(HAVE_PRI)
17761 #if defined(HAVE_PRI_CCSS)
17762 /*!
17763 * \internal
17764 * \brief CC agent initialization.
17765 * \since 1.8
17766 *
17767 * \param agent CC core agent control.
17768 * \param chan Original channel the agent will attempt to recall.
17769 *
17770 * \details
17771 * This callback is called when the CC core is initialized. Agents should allocate
17772 * any private data necessary for the call and assign it to the private_data
17773 * on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the
17774 * specific agent type, they should be set in this function as well.
17775 *
17776 * \retval 0 on success.
17777 * \retval -1 on error.
17778 */
17779 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17780 {
17781 struct dahdi_pvt *pvt;
17782 struct sig_pri_chan *pvt_chan;
17783 int res;
17784
17785 ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17786
17787 pvt = ast_channel_tech_pvt(chan);
17788 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17789 pvt_chan = pvt->sig_pvt;
17790 } else {
17791 pvt_chan = NULL;
17792 }
17793 if (!pvt_chan) {
17794 return -1;
17795 }
17796
17797 ast_module_ref(ast_module_info->self);
17798
17799 res = sig_pri_cc_agent_init(agent, pvt_chan);
17800 if (res) {
17801 ast_module_unref(ast_module_info->self);
17802 }
17803 return res;
17804 }
17805 #endif /* defined(HAVE_PRI_CCSS) */
17806 #endif /* defined(HAVE_PRI) */
17807
17808 #if defined(HAVE_PRI)
17809 #if defined(HAVE_PRI_CCSS)
17810 /*!
17811 * \internal
17812 * \brief Destroy private data on the agent.
17813 * \since 1.8
17814 *
17815 * \param agent CC core agent control.
17816 *
17817 * \details
17818 * The core will call this function upon completion
17819 * or failure of CC.
17820 */
17821 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17822 {
17823 sig_pri_cc_agent_destructor(agent);
17824
17825 ast_module_unref(ast_module_info->self);
17826 }
17827 #endif /* defined(HAVE_PRI_CCSS) */
17828 #endif /* defined(HAVE_PRI) */
17829
17830 #if defined(HAVE_PRI)
17831 #if defined(HAVE_PRI_CCSS)
17832 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17833 .type = dahdi_pri_cc_type,
17834 .init = dahdi_pri_cc_agent_init,
17835 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17836 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17837 .respond = sig_pri_cc_agent_req_rsp,
17838 .status_request = sig_pri_cc_agent_status_req,
17839 .stop_ringing = sig_pri_cc_agent_stop_ringing,
17840 .party_b_free = sig_pri_cc_agent_party_b_free,
17841 .start_monitoring = sig_pri_cc_agent_start_monitoring,
17842 .callee_available = sig_pri_cc_agent_callee_available,
17843 .destructor = dahdi_pri_cc_agent_destructor,
17844 };
17845 #endif /* defined(HAVE_PRI_CCSS) */
17846 #endif /* defined(HAVE_PRI) */
17847
17848 #if defined(HAVE_PRI)
17849 #if defined(HAVE_PRI_CCSS)
17850 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17851 .type = dahdi_pri_cc_type,
17852 .request_cc = sig_pri_cc_monitor_req_cc,
17853 .suspend = sig_pri_cc_monitor_suspend,
17854 .unsuspend = sig_pri_cc_monitor_unsuspend,
17855 .status_response = sig_pri_cc_monitor_status_rsp,
17856 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17857 .destructor = sig_pri_cc_monitor_destructor,
17858 };
17859 #endif /* defined(HAVE_PRI_CCSS) */
17860 #endif /* defined(HAVE_PRI) */
17861
17862 static int __unload_module(void)
17863 {
17864 struct dahdi_pvt *p;
17865 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17866 int i, j;
17867 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17868
17869 #ifdef HAVE_PRI
17870 for (i = 0; i < NUM_SPANS; i++) {
17871 if (pris[i].pri.master != AST_PTHREADT_NULL) {
17872 pthread_cancel(pris[i].pri.master);
17873 pthread_kill(pris[i].pri.master, SIGURG);
17874 }
17875 }
17876 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17877 ast_unregister_application(dahdi_send_keypad_facility_app);
17878 #ifdef HAVE_PRI_PROG_W_CAUSE
17879 ast_unregister_application(dahdi_send_callrerouting_facility_app);
17880 #endif
17881 #endif
17882 #if defined(HAVE_SS7)
17883 for (i = 0; i < NUM_SPANS; i++) {
17884 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17885 pthread_cancel(linksets[i].ss7.master);
17886 pthread_kill(linksets[i].ss7.master, SIGURG);
17887 }
17888 }
17889 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17890 #endif /* defined(HAVE_SS7) */
17891 #if defined(HAVE_OPENR2)
17892 dahdi_r2_destroy_links();
17893 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17894 ast_unregister_application(dahdi_accept_r2_call_app);
17895 #endif
17896
17897 ast_custom_function_unregister(&polarity_function);
17898
17899 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17900 ast_manager_unregister("DAHDIDialOffhook");
17901 ast_manager_unregister("DAHDIHangup");
17902 ast_manager_unregister("DAHDITransfer");
17903 ast_manager_unregister("DAHDIDNDoff");
17904 ast_manager_unregister("DAHDIDNDon");
17905 ast_manager_unregister("DAHDIShowChannels");
17906 ast_manager_unregister("DAHDIRestart");
17907 #if defined(HAVE_PRI)
17908 ast_manager_unregister("PRIShowSpans");
17909 ast_manager_unregister("PRIDebugSet");
17910 ast_manager_unregister("PRIDebugFileSet");
17911 ast_manager_unregister("PRIDebugFileUnset");
17912 #endif /* defined(HAVE_PRI) */
17913 ast_channel_unregister(&dahdi_tech);
17914
17915 /* Hangup all interfaces if they have an owner */
17916 ast_mutex_lock(&iflock);
17917 for (p = iflist; p; p = p->next) {
17918 if (p->owner)
17919 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17920 }
17921 ast_mutex_unlock(&iflock);
17922
17923 ast_mutex_lock(&monlock);
17924 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17925 pthread_cancel(monitor_thread);
17926 pthread_kill(monitor_thread, SIGURG);
17927 pthread_join(monitor_thread, NULL);
17928 }
17929 monitor_thread = AST_PTHREADT_STOP;
17930 ast_mutex_unlock(&monlock);
17931
17932 destroy_all_channels();
17933
17934 #if defined(HAVE_PRI)
17935 for (i = 0; i < NUM_SPANS; i++) {
17936 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17937 pthread_join(pris[i].pri.master, NULL);
17938 }
17939 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17940 dahdi_close_pri_fd(&(pris[i]), j);
17941 }
17942 sig_pri_stop_pri(&pris[i].pri);
17943 }
17944 #if defined(HAVE_PRI_CCSS)
17945 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17946 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17947 #endif /* defined(HAVE_PRI_CCSS) */
17948 sig_pri_unload();
17949 #endif
17950
17951 #if defined(HAVE_SS7)
17952 for (i = 0; i < NUM_SPANS; i++) {
17953 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17954 pthread_join(linksets[i].ss7.master, NULL);
17955 }
17956 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17957 dahdi_close_ss7_fd(&(linksets[i]), j);
17958 }
17959 if (linksets[i].ss7.ss7) {
17960 ss7_destroy(linksets[i].ss7.ss7);
17961 linksets[i].ss7.ss7 = NULL;
17962 }
17963 }
17964 #endif /* defined(HAVE_SS7) */
17965 ast_cond_destroy(&ss_thread_complete);
17966
17967 dahdi_native_unload();
17968
17969 ao2_cleanup(dahdi_tech.capabilities);
17970 dahdi_tech.capabilities = NULL;
17971 STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17972 return 0;
17973 }
17974
17975 static int unload_module(void)
17976 {
17977 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17978 int y;
17979 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17980 #ifdef HAVE_PRI
17981 for (y = 0; y < NUM_SPANS; y++)
17982 ast_mutex_destroy(&pris[y].pri.lock);
17983 #endif
17984 #if defined(HAVE_SS7)
17985 for (y = 0; y < NUM_SPANS; y++)
17986 ast_mutex_destroy(&linksets[y].ss7.lock);
17987 #endif /* defined(HAVE_SS7) */
17988 return __unload_module();
17989 }
17990
17991 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
17992 {
17993 char *c, *chan;
17994 int x, start, finish;
17995 struct dahdi_pvt *tmp;
17996
17997 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17998 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17999 return -1;
18000 }
18001
18002 c = ast_strdupa(value);
18003
18004 while ((chan = strsep(&c, ","))) {
18005 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
18006 /* Range */
18007 } else if (sscanf(chan, "%30d", &start)) {
18008 /* Just one */
18009 finish = start;
18010 } else if (!strcasecmp(chan, "pseudo")) {
18011 finish = start = CHAN_PSEUDO;
18012 } else {
18013 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
18014 return -1;
18015 }
18016 if (finish < start) {
18017 ast_log(LOG_WARNING, "Silliness: %d < %d\n", start, finish);
18018 x = finish;
18019 finish = start;
18020 start = x;
18021 }
18022
18023 for (x = start; x <= finish; x++) {
18024 if (conf->wanted_channels_start &&
18025 (x < conf->wanted_channels_start ||
18026 x > conf->wanted_channels_end)
18027 ) {
18028 continue;
18029 }
18030 tmp = mkintf(x, conf, reload);
18031
18032 if (tmp) {
18033 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
18034 } else {
18035 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
18036 (reload == 1) ? "reconfigure" : "register", value);
18037 return -1;
18038 }
18039 if (x == CHAN_PSEUDO) {
18040 has_pseudo = 1;
18041 }
18042 }
18043 }
18044
18045 return 0;
18046 }
18047
18048 /** The length of the parameters list of 'dahdichan'.
18049 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
18050 #define MAX_CHANLIST_LEN 80
18051
18052 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
18053 {
18054 char *parse = ast_strdupa(data);
18055 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18056 unsigned int param_count;
18057 unsigned int x;
18058
18059 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
18060 return;
18061
18062 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
18063
18064 /* first parameter is tap length, process it here */
18065
18066 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18067
18068 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18069 confp->chan.echocancel.head.tap_length = x;
18070 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
18071 confp->chan.echocancel.head.tap_length = 128;
18072
18073 /* now process any remaining parameters */
18074
18075 for (x = 1; x < param_count; x++) {
18076 struct {
18077 char *name;
18078 char *value;
18079 } param;
18080
18081 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
18082 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18083 continue;
18084 }
18085
18086 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
18087 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18088 continue;
18089 }
18090
18091 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
18092
18093 if (param.value) {
18094 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
18095 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18096 continue;
18097 }
18098 }
18099 confp->chan.echocancel.head.param_count++;
18100 }
18101 }
18102
18103 #if defined(HAVE_PRI)
18104 #if defined(HAVE_PRI_DISPLAY_TEXT)
18105 /*!
18106 * \internal
18107 * \brief Determine the configured display text options.
18108 * \since 10.0
18109 *
18110 * \param value Configuration value string.
18111 *
18112 * \return Configured display text option flags.
18113 */
18114 static unsigned long dahdi_display_text_option(const char *value)
18115 {
18116 char *val_str;
18117 char *opt_str;
18118 unsigned long options;
18119
18120 options = 0;
18121 val_str = ast_strdupa(value);
18122
18123 for (;;) {
18124 opt_str = strsep(&val_str, ",");
18125 if (!opt_str) {
18126 break;
18127 }
18128 opt_str = ast_strip(opt_str);
18129 if (!*opt_str) {
18130 continue;
18131 }
18132
18133 if (!strcasecmp(opt_str, "block")) {
18134 options |= PRI_DISPLAY_OPTION_BLOCK;
18135 } else if (!strcasecmp(opt_str, "name_initial")) {
18136 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
18137 } else if (!strcasecmp(opt_str, "name_update")) {
18138 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
18139 } else if (!strcasecmp(opt_str, "name")) {
18140 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
18141 } else if (!strcasecmp(opt_str, "text")) {
18142 options |= PRI_DISPLAY_OPTION_TEXT;
18143 }
18144 }
18145 return options;
18146 }
18147 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
18148 #endif /* defined(HAVE_PRI) */
18149
18150 #if defined(HAVE_PRI)
18151 #if defined(HAVE_PRI_DATETIME_SEND)
18152 /*!
18153 * \internal
18154 * \brief Determine the configured date/time send policy option.
18155 * \since 10.0
18156 *
18157 * \param value Configuration value string.
18158 *
18159 * \return Configured date/time send policy option.
18160 */
18161 static int dahdi_datetime_send_option(const char *value)
18162 {
18163 int option;
18164
18165 option = PRI_DATE_TIME_SEND_DEFAULT;
18166
18167 if (ast_false(value)) {
18168 option = PRI_DATE_TIME_SEND_NO;
18169 } else if (!strcasecmp(value, "date")) {
18170 option = PRI_DATE_TIME_SEND_DATE;
18171 } else if (!strcasecmp(value, "date_hh")) {
18172 option = PRI_DATE_TIME_SEND_DATE_HH;
18173 } else if (!strcasecmp(value, "date_hhmm")) {
18174 option = PRI_DATE_TIME_SEND_DATE_HHMM;
18175 } else if (!strcasecmp(value, "date_hhmmss")) {
18176 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
18177 }
18178
18179 return option;
18180 }
18181 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
18182 #endif /* defined(HAVE_PRI) */
18183
18184 /*! process_dahdi() - ignore keyword 'channel' and similar */
18185 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
18186 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
18187 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
18188
18189 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
18190 {
18191 int count_pattern = 0;
18192 int norval = 0;
18193 char *temp = NULL;
18194
18195 for (; ;) {
18196 /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
18197 if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
18198 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18199 break;
18200 }
18201
18202 busy_cadence->pattern[count_pattern] = norval;
18203
18204 count_pattern++;
18205 if (count_pattern == 4) {
18206 break;
18207 }
18208
18209 temp = strchr(v->value, ',');
18210 if (temp == NULL) {
18211 break;
18212 }
18213 v->value = temp + 1;
18214 }
18215 busy_cadence->length = count_pattern;
18216
18217 if (count_pattern % 2 != 0) {
18218 /* The pattern length must be divisible by two */
18219 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18220 }
18221
18222 }
18223
18224 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
18225 {
18226 struct dahdi_pvt *tmp;
18227 int y;
18228 struct ast_variable *dahdichan = NULL;
18229
18230 /* Re-parse any cadences from beginning, rather than appending until we run out of room */
18231 user_has_defined_cadences = 0;
18232
18233 for (; v; v = v->next) {
18234 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
18235 continue;
18236
18237 /* Create the interface list */
18238 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
18239 if (options & PROC_DAHDI_OPT_NOCHAN) {
18240 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
18241 continue;
18242 }
18243 if (build_channels(confp, v->value, reload, v->lineno)) {
18244 if (confp->ignore_failed_channels) {
18245 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
18246 continue;
18247 } else {
18248 return -1;
18249 }
18250 }
18251 ast_debug(1, "Channel '%s' configured.\n", v->value);
18252 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
18253 confp->ignore_failed_channels = ast_true(v->value);
18254 } else if (!strcasecmp(v->name, "buffers")) {
18255 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
18256 ast_log(LOG_WARNING, "Using default buffer policy.\n");
18257 confp->chan.buf_no = numbufs;
18258 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
18259 }
18260 } else if (!strcasecmp(v->name, "faxbuffers")) {
18261 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
18262 confp->chan.usefaxbuffers = 1;
18263 }
18264 } else if (!strcasecmp(v->name, "dahdichan")) {
18265 /* Only process the last dahdichan value. */
18266 dahdichan = v;
18267 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
18268 usedistinctiveringdetection = ast_true(v->value);
18269 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
18270 distinctiveringaftercid = ast_true(v->value);
18271 } else if (!strcasecmp(v->name, "dring1context")) {
18272 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
18273 } else if (!strcasecmp(v->name, "dring2context")) {
18274 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
18275 } else if (!strcasecmp(v->name, "dring3context")) {
18276 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
18277 } else if (!strcasecmp(v->name, "dring1range")) {
18278 confp->chan.drings.ringnum[0].range = atoi(v->value);
18279 } else if (!strcasecmp(v->name, "dring2range")) {
18280 confp->chan.drings.ringnum[1].range = atoi(v->value);
18281 } else if (!strcasecmp(v->name, "dring3range")) {
18282 confp->chan.drings.ringnum[2].range = atoi(v->value);
18283 } else if (!strcasecmp(v->name, "dring1")) {
18284 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]);
18285 } else if (!strcasecmp(v->name, "dring2")) {
18286 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]);
18287 } else if (!strcasecmp(v->name, "dring3")) {
18288 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]);
18289 } else if (!strcasecmp(v->name, "usecallerid")) {
18290 confp->chan.use_callerid = ast_true(v->value);
18291 } else if (!strcasecmp(v->name, "cidsignalling")) {
18292 if (!strcasecmp(v->value, "bell"))
18293 confp->chan.cid_signalling = CID_SIG_BELL;
18294 else if (!strcasecmp(v->value, "v23"))
18295 confp->chan.cid_signalling = CID_SIG_V23;
18296 else if (!strcasecmp(v->value, "dtmf"))
18297 confp->chan.cid_signalling = CID_SIG_DTMF;
18298 else if (!strcasecmp(v->value, "smdi"))
18299 confp->chan.cid_signalling = CID_SIG_SMDI;
18300 else if (!strcasecmp(v->value, "v23_jp"))
18301 confp->chan.cid_signalling = CID_SIG_V23_JP;
18302 else if (ast_true(v->value))
18303 confp->chan.cid_signalling = CID_SIG_BELL;
18304 } else if (!strcasecmp(v->name, "cidstart")) {
18305 if (!strcasecmp(v->value, "ring"))
18306 confp->chan.cid_start = CID_START_RING;
18307 else if (!strcasecmp(v->value, "polarity_in"))
18308 confp->chan.cid_start = CID_START_POLARITY_IN;
18309 else if (!strcasecmp(v->value, "polarity"))
18310 confp->chan.cid_start = CID_START_POLARITY;
18311 else if (!strcasecmp(v->value, "dtmf"))
18312 confp->chan.cid_start = CID_START_DTMF_NOALERT;
18313 else if (ast_true(v->value))
18314 confp->chan.cid_start = CID_START_RING;
18315 } else if (!strcasecmp(v->name, "threewaycalling")) {
18316 confp->chan.threewaycalling = ast_true(v->value);
18317 } else if (!strcasecmp(v->name, "threewaysilenthold")) {
18318 confp->chan.threewaysilenthold = ast_true(v->value);
18319 } else if (!strcasecmp(v->name, "cancallforward")) {
18320 confp->chan.cancallforward = ast_true(v->value);
18321 } else if (!strcasecmp(v->name, "relaxdtmf")) {
18322 if (ast_true(v->value))
18323 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
18324 else
18325 confp->chan.dtmfrelax = 0;
18326 } else if (!strcasecmp(v->name, "mailbox")) {
18327 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
18328 } else if (!strcasecmp(v->name, "description")) {
18329 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18330 } else if (!strcasecmp(v->name, "hasvoicemail")) {
18331 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18332 /*
18333 * hasvoicemail is a users.conf legacy voicemail enable method.
18334 * hasvoicemail is only going to work for app_voicemail mailboxes.
18335 */
18336 if (strchr(cat, '@')) {
18337 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18338 } else {
18339 snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18340 "%s@default", cat);
18341 }
18342 }
18343 } else if (!strcasecmp(v->name, "adsi")) {
18344 confp->chan.adsi = ast_true(v->value);
18345 } else if (!strcasecmp(v->name, "usesmdi")) {
18346 confp->chan.use_smdi = ast_true(v->value);
18347 } else if (!strcasecmp(v->name, "smdiport")) {
18348 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18349 } else if (!strcasecmp(v->name, "transfer")) {
18350 confp->chan.transfer = ast_true(v->value);
18351 } else if (!strcasecmp(v->name, "canpark")) {
18352 confp->chan.canpark = ast_true(v->value);
18353 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18354 confp->chan.echocanbridged = ast_true(v->value);
18355 } else if (!strcasecmp(v->name, "busydetect")) {
18356 confp->chan.busydetect = ast_true(v->value);
18357 } else if (!strcasecmp(v->name, "busycount")) {
18358 confp->chan.busycount = atoi(v->value);
18359 } else if (!strcasecmp(v->name, "busypattern")) {
18360 parse_busy_pattern(v, &confp->chan.busy_cadence);
18361 } else if (!strcasecmp(v->name, "calledsubscriberheld")) {
18362 confp->chan.calledsubscriberheld = ast_true(v->value);
18363 } else if (!strcasecmp(v->name, "callprogress")) {
18364 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
18365 if (ast_true(v->value))
18366 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
18367 } else if (!strcasecmp(v->name, "waitfordialtone")) {
18368 confp->chan.waitfordialtone = atoi(v->value);
18369 } else if (!strcasecmp(v->name, "dialtone_detect")) {
18370 if (!strcasecmp(v->value, "always")) {
18371 confp->chan.dialtone_detect = -1;
18372 } else if (ast_true(v->value)) {
18373 confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
18374 } else if (ast_false(v->value)) {
18375 confp->chan.dialtone_detect = 0;
18376 } else {
18377 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18378 }
18379 } else if (!strcasecmp(v->name, "faxdetect")) {
18380 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18381 if (!strcasecmp(v->value, "incoming")) {
18382 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
18383 } else if (!strcasecmp(v->value, "outgoing")) {
18384 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
18385 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18386 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
18387 } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18388 if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18389 confp->chan.faxdetect_timeout = 0;
18390 }
18391 } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18392 if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18393 || confp->chan.firstdigit_timeout <= 0) {
18394 confp->chan.firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT;
18395 }
18396 } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18397 if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18398 || confp->chan.interdigit_timeout <= 0) {
18399 confp->chan.interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT;
18400 }
18401 } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18402 if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18403 || confp->chan.matchdigit_timeout <= 0) {
18404 confp->chan.matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT;
18405 }
18406 } else if (!strcasecmp(v->name, "echocancel")) {
18407 process_echocancel(confp, v->value, v->lineno);
18408 } else if (!strcasecmp(v->name, "echotraining")) {
18409 if (sscanf(v->value, "%30d", &y) == 1) {
18410 if ((y < 10) || (y > 4000)) {
18411 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18412 } else {
18413 confp->chan.echotraining = y;
18414 }
18415 } else if (ast_true(v->value)) {
18416 confp->chan.echotraining = 400;
18417 } else
18418 confp->chan.echotraining = 0;
18419 } else if (!strcasecmp(v->name, "hidecallerid")) {
18420 confp->chan.hidecallerid = ast_true(v->value);
18421 } else if (!strcasecmp(v->name, "hidecalleridname")) {
18422 confp->chan.hidecalleridname = ast_true(v->value);
18423 } else if (!strcasecmp(v->name, "pulsedial")) {
18424 confp->chan.pulse = ast_true(v->value);
18425 } else if (!strcasecmp(v->name, "callreturn")) {
18426 confp->chan.callreturn = ast_true(v->value);
18427 } else if (!strcasecmp(v->name, "callwaiting")) {
18428 confp->chan.callwaiting = ast_true(v->value);
18429 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18430 confp->chan.callwaitingcallerid = ast_true(v->value);
18431 } else if (!strcasecmp(v->name, "context")) {
18432 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18433 } else if (!strcasecmp(v->name, "language")) {
18434 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18435 } else if (!strcasecmp(v->name, "progzone")) {
18436 ast_copy_string(progzone, v->value, sizeof(progzone));
18437 } else if (!strcasecmp(v->name, "mohinterpret")
18438 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18439 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18440 } else if (!strcasecmp(v->name, "mohsuggest")) {
18441 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18442 } else if (!strcasecmp(v->name, "parkinglot")) {
18443 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18444 } else if (!strcasecmp(v->name, "stripmsd")) {
18445 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18446 confp->chan.stripmsd = atoi(v->value);
18447 } else if (!strcasecmp(v->name, "jitterbuffers")) {
18448 numbufs = atoi(v->value);
18449 } else if (!strcasecmp(v->name, "group")) {
18450 confp->chan.group = ast_get_group(v->value);
18451 } else if (!strcasecmp(v->name, "callgroup")) {
18452 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18453 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a call group\n");
18454 }
18455 if (!strcasecmp(v->value, "none"))
18456 confp->chan.callgroup = 0;
18457 else
18458 confp->chan.callgroup = ast_get_group(v->value);
18459 } else if (!strcasecmp(v->name, "pickupgroup")) {
18460 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18461 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a pickup group\n");
18462 }
18463 if (!strcasecmp(v->value, "none"))
18464 confp->chan.pickupgroup = 0;
18465 else
18466 confp->chan.pickupgroup = ast_get_group(v->value);
18467 } else if (!strcasecmp(v->name, "namedcallgroup")) {
18468 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18469 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named call group\n");
18470 }
18471 confp->chan.named_callgroups = ast_get_namedgroups(v->value);
18472 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18473 if (!((confp->chan.sig == SIG_FXOKS) || (confp->chan.sig == SIG_FXOGS) || (confp->chan.sig == SIG_FXOLS))) {
18474 ast_log(LOG_WARNING, "Only FXO signalled channels may belong to a named pickup group\n");
18475 }
18476 confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
18477 } else if (!strcasecmp(v->name, "setvar")) {
18478 if (v->value) {
18479 char *varval = NULL;
18480 struct ast_variable *tmpvar;
18481 char varname[strlen(v->value) + 1];
18482 strcpy(varname, v->value); /* safe */
18483 if ((varval = strchr(varname, '='))) {
18484 *varval++ = '\0';
18485 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18486 if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18487 tmpvar->next = confp->chan.vars;
18488 confp->chan.vars = tmpvar;
18489 }
18490 }
18491 }
18492 }
18493 } else if (!strcasecmp(v->name, "immediate")) {
18494 confp->chan.immediate = ast_true(v->value);
18495 } else if (!strcasecmp(v->name, "immediatering")) {
18496 confp->chan.immediatering = ast_true(v->value);
18497 } else if (!strcasecmp(v->name, "transfertobusy")) {
18498 confp->chan.transfertobusy = ast_true(v->value);
18499 } else if (!strcasecmp(v->name, "dialmode")) {
18500 if (!strcasecmp(v->value, "pulse")) {
18501 confp->chan.dialmode = ANALOG_DIALMODE_PULSE;
18502 } else if (!strcasecmp(v->value, "dtmf") || !strcasecmp(v->value, "tone")) {
18503 confp->chan.dialmode = ANALOG_DIALMODE_DTMF;
18504 } else if (!strcasecmp(v->value, "none")) {
18505 confp->chan.dialmode = ANALOG_DIALMODE_NONE;
18506 } else {
18507 confp->chan.dialmode = ANALOG_DIALMODE_BOTH;
18508 }
18509 } else if (!strcasecmp(v->name, "mwimonitor")) {
18510 confp->chan.mwimonitor_neon = 0;
18511 confp->chan.mwimonitor_fsk = 0;
18512 confp->chan.mwimonitor_rpas = 0;
18513 if (strcasestr(v->value, "fsk")) {
18514 confp->chan.mwimonitor_fsk = 1;
18515 }
18516 if (strcasestr(v->value, "rpas")) {
18517 confp->chan.mwimonitor_rpas = 1;
18518 }
18519 if (strcasestr(v->value, "neon")) {
18520 confp->chan.mwimonitor_neon = 1;
18521 }
18522 /* If set to true or yes, assume that simple fsk is desired */
18523 if (ast_true(v->value)) {
18524 confp->chan.mwimonitor_fsk = 1;
18525 }
18526 } else if (!strcasecmp(v->name, "hwrxgain")) {
18527 confp->chan.hwrxgain_enabled = 0;
18528 if (strcasecmp(v->value, "disabled")) {
18529 if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18530 confp->chan.hwrxgain_enabled = 1;
18531 } else {
18532 ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18533 }
18534 }
18535 } else if (!strcasecmp(v->name, "hwtxgain")) {
18536 confp->chan.hwtxgain_enabled = 0;
18537 if (strcasecmp(v->value, "disabled")) {
18538 if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18539 confp->chan.hwtxgain_enabled = 1;
18540 } else {
18541 ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18542 }
18543 }
18544 } else if (!strcasecmp(v->name, "cid_rxgain")) {
18545 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18546 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18547 }
18548 } else if (!strcasecmp(v->name, "rxgain")) {
18549 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18550 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18551 }
18552 } else if (!strcasecmp(v->name, "txgain")) {
18553 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18554 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18555 }
18556 } else if (!strcasecmp(v->name, "txdrc")) {
18557 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18558 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18559 }
18560 } else if (!strcasecmp(v->name, "rxdrc")) {
18561 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18562 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18563 }
18564 } else if (!strcasecmp(v->name, "tonezone")) {
18565 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18566 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18567 }
18568 } else if (!strcasecmp(v->name, "callerid")) {
18569 if (!strcasecmp(v->value, "asreceived")) {
18570 confp->chan.cid_num[0] = '\0';
18571 confp->chan.cid_name[0] = '\0';
18572 } else {
18573 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18574 }
18575 } else if (!strcasecmp(v->name, "fullname")) {
18576 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18577 } else if (!strcasecmp(v->name, "cid_number")) {
18578 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18579 } else if (!strcasecmp(v->name, "cid_tag")) {
18580 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18581 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18582 confp->chan.dahditrcallerid = ast_true(v->value);
18583 } else if (!strcasecmp(v->name, "restrictcid")) {
18584 confp->chan.restrictcid = ast_true(v->value);
18585 } else if (!strcasecmp(v->name, "usecallingpres")) {
18586 confp->chan.use_callingpres = ast_true(v->value);
18587 } else if (!strcasecmp(v->name, "accountcode")) {
18588 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18589 } else if (!strcasecmp(v->name, "amaflags")) {
18590 y = ast_channel_string2amaflag(v->value);
18591 if (y < 0)
18592 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18593 else
18594 confp->chan.amaflags = y;
18595 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18596 confp->chan.polarityonanswerdelay = atoi(v->value);
18597 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18598 confp->chan.answeronpolarityswitch = ast_true(v->value);
18599 } else if (!strcasecmp(v->name, "ani_info_digits")) {
18600 confp->chan.ani_info_digits = atoi(v->value);
18601 } else if (!strcasecmp(v->name, "ani_wink_time")) {
18602 confp->chan.ani_wink_time = atoi(v->value);
18603 } else if (!strcasecmp(v->name, "ani_timeout")) {
18604 confp->chan.ani_timeout = atoi(v->value);
18605 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18606 confp->chan.hanguponpolarityswitch = ast_true(v->value);
18607 } else if (!strcasecmp(v->name, "autoreoriginate")) {
18608 confp->chan.reoriginate = ast_true(v->value);
18609 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18610 confp->chan.sendcalleridafter = atoi(v->value);
18611 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18612 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
18613 } else if (ast_cc_is_config_param(v->name)) {
18614 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18615 } else if (!strcasecmp(v->name, "mwisendtype")) {
18616 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18617 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18618 mwisend_rpas = 1;
18619 } else {
18620 mwisend_rpas = 0;
18621 }
18622 #else
18623 /* Default is fsk, to turn it off you must specify nofsk */
18624 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18625 if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18626 confp->chan.mwisend_fsk = 0;
18627 } else { /* Default FSK */
18628 confp->chan.mwisend_fsk = 1;
18629 }
18630 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18631 confp->chan.mwisend_rpas = 1;
18632 } else {
18633 confp->chan.mwisend_rpas = 0;
18634 }
18635 if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18636 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18637 }
18638 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18639 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18640 }
18641 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18642 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18643 }
18644 #endif
18645 } else if (reload != 1) {
18646 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18647 int orig_radio = confp->chan.radio;
18648 int orig_outsigmod = confp->chan.outsigmod;
18649 int orig_auto = confp->is_sig_auto;
18650
18651 confp->chan.radio = 0;
18652 confp->chan.outsigmod = -1;
18653 confp->is_sig_auto = 0;
18654 if (!strcasecmp(v->value, "em")) {
18655 confp->chan.sig = SIG_EM;
18656 } else if (!strcasecmp(v->value, "em_e1")) {
18657 confp->chan.sig = SIG_EM_E1;
18658 } else if (!strcasecmp(v->value, "em_w")) {
18659 confp->chan.sig = SIG_EMWINK;
18660 } else if (!strcasecmp(v->value, "fxs_ls")) {
18661 confp->chan.sig = SIG_FXSLS;
18662 } else if (!strcasecmp(v->value, "fxs_gs")) {
18663 confp->chan.sig = SIG_FXSGS;
18664 } else if (!strcasecmp(v->value, "fxs_ks")) {
18665 confp->chan.sig = SIG_FXSKS;
18666 } else if (!strcasecmp(v->value, "fxo_ls")) {
18667 confp->chan.sig = SIG_FXOLS;
18668 } else if (!strcasecmp(v->value, "fxo_gs")) {
18669 confp->chan.sig = SIG_FXOGS;
18670 } else if (!strcasecmp(v->value, "fxo_ks")) {
18671 confp->chan.sig = SIG_FXOKS;
18672 } else if (!strcasecmp(v->value, "fxs_rx")) {
18673 confp->chan.sig = SIG_FXSKS;
18674 confp->chan.radio = 1;
18675 } else if (!strcasecmp(v->value, "fxo_rx")) {
18676 confp->chan.sig = SIG_FXOLS;
18677 confp->chan.radio = 1;
18678 } else if (!strcasecmp(v->value, "fxs_tx")) {
18679 confp->chan.sig = SIG_FXSLS;
18680 confp->chan.radio = 1;
18681 } else if (!strcasecmp(v->value, "fxo_tx")) {
18682 confp->chan.sig = SIG_FXOGS;
18683 confp->chan.radio = 1;
18684 } else if (!strcasecmp(v->value, "em_rx")) {
18685 confp->chan.sig = SIG_EM;
18686 confp->chan.radio = 1;
18687 } else if (!strcasecmp(v->value, "em_tx")) {
18688 confp->chan.sig = SIG_EM;
18689 confp->chan.radio = 1;
18690 } else if (!strcasecmp(v->value, "em_rxtx")) {
18691 confp->chan.sig = SIG_EM;
18692 confp->chan.radio = 2;
18693 } else if (!strcasecmp(v->value, "em_txrx")) {
18694 confp->chan.sig = SIG_EM;
18695 confp->chan.radio = 2;
18696 } else if (!strcasecmp(v->value, "sf")) {
18697 confp->chan.sig = SIG_SF;
18698 } else if (!strcasecmp(v->value, "sf_w")) {
18699 confp->chan.sig = SIG_SFWINK;
18700 } else if (!strcasecmp(v->value, "sf_featd")) {
18701 confp->chan.sig = SIG_FEATD;
18702 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18703 confp->chan.sig = SIG_FEATDMF;
18704 } else if (!strcasecmp(v->value, "sf_featb")) {
18705 confp->chan.sig = SIG_SF_FEATB;
18706 } else if (!strcasecmp(v->value, "sf")) {
18707 confp->chan.sig = SIG_SF;
18708 } else if (!strcasecmp(v->value, "sf_rx")) {
18709 confp->chan.sig = SIG_SF;
18710 confp->chan.radio = 1;
18711 } else if (!strcasecmp(v->value, "sf_tx")) {
18712 confp->chan.sig = SIG_SF;
18713 confp->chan.radio = 1;
18714 } else if (!strcasecmp(v->value, "sf_rxtx")) {
18715 confp->chan.sig = SIG_SF;
18716 confp->chan.radio = 2;
18717 } else if (!strcasecmp(v->value, "sf_txrx")) {
18718 confp->chan.sig = SIG_SF;
18719 confp->chan.radio = 2;
18720 } else if (!strcasecmp(v->value, "featd")) {
18721 confp->chan.sig = SIG_FEATD;
18722 } else if (!strcasecmp(v->value, "featdmf")) {
18723 confp->chan.sig = SIG_FEATDMF;
18724 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18725 confp->chan.sig = SIG_FEATDMF_TA;
18726 } else if (!strcasecmp(v->value, "e911")) {
18727 confp->chan.sig = SIG_E911;
18728 } else if (!strcasecmp(v->value, "fgccama")) {
18729 confp->chan.sig = SIG_FGC_CAMA;
18730 } else if (!strcasecmp(v->value, "fgccamamf")) {
18731 confp->chan.sig = SIG_FGC_CAMAMF;
18732 } else if (!strcasecmp(v->value, "featb")) {
18733 confp->chan.sig = SIG_FEATB;
18734 #ifdef HAVE_PRI
18735 } else if (!strcasecmp(v->value, "pri_net")) {
18736 confp->chan.sig = SIG_PRI;
18737 confp->pri.pri.nodetype = PRI_NETWORK;
18738 } else if (!strcasecmp(v->value, "pri_cpe")) {
18739 confp->chan.sig = SIG_PRI;
18740 confp->pri.pri.nodetype = PRI_CPE;
18741 } else if (!strcasecmp(v->value, "bri_cpe")) {
18742 confp->chan.sig = SIG_BRI;
18743 confp->pri.pri.nodetype = PRI_CPE;
18744 } else if (!strcasecmp(v->value, "bri_net")) {
18745 confp->chan.sig = SIG_BRI;
18746 confp->pri.pri.nodetype = PRI_NETWORK;
18747 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
18748 confp->chan.sig = SIG_BRI_PTMP;
18749 confp->pri.pri.nodetype = PRI_CPE;
18750 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
18751 #if defined(HAVE_PRI_CALL_HOLD)
18752 confp->chan.sig = SIG_BRI_PTMP;
18753 confp->pri.pri.nodetype = PRI_NETWORK;
18754 #else
18755 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
18756 #endif /* !defined(HAVE_PRI_CALL_HOLD) */
18757 #endif
18758 #if defined(HAVE_SS7)
18759 } else if (!strcasecmp(v->value, "ss7")) {
18760 confp->chan.sig = SIG_SS7;
18761 #endif /* defined(HAVE_SS7) */
18762 #ifdef HAVE_OPENR2
18763 } else if (!strcasecmp(v->value, "mfcr2")) {
18764 confp->chan.sig = SIG_MFCR2;
18765 #endif
18766 } else if (!strcasecmp(v->value, "auto")) {
18767 confp->is_sig_auto = 1;
18768 } else {
18769 confp->chan.outsigmod = orig_outsigmod;
18770 confp->chan.radio = orig_radio;
18771 confp->is_sig_auto = orig_auto;
18772 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18773 }
18774 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18775 if (!strcasecmp(v->value, "em")) {
18776 confp->chan.outsigmod = SIG_EM;
18777 } else if (!strcasecmp(v->value, "em_e1")) {
18778 confp->chan.outsigmod = SIG_EM_E1;
18779 } else if (!strcasecmp(v->value, "em_w")) {
18780 confp->chan.outsigmod = SIG_EMWINK;
18781 } else if (!strcasecmp(v->value, "sf")) {
18782 confp->chan.outsigmod = SIG_SF;
18783 } else if (!strcasecmp(v->value, "sf_w")) {
18784 confp->chan.outsigmod = SIG_SFWINK;
18785 } else if (!strcasecmp(v->value, "sf_featd")) {
18786 confp->chan.outsigmod = SIG_FEATD;
18787 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18788 confp->chan.outsigmod = SIG_FEATDMF;
18789 } else if (!strcasecmp(v->value, "sf_featb")) {
18790 confp->chan.outsigmod = SIG_SF_FEATB;
18791 } else if (!strcasecmp(v->value, "sf")) {
18792 confp->chan.outsigmod = SIG_SF;
18793 } else if (!strcasecmp(v->value, "featd")) {
18794 confp->chan.outsigmod = SIG_FEATD;
18795 } else if (!strcasecmp(v->value, "featdmf")) {
18796 confp->chan.outsigmod = SIG_FEATDMF;
18797 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18798 confp->chan.outsigmod = SIG_FEATDMF_TA;
18799 } else if (!strcasecmp(v->value, "e911")) {
18800 confp->chan.outsigmod = SIG_E911;
18801 } else if (!strcasecmp(v->value, "fgccama")) {
18802 confp->chan.outsigmod = SIG_FGC_CAMA;
18803 } else if (!strcasecmp(v->value, "fgccamamf")) {
18804 confp->chan.outsigmod = SIG_FGC_CAMAMF;
18805 } else if (!strcasecmp(v->value, "featb")) {
18806 confp->chan.outsigmod = SIG_FEATB;
18807 } else {
18808 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18809 }
18810 #ifdef HAVE_PRI
18811 } else if (!strcasecmp(v->name, "pridialplan")) {
18812 if (!strcasecmp(v->value, "national")) {
18813 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18814 } else if (!strcasecmp(v->value, "unknown")) {
18815 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18816 } else if (!strcasecmp(v->value, "private")) {
18817 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18818 } else if (!strcasecmp(v->value, "international")) {
18819 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18820 } else if (!strcasecmp(v->value, "local")) {
18821 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18822 } else if (!strcasecmp(v->value, "dynamic")) {
18823 confp->pri.pri.dialplan = -1;
18824 } else if (!strcasecmp(v->value, "redundant")) {
18825 confp->pri.pri.dialplan = -2;
18826 } else {
18827 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18828 }
18829 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18830 if (!strcasecmp(v->value, "national")) {
18831 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18832 } else if (!strcasecmp(v->value, "unknown")) {
18833 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18834 } else if (!strcasecmp(v->value, "private")) {
18835 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18836 } else if (!strcasecmp(v->value, "international")) {
18837 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18838 } else if (!strcasecmp(v->value, "local")) {
18839 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18840 } else if (!strcasecmp(v->value, "from_channel")) {
18841 confp->pri.pri.localdialplan = 0;
18842 } else if (!strcasecmp(v->value, "dynamic")) {
18843 confp->pri.pri.localdialplan = -1;
18844 } else if (!strcasecmp(v->value, "redundant")) {
18845 confp->pri.pri.localdialplan = -2;
18846 } else {
18847 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18848 }
18849 } else if (!strcasecmp(v->name, "pricpndialplan")) {
18850 if (!strcasecmp(v->value, "national")) {
18851 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18852 } else if (!strcasecmp(v->value, "unknown")) {
18853 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18854 } else if (!strcasecmp(v->value, "private")) {
18855 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18856 } else if (!strcasecmp(v->value, "international")) {
18857 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18858 } else if (!strcasecmp(v->value, "local")) {
18859 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18860 } else if (!strcasecmp(v->value, "from_channel")) {
18861 confp->pri.pri.cpndialplan = 0;
18862 } else if (!strcasecmp(v->value, "dynamic")) {
18863 confp->pri.pri.cpndialplan = -1;
18864 } else if (!strcasecmp(v->value, "redundant")) {
18865 confp->pri.pri.cpndialplan = -2;
18866 } else {
18867 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18868 }
18869 } else if (!strcasecmp(v->name, "switchtype")) {
18870 if (!strcasecmp(v->value, "national"))
18871 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18872 else if (!strcasecmp(v->value, "ni1"))
18873 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18874 else if (!strcasecmp(v->value, "dms100"))
18875 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18876 else if (!strcasecmp(v->value, "4ess"))
18877 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18878 else if (!strcasecmp(v->value, "5ess"))
18879 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18880 else if (!strcasecmp(v->value, "euroisdn"))
18881 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18882 else if (!strcasecmp(v->value, "qsig"))
18883 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18884 else {
18885 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18886 return -1;
18887 }
18888 } else if (!strcasecmp(v->name, "msn")) {
18889 ast_copy_string(confp->pri.pri.msn_list, v->value,
18890 sizeof(confp->pri.pri.msn_list));
18891 } else if (!strcasecmp(v->name, "nsf")) {
18892 if (!strcasecmp(v->value, "sdn"))
18893 confp->pri.pri.nsf = PRI_NSF_SDN;
18894 else if (!strcasecmp(v->value, "megacom"))
18895 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18896 else if (!strcasecmp(v->value, "tollfreemegacom"))
18897 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18898 else if (!strcasecmp(v->value, "accunet"))
18899 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18900 else if (!strcasecmp(v->value, "none"))
18901 confp->pri.pri.nsf = PRI_NSF_NONE;
18902 else {
18903 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18904 confp->pri.pri.nsf = PRI_NSF_NONE;
18905 }
18906 } else if (!strcasecmp(v->name, "priindication")) {
18907 if (!strcasecmp(v->value, "outofband"))
18908 confp->chan.priindication_oob = 1;
18909 else if (!strcasecmp(v->value, "inband"))
18910 confp->chan.priindication_oob = 0;
18911 else
18912 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18913 v->value, v->lineno);
18914 } else if (!strcasecmp(v->name, "priexclusive")) {
18915 confp->chan.priexclusive = ast_true(v->value);
18916 } else if (!strcasecmp(v->name, "internationalprefix")) {
18917 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18918 } else if (!strcasecmp(v->name, "nationalprefix")) {
18919 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18920 } else if (!strcasecmp(v->name, "localprefix")) {
18921 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18922 } else if (!strcasecmp(v->name, "privateprefix")) {
18923 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18924 } else if (!strcasecmp(v->name, "unknownprefix")) {
18925 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18926 } else if (!strcasecmp(v->name, "resetinterval")) {
18927 if (!strcasecmp(v->value, "never"))
18928 confp->pri.pri.resetinterval = -1;
18929 else if (atoi(v->value) >= 60)
18930 confp->pri.pri.resetinterval = atoi(v->value);
18931 else
18932 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18933 v->value, v->lineno);
18934 } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
18935 confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
18936 } else if (!strcasecmp(v->name, "minunused")) {
18937 confp->pri.pri.minunused = atoi(v->value);
18938 } else if (!strcasecmp(v->name, "minidle")) {
18939 confp->pri.pri.minidle = atoi(v->value);
18940 } else if (!strcasecmp(v->name, "idleext")) {
18941 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18942 } else if (!strcasecmp(v->name, "idledial")) {
18943 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18944 } else if (!strcasecmp(v->name, "overlapdial")) {
18945 if (ast_true(v->value)) {
18946 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18947 } else if (!strcasecmp(v->value, "incoming")) {
18948 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18949 } else if (!strcasecmp(v->value, "outgoing")) {
18950 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18951 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18952 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18953 } else {
18954 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18955 }
18956 #ifdef HAVE_PRI_PROG_W_CAUSE
18957 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18958 if (!strcasecmp(v->value, "logical")) {
18959 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18960 } else if (!strcasecmp(v->value, "physical")) {
18961 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18962 } else {
18963 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18964 }
18965 #endif
18966 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18967 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18968 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18969 } else if (!strcasecmp(v->name, "service_message_support")) {
18970 /* assuming switchtype for this channel group has been configured already */
18971 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
18972 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18973 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18974 confp->pri.pri.enable_service_message_support = 1;
18975 } else {
18976 confp->pri.pri.enable_service_message_support = 0;
18977 }
18978 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
18979 #ifdef HAVE_PRI_INBANDDISCONNECT
18980 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18981 confp->pri.pri.inbanddisconnect = ast_true(v->value);
18982 #endif
18983 } else if (!strcasecmp(v->name, "pritimer")) {
18984 #ifdef PRI_GETSET_TIMERS
18985 char tmp[20];
18986 char *timerc;
18987 char *c;
18988 int timer;
18989 int timeridx;
18990
18991 ast_copy_string(tmp, v->value, sizeof(tmp));
18992 c = tmp;
18993 timerc = strsep(&c, ",");
18994 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18995 timeridx = pri_timer2idx(timerc);
18996 timer = atoi(c);
18997 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18998 ast_log(LOG_WARNING,
18999 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19000 v->lineno);
19001 } else if (!timer) {
19002 ast_log(LOG_WARNING,
19003 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19004 c, timerc, v->lineno);
19005 } else {
19006 confp->pri.pri.pritimers[timeridx] = timer;
19007 }
19008 } else {
19009 ast_log(LOG_WARNING,
19010 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19011 v->value, v->lineno);
19012 }
19013 #endif /* PRI_GETSET_TIMERS */
19014 } else if (!strcasecmp(v->name, "facilityenable")) {
19015 confp->pri.pri.facilityenable = ast_true(v->value);
19016 #if defined(HAVE_PRI_AOC_EVENTS)
19017 } else if (!strcasecmp(v->name, "aoc_enable")) {
19018 confp->pri.pri.aoc_passthrough_flag = 0;
19019 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
19020 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
19021 }
19022 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
19023 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
19024 }
19025 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
19026 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
19027 }
19028 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
19029 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
19030 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
19031 #if defined(HAVE_PRI_CALL_HOLD)
19032 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
19033 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
19034 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19035 } else if (!strcasecmp(v->name, "moh_signaling")
19036 || !strcasecmp(v->name, "moh_signalling")) {
19037 if (!strcasecmp(v->value, "moh")) {
19038 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19039 } else if (!strcasecmp(v->value, "notify")) {
19040 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
19041 #if defined(HAVE_PRI_CALL_HOLD)
19042 } else if (!strcasecmp(v->value, "hold")) {
19043 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
19044 #endif /* defined(HAVE_PRI_CALL_HOLD) */
19045 } else {
19046 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
19047 }
19048 #if defined(HAVE_PRI_CCSS)
19049 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
19050 if (!strcasecmp(v->value, "global")) {
19051 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
19052 } else if (!strcasecmp(v->value, "specific")) {
19053 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19054 } else {
19055 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
19056 }
19057 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
19058 if (!strcasecmp(v->value, "release")) {
19059 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
19060 } else if (!strcasecmp(v->value, "retain")) {
19061 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19062 } else if (!strcasecmp(v->value, "do_not_care")) {
19063 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
19064 } else {
19065 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
19066 }
19067 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
19068 if (!strcasecmp(v->value, "release")) {
19069 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
19070 } else if (!strcasecmp(v->value, "retain")) {
19071 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19072 } else {
19073 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
19074 }
19075 #endif /* defined(HAVE_PRI_CCSS) */
19076 #if defined(HAVE_PRI_CALL_WAITING)
19077 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
19078 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
19079 if (confp->pri.pri.max_call_waiting_calls < 0) {
19080 /* Negative values are not allowed. */
19081 confp->pri.pri.max_call_waiting_calls = 0;
19082 }
19083 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
19084 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
19085 #endif /* defined(HAVE_PRI_CALL_WAITING) */
19086 #if defined(HAVE_PRI_MWI)
19087 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
19088 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
19089 sizeof(confp->pri.pri.mwi_mailboxes));
19090 } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
19091 ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
19092 sizeof(confp->pri.pri.mwi_vm_boxes));
19093 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
19094 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
19095 sizeof(confp->pri.pri.mwi_vm_numbers));
19096 #endif /* defined(HAVE_PRI_MWI) */
19097 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
19098 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
19099 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
19100 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
19101 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
19102 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
19103 #if defined(HAVE_PRI_DISPLAY_TEXT)
19104 } else if (!strcasecmp(v->name, "display_send")) {
19105 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
19106 } else if (!strcasecmp(v->name, "display_receive")) {
19107 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
19108 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19109 #if defined(HAVE_PRI_MCID)
19110 } else if (!strcasecmp(v->name, "mcid_send")) {
19111 confp->pri.pri.mcid_send = ast_true(v->value);
19112 #endif /* defined(HAVE_PRI_MCID) */
19113 #if defined(HAVE_PRI_DATETIME_SEND)
19114 } else if (!strcasecmp(v->name, "datetime_send")) {
19115 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
19116 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
19117 } else if (!strcasecmp(v->name, "layer1_presence")) {
19118 if (!strcasecmp(v->value, "required")) {
19119 confp->pri.pri.layer1_ignored = 0;
19120 } else if (!strcasecmp(v->value, "ignore")) {
19121 confp->pri.pri.layer1_ignored = 1;
19122 } else {
19123 /* Default */
19124 confp->pri.pri.layer1_ignored = 0;
19125 }
19126 #if defined(HAVE_PRI_L2_PERSISTENCE)
19127 } else if (!strcasecmp(v->name, "layer2_persistence")) {
19128 if (!strcasecmp(v->value, "keep_up")) {
19129 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
19130 } else if (!strcasecmp(v->value, "leave_down")) {
19131 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
19132 } else {
19133 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
19134 }
19135 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
19136 } else if (!strcasecmp(v->name, "colp_send")) {
19137 if (!strcasecmp(v->value, "block")) {
19138 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
19139 } else if (!strcasecmp(v->value, "connect")) {
19140 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
19141 } else if (!strcasecmp(v->value, "update")) {
19142 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19143 } else {
19144 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
19145 }
19146 #endif /* HAVE_PRI */
19147 #if defined(HAVE_SS7)
19148 } else if (!strcasecmp(v->name, "ss7type")) {
19149 if (!strcasecmp(v->value, "itu")) {
19150 cur_ss7type = SS7_ITU;
19151 } else if (!strcasecmp(v->value, "ansi")) {
19152 cur_ss7type = SS7_ANSI;
19153 } else {
19154 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
19155 }
19156 } else if (!strcasecmp(v->name, "slc")) {
19157 cur_slc = atoi(v->value);
19158 } else if (!strcasecmp(v->name, "linkset")) {
19159 cur_linkset = atoi(v->value);
19160 } else if (!strcasecmp(v->name, "pointcode")) {
19161 cur_pointcode = parse_pointcode(v->value);
19162 } else if (!strcasecmp(v->name, "adjpointcode")) {
19163 cur_adjpointcode = parse_pointcode(v->value);
19164 } else if (!strcasecmp(v->name, "defaultdpc")) {
19165 cur_defaultdpc = parse_pointcode(v->value);
19166 } else if (!strcasecmp(v->name, "cicbeginswith")) {
19167 cur_cicbeginswith = atoi(v->value);
19168 } else if (!strcasecmp(v->name, "networkindicator")) {
19169 if (!strcasecmp(v->value, "national")) {
19170 cur_networkindicator = SS7_NI_NAT;
19171 } else if (!strcasecmp(v->value, "national_spare")) {
19172 cur_networkindicator = SS7_NI_NAT_SPARE;
19173 } else if (!strcasecmp(v->value, "international")) {
19174 cur_networkindicator = SS7_NI_INT;
19175 } else if (!strcasecmp(v->value, "international_spare")) {
19176 cur_networkindicator = SS7_NI_INT_SPARE;
19177 } else {
19178 cur_networkindicator = -1;
19179 }
19180 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
19181 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
19182 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
19183 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
19184 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
19185 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
19186 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
19187 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
19188 } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
19189 ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
19190 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
19191 if (!strcasecmp(v->value, "national")) {
19192 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19193 } else if (!strcasecmp(v->value, "international")) {
19194 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19195 } else if (!strcasecmp(v->value, "subscriber")) {
19196 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19197 } else if (!strcasecmp(v->value, "unknown")) {
19198 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19199 } else if (!strcasecmp(v->value, "dynamic")) {
19200 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19201 } else {
19202 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
19203 }
19204 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
19205 if (!strcasecmp(v->value, "national")) {
19206 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19207 } else if (!strcasecmp(v->value, "international")) {
19208 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19209 } else if (!strcasecmp(v->value, "subscriber")) {
19210 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19211 } else if (!strcasecmp(v->value, "unknown")) {
19212 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19213 } else if (!strcasecmp(v->value, "dynamic")) {
19214 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19215 } else {
19216 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
19217 }
19218 } else if (!strcasecmp(v->name, "sigchan")) {
19219 int sigchan, res;
19220 sigchan = atoi(v->value);
19221 res = linkset_addsigchan(sigchan);
19222 if (res < 0) {
19223 return -1;
19224 }
19225 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
19226 struct dahdi_ss7 *link;
19227 link = ss7_resolve_linkset(cur_linkset);
19228 if (!link) {
19229 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19230 return -1;
19231 }
19232 if (ast_true(v->value)) {
19233 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19234 } else {
19235 link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19236 }
19237 } else if (!strcasecmp(v->name, "ss7_autoacm")) {
19238 struct dahdi_ss7 *link;
19239 link = ss7_resolve_linkset(cur_linkset);
19240 if (!link) {
19241 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19242 return -1;
19243 }
19244 if (ast_true(v->value)) {
19245 link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19246 } else {
19247 link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19248 }
19249 } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
19250 struct dahdi_ss7 *link;
19251 link = ss7_resolve_linkset(cur_linkset);
19252 if (!link) {
19253 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19254 return -1;
19255 }
19256 if (ast_true(v->value)) {
19257 link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19258 } else {
19259 link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19260 }
19261 } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
19262 struct dahdi_ss7 *link;
19263 link = ss7_resolve_linkset(cur_linkset);
19264 if (!link) {
19265 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19266 return -1;
19267 }
19268 if (ast_true(v->value)) {
19269 link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19270 } else {
19271 link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19272 }
19273 } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
19274 struct dahdi_ss7 *link;
19275 link = ss7_resolve_linkset(cur_linkset);
19276 if (!link) {
19277 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19278 return -1;
19279 }
19280 if (ast_true(v->value)) {
19281 link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19282 } else {
19283 link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19284 }
19285 } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
19286 struct dahdi_ss7 *link;
19287 link = ss7_resolve_linkset(cur_linkset);
19288 if (!link) {
19289 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19290 return -1;
19291 }
19292 if (!link->ss7.ss7) {
19293 ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
19294 } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19295 ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
19296 }
19297 } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
19298 struct dahdi_ss7 *link;
19299 link = ss7_resolve_linkset(cur_linkset);
19300 if (!link) {
19301 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19302 return -1;
19303 }
19304 if (!link->ss7.ss7) {
19305 ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
19306 } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
19307 ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
19308 }
19309 } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
19310 struct dahdi_ss7 *link;
19311 link = ss7_resolve_linkset(cur_linkset);
19312 if (!link) {
19313 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19314 return -1;
19315 }
19316 if (!link->ss7.ss7) {
19317 ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
19318 } else if (ast_true(v->value)) {
19319 ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19320 } else {
19321 ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19322 }
19323 } else if (!strcasecmp(v->name, "non_isdn_access")) {
19324 struct dahdi_ss7 *link;
19325 link = ss7_resolve_linkset(cur_linkset);
19326 if (!link) {
19327 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19328 return -1;
19329 }
19330 if (!link->ss7.ss7) {
19331 ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
19332 } else if (ast_true(v->value)) {
19333 ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19334 } else {
19335 ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19336 }
19337 } else if (!strcasecmp(v->name, "sls_shift")) {
19338 struct dahdi_ss7 *link;
19339 int sls_shift = atoi(v->value);
19340
19341 if (sls_shift < 0 || sls_shift > 7) {
19342 ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
19343 return -1;
19344 }
19345
19346 link = ss7_resolve_linkset(cur_linkset);
19347 if (!link) {
19348 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19349 return -1;
19350 }
19351 if (!link->ss7.ss7) {
19352 ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
19353 } else {
19354 ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19355 }
19356 } else if (!strcasecmp(v->name, "cause_location")) {
19357 struct dahdi_ss7 *link;
19358 int cause_location = atoi(v->value);
19359
19360 if (cause_location < 0 || cause_location > 15) {
19361 ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
19362 return -1;
19363 }
19364 link = ss7_resolve_linkset(cur_linkset);
19365 if (!link) {
19366 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19367 return -1;
19368 }
19369 if (!link->ss7.ss7) {
19370 ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19371 } else {
19372 ss7_set_cause_location(link->ss7.ss7, cause_location);
19373 }
19374 #endif /* defined(HAVE_SS7) */
19375 #ifdef HAVE_OPENR2
19376 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19377 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19378 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);
19379 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19380 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19381 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19382 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19383 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19384 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19385 confp->mfcr2.variant = OR2_VAR_ITU;
19386 }
19387 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19388 confp->mfcr2.mfback_timeout = atoi(v->value);
19389 if (!confp->mfcr2.mfback_timeout) {
19390 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19391 confp->mfcr2.mfback_timeout = -1;
19392 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19393 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19394 }
19395 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19396 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19397 if (confp->mfcr2.metering_pulse_timeout > 500) {
19398 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19399 }
19400 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19401 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19402 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19403 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19404 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19405 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19406 confp->mfcr2.dtmf_time_on = atoi(v->value);
19407 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19408 confp->mfcr2.dtmf_time_off = atoi(v->value);
19409 #endif
19410 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19411 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19412 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19413 #endif
19414 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19415 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19416 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19417 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19418 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19419 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19420 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19421 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19422 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19423 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19424 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19425 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19426 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19427 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19428 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19429 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19430 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19431 #endif
19432 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19433 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19434 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19435 confp->mfcr2.max_ani = atoi(v->value);
19436 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19437 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19438 }
19439 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19440 confp->mfcr2.max_dnis = atoi(v->value);
19441 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19442 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19443 }
19444 } else if (!strcasecmp(v->name, "mfcr2_category")) {
19445 confp->mfcr2.category = openr2_proto_get_category(v->value);
19446 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19447 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19448 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19449 v->value, v->lineno);
19450 }
19451 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19452 openr2_log_level_t tmplevel;
19453 char *clevel;
19454 char *logval;
19455 char copy[strlen(v->value) + 1];
19456 strcpy(copy, v->value); /* safe */
19457 logval = copy;
19458 while (logval) {
19459 clevel = strsep(&logval,",");
19460 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19461 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19462 continue;
19463 }
19464 confp->mfcr2.loglevel |= tmplevel;
19465 }
19466 #endif /* HAVE_OPENR2 */
19467 } else if (!strcasecmp(v->name, "cadence")) {
19468 /* setup to scan our argument */
19469 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19470 int i;
19471 struct dahdi_ring_cadence new_cadence;
19472 int cid_location = -1;
19473 int firstcadencepos = 0;
19474 char original_args[80];
19475 int cadence_is_ok = 1;
19476
19477 ast_copy_string(original_args, v->value, sizeof(original_args));
19478 /* 16 cadences allowed (8 pairs) */
19479 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]);
19480
19481 /* Cadence must be even (on/off) */
19482 if (element_count % 2 == 1) {
19483 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19484 cadence_is_ok = 0;
19485 }
19486
19487 /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19488 if (element_count > ARRAY_LEN(c)) {
19489 element_count = ARRAY_LEN(c);
19490 }
19491
19492 /* Ring cadences cannot be negative */
19493 for (i = 0; i < element_count; i++) {
19494 if (c[i] == 0) {
19495 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19496 cadence_is_ok = 0;
19497 break;
19498 } else if (c[i] < 0) {
19499 if (i % 2 == 1) {
19500 /* Silence duration, negative possibly okay */
19501 if (cid_location == -1) {
19502 cid_location = i;
19503 c[i] *= -1;
19504 } else {
19505 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19506 cadence_is_ok = 0;
19507 break;
19508 }
19509 } else {
19510 if (firstcadencepos == 0) {
19511 firstcadencepos = i; /* only recorded to avoid duplicate specification */
19512 /* duration will be passed negative to the DAHDI driver */
19513 } else {
19514 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19515 cadence_is_ok = 0;
19516 break;
19517 }
19518 }
19519 }
19520 }
19521
19522 /* Substitute our scanned cadence */
19523 for (i = 0; i < 16; i++) {
19524 new_cadence.ringcadence[i] = c[i];
19525 }
19526
19527 if (cadence_is_ok) {
19528 /* ---we scanned it without getting annoyed; now some sanity checks--- */
19529 if (element_count < 2) {
19530 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19531 } else {
19532 if (cid_location == -1) {
19533 /* user didn't say; default to first pause */
19534 cid_location = 1;
19535 } else {
19536 /* convert element_index to cidrings value */
19537 cid_location = (cid_location + 1) / 2;
19538 }
19539 /* ---we like their cadence; try to install it--- */
19540 if (!user_has_defined_cadences++)
19541 /* this is the first user-defined cadence; clear the default user cadences */
19542 num_cadence = 0;
19543 if ((num_cadence+1) >= NUM_CADENCE_MAX)
19544 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19545 else {
19546 cadences[num_cadence] = new_cadence;
19547 cidrings[num_cadence++] = cid_location;
19548 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19549 }
19550 }
19551 }
19552 } else if (!strcasecmp(v->name, "ringtimeout")) {
19553 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19554 } else if (!strcasecmp(v->name, "prewink")) {
19555 confp->timing.prewinktime = atoi(v->value);
19556 } else if (!strcasecmp(v->name, "preflash")) {
19557 confp->timing.preflashtime = atoi(v->value);
19558 } else if (!strcasecmp(v->name, "wink")) {
19559 confp->timing.winktime = atoi(v->value);
19560 } else if (!strcasecmp(v->name, "flash")) {
19561 confp->timing.flashtime = atoi(v->value);
19562 } else if (!strcasecmp(v->name, "start")) {
19563 confp->timing.starttime = atoi(v->value);
19564 } else if (!strcasecmp(v->name, "rxwink")) {
19565 confp->timing.rxwinktime = atoi(v->value);
19566 } else if (!strcasecmp(v->name, "rxflash")) {
19567 confp->timing.rxflashtime = atoi(v->value);
19568 } else if (!strcasecmp(v->name, "debounce")) {
19569 confp->timing.debouncetime = atoi(v->value);
19570 } else if (!strcasecmp(v->name, "toneduration")) {
19571 int toneduration;
19572 int ctlfd;
19573 int res;
19574 struct dahdi_dialparams dps;
19575
19576 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19577 if (ctlfd == -1) {
19578 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19579 return -1;
19580 }
19581
19582 toneduration = atoi(v->value);
19583 if (toneduration > -1) {
19584 memset(&dps, 0, sizeof(dps));
19585
19586 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19587 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19588 if (res < 0) {
19589 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19590 close(ctlfd);
19591 return -1;
19592 }
19593 }
19594 close(ctlfd);
19595 } else if (!strcasecmp(v->name, "defaultcic")) {
19596 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
19597 } else if (!strcasecmp(v->name, "defaultozz")) {
19598 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
19599 } else if (!strcasecmp(v->name, "mwilevel")) {
19600 mwilevel = atoi(v->value);
19601 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19602 dtmfcid_level = atoi(v->value);
19603 } else if (!strcasecmp(v->name, "reportalarms")) {
19604 if (!strcasecmp(v->value, "all"))
19605 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
19606 if (!strcasecmp(v->value, "none"))
19607 report_alarms = 0;
19608 else if (!strcasecmp(v->value, "channels"))
19609 report_alarms = REPORT_CHANNEL_ALARMS;
19610 else if (!strcasecmp(v->value, "spans"))
19611 report_alarms = REPORT_SPAN_ALARMS;
19612 }
19613 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19614 ast_log(LOG_NOTICE, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19615 }
19616
19617 if (dahdichan) {
19618 /* Process the deferred dahdichan value. */
19619 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19620 if (confp->ignore_failed_channels) {
19621 ast_log(LOG_WARNING,
19622 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19623 dahdichan->value);
19624 } else {
19625 return -1;
19626 }
19627 }
19628 }
19629
19630 /*
19631 * Since confp has already filled individual dahdi_pvt objects with channels
19632 * at this point, clear the variables in confp's pvt.
19633 */
19634 if (confp->chan.vars) {
19635 ast_variables_destroy(confp->chan.vars);
19636 confp->chan.vars = NULL;
19637 }
19638
19639 /* mark the first channels of each DAHDI span to watch for their span alarms */
19640 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19641 if (!tmp->destroy && tmp->span != y) {
19642 tmp->manages_span_alarms = 1;
19643 y = tmp->span;
19644 } else {
19645 tmp->manages_span_alarms = 0;
19646 }
19647 }
19648
19649 /*< \todo why check for the pseudo in the per-channel section.
19650 * Any actual use for manual setup of the pseudo channel? */
19651 if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19652 /* use the default configuration for a channel, so
19653 that any settings from real configured channels
19654 don't "leak" into the pseudo channel config
19655 */
19656 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19657
19658 if (conf.chan.cc_params) {
19659 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
19660 } else {
19661 tmp = NULL;
19662 }
19663 if (tmp) {
19664 ast_verb(3, "Automatically generated pseudo channel\n");
19665 has_pseudo = 1;
19666 } else {
19667 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19668 }
19669 ast_cc_config_params_destroy(conf.chan.cc_params);
19670 }
19671
19672 /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19673 confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
19674 confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
19675
19676 return 0;
19677 }
19678
19679 /*!
19680 * \internal
19681 * \brief Deep copy struct dahdi_chan_conf.
19682 * \since 1.8
19683 *
19684 * \param dest Destination.
19685 * \param src Source.
19686 */
19687 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
19688 {
19689 struct ast_cc_config_params *cc_params;
19690
19691 cc_params = dest->chan.cc_params;
19692 *dest = *src;
19693 dest->chan.cc_params = cc_params;
19694 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
19695 }
19696
19697 /*!
19698 * \internal
19699 * \brief Setup DAHDI channel driver.
19700 *
19701 * \param reload enum: load_module(0), reload(1), restart(2).
19702 * \param default_conf Default config parameters. So cc_params can be properly destroyed.
19703 * \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
19704 * \param conf Local config parameters. So cc_params can be properly destroyed.
19705 *
19706 * \retval 0 on success.
19707 * \retval -1 on error.
19708 */
19709 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
19710 {
19711 struct ast_config *cfg;
19712 struct ast_config *ucfg;
19713 struct ast_variable *v;
19714 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19715 const char *chans;
19716 const char *cat;
19717 int res;
19718
19719 #ifdef HAVE_PRI
19720 char *c;
19721 int spanno;
19722 int i;
19723 int logicalspan;
19724 int trunkgroup;
19725 int dchannels[SIG_PRI_NUM_DCHANS];
19726 #endif
19727 int have_cfg_now;
19728 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19729
19730 cfg = ast_config_load(config, config_flags);
19731 have_cfg_now = !!cfg;
19732 if (!cfg) {
19733 /* Error if we have no config file */
19734 if (had_cfg_before) {
19735 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19736 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19737 }
19738 cfg = ast_config_new();/* Dummy config */
19739 if (!cfg) {
19740 return 0;
19741 }
19742 ucfg = ast_config_load("users.conf", config_flags);
19743 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19744 ast_config_destroy(cfg);
19745 return 0;
19746 }
19747 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19748 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19749 ast_config_destroy(cfg);
19750 return 0;
19751 }
19752 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
19753 ucfg = ast_config_load("users.conf", config_flags);
19754 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19755 return 0;
19756 }
19757 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19758 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19759 return 0;
19760 }
19761 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19762 cfg = ast_config_load(config, config_flags);
19763 have_cfg_now = !!cfg;
19764 if (!cfg) {
19765 if (had_cfg_before) {
19766 /* We should have been able to load the config. */
19767 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
19768 ast_config_destroy(ucfg);
19769 return 0;
19770 }
19771 cfg = ast_config_new();/* Dummy config */
19772 if (!cfg) {
19773 ast_config_destroy(ucfg);
19774 return 0;
19775 }
19776 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19777 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19778 ast_config_destroy(ucfg);
19779 return 0;
19780 }
19781 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19782 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19783 return 0;
19784 } else {
19785 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19786 ucfg = ast_config_load("users.conf", config_flags);
19787 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19788 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19789 ast_config_destroy(cfg);
19790 return 0;
19791 }
19792 }
19793 had_cfg_before = have_cfg_now;
19794
19795 /* It's a little silly to lock it, but we might as well just to be sure */
19796 ast_mutex_lock(&iflock);
19797 #ifdef HAVE_PRI
19798 if (reload != 1) {
19799 /* Process trunkgroups first */
19800 v = ast_variable_browse(cfg, "trunkgroups");
19801 while (v) {
19802 if (!strcasecmp(v->name, "trunkgroup")) {
19803 trunkgroup = atoi(v->value);
19804 if (trunkgroup > 0) {
19805 if ((c = strchr(v->value, ','))) {
19806 i = 0;
19807 memset(dchannels, 0, sizeof(dchannels));
19808 while (c && (i < SIG_PRI_NUM_DCHANS)) {
19809 dchannels[i] = atoi(c + 1);
19810 if (dchannels[i] < 0) {
19811 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);
19812 } else
19813 i++;
19814 c = strchr(c + 1, ',');
19815 }
19816 if (i) {
19817 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
19818 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);
19819 } else
19820 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");
19821 } else
19822 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19823 } else
19824 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19825 } else
19826 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
19827 } else if (!strcasecmp(v->name, "spanmap")) {
19828 spanno = atoi(v->value);
19829 if (spanno > 0) {
19830 if ((c = strchr(v->value, ','))) {
19831 trunkgroup = atoi(c + 1);
19832 if (trunkgroup > 0) {
19833 if ((c = strchr(c + 1, ',')))
19834 logicalspan = atoi(c + 1);
19835 else
19836 logicalspan = 0;
19837 if (logicalspan >= 0) {
19838 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
19839 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19840 } else
19841 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19842 } else
19843 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);
19844 } else
19845 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
19846 } else
19847 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
19848 } else
19849 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
19850 } else {
19851 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
19852 }
19853 v = v->next;
19854 }
19855 }
19856 #endif
19857
19858 /* Copy the default jb config over global_jbconf */
19859 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
19860
19861 mwimonitornotify[0] = '\0';
19862
19863 v = ast_variable_browse(cfg, "channels");
19864 if ((res = process_dahdi(base_conf,
19865 "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
19866 v, reload, 0))) {
19867 ast_mutex_unlock(&iflock);
19868 ast_config_destroy(cfg);
19869 if (ucfg) {
19870 ast_config_destroy(ucfg);
19871 }
19872 return res;
19873 }
19874
19875 /* Now get configuration from all normal sections in chan_dahdi.conf: */
19876 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
19877 /* [channels] and [trunkgroups] are used. Let's also reserve
19878 * [globals] and [general] for future use
19879 */
19880 if (!strcasecmp(cat, "general") ||
19881 !strcasecmp(cat, "trunkgroups") ||
19882 !strcasecmp(cat, "globals") ||
19883 !strcasecmp(cat, "channels")) {
19884 continue;
19885 }
19886
19887 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
19888 if (ast_strlen_zero(chans)) {
19889 /* Section is useless without a dahdichan value present. */
19890 continue;
19891 }
19892
19893 /* Copy base_conf to conf. */
19894 deep_copy_dahdi_chan_conf(conf, base_conf);
19895
19896 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
19897 ast_mutex_unlock(&iflock);
19898 ast_config_destroy(cfg);
19899 if (ucfg) {
19900 ast_config_destroy(ucfg);
19901 }
19902 return res;
19903 }
19904 }
19905
19906 ast_config_destroy(cfg);
19907
19908 if (ucfg) {
19909 /* Reset base_conf, so things don't leak from chan_dahdi.conf */
19910 deep_copy_dahdi_chan_conf(base_conf, default_conf);
19911 process_dahdi(base_conf,
19912 "" /* Must be empty for the general category. Silly voicemail mailbox. */,
19913 ast_variable_browse(ucfg, "general"), 1, 0);
19914
19915 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
19916 if (!strcasecmp(cat, "general")) {
19917 continue;
19918 }
19919
19920 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19921 if (ast_strlen_zero(chans)) {
19922 /* Section is useless without a dahdichan value present. */
19923 continue;
19924 }
19925
19926 /* Copy base_conf to conf. */
19927 deep_copy_dahdi_chan_conf(conf, base_conf);
19928
19929 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19930 ast_config_destroy(ucfg);
19931 ast_mutex_unlock(&iflock);
19932 return res;
19933 }
19934 }
19935 ast_config_destroy(ucfg);
19936 }
19937 ast_mutex_unlock(&iflock);
19938
19939 #ifdef HAVE_PRI
19940 if (reload != 1) {
19941 int x;
19942 for (x = 0; x < NUM_SPANS; x++) {
19943 if (pris[x].pri.pvts[0] &&
19944 pris[x].pri.master == AST_PTHREADT_NULL) {
19945 prepare_pri(pris + x);
19946 if (sig_pri_start_pri(&pris[x].pri)) {
19947 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19948 return -1;
19949 } else
19950 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19951 }
19952 }
19953 }
19954 #endif
19955 #if defined(HAVE_SS7)
19956 if (reload != 1) {
19957 int x;
19958 for (x = 0; x < NUM_SPANS; x++) {
19959 if (linksets[x].ss7.ss7) {
19960 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19961 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19962 return -1;
19963 } else
19964 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19965 }
19966 }
19967 }
19968 #endif /* defined(HAVE_SS7) */
19969 #ifdef HAVE_OPENR2
19970 if (reload != 1) {
19971 struct r2link_entry *cur;
19972 int x = 0;
19973 AST_LIST_LOCK(&r2links);
19974 AST_LIST_TRAVERSE(&r2links, cur, list) {
19975 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
19976 if (r2->r2master == AST_PTHREADT_NULL) {
19977 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
19978 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19979 return -1;
19980 } else {
19981 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19982 }
19983 x++;
19984 }
19985 }
19986 AST_LIST_UNLOCK(&r2links);
19987 }
19988 #endif
19989 /* And start the monitor for the first time */
19990 restart_monitor();
19991 return 0;
19992 }
19993
19994 /*!
19995 * \internal
19996 * \brief Setup DAHDI channel driver.
19997 *
19998 * \param reload enum: load_module(0), reload(1), restart(2).
19999 *
20000 * \retval 0 on success.
20001 * \retval -1 on error.
20002 */
20003 static int setup_dahdi(int reload)
20004 {
20005 int res;
20006 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
20007 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
20008 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
20009
20010 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20011 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20012 } else {
20013 res = -1;
20014 }
20015 ast_cc_config_params_destroy(default_conf.chan.cc_params);
20016 ast_cc_config_params_destroy(base_conf.chan.cc_params);
20017 ast_cc_config_params_destroy(conf.chan.cc_params);
20018
20019 return res;
20020 }
20021
20022 /*!
20023 * \brief Load the module
20024 *
20025 * Module loading including tests for configuration or dependencies.
20026 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
20027 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
20028 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
20029 * configuration file or other non-critical problem return
20030 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
20031 */
20032 static int load_module(void)
20033 {
20034 int res;
20035 #if defined(HAVE_PRI) || defined(HAVE_SS7)
20036 int y;
20037 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
20038
20039 if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
20040 return AST_MODULE_LOAD_DECLINE;
20041 }
20042
20043 if (!(dahdi_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
20044 return AST_MODULE_LOAD_DECLINE;
20045 }
20046 ast_format_cap_append(dahdi_tech.capabilities, ast_format_slin, 0);
20047 ast_format_cap_append(dahdi_tech.capabilities, ast_format_ulaw, 0);
20048 ast_format_cap_append(dahdi_tech.capabilities, ast_format_alaw, 0);
20049
20050 if (dahdi_native_load(&dahdi_tech)) {
20051 ao2_ref(dahdi_tech.capabilities, -1);
20052 return AST_MODULE_LOAD_DECLINE;
20053 }
20054
20055 #ifdef HAVE_PRI
20056 memset(pris, 0, sizeof(pris));
20057 for (y = 0; y < NUM_SPANS; y++) {
20058 sig_pri_init_pri(&pris[y].pri);
20059 }
20060 pri_set_error(dahdi_pri_error);
20061 pri_set_message(dahdi_pri_message);
20062 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
20063 #ifdef HAVE_PRI_PROG_W_CAUSE
20064 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
20065 #endif
20066 #if defined(HAVE_PRI_CCSS)
20067 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
20068 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
20069 __unload_module();
20070 return AST_MODULE_LOAD_DECLINE;
20071 }
20072 #endif /* defined(HAVE_PRI_CCSS) */
20073 if (sig_pri_load(
20074 #if defined(HAVE_PRI_CCSS)
20075 dahdi_pri_cc_type
20076 #else
20077 NULL
20078 #endif /* defined(HAVE_PRI_CCSS) */
20079 )) {
20080 __unload_module();
20081 return AST_MODULE_LOAD_DECLINE;
20082 }
20083 #endif
20084 #if defined(HAVE_SS7)
20085 memset(linksets, 0, sizeof(linksets));
20086 for (y = 0; y < NUM_SPANS; y++) {
20087 sig_ss7_init_linkset(&linksets[y].ss7);
20088 }
20089 ss7_set_error(dahdi_ss7_error);
20090 ss7_set_message(dahdi_ss7_message);
20091 ss7_set_hangup(sig_ss7_cb_hangup);
20092 ss7_set_notinservice(sig_ss7_cb_notinservice);
20093 ss7_set_call_null(sig_ss7_cb_call_null);
20094 #endif /* defined(HAVE_SS7) */
20095 res = setup_dahdi(0);
20096 /* Make sure we can register our DAHDI channel type */
20097 if (res) {
20098 __unload_module();
20099 return AST_MODULE_LOAD_DECLINE;
20100 }
20101 if (ast_channel_register(&dahdi_tech)) {
20102 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
20103 __unload_module();
20104 return AST_MODULE_LOAD_DECLINE;
20105 }
20106 #ifdef HAVE_PRI
20107 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
20108 #endif
20109 #if defined(HAVE_SS7)
20110 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
20111 #endif /* defined(HAVE_SS7) */
20112 #ifdef HAVE_OPENR2
20113 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
20114 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
20115 #endif
20116
20117 ast_custom_function_register(&polarity_function);
20118
20119 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
20120 memset(round_robin, 0, sizeof(round_robin));
20121 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
20122 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
20123 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
20124 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
20125 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
20126 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
20127 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
20128 #if defined(HAVE_PRI)
20129 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
20130 ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
20131 ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
20132 ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
20133 #endif /* defined(HAVE_PRI) */
20134
20135 ast_cond_init(&ss_thread_complete, NULL);
20136
20137 return res;
20138 }
20139
20140 static int dahdi_sendtext(struct ast_channel *c, const char *text)
20141 {
20142 #define END_SILENCE_LEN 400
20143 #define HEADER_MS 50
20144 #define TRAILER_MS 5
20145 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20146 #define ASCII_BYTES_PER_CHAR 80
20147
20148 unsigned char *buf,*mybuf;
20149 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20150 struct pollfd fds[1];
20151 int size,res,fd,len,x;
20152 int bytes=0;
20153 int idx;
20154
20155 /*
20156 * Initial carrier (imaginary)
20157 *
20158 * Note: The following float variables are used by the
20159 * PUT_CLID_MARKMS and PUT_CLID() macros.
20160 */
20161 float cr = 1.0;
20162 float ci = 0.0;
20163 float scont = 0.0;
20164
20165 if (!text[0]) {
20166 return(0); /* if nothing to send, don't */
20167 }
20168 idx = dahdi_get_index(c, p, 0);
20169 if (idx < 0) {
20170 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
20171 return -1;
20172 }
20173 if ((!p->tdd) && (!p->mate)) {
20174 #if defined(HAVE_PRI)
20175 #if defined(HAVE_PRI_DISPLAY_TEXT)
20176 ast_mutex_lock(&p->lock);
20177 if (dahdi_sig_pri_lib_handles(p->sig)) {
20178 sig_pri_sendtext(p->sig_pvt, text);
20179 }
20180 ast_mutex_unlock(&p->lock);
20181 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
20182 #endif /* defined(HAVE_PRI) */
20183 return(0); /* if not in TDD mode, just return */
20184 }
20185 if (p->mate)
20186 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
20187 else
20188 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20189 if (!buf)
20190 return -1;
20191 mybuf = buf;
20192 if (p->mate) {
20193 /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
20194 struct ast_format *codec = AST_LAW(p);
20195
20196 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
20197 PUT_CLID_MARKMS;
20198 }
20199 /* Put actual message */
20200 for (x = 0; text[x]; x++) {
20201 PUT_CLID(text[x]);
20202 }
20203 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
20204 PUT_CLID_MARKMS;
20205 }
20206 len = bytes;
20207 buf = mybuf;
20208 } else {
20209 len = tdd_generate(p->tdd, buf, text);
20210 if (len < 1) {
20211 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
20212 ast_free(mybuf);
20213 return -1;
20214 }
20215 }
20216 memset(buf + len, 0x7f, END_SILENCE_LEN);
20217 len += END_SILENCE_LEN;
20218 fd = p->subs[idx].dfd;
20219 while (len) {
20220 if (ast_check_hangup(c)) {
20221 ast_free(mybuf);
20222 return -1;
20223 }
20224 size = len;
20225 if (size > READ_SIZE)
20226 size = READ_SIZE;
20227 fds[0].fd = fd;
20228 fds[0].events = POLLOUT | POLLPRI;
20229 fds[0].revents = 0;
20230 res = poll(fds, 1, -1);
20231 if (!res) {
20232 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
20233 continue;
20234 }
20235 /* if got exception */
20236 if (fds[0].revents & POLLPRI) {
20237 ast_free(mybuf);
20238 return -1;
20239 }
20240 if (!(fds[0].revents & POLLOUT)) {
20241 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
20242 continue;
20243 }
20244 res = write(fd, buf, size);
20245 if (res != size) {
20246 if (res == -1) {
20247 ast_free(mybuf);
20248 return -1;
20249 }
20250 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
20251 break;
20252 }
20253 len -= size;
20254 buf += size;
20255 }
20256 ast_free(mybuf);
20257 return(0);
20258 }
20259
20260
20261 static int reload(void)
20262 {
20263 int res = 0;
20264
20265 res = setup_dahdi(1);
20266 if (res) {
20267 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
20268 return -1;
20269 }
20270 return 0;
20271 }
20272
20273 /* This is a workaround so that menuselect displays a proper description
20274 * AST_MODULE_INFO(, , "DAHDI Telephony"
20275 */
20276
20277 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
20278 .support_level = AST_MODULE_SUPPORT_CORE,
20279 .load = load_module,
20280 .unload = unload_module,
20281 .reload = reload,
20282 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
20283 .requires = "ccss",
20284 .optional_modules = "res_smdi",
20285 );