34a134eb4f631f63852f6c5d62acc23f65efbb8f
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2006, Christian Richter
5  *
6  * Christian Richter <crich@beronet.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
20 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  *
25  * \author Christian Richter <crich@beronet.com>
26  *
27  * MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31
32 /*! \li \ref chan_misdn.c uses the configuration file \ref misdn.conf
33  * \addtogroup configuration_file
34  */
35
36 /*! \page misdn.conf misdn.conf
37  * \verbinclude misdn.conf.sample
38  */
39
40 /*!
41  * \note
42  * To use the CCBS/CCNR supplementary service feature and other
43  * supplementary services using FACILITY messages requires a
44  * modified version of mISDN.
45  *
46  * \note
47  * The latest modified mISDN v1.1.x based version is available at:
48  * http://svn.digium.com/svn/thirdparty/mISDN/trunk
49  * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
50  *
51  * \note
52  * Taged versions of the modified mISDN code are available under:
53  * http://svn.digium.com/svn/thirdparty/mISDN/tags
54  * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
55  */
56
57 /* Define to enable cli commands to generate canned CCBS messages. */
58 // #define CCBS_TEST_MESSAGES   1
59
60 /*** MODULEINFO
61         <depend>isdnnet</depend>
62         <depend>misdn</depend>
63         <depend>suppserv</depend>
64         <support_level>extended</support_level>
65  ***/
66
67 #include "asterisk.h"
68
69 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
70
71 #include <pthread.h>
72 #include <sys/socket.h>
73 #include <sys/time.h>
74 #include <arpa/inet.h>
75 #include <fcntl.h>
76 #include <sys/ioctl.h>
77 #include <signal.h>
78 #include <sys/file.h>
79 #include <semaphore.h>
80 #include <ctype.h>
81 #include <time.h>
82
83 #include "asterisk/channel.h"
84 #include "asterisk/config.h"
85 #include "asterisk/module.h"
86 #include "asterisk/pbx.h"
87 #include "asterisk/io.h"
88 #include "asterisk/frame.h"
89 #include "asterisk/translate.h"
90 #include "asterisk/cli.h"
91 #include "asterisk/musiconhold.h"
92 #include "asterisk/dsp.h"
93 #include "asterisk/file.h"
94 #include "asterisk/callerid.h"
95 #include "asterisk/indications.h"
96 #include "asterisk/app.h"
97 #include "asterisk/features.h"
98 #include "asterisk/term.h"
99 #include "asterisk/sched.h"
100 #include "asterisk/stringfields.h"
101 #include "asterisk/abstract_jb.h"
102 #include "asterisk/causes.h"
103 #include "asterisk/format.h"
104 #include "asterisk/format_cap.h"
105 #include "asterisk/features_config.h"
106 #include "asterisk/bridge.h"
107
108 #include "chan_misdn_config.h"
109 #include "isdn_lib.h"
110
111 static char global_tracefile[BUFFERSIZE + 1];
112
113 static int g_config_initialized = 0;
114
115 struct misdn_jb{
116         int size;
117         int upper_threshold;
118         char *samples, *ok;
119         int wp,rp;
120         int state_empty;
121         int state_full;
122         int state_buffer;
123         int bytes_wrote;
124         ast_mutex_t mutexjb;
125 };
126
127 /*! \brief allocates the jb-structure and initialize the elements */
128 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
129
130 /*! \brief frees the data and destroys the given jitterbuffer struct */
131 void misdn_jb_destroy(struct misdn_jb *jb);
132
133 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
134 error (buffer overrun). */
135 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
136
137 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
138 available data is returned and the return value indicates the number
139 of data. */
140 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
141
142 static char *complete_ch(struct ast_cli_args *a);
143 static char *complete_debug_port(struct ast_cli_args *a);
144 static char *complete_show_config(struct ast_cli_args *a);
145
146 /* BEGIN: chan_misdn.h */
147
148 #if defined(AST_MISDN_ENHANCEMENTS)
149 /*
150  * This timeout duration is to clean up any call completion records that
151  * are forgotten about by the switch.
152  */
153 #define MISDN_CC_RECORD_AGE_MAX         (6UL * 60 * 60) /* seconds */
154
155 #define MISDN_CC_REQUEST_WAIT_MAX       5       /* seconds */
156
157 /*!
158  * \brief Caller that initialized call completion services
159  *
160  * \details
161  * This data is the payload for a datastore that is put on the channel that
162  * initializes call completion services.  This datastore is set to be inherited
163  * by the outbound mISDN channel.  When one of these channels hangs up, the
164  * channel pointer will be set to NULL.  That way, we can ensure that we do not
165  * touch this channel after it gets destroyed.
166  */
167 struct misdn_cc_caller {
168         /*! \brief The channel that initialized call completion services */
169         struct ast_channel *chan;
170 };
171
172 struct misdn_cc_notify {
173         /*! \brief Dialplan: Notify extension priority */
174         int priority;
175
176         /*! \brief Dialplan: Notify extension context */
177         char context[AST_MAX_CONTEXT];
178
179         /*! \brief Dialplan: Notify extension number (User-A) */
180         char exten[AST_MAX_EXTENSION];
181 };
182
183 /*! \brief mISDN call completion record */
184 struct misdn_cc_record {
185         /*! \brief Call completion record linked list */
186         AST_LIST_ENTRY(misdn_cc_record) list;
187
188         /*! \brief Time the record was created. */
189         time_t time_created;
190
191         /*! \brief MISDN_CC_RECORD_ID value */
192         long record_id;
193
194         /*!
195          * \brief Logical Layer 1 port associated with this
196          * call completion record
197          */
198         int port;
199
200         /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
201         int ptp;
202
203         /*! \brief Mode specific parameters */
204         union {
205                 /*! \brief point-to-point specific parameters. */
206                 struct {
207                         /*!
208                          * \brief Call-completion signaling link.
209                          * NULL if signaling link not established.
210                          */
211                         struct misdn_bchannel *bc;
212
213                         /*!
214                          * \brief TRUE if we requested the request retention option
215                          * to be enabled.
216                          */
217                         int requested_retention;
218
219                         /*!
220                          * \brief TRUE if the request retention option is enabled.
221                          */
222                         int retention_enabled;
223                 } ptp;
224
225                 /*! \brief point-to-multi-point specific parameters. */
226                 struct {
227                         /*! \brief CallLinkageID (valid when port determined) */
228                         int linkage_id;
229
230                         /*! \breif CCBSReference (valid when activated is TRUE) */
231                         int reference_id;
232
233                         /*! \brief globalRecall(0),     specificRecall(1) */
234                         int recall_mode;
235                 } ptmp;
236         } mode;
237
238         /*! \brief TRUE if call completion activated */
239         int activated;
240
241         /*! \brief Outstanding message ID (valid when outstanding_message) */
242         int invoke_id;
243
244         /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
245         int outstanding_message;
246
247         /*! \brief TRUE if activation has been requested */
248         int activation_requested;
249
250         /*!
251          * \brief TRUE if User-A is free
252          * \note PTMP - Used to answer CCBSStatusRequest.
253          * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
254          */
255         int party_a_free;
256
257         /*! \brief Error code received from last outstanding message. */
258         enum FacErrorCode error_code;
259
260         /*! \brief Reject code received from last outstanding message. */
261         enum FacRejectCode reject_code;
262
263         /*!
264          * \brief Saved struct misdn_bchannel call information when
265          * attempted to call User-B
266          */
267         struct {
268                 /*! \brief User-A caller id information */
269                 struct misdn_party_id caller;
270
271                 /*! \brief User-B number information */
272                 struct misdn_party_dialing dialed;
273
274                 /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
275                 struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
276
277                 /*! \brief SETUP message bearer capability field code value */
278                 int capability;
279
280                 /*! \brief TRUE if call made in digital HDLC mode */
281                 int hdlc;
282         } redial;
283
284         /*! \brief Dialplan location to indicate User-B free and User-A is free */
285         struct misdn_cc_notify remote_user_free;
286
287         /*! \brief Dialplan location to indicate User-B free and User-A is busy */
288         struct misdn_cc_notify b_free;
289 };
290
291 /*! \brief mISDN call completion record database */
292 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
293 /*! \brief Next call completion record ID to use */
294 static __u16 misdn_cc_record_id;
295 /*! \brief Next invoke ID to use */
296 static __s16 misdn_invoke_id;
297
298 static const char misdn_no_response_from_network[] = "No response from network";
299 static const char misdn_cc_record_not_found[] = "Call completion record not found";
300
301 /* mISDN channel variable names */
302 #define MISDN_CC_RECORD_ID      "MISDN_CC_RECORD_ID"
303 #define MISDN_CC_STATUS         "MISDN_CC_STATUS"
304 #define MISDN_ERROR_MSG         "MISDN_ERROR_MSG"
305 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
306
307 static ast_mutex_t release_lock;
308
309 enum misdn_chan_state {
310         MISDN_NOTHING = 0,         /*!< at beginning */
311         MISDN_WAITING4DIGS,        /*!< when waiting for info */
312         MISDN_EXTCANTMATCH,        /*!< when asterisk couldn't match our ext */
313         MISDN_INCOMING_SETUP,      /*!< for incoming setup */
314         MISDN_DIALING,             /*!< when pbx_start */
315         MISDN_PROGRESS,            /*!< we have progress */
316         MISDN_PROCEEDING,          /*!< we have progress */
317         MISDN_CALLING,             /*!< when misdn_call is called */
318         MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
319         MISDN_ALERTING,            /*!< when Alerting */
320         MISDN_BUSY,                /*!< when BUSY */
321         MISDN_CONNECTED,           /*!< when connected */
322         MISDN_DISCONNECTED,        /*!< when connected */
323         MISDN_CLEANING,            /*!< when hangup from * but we were connected before */
324 };
325
326 /*! Asterisk created the channel (outgoing call) */
327 #define ORG_AST 1
328 /*! mISDN created the channel (incoming call) */
329 #define ORG_MISDN 2
330
331 enum misdn_hold_state {
332         MISDN_HOLD_IDLE,                /*!< HOLD not active */
333         MISDN_HOLD_ACTIVE,              /*!< Call is held */
334         MISDN_HOLD_TRANSFER,    /*!< Held call is being transferred */
335         MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
336 };
337 struct hold_info {
338         /*!
339          * \brief Call HOLD state.
340          */
341         enum misdn_hold_state state;
342         /*!
343          * \brief Logical port the channel call record is HELD on
344          * because the B channel is no longer associated.
345          */
346         int port;
347
348         /*!
349          * \brief Original B channel number the HELD call was using.
350          * \note Used only for debug display messages.
351          */
352         int channel;
353 };
354
355 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
356 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
357
358 /*!
359  * \brief Channel call record structure
360  */
361 struct chan_list {
362         /*!
363          * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
364          */
365         char allowed_bearers[BUFFERSIZE + 1];
366
367         /*!
368          * \brief State of the channel
369          */
370         enum misdn_chan_state state;
371
372         /*!
373          * \brief TRUE if a hangup needs to be queued
374          * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
375          */
376         int need_queue_hangup;
377
378         /*!
379          * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
380          */
381         int need_hangup;
382
383         /*!
384          * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
385          */
386         int need_busy;
387
388         /*!
389          * \brief Who originally created this channel. ORG_AST or ORG_MISDN
390          */
391         int originator;
392
393         /*!
394          * \brief TRUE of we are not to respond immediately to a SETUP message.  Check the dialplan first.
395          * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
396          */
397         int noautorespond_on_setup;
398
399         int norxtone;   /*!< Boolean assigned values but the value is not used. */
400
401         /*!
402          * \brief TRUE if we are not to generate tones (Playtones)
403          */
404         int notxtone;
405
406         /*!
407          * \brief TRUE if echo canceller is enabled.  Value is toggled.
408          */
409         int toggle_ec;
410
411         /*!
412          * \brief TRUE if you want to send Tone Indications to an incoming
413          * ISDN channel on a TE Port.
414          * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
415          */
416         int incoming_early_audio;
417
418         /*!
419          * \brief TRUE if DTMF digits are to be passed inband only.
420          * \note It is settable by the misdn_set_opt() application.
421          */
422         int ignore_dtmf;
423
424         /*!
425          * \brief Pipe file descriptor handles array.
426          * Read from pipe[0], write to pipe[1]
427          */
428         int pipe[2];
429
430         /*!
431          * \brief Read buffer for inbound audio from pipe[0]
432          */
433         char ast_rd_buf[4096];
434
435         /*!
436          * \brief Inbound audio frame returned by misdn_read().
437          */
438         struct ast_frame frame;
439
440         /*!
441          * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
442          * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
443          * \note It is settable by the misdn_set_opt() application.
444          */
445         int faxdetect;
446
447         /*!
448          * \brief Number of seconds to detect a Fax machine when detection enabled.
449          * \note 0 disables the timeout.
450          * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
451          */
452         int faxdetect_timeout;
453
454         /*!
455          * \brief Starting time of fax detection with timeout when nonzero.
456          */
457         struct timeval faxdetect_tv;
458
459         /*!
460          * \brief TRUE if a fax has been detected.
461          */
462         int faxhandled;
463
464         /*!
465          * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
466          * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
467          */
468         int ast_dsp;
469
470         /*!
471          * \brief Jitterbuffer length
472          * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
473          */
474         int jb_len;
475
476         /*!
477          * \brief Jitterbuffer upper threshold
478          * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
479          */
480         int jb_upper_threshold;
481
482         /*!
483          * \brief Allocated jitterbuffer controller
484          * \note misdn_jb_init() creates the jitterbuffer.
485          * \note Must use misdn_jb_destroy() to clean up.
486          */
487         struct misdn_jb *jb;
488
489         /*!
490          * \brief Allocated DSP controller
491          * \note ast_dsp_new() creates the DSP controller.
492          * \note Must use ast_dsp_free() to clean up.
493          */
494         struct ast_dsp *dsp;
495
496         /*!
497          * \brief Associated Asterisk channel structure.
498          */
499         struct ast_channel * ast;
500
501         /*!
502          * \brief Associated B channel structure.
503          */
504         struct misdn_bchannel *bc;
505
506 #if defined(AST_MISDN_ENHANCEMENTS)
507         /*!
508          * \brief Peer channel for which call completion was initialized.
509          */
510         struct misdn_cc_caller *peer;
511
512         /*! \brief Associated call completion record ID (-1 if not associated) */
513         long record_id;
514 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
515
516         /*!
517          * \brief HELD channel call information
518          */
519         struct hold_info hold;
520
521         /*!
522          * \brief From associated B channel: Layer 3 process ID
523          * \note Used to find the HELD channel call record when retrieving a call.
524          */
525         unsigned int l3id;
526
527         /*!
528          * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
529          * \note Used only for debug display messages.
530          */
531         int addr;
532
533         /*!
534          * \brief Incoming call dialplan context identifier.
535          * \note The "context" string read in from /etc/asterisk/misdn.conf
536          */
537         char context[AST_MAX_CONTEXT];
538
539         /*!
540          * \brief The configured music-on-hold class to use for this call.
541          * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
542          */
543         char mohinterpret[MAX_MUSICCLASS];
544
545         /*!
546          * \brief Number of outgoing audio frames dropped since last debug gripe message.
547          */
548         int dropped_frame_cnt;
549
550         /*!
551          * \brief TRUE if we must do the ringback tones.
552          * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
553          */
554         int far_alerting;
555
556         /*!
557          * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
558          * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
559          */
560         int nttimeout;
561
562         /*!
563          * \brief Tone zone sound used for dialtone generation.
564          * \note Used as a boolean.  Non-NULL to prod generation if enabled.
565          */
566         struct ast_tone_zone_sound *ts;
567
568         /*!
569          * \brief Enables overlap dialing for the set amount of seconds.  (0 = Disabled)
570          * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
571          */
572         int overlap_dial;
573
574         /*!
575          * \brief Overlap dialing timeout Task ID.  -1 if not running.
576          */
577         int overlap_dial_task;
578
579         /*!
580          * \brief overlap_tv access lock.
581          */
582         ast_mutex_t overlap_tv_lock;
583
584         /*!
585          * \brief Overlap timer start time.  Timer restarted for every digit received.
586          */
587         struct timeval overlap_tv;
588
589         /*!
590          * \brief Next channel call record in the list.
591          */
592         struct chan_list *next;
593 };
594
595
596 int MAXTICS = 8;
597
598
599 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
600 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
601 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
602
603 struct robin_list {
604         char *group;
605         int port;
606         int channel;
607         struct robin_list *next;
608         struct robin_list *prev;
609 };
610 static struct robin_list *robin = NULL;
611
612
613 static void free_robin_list(void)
614 {
615         struct robin_list *r;
616         struct robin_list *next;
617
618         for (r = robin, robin = NULL; r; r = next) {
619                 next = r->next;
620                 ast_free(r->group);
621                 ast_free(r);
622         }
623 }
624
625 static struct robin_list *get_robin_position(char *group)
626 {
627         struct robin_list *new;
628         struct robin_list *iter = robin;
629         for (; iter; iter = iter->next) {
630                 if (!strcasecmp(iter->group, group)) {
631                         return iter;
632                 }
633         }
634         new = ast_calloc(1, sizeof(*new));
635         if (!new) {
636                 return NULL;
637         }
638         new->group = ast_strdup(group);
639         if (!new->group) {
640                 ast_free(new);
641                 return NULL;
642         }
643         new->channel = 1;
644         if (robin) {
645                 new->next = robin;
646                 robin->prev = new;
647         }
648         robin = new;
649         return robin;
650 }
651
652
653 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
654 static struct ast_sched_context *misdn_tasks = NULL;
655 static pthread_t misdn_tasks_thread;
656
657 static int *misdn_ports;
658
659 static void chan_misdn_log(int level, int port, char *tmpl, ...)
660         __attribute__((format(printf, 3, 4)));
661
662 static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c);
663 static void send_digit_to_chan(struct chan_list *cl, char digit);
664
665 static int pbx_start_chan(struct chan_list *ch);
666
667 #define MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast)
668 #define MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value)
669
670 #include "asterisk/strings.h"
671
672 /* #define MISDN_DEBUG 1 */
673
674 static const char misdn_type[] = "mISDN";
675
676 static int tracing = 0;
677
678 /*! \brief Only alaw and mulaw is allowed for now */
679 static struct ast_format prefformat; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
680
681 static int *misdn_debug;
682 static int *misdn_debug_only;
683 static int max_ports;
684
685 static int *misdn_in_calls;
686 static int *misdn_out_calls;
687
688 /*!
689  * \brief Global channel call record list head.
690  */
691 static struct chan_list *cl_te=NULL;
692 static ast_mutex_t cl_te_lock;
693
694 static enum event_response_e
695 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
696
697 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
698
699 static void cl_queue_chan(struct chan_list *chan);
700
701 static int dialtone_indicate(struct chan_list *cl);
702 static void hanguptone_indicate(struct chan_list *cl);
703 static int stop_indicate(struct chan_list *cl);
704
705 static int start_bc_tones(struct chan_list *cl);
706 static int stop_bc_tones(struct chan_list *cl);
707 static void release_chan_early(struct chan_list *ch);
708 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
709
710 #if defined(AST_MISDN_ENHANCEMENTS)
711 static const char misdn_command_name[] = "misdn_command";
712 static int misdn_command_exec(struct ast_channel *chan, const char *data);
713 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
714 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
715 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
716 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
717
718 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
719
720 void debug_numtype(int port, int numtype, char *type);
721
722 int add_out_calls(int port);
723 int add_in_calls(int port);
724
725
726 #ifdef MISDN_1_2
727 static int update_pipeline_config(struct misdn_bchannel *bc);
728 #else
729 static int update_ec_config(struct misdn_bchannel *bc);
730 #endif
731
732
733
734 /*************** Helpers *****************/
735
736 static int misdn_chan_is_valid(struct chan_list *ch)
737 {
738         struct chan_list *list;
739
740         ast_mutex_lock(&cl_te_lock);
741         for (list = cl_te; list; list = list->next) {
742                 if (list == ch) {
743                         ast_mutex_unlock(&cl_te_lock);
744                         return 1;
745                 }
746         }
747         ast_mutex_unlock(&cl_te_lock);
748
749         return 0;
750 }
751
752 /*! Returns a reference to the found chan_list. */
753 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
754 {
755         struct chan_list *tmp;
756
757         ast_mutex_lock(&cl_te_lock);
758         for (tmp = cl_te; tmp; tmp = tmp->next) {
759                 if (tmp->ast == ast) {
760                         chan_list_ref(tmp, "Found chan_list by ast");
761                         ast_mutex_unlock(&cl_te_lock);
762                         return tmp;
763                 }
764         }
765         ast_mutex_unlock(&cl_te_lock);
766
767         return NULL;
768 }
769
770 /*! Returns a reference to the found chan_list. */
771 static struct chan_list *get_chan_by_ast_name(const char *name)
772 {
773         struct chan_list *tmp;
774
775         ast_mutex_lock(&cl_te_lock);
776         for (tmp = cl_te; tmp; tmp = tmp->next) {
777                 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
778                         chan_list_ref(tmp, "Found chan_list by ast name");
779                         ast_mutex_unlock(&cl_te_lock);
780                         return tmp;
781                 }
782         }
783         ast_mutex_unlock(&cl_te_lock);
784
785         return NULL;
786 }
787
788 #if defined(AST_MISDN_ENHANCEMENTS)
789 /*!
790  * \internal
791  * \brief Destroy the misdn_cc_ds_info datastore payload
792  *
793  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
794  *
795  * \details
796  * Since the payload is a reference to an astobj2 object, we just decrement its
797  * reference count.  Before doing so, we NULL out the channel pointer inside of
798  * the misdn_cc_caller instance.  This function will be called in one of two
799  * cases.  In both cases, we no longer need the channel pointer:
800  *
801  *  - The original channel that initialized call completion services, the same
802  *    channel that is stored here, has been destroyed early.  This could happen
803  *    if it transferred the mISDN channel, for example.
804  *
805  *  - The mISDN channel that had this datastore inherited on to it is now being
806  *    destroyed.  If this is the case, then the call completion events have
807  *    already occurred and the appropriate channel variables have already been
808  *    set on the original channel that requested call completion services.
809  *
810  * \return Nothing
811  */
812 static void misdn_cc_ds_destroy(void *data)
813 {
814         struct misdn_cc_caller *cc_caller = data;
815
816         ao2_lock(cc_caller);
817         cc_caller->chan = NULL;
818         ao2_unlock(cc_caller);
819
820         ao2_ref(cc_caller, -1);
821 }
822 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
823
824 #if defined(AST_MISDN_ENHANCEMENTS)
825 /*!
826  * \internal
827  * \brief Duplicate the misdn_cc_ds_info datastore payload
828  *
829  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
830  *
831  * \details
832  * All we need to do is bump the reference count and return the same instance.
833  *
834  * \return A reference to an instance of a misdn_cc_caller
835  */
836 static void *misdn_cc_ds_duplicate(void *data)
837 {
838         struct misdn_cc_caller *cc_caller = data;
839
840         ao2_ref(cc_caller, +1);
841
842         return cc_caller;
843 }
844 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
845
846 #if defined(AST_MISDN_ENHANCEMENTS)
847 static const struct ast_datastore_info misdn_cc_ds_info = {
848         .type      = "misdn_cc",
849         .destroy   = misdn_cc_ds_destroy,
850         .duplicate = misdn_cc_ds_duplicate,
851 };
852 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
853
854 #if defined(AST_MISDN_ENHANCEMENTS)
855 /*!
856  * \internal
857  * \brief Set a channel var on the peer channel for call completion services
858  *
859  * \param[in] peer The peer that initialized call completion services
860  * \param[in] var The variable name to set
861  * \param[in] value The variable value to set
862  *
863  * This function may be called from outside of the channel thread.  It handles
864  * the fact that the peer channel may be hung up and destroyed at any time.
865  *
866  * \return nothing
867  */
868 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
869         const char *value)
870 {
871         ao2_lock(peer);
872
873         /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
874         while (peer->chan && ast_channel_trylock(peer->chan)) {
875                 ao2_unlock(peer);
876                 sched_yield();
877                 ao2_lock(peer);
878         }
879
880         if (peer->chan) {
881                 pbx_builtin_setvar_helper(peer->chan, var, value);
882                 ast_channel_unlock(peer->chan);
883         }
884
885         ao2_unlock(peer);
886 }
887 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
888
889 #if defined(AST_MISDN_ENHANCEMENTS)
890 /*!
891  * \internal
892  * \brief Get a reference to the CC caller if it exists
893  */
894 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
895 {
896         struct ast_datastore *datastore;
897         struct misdn_cc_caller *cc_caller;
898
899         ast_channel_lock(chan);
900
901         if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
902                 ast_channel_unlock(chan);
903                 return NULL;
904         }
905
906         ao2_ref(datastore->data, +1);
907         cc_caller = datastore->data;
908
909         ast_channel_unlock(chan);
910
911         return cc_caller;
912 }
913 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
914
915 #if defined(AST_MISDN_ENHANCEMENTS)
916 /*!
917  * \internal
918  * \brief Find the call completion record given the record id.
919  *
920  * \param record_id
921  *
922  * \retval pointer to found call completion record
923  * \retval NULL if not found
924  *
925  * \note Assumes the misdn_cc_records_db lock is already obtained.
926  */
927 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
928 {
929         struct misdn_cc_record *current;
930
931         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
932                 if (current->record_id == record_id) {
933                         /* Found the record */
934                         break;
935                 }
936         }
937
938         return current;
939 }
940 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
941
942 #if defined(AST_MISDN_ENHANCEMENTS)
943 /*!
944  * \internal
945  * \brief Find the call completion record given the port and call linkage id.
946  *
947  * \param port Logical port number
948  * \param linkage_id Call linkage ID number from switch.
949  *
950  * \retval pointer to found call completion record
951  * \retval NULL if not found
952  *
953  * \note Assumes the misdn_cc_records_db lock is already obtained.
954  */
955 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
956 {
957         struct misdn_cc_record *current;
958
959         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
960                 if (current->port == port
961                         && !current->ptp
962                         && current->mode.ptmp.linkage_id == linkage_id) {
963                         /* Found the record */
964                         break;
965                 }
966         }
967
968         return current;
969 }
970 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
971
972 #if defined(AST_MISDN_ENHANCEMENTS)
973 /*!
974  * \internal
975  * \brief Find the call completion record given the port and outstanding invocation id.
976  *
977  * \param port Logical port number
978  * \param invoke_id Outstanding message invocation ID number.
979  *
980  * \retval pointer to found call completion record
981  * \retval NULL if not found
982  *
983  * \note Assumes the misdn_cc_records_db lock is already obtained.
984  */
985 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
986 {
987         struct misdn_cc_record *current;
988
989         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
990                 if (current->outstanding_message
991                         && current->invoke_id == invoke_id
992                         && current->port == port) {
993                         /* Found the record */
994                         break;
995                 }
996         }
997
998         return current;
999 }
1000 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1001
1002 #if defined(AST_MISDN_ENHANCEMENTS)
1003 /*!
1004  * \internal
1005  * \brief Find the call completion record given the port and CCBS reference id.
1006  *
1007  * \param port Logical port number
1008  * \param reference_id CCBS reference ID number from switch.
1009  *
1010  * \retval pointer to found call completion record
1011  * \retval NULL if not found
1012  *
1013  * \note Assumes the misdn_cc_records_db lock is already obtained.
1014  */
1015 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1016 {
1017         struct misdn_cc_record *current;
1018
1019         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1020                 if (current->activated
1021                         && current->port == port
1022                         && !current->ptp
1023                         && current->mode.ptmp.reference_id == reference_id) {
1024                         /* Found the record */
1025                         break;
1026                 }
1027         }
1028
1029         return current;
1030 }
1031 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1032
1033 #if defined(AST_MISDN_ENHANCEMENTS)
1034 /*!
1035  * \internal
1036  * \brief Find the call completion record given the B channel pointer
1037  *
1038  * \param bc B channel control structure pointer.
1039  *
1040  * \retval pointer to found call completion record
1041  * \retval NULL if not found
1042  *
1043  * \note Assumes the misdn_cc_records_db lock is already obtained.
1044  */
1045 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1046 {
1047         struct misdn_cc_record *current;
1048
1049         if (bc) {
1050                 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1051                         if (current->ptp
1052                                 && current->mode.ptp.bc == bc) {
1053                                 /* Found the record */
1054                                 break;
1055                         }
1056                 }
1057         } else {
1058                 current = NULL;
1059         }
1060
1061         return current;
1062 }
1063 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1064
1065 #if defined(AST_MISDN_ENHANCEMENTS)
1066 /*!
1067  * \internal
1068  * \brief Delete the given call completion record
1069  *
1070  * \param doomed Call completion record to destroy
1071  *
1072  * \return Nothing
1073  *
1074  * \note Assumes the misdn_cc_records_db lock is already obtained.
1075  */
1076 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1077 {
1078         struct misdn_cc_record *current;
1079
1080         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1081                 if (current == doomed) {
1082                         AST_LIST_REMOVE_CURRENT(list);
1083                         ast_free(current);
1084                         return;
1085                 }
1086         }
1087         AST_LIST_TRAVERSE_SAFE_END;
1088
1089         /* The doomed node is not in the call completion database */
1090 }
1091 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1092
1093 #if defined(AST_MISDN_ENHANCEMENTS)
1094 /*!
1095  * \internal
1096  * \brief Delete all old call completion records
1097  *
1098  * \return Nothing
1099  *
1100  * \note Assumes the misdn_cc_records_db lock is already obtained.
1101  */
1102 static void misdn_cc_remove_old(void)
1103 {
1104         struct misdn_cc_record *current;
1105         time_t now;
1106
1107         now = time(NULL);
1108         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1109                 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1110                         if (current->ptp && current->mode.ptp.bc) {
1111                                 /* Close the old call-completion signaling link */
1112                                 current->mode.ptp.bc->fac_out.Function = Fac_None;
1113                                 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1114                                 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1115                         }
1116
1117                         /* Remove the old call completion record */
1118                         AST_LIST_REMOVE_CURRENT(list);
1119                         ast_free(current);
1120                 }
1121         }
1122         AST_LIST_TRAVERSE_SAFE_END;
1123 }
1124 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1125
1126 #if defined(AST_MISDN_ENHANCEMENTS)
1127 /*!
1128  * \internal
1129  * \brief Allocate the next record id.
1130  *
1131  * \retval New record id on success.
1132  * \retval -1 on error.
1133  *
1134  * \note Assumes the misdn_cc_records_db lock is already obtained.
1135  */
1136 static long misdn_cc_record_id_new(void)
1137 {
1138         long record_id;
1139         long first_id;
1140
1141         record_id = ++misdn_cc_record_id;
1142         first_id = record_id;
1143         while (misdn_cc_find_by_id(record_id)) {
1144                 record_id = ++misdn_cc_record_id;
1145                 if (record_id == first_id) {
1146                         /*
1147                          * We have a resource leak.
1148                          * We should never need to allocate 64k records.
1149                          */
1150                         chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1151                         record_id = -1;
1152                         break;
1153                 }
1154         }
1155
1156         return record_id;
1157 }
1158 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1159
1160 #if defined(AST_MISDN_ENHANCEMENTS)
1161 /*!
1162  * \internal
1163  * \brief Create a new call completion record
1164  *
1165  * \retval pointer to new call completion record
1166  * \retval NULL if failed
1167  *
1168  * \note Assumes the misdn_cc_records_db lock is already obtained.
1169  */
1170 static struct misdn_cc_record *misdn_cc_new(void)
1171 {
1172         struct misdn_cc_record *cc_record;
1173         long record_id;
1174
1175         misdn_cc_remove_old();
1176
1177         cc_record = ast_calloc(1, sizeof(*cc_record));
1178         if (cc_record) {
1179                 record_id = misdn_cc_record_id_new();
1180                 if (record_id < 0) {
1181                         ast_free(cc_record);
1182                         return NULL;
1183                 }
1184
1185                 /* Initialize the new record */
1186                 cc_record->record_id = record_id;
1187                 cc_record->port = -1;/* Invalid port so it will never be found this way */
1188                 cc_record->invoke_id = ++misdn_invoke_id;
1189                 cc_record->party_a_free = 1;/* Default User-A as free */
1190                 cc_record->error_code = FacError_None;
1191                 cc_record->reject_code = FacReject_None;
1192                 cc_record->time_created = time(NULL);
1193
1194                 /* Insert the new record into the database */
1195                 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1196         }
1197         return cc_record;
1198 }
1199 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1200
1201 #if defined(AST_MISDN_ENHANCEMENTS)
1202 /*!
1203  * \internal
1204  * \brief Destroy the call completion record database
1205  *
1206  * \return Nothing
1207  */
1208 static void misdn_cc_destroy(void)
1209 {
1210         struct misdn_cc_record *current;
1211
1212         while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1213                 /* Do a misdn_cc_delete(current) inline */
1214                 ast_free(current);
1215         }
1216 }
1217 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1218
1219 #if defined(AST_MISDN_ENHANCEMENTS)
1220 /*!
1221  * \internal
1222  * \brief Initialize the call completion record database
1223  *
1224  * \return Nothing
1225  */
1226 static void misdn_cc_init(void)
1227 {
1228         misdn_cc_record_id = 0;
1229 }
1230 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1231
1232 #if defined(AST_MISDN_ENHANCEMENTS)
1233 /*!
1234  * \internal
1235  * \brief Check the status of an outstanding invocation request.
1236  *
1237  * \param data Points to an integer containing the call completion record id.
1238  *
1239  * \retval 0 if got a response.
1240  * \retval -1 if no response yet.
1241  */
1242 static int misdn_cc_response_check(void *data)
1243 {
1244         int not_responded;
1245         struct misdn_cc_record *cc_record;
1246
1247         AST_LIST_LOCK(&misdn_cc_records_db);
1248         cc_record = misdn_cc_find_by_id(*(long *) data);
1249         if (cc_record) {
1250                 if (cc_record->outstanding_message) {
1251                         not_responded = -1;
1252                 } else {
1253                         not_responded = 0;
1254                 }
1255         } else {
1256                 /* No record so there is no response to check. */
1257                 not_responded = 0;
1258         }
1259         AST_LIST_UNLOCK(&misdn_cc_records_db);
1260
1261         return not_responded;
1262 }
1263 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1264
1265 #if defined(AST_MISDN_ENHANCEMENTS)
1266 /*!
1267  * \internal
1268  * \brief Wait for a response from the switch for an outstanding
1269  * invocation request.
1270  *
1271  * \param chan Asterisk channel to operate upon.
1272  * \param wait_seconds Number of seconds to wait
1273  * \param record_id Call completion record ID.
1274  *
1275  * \return Nothing
1276  */
1277 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1278 {
1279         unsigned count;
1280
1281         for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1282                 /* Sleep in 500 ms increments */
1283                 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1284                         /* We got hung up or our response came in. */
1285                         break;
1286                 }
1287         }
1288 }
1289 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1290
1291 #if defined(AST_MISDN_ENHANCEMENTS)
1292 /*!
1293  * \internal
1294  * \brief Convert the mISDN reject code to a string
1295  *
1296  * \param code mISDN reject code.
1297  *
1298  * \return The mISDN reject code as a string
1299  */
1300 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1301 {
1302         static const struct {
1303                 enum FacRejectCode code;
1304                 char *name;
1305         } arr[] = {
1306 /* *INDENT-OFF* */
1307                 { FacReject_None,                           "No reject occurred" },
1308                 { FacReject_Unknown,                        "Unknown reject code" },
1309
1310                 { FacReject_Gen_UnrecognizedComponent,      "General: Unrecognized Component" },
1311                 { FacReject_Gen_MistypedComponent,          "General: Mistyped Component" },
1312                 { FacReject_Gen_BadlyStructuredComponent,   "General: Badly Structured Component" },
1313
1314                 { FacReject_Inv_DuplicateInvocation,        "Invoke: Duplicate Invocation" },
1315                 { FacReject_Inv_UnrecognizedOperation,      "Invoke: Unrecognized Operation" },
1316                 { FacReject_Inv_MistypedArgument,           "Invoke: Mistyped Argument" },
1317                 { FacReject_Inv_ResourceLimitation,         "Invoke: Resource Limitation" },
1318                 { FacReject_Inv_InitiatorReleasing,         "Invoke: Initiator Releasing" },
1319                 { FacReject_Inv_UnrecognizedLinkedID,       "Invoke: Unrecognized Linked ID" },
1320                 { FacReject_Inv_LinkedResponseUnexpected,   "Invoke: Linked Response Unexpected" },
1321                 { FacReject_Inv_UnexpectedChildOperation,   "Invoke: Unexpected Child Operation" },
1322
1323                 { FacReject_Res_UnrecognizedInvocation,     "Result: Unrecognized Invocation" },
1324                 { FacReject_Res_ResultResponseUnexpected,   "Result: Result Response Unexpected" },
1325                 { FacReject_Res_MistypedResult,             "Result: Mistyped Result" },
1326
1327                 { FacReject_Err_UnrecognizedInvocation,     "Error: Unrecognized Invocation" },
1328                 { FacReject_Err_ErrorResponseUnexpected,    "Error: Error Response Unexpected" },
1329                 { FacReject_Err_UnrecognizedError,          "Error: Unrecognized Error" },
1330                 { FacReject_Err_UnexpectedError,            "Error: Unexpected Error" },
1331                 { FacReject_Err_MistypedParameter,          "Error: Mistyped Parameter" },
1332 /* *INDENT-ON* */
1333         };
1334
1335         unsigned index;
1336
1337         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1338                 if (arr[index].code == code) {
1339                         return arr[index].name;
1340                 }
1341         }
1342
1343         return "unknown";
1344 }
1345 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1346
1347 #if defined(AST_MISDN_ENHANCEMENTS)
1348 /*!
1349  * \internal
1350  * \brief Convert the mISDN error code to a string
1351  *
1352  * \param code mISDN error code.
1353  *
1354  * \return The mISDN error code as a string
1355  */
1356 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1357 {
1358         static const struct {
1359                 enum FacErrorCode code;
1360                 char *name;
1361         } arr[] = {
1362 /* *INDENT-OFF* */
1363                 { FacError_None,                            "No error occurred" },
1364                 { FacError_Unknown,                         "Unknown OID error code" },
1365
1366                 { FacError_Gen_NotSubscribed,               "General: Not Subscribed" },
1367                 { FacError_Gen_NotAvailable,                "General: Not Available" },
1368                 { FacError_Gen_NotImplemented,              "General: Not Implemented" },
1369                 { FacError_Gen_InvalidServedUserNr,         "General: Invalid Served User Number" },
1370                 { FacError_Gen_InvalidCallState,            "General: Invalid Call State" },
1371                 { FacError_Gen_BasicServiceNotProvided,     "General: Basic Service Not Provided" },
1372                 { FacError_Gen_NotIncomingCall,             "General: Not Incoming Call" },
1373                 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1374                 { FacError_Gen_ResourceUnavailable,         "General: Resource Unavailable" },
1375
1376                 { FacError_Div_InvalidDivertedToNr,         "Diversion: Invalid Diverted To Number" },
1377                 { FacError_Div_SpecialServiceNr,            "Diversion: Special Service Number" },
1378                 { FacError_Div_DiversionToServedUserNr,     "Diversion: Diversion To Served User Number" },
1379                 { FacError_Div_IncomingCallAccepted,        "Diversion: Incoming Call Accepted" },
1380                 { FacError_Div_NumberOfDiversionsExceeded,  "Diversion: Number Of Diversions Exceeded" },
1381                 { FacError_Div_NotActivated,                "Diversion: Not Activated" },
1382                 { FacError_Div_RequestAlreadyAccepted,      "Diversion: Request Already Accepted" },
1383
1384                 { FacError_AOC_NoChargingInfoAvailable,     "AOC: No Charging Info Available" },
1385
1386                 { FacError_CCBS_InvalidCallLinkageID,       "CCBS: Invalid Call Linkage ID" },
1387                 { FacError_CCBS_InvalidCCBSReference,       "CCBS: Invalid CCBS Reference" },
1388                 { FacError_CCBS_LongTermDenial,             "CCBS: Long Term Denial" },
1389                 { FacError_CCBS_ShortTermDenial,            "CCBS: Short Term Denial" },
1390                 { FacError_CCBS_IsAlreadyActivated,         "CCBS: Is Already Activated" },
1391                 { FacError_CCBS_AlreadyAccepted,            "CCBS: Already Accepted" },
1392                 { FacError_CCBS_OutgoingCCBSQueueFull,      "CCBS: Outgoing CCBS Queue Full" },
1393                 { FacError_CCBS_CallFailureReasonNotBusy,   "CCBS: Call Failure Reason Not Busy" },
1394                 { FacError_CCBS_NotReadyForCall,            "CCBS: Not Ready For Call" },
1395
1396                 { FacError_CCBS_T_LongTermDenial,           "CCBS-T: Long Term Denial" },
1397                 { FacError_CCBS_T_ShortTermDenial,          "CCBS-T: Short Term Denial" },
1398
1399                 { FacError_ECT_LinkIdNotAssignedByNetwork,  "ECT: Link ID Not Assigned By Network" },
1400 /* *INDENT-ON* */
1401         };
1402
1403         unsigned index;
1404
1405         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1406                 if (arr[index].code == code) {
1407                         return arr[index].name;
1408                 }
1409         }
1410
1411         return "unknown";
1412 }
1413 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1414
1415 #if defined(AST_MISDN_ENHANCEMENTS)
1416 /*!
1417  * \internal
1418  * \brief Convert mISDN redirecting reason to diversion reason.
1419  *
1420  * \param reason mISDN redirecting reason code.
1421  *
1422  * \return Supported diversion reason code.
1423  */
1424 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1425 {
1426         unsigned diversion_reason;
1427
1428         switch (reason) {
1429         case mISDN_REDIRECTING_REASON_CALL_FWD:
1430                 diversion_reason = 1;/* cfu */
1431                 break;
1432         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
1433                 diversion_reason = 2;/* cfb */
1434                 break;
1435         case mISDN_REDIRECTING_REASON_NO_REPLY:
1436                 diversion_reason = 3;/* cfnr */
1437                 break;
1438         default:
1439                 diversion_reason = 0;/* unknown */
1440                 break;
1441         }
1442
1443         return diversion_reason;
1444 }
1445 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1446
1447 #if defined(AST_MISDN_ENHANCEMENTS)
1448 /*!
1449  * \internal
1450  * \brief Convert diversion reason to mISDN redirecting reason
1451  *
1452  * \param diversion_reason Diversion reason to convert
1453  *
1454  * \return Supported redirecting reason code.
1455  */
1456 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1457 {
1458         enum mISDN_REDIRECTING_REASON reason;
1459
1460         switch (diversion_reason) {
1461         case 1:/* cfu */
1462                 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
1463                 break;
1464         case 2:/* cfb */
1465                 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
1466                 break;
1467         case 3:/* cfnr */
1468                 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
1469                 break;
1470         default:
1471                 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
1472                 break;
1473         }
1474
1475         return reason;
1476 }
1477 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1478
1479 #if defined(AST_MISDN_ENHANCEMENTS)
1480 /*!
1481  * \internal
1482  * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1483  *
1484  * \param presentation mISDN presentation to convert
1485  * \param number_present TRUE if the number is present
1486  *
1487  * \return PresentedNumberUnscreened type
1488  */
1489 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1490 {
1491         unsigned type;
1492
1493         switch (presentation) {
1494         case 0:/* allowed */
1495                 if (number_present) {
1496                         type = 0;/* presentationAllowedNumber */
1497                 } else {
1498                         type = 2;/* numberNotAvailableDueToInterworking */
1499                 }
1500                 break;
1501         case 1:/* restricted */
1502                 if (number_present) {
1503                         type = 3;/* presentationRestrictedNumber */
1504                 } else {
1505                         type = 1;/* presentationRestricted */
1506                 }
1507                 break;
1508         default:
1509                 type = 2;/* numberNotAvailableDueToInterworking */
1510                 break;
1511         }
1512
1513         return type;
1514 }
1515 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1516
1517 #if defined(AST_MISDN_ENHANCEMENTS)
1518 /*!
1519  * \internal
1520  * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1521  *
1522  * \param type PresentedNumberUnscreened type
1523  *
1524  * \return mISDN presentation
1525  */
1526 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1527 {
1528         int presentation;
1529
1530         switch (type) {
1531         default:
1532         case 0:/* presentationAllowedNumber */
1533                 presentation = 0;/* allowed */
1534                 break;
1535
1536         case 1:/* presentationRestricted */
1537         case 3:/* presentationRestrictedNumber */
1538                 presentation = 1;/* restricted */
1539                 break;
1540
1541         case 2:/* numberNotAvailableDueToInterworking */
1542                 presentation = 2;/* unavailable */
1543                 break;
1544         }
1545
1546         return presentation;
1547 }
1548 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1549
1550 #if defined(AST_MISDN_ENHANCEMENTS)
1551 /*!
1552  * \internal
1553  * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1554  *
1555  * \param number_plan mISDN numbering plan
1556  *
1557  * \return PartyNumber numbering plan
1558  */
1559 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1560 {
1561         unsigned party_plan;
1562
1563         switch (number_plan) {
1564         default:
1565         case NUMPLAN_UNKNOWN:
1566                 party_plan = 0;/* unknown */
1567                 break;
1568
1569         case NUMPLAN_ISDN:
1570                 party_plan = 1;/* public */
1571                 break;
1572
1573         case NUMPLAN_DATA:
1574                 party_plan = 3;/* data */
1575                 break;
1576
1577         case NUMPLAN_TELEX:
1578                 party_plan = 4;/* telex */
1579                 break;
1580
1581         case NUMPLAN_NATIONAL:
1582                 party_plan = 8;/* nationalStandard */
1583                 break;
1584
1585         case NUMPLAN_PRIVATE:
1586                 party_plan = 5;/* private */
1587                 break;
1588         }
1589
1590         return party_plan;
1591 }
1592 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1593
1594 #if defined(AST_MISDN_ENHANCEMENTS)
1595 /*!
1596  * \internal
1597  * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1598  *
1599  * \param party_plan PartyNumber numbering plan
1600  *
1601  * \return mISDN numbering plan
1602  */
1603 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1604 {
1605         enum mISDN_NUMBER_PLAN number_plan;
1606
1607         switch (party_plan) {
1608         default:
1609         case 0:/* unknown */
1610                 number_plan = NUMPLAN_UNKNOWN;
1611                 break;
1612         case 1:/* public */
1613                 number_plan = NUMPLAN_ISDN;
1614                 break;
1615         case 3:/* data */
1616                 number_plan = NUMPLAN_DATA;
1617                 break;
1618         case 4:/* telex */
1619                 number_plan = NUMPLAN_TELEX;
1620                 break;
1621         case 8:/* nationalStandard */
1622                 number_plan = NUMPLAN_NATIONAL;
1623                 break;
1624         case 5:/* private */
1625                 number_plan = NUMPLAN_PRIVATE;
1626                 break;
1627         }
1628
1629         return number_plan;
1630 }
1631 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1632
1633 #if defined(AST_MISDN_ENHANCEMENTS)
1634 /*!
1635  * \internal
1636  * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1637  *
1638  * \param ton mISDN type-of-number
1639  *
1640  * \return PartyNumber public type-of-number
1641  */
1642 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1643 {
1644         unsigned party_ton;
1645
1646         switch (ton) {
1647         default:
1648         case NUMTYPE_UNKNOWN:
1649                 party_ton = 0;/* unknown */
1650                 break;
1651
1652         case NUMTYPE_INTERNATIONAL:
1653                 party_ton = 1;/* internationalNumber */
1654                 break;
1655
1656         case NUMTYPE_NATIONAL:
1657                 party_ton = 2;/* nationalNumber */
1658                 break;
1659
1660         case NUMTYPE_NETWORK_SPECIFIC:
1661                 party_ton = 3;/* networkSpecificNumber */
1662                 break;
1663
1664         case NUMTYPE_SUBSCRIBER:
1665                 party_ton = 4;/* subscriberNumber */
1666                 break;
1667
1668         case NUMTYPE_ABBREVIATED:
1669                 party_ton = 6;/* abbreviatedNumber */
1670                 break;
1671         }
1672
1673         return party_ton;
1674 }
1675 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1676
1677 #if defined(AST_MISDN_ENHANCEMENTS)
1678 /*!
1679  * \internal
1680  * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1681  *
1682  * \param party_ton PartyNumber public type-of-number
1683  *
1684  * \return mISDN type-of-number
1685  */
1686 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1687 {
1688         enum mISDN_NUMBER_TYPE ton;
1689
1690         switch (party_ton) {
1691         default:
1692         case 0:/* unknown */
1693                 ton = NUMTYPE_UNKNOWN;
1694                 break;
1695
1696         case 1:/* internationalNumber */
1697                 ton = NUMTYPE_INTERNATIONAL;
1698                 break;
1699
1700         case 2:/* nationalNumber */
1701                 ton = NUMTYPE_NATIONAL;
1702                 break;
1703
1704         case 3:/* networkSpecificNumber */
1705                 ton = NUMTYPE_NETWORK_SPECIFIC;
1706                 break;
1707
1708         case 4:/* subscriberNumber */
1709                 ton = NUMTYPE_SUBSCRIBER;
1710                 break;
1711
1712         case 6:/* abbreviatedNumber */
1713                 ton = NUMTYPE_ABBREVIATED;
1714                 break;
1715         }
1716
1717         return ton;
1718 }
1719 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1720
1721 #if defined(AST_MISDN_ENHANCEMENTS)
1722 /*!
1723  * \internal
1724  * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1725  *
1726  * \param ton mISDN type-of-number
1727  *
1728  * \return PartyNumber private type-of-number
1729  */
1730 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1731 {
1732         unsigned party_ton;
1733
1734         switch (ton) {
1735         default:
1736         case NUMTYPE_UNKNOWN:
1737                 party_ton = 0;/* unknown */
1738                 break;
1739
1740         case NUMTYPE_INTERNATIONAL:
1741                 party_ton = 1;/* level2RegionalNumber */
1742                 break;
1743
1744         case NUMTYPE_NATIONAL:
1745                 party_ton = 2;/* level1RegionalNumber */
1746                 break;
1747
1748         case NUMTYPE_NETWORK_SPECIFIC:
1749                 party_ton = 3;/* pTNSpecificNumber */
1750                 break;
1751
1752         case NUMTYPE_SUBSCRIBER:
1753                 party_ton = 4;/* localNumber */
1754                 break;
1755
1756         case NUMTYPE_ABBREVIATED:
1757                 party_ton = 6;/* abbreviatedNumber */
1758                 break;
1759         }
1760
1761         return party_ton;
1762 }
1763 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1764
1765 #if defined(AST_MISDN_ENHANCEMENTS)
1766 /*!
1767  * \internal
1768  * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1769  *
1770  * \param party_ton PartyNumber private type-of-number
1771  *
1772  * \return mISDN type-of-number
1773  */
1774 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1775 {
1776         enum mISDN_NUMBER_TYPE ton;
1777
1778         switch (party_ton) {
1779         default:
1780         case 0:/* unknown */
1781                 ton = NUMTYPE_UNKNOWN;
1782                 break;
1783
1784         case 1:/* level2RegionalNumber */
1785                 ton = NUMTYPE_INTERNATIONAL;
1786                 break;
1787
1788         case 2:/* level1RegionalNumber */
1789                 ton = NUMTYPE_NATIONAL;
1790                 break;
1791
1792         case 3:/* pTNSpecificNumber */
1793                 ton = NUMTYPE_NETWORK_SPECIFIC;
1794                 break;
1795
1796         case 4:/* localNumber */
1797                 ton = NUMTYPE_SUBSCRIBER;
1798                 break;
1799
1800         case 6:/* abbreviatedNumber */
1801                 ton = NUMTYPE_ABBREVIATED;
1802                 break;
1803         }
1804
1805         return ton;
1806 }
1807 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1808
1809 /*!
1810  * \internal
1811  * \brief Convert the mISDN type of number code to a string
1812  *
1813  * \param number_type mISDN type of number code.
1814  *
1815  * \return The mISDN type of number code as a string
1816  */
1817 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1818 {
1819         const char *str;
1820
1821         switch (number_type) {
1822         default:
1823         case NUMTYPE_UNKNOWN:
1824                 str = "Unknown";
1825                 break;
1826
1827         case NUMTYPE_INTERNATIONAL:
1828                 str = "International";
1829                 break;
1830
1831         case NUMTYPE_NATIONAL:
1832                 str = "National";
1833                 break;
1834
1835         case NUMTYPE_NETWORK_SPECIFIC:
1836                 str = "Network Specific";
1837                 break;
1838
1839         case NUMTYPE_SUBSCRIBER:
1840                 str = "Subscriber";
1841                 break;
1842
1843         case NUMTYPE_ABBREVIATED:
1844                 str = "Abbreviated";
1845                 break;
1846         }
1847
1848         return str;
1849 }
1850
1851 /*!
1852  * \internal
1853  * \brief Convert the mISDN type of number code to Asterisk type of number code
1854  *
1855  * \param number_type mISDN type of number code.
1856  *
1857  * \return Asterisk type of number code
1858  */
1859 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1860 {
1861         int ast_number_type;
1862
1863         switch (number_type) {
1864         default:
1865         case NUMTYPE_UNKNOWN:
1866                 ast_number_type = NUMTYPE_UNKNOWN << 4;
1867                 break;
1868
1869         case NUMTYPE_INTERNATIONAL:
1870                 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1871                 break;
1872
1873         case NUMTYPE_NATIONAL:
1874                 ast_number_type = NUMTYPE_NATIONAL << 4;
1875                 break;
1876
1877         case NUMTYPE_NETWORK_SPECIFIC:
1878                 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1879                 break;
1880
1881         case NUMTYPE_SUBSCRIBER:
1882                 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1883                 break;
1884
1885         case NUMTYPE_ABBREVIATED:
1886                 ast_number_type = NUMTYPE_ABBREVIATED << 4;
1887                 break;
1888         }
1889
1890         return ast_number_type;
1891 }
1892
1893 /*!
1894  * \internal
1895  * \brief Convert the Asterisk type of number code to mISDN type of number code
1896  *
1897  * \param ast_number_type Asterisk type of number code.
1898  *
1899  * \return mISDN type of number code
1900  */
1901 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1902 {
1903         enum mISDN_NUMBER_TYPE number_type;
1904
1905         switch ((ast_number_type >> 4) & 0x07) {
1906         default:
1907         case NUMTYPE_UNKNOWN:
1908                 number_type = NUMTYPE_UNKNOWN;
1909                 break;
1910
1911         case NUMTYPE_INTERNATIONAL:
1912                 number_type = NUMTYPE_INTERNATIONAL;
1913                 break;
1914
1915         case NUMTYPE_NATIONAL:
1916                 number_type = NUMTYPE_NATIONAL;
1917                 break;
1918
1919         case NUMTYPE_NETWORK_SPECIFIC:
1920                 number_type = NUMTYPE_NETWORK_SPECIFIC;
1921                 break;
1922
1923         case NUMTYPE_SUBSCRIBER:
1924                 number_type = NUMTYPE_SUBSCRIBER;
1925                 break;
1926
1927         case NUMTYPE_ABBREVIATED:
1928                 number_type = NUMTYPE_ABBREVIATED;
1929                 break;
1930         }
1931
1932         return number_type;
1933 }
1934
1935 /*!
1936  * \internal
1937  * \brief Convert the mISDN numbering plan code to a string
1938  *
1939  * \param number_plan mISDN numbering plan code.
1940  *
1941  * \return The mISDN numbering plan code as a string
1942  */
1943 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1944 {
1945         const char *str;
1946
1947         switch (number_plan) {
1948         default:
1949         case NUMPLAN_UNKNOWN:
1950                 str = "Unknown";
1951                 break;
1952
1953         case NUMPLAN_ISDN:
1954                 str = "ISDN";
1955                 break;
1956
1957         case NUMPLAN_DATA:
1958                 str = "Data";
1959                 break;
1960
1961         case NUMPLAN_TELEX:
1962                 str = "Telex";
1963                 break;
1964
1965         case NUMPLAN_NATIONAL:
1966                 str = "National";
1967                 break;
1968
1969         case NUMPLAN_PRIVATE:
1970                 str = "Private";
1971                 break;
1972         }
1973
1974         return str;
1975 }
1976
1977 /*!
1978  * \internal
1979  * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1980  *
1981  * \param number_plan mISDN numbering plan code.
1982  *
1983  * \return Asterisk numbering plan code
1984  */
1985 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
1986 {
1987         int ast_number_plan;
1988
1989         switch (number_plan) {
1990         default:
1991         case NUMPLAN_UNKNOWN:
1992                 ast_number_plan = NUMPLAN_UNKNOWN;
1993                 break;
1994
1995         case NUMPLAN_ISDN:
1996                 ast_number_plan = NUMPLAN_ISDN;
1997                 break;
1998
1999         case NUMPLAN_DATA:
2000                 ast_number_plan = NUMPLAN_DATA;
2001                 break;
2002
2003         case NUMPLAN_TELEX:
2004                 ast_number_plan = NUMPLAN_TELEX;
2005                 break;
2006
2007         case NUMPLAN_NATIONAL:
2008                 ast_number_plan = NUMPLAN_NATIONAL;
2009                 break;
2010
2011         case NUMPLAN_PRIVATE:
2012                 ast_number_plan = NUMPLAN_PRIVATE;
2013                 break;
2014         }
2015
2016         return ast_number_plan;
2017 }
2018
2019 /*!
2020  * \internal
2021  * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2022  *
2023  * \param ast_number_plan Asterisk numbering plan code.
2024  *
2025  * \return mISDN numbering plan code
2026  */
2027 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2028 {
2029         enum mISDN_NUMBER_PLAN number_plan;
2030
2031         switch (ast_number_plan & 0x0F) {
2032         default:
2033         case NUMPLAN_UNKNOWN:
2034                 number_plan = NUMPLAN_UNKNOWN;
2035                 break;
2036
2037         case NUMPLAN_ISDN:
2038                 number_plan = NUMPLAN_ISDN;
2039                 break;
2040
2041         case NUMPLAN_DATA:
2042                 number_plan = NUMPLAN_DATA;
2043                 break;
2044
2045         case NUMPLAN_TELEX:
2046                 number_plan = NUMPLAN_TELEX;
2047                 break;
2048
2049         case NUMPLAN_NATIONAL:
2050                 number_plan = NUMPLAN_NATIONAL;
2051                 break;
2052
2053         case NUMPLAN_PRIVATE:
2054                 number_plan = NUMPLAN_PRIVATE;
2055                 break;
2056         }
2057
2058         return number_plan;
2059 }
2060
2061 /*!
2062  * \internal
2063  * \brief Convert the mISDN presentation code to a string
2064  *
2065  * \param presentation mISDN number presentation restriction code.
2066  *
2067  * \return The mISDN presentation code as a string
2068  */
2069 static const char *misdn_to_str_pres(int presentation)
2070 {
2071         const char *str;
2072
2073         switch (presentation) {
2074         case 0:
2075                 str = "Allowed";
2076                 break;
2077
2078         case 1:
2079                 str = "Restricted";
2080                 break;
2081
2082         case 2:
2083                 str = "Unavailable";
2084                 break;
2085
2086         default:
2087                 str = "Unknown";
2088                 break;
2089         }
2090
2091         return str;
2092 }
2093
2094 /*!
2095  * \internal
2096  * \brief Convert the mISDN presentation code to Asterisk presentation code
2097  *
2098  * \param presentation mISDN number presentation restriction code.
2099  *
2100  * \return Asterisk presentation code
2101  */
2102 static int misdn_to_ast_pres(int presentation)
2103 {
2104         switch (presentation) {
2105         default:
2106         case 0:
2107                 presentation = AST_PRES_ALLOWED;
2108                 break;
2109
2110         case 1:
2111                 presentation = AST_PRES_RESTRICTED;
2112                 break;
2113
2114         case 2:
2115                 presentation = AST_PRES_UNAVAILABLE;
2116                 break;
2117         }
2118
2119         return presentation;
2120 }
2121
2122 /*!
2123  * \internal
2124  * \brief Convert the Asterisk presentation code to mISDN presentation code
2125  *
2126  * \param presentation Asterisk number presentation restriction code.
2127  *
2128  * \return mISDN presentation code
2129  */
2130 static int ast_to_misdn_pres(int presentation)
2131 {
2132         switch (presentation & AST_PRES_RESTRICTION) {
2133         default:
2134         case AST_PRES_ALLOWED:
2135                 presentation = 0;
2136                 break;
2137
2138         case AST_PRES_RESTRICTED:
2139                 presentation = 1;
2140                 break;
2141
2142         case AST_PRES_UNAVAILABLE:
2143                 presentation = 2;
2144                 break;
2145         }
2146
2147         return presentation;
2148 }
2149
2150 /*!
2151  * \internal
2152  * \brief Convert the mISDN screening code to a string
2153  *
2154  * \param screening mISDN number screening code.
2155  *
2156  * \return The mISDN screening code as a string
2157  */
2158 static const char *misdn_to_str_screen(int screening)
2159 {
2160         const char *str;
2161
2162         switch (screening) {
2163         case 0:
2164                 str = "Unscreened";
2165                 break;
2166
2167         case 1:
2168                 str = "Passed Screen";
2169                 break;
2170
2171         case 2:
2172                 str = "Failed Screen";
2173                 break;
2174
2175         case 3:
2176                 str = "Network Number";
2177                 break;
2178
2179         default:
2180                 str = "Unknown";
2181                 break;
2182         }
2183
2184         return str;
2185 }
2186
2187 /*!
2188  * \internal
2189  * \brief Convert the mISDN screening code to Asterisk screening code
2190  *
2191  * \param screening mISDN number screening code.
2192  *
2193  * \return Asterisk screening code
2194  */
2195 static int misdn_to_ast_screen(int screening)
2196 {
2197         switch (screening) {
2198         default:
2199         case 0:
2200                 screening = AST_PRES_USER_NUMBER_UNSCREENED;
2201                 break;
2202
2203         case 1:
2204                 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
2205                 break;
2206
2207         case 2:
2208                 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
2209                 break;
2210
2211         case 3:
2212                 screening = AST_PRES_NETWORK_NUMBER;
2213                 break;
2214         }
2215
2216         return screening;
2217 }
2218
2219 /*!
2220  * \internal
2221  * \brief Convert the Asterisk screening code to mISDN screening code
2222  *
2223  * \param screening Asterisk number screening code.
2224  *
2225  * \return mISDN screening code
2226  */
2227 static int ast_to_misdn_screen(int screening)
2228 {
2229         switch (screening & AST_PRES_NUMBER_TYPE) {
2230         default:
2231         case AST_PRES_USER_NUMBER_UNSCREENED:
2232                 screening = 0;
2233                 break;
2234
2235         case AST_PRES_USER_NUMBER_PASSED_SCREEN:
2236                 screening = 1;
2237                 break;
2238
2239         case AST_PRES_USER_NUMBER_FAILED_SCREEN:
2240                 screening = 2;
2241                 break;
2242
2243         case AST_PRES_NETWORK_NUMBER:
2244                 screening = 3;
2245                 break;
2246         }
2247
2248         return screening;
2249 }
2250
2251 /*!
2252  * \internal
2253  * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2254  *
2255  * \param ast Asterisk redirecting reason code.
2256  *
2257  * \return mISDN reason code
2258  */
2259 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
2260 {
2261         unsigned index;
2262
2263         static const struct misdn_reasons {
2264                 enum AST_REDIRECTING_REASON ast;
2265                 enum mISDN_REDIRECTING_REASON q931;
2266         } misdn_reason_table[] = {
2267         /* *INDENT-OFF* */
2268                 { AST_REDIRECTING_REASON_UNKNOWN,        mISDN_REDIRECTING_REASON_UNKNOWN },
2269                 { AST_REDIRECTING_REASON_USER_BUSY,      mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
2270                 { AST_REDIRECTING_REASON_NO_ANSWER,      mISDN_REDIRECTING_REASON_NO_REPLY },
2271                 { AST_REDIRECTING_REASON_UNAVAILABLE,    mISDN_REDIRECTING_REASON_NO_REPLY },
2272                 { AST_REDIRECTING_REASON_UNCONDITIONAL,  mISDN_REDIRECTING_REASON_CALL_FWD },
2273                 { AST_REDIRECTING_REASON_TIME_OF_DAY,    mISDN_REDIRECTING_REASON_UNKNOWN },
2274                 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2275                 { AST_REDIRECTING_REASON_DEFLECTION,     mISDN_REDIRECTING_REASON_DEFLECTION },
2276                 { AST_REDIRECTING_REASON_FOLLOW_ME,      mISDN_REDIRECTING_REASON_UNKNOWN },
2277                 { AST_REDIRECTING_REASON_OUT_OF_ORDER,   mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
2278                 { AST_REDIRECTING_REASON_AWAY,           mISDN_REDIRECTING_REASON_UNKNOWN },
2279                 { AST_REDIRECTING_REASON_CALL_FWD_DTE,   mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
2280         /* *INDENT-ON* */
2281         };
2282
2283         for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2284                 if (misdn_reason_table[index].ast == ast) {
2285                         return misdn_reason_table[index].q931;
2286                 }
2287         }
2288         return mISDN_REDIRECTING_REASON_UNKNOWN;
2289 }
2290
2291 /*!
2292  * \internal
2293  * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2294  *
2295  * \param q931 mISDN redirecting reason code.
2296  *
2297  * \return Asterisk redirecting reason code
2298  */
2299 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
2300 {
2301         enum AST_REDIRECTING_REASON ast;
2302
2303         switch (q931) {
2304         default:
2305         case mISDN_REDIRECTING_REASON_UNKNOWN:
2306                 ast = AST_REDIRECTING_REASON_UNKNOWN;
2307                 break;
2308
2309         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
2310                 ast = AST_REDIRECTING_REASON_USER_BUSY;
2311                 break;
2312
2313         case mISDN_REDIRECTING_REASON_NO_REPLY:
2314                 ast = AST_REDIRECTING_REASON_NO_ANSWER;
2315                 break;
2316
2317         case mISDN_REDIRECTING_REASON_DEFLECTION:
2318                 ast = AST_REDIRECTING_REASON_DEFLECTION;
2319                 break;
2320
2321         case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
2322                 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
2323                 break;
2324
2325         case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
2326                 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
2327                 break;
2328
2329         case mISDN_REDIRECTING_REASON_CALL_FWD:
2330                 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
2331                 break;
2332         }
2333
2334         return ast;
2335 }
2336
2337
2338
2339 struct allowed_bearers {
2340         char *name;         /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2341         char *display;      /*!< Bearer capability displayable name */
2342         int cap;            /*!< SETUP message bearer capability field code value */
2343         int deprecated;     /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2344 };
2345
2346 /* *INDENT-OFF* */
2347 static const struct allowed_bearers allowed_bearers_array[] = {
2348         /* Name,                      Displayable Name       Bearer Capability,                    Deprecated */
2349         { "speech",                  "Speech",               INFO_CAPABILITY_SPEECH,               0 },
2350         { "3_1khz",                  "3.1KHz Audio",         INFO_CAPABILITY_AUDIO_3_1K,           0 },
2351         { "digital_unrestricted",    "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2352         { "digital_restricted",      "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   0 },
2353         { "digital_restriced",       "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   1 }, /* Allow misspelling for backwards compatibility */
2354         { "video",                   "Video",                INFO_CAPABILITY_VIDEO,                0 }
2355 };
2356 /* *INDENT-ON* */
2357
2358 static const char *bearer2str(int cap)
2359 {
2360         unsigned index;
2361
2362         for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2363                 if (allowed_bearers_array[index].cap == cap) {
2364                         return allowed_bearers_array[index].display;
2365                 }
2366         }
2367
2368         return "Unknown Bearer";
2369 }
2370
2371 #if defined(AST_MISDN_ENHANCEMENTS)
2372 /*!
2373  * \internal
2374  * \brief Fill in facility PartyNumber information
2375  *
2376  * \param party PartyNumber structure to fill in.
2377  * \param id Information to put in PartyNumber structure.
2378  *
2379  * \return Nothing
2380  */
2381 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2382 {
2383         ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2384         party->LengthOfNumber = strlen((char *) party->Number);
2385         party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2386         switch (party->Type) {
2387         case 1:/* public */
2388                 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2389                 break;
2390         case 5:/* private */
2391                 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2392                 break;
2393         default:
2394                 party->TypeOfNumber = 0;/* Don't care */
2395                 break;
2396         }
2397 }
2398 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2399
2400 #if defined(AST_MISDN_ENHANCEMENTS)
2401 /*!
2402  * \internal
2403  * \brief Extract the information from PartyNumber
2404  *
2405  * \param id Where to put extracted PartyNumber information
2406  * \param party PartyNumber information to extract
2407  *
2408  * \return Nothing
2409  */
2410 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2411 {
2412         if (party->LengthOfNumber) {
2413                 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2414                 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2415                 switch (party->Type) {
2416                 case 1:/* public */
2417                         id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2418                         break;
2419                 case 5:/* private */
2420                         id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2421                         break;
2422                 default:
2423                         id->number_type = NUMTYPE_UNKNOWN;
2424                         break;
2425                 }
2426         } else {
2427                 /* Number not present */
2428                 id->number_type = NUMTYPE_UNKNOWN;
2429                 id->number_plan = NUMPLAN_ISDN;
2430                 id->number[0] = 0;
2431         }
2432 }
2433 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2434
2435 #if defined(AST_MISDN_ENHANCEMENTS)
2436 /*!
2437  * \internal
2438  * \brief Fill in facility Address information
2439  *
2440  * \param Address Address structure to fill in.
2441  * \param id Information to put in Address structure.
2442  *
2443  * \return Nothing
2444  */
2445 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2446 {
2447         misdn_PartyNumber_fill(&Address->Party, id);
2448
2449         /* Subaddresses are not supported yet */
2450         Address->Subaddress.Length = 0;
2451 }
2452 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2453
2454 #if defined(AST_MISDN_ENHANCEMENTS)
2455 /*!
2456  * \internal
2457  * \brief Fill in facility PresentedNumberUnscreened information
2458  *
2459  * \param presented PresentedNumberUnscreened structure to fill in.
2460  * \param id Information to put in PresentedNumberUnscreened structure.
2461  *
2462  * \return Nothing
2463  */
2464 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2465 {
2466         presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2467         misdn_PartyNumber_fill(&presented->Unscreened, id);
2468 }
2469 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2470
2471 #if defined(AST_MISDN_ENHANCEMENTS)
2472 /*!
2473  * \internal
2474  * \brief Extract the information from PartyNumber
2475  *
2476  * \param id Where to put extracted PresentedNumberUnscreened information
2477  * \param presented PresentedNumberUnscreened information to extract
2478  *
2479  * \return Nothing
2480  */
2481 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2482 {
2483         id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2484         id->screening = 0;/* unscreened */
2485         switch (presented->Type) {
2486         case 0:/* presentationAllowedNumber */
2487         case 3:/* presentationRestrictedNumber */
2488                 misdn_PartyNumber_extract(id, &presented->Unscreened);
2489                 break;
2490         case 1:/* presentationRestricted */
2491         case 2:/* numberNotAvailableDueToInterworking */
2492         default:
2493                 /* Number not present (And uninitialized so do not even look at it!) */
2494                 id->number_type = NUMTYPE_UNKNOWN;
2495                 id->number_plan = NUMPLAN_ISDN;
2496                 id->number[0] = 0;
2497                 break;
2498         }
2499 }
2500 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2501
2502 #if defined(AST_MISDN_ENHANCEMENTS)
2503 static const char Level_Spacing[] = "          ";/* Work for up to 10 levels */
2504 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2505
2506 #if defined(AST_MISDN_ENHANCEMENTS)
2507 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2508 {
2509         if (Party->LengthOfNumber) {
2510                 const char *Spacing;
2511
2512                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2513                 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2514                         Spacing, Party->Type);
2515                 switch (Party->Type) {
2516                 case 0: /* Unknown PartyNumber */
2517                         chan_misdn_log(1, bc->port, " -->%s  Unknown: %s\n",
2518                                 Spacing, Party->Number);
2519                         break;
2520                 case 1: /* Public PartyNumber */
2521                         chan_misdn_log(1, bc->port, " -->%s  Public TON:%d %s\n",
2522                                 Spacing, Party->TypeOfNumber, Party->Number);
2523                         break;
2524                 case 2: /* NSAP encoded PartyNumber */
2525                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2526                                 Spacing, Party->Number);
2527                         break;
2528                 case 3: /* Data PartyNumber (Not used) */
2529                         chan_misdn_log(1, bc->port, " -->%s  Data: %s\n",
2530                                 Spacing, Party->Number);
2531                         break;
2532                 case 4: /* Telex PartyNumber (Not used) */
2533                         chan_misdn_log(1, bc->port, " -->%s  Telex: %s\n",
2534                                 Spacing, Party->Number);
2535                         break;
2536                 case 5: /* Private PartyNumber */
2537                         chan_misdn_log(1, bc->port, " -->%s  Private TON:%d %s\n",
2538                                 Spacing, Party->TypeOfNumber, Party->Number);
2539                         break;
2540                 case 8: /* National Standard PartyNumber (Not used) */
2541                         chan_misdn_log(1, bc->port, " -->%s  National: %s\n",
2542                                 Spacing, Party->Number);
2543                         break;
2544                 default:
2545                         break;
2546                 }
2547         }
2548 }
2549 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2550
2551 #if defined(AST_MISDN_ENHANCEMENTS)
2552 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2553 {
2554         if (Subaddress->Length) {
2555                 const char *Spacing;
2556
2557                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2558                 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2559                         Spacing, Subaddress->Type);
2560                 switch (Subaddress->Type) {
2561                 case 0: /* UserSpecified */
2562                         if (Subaddress->u.UserSpecified.OddCountPresent) {
2563                                 chan_misdn_log(1, bc->port, " -->%s  User BCD OddCount:%d NumOctets:%d\n",
2564                                         Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2565                         } else {
2566                                 chan_misdn_log(1, bc->port, " -->%s  User: %s\n",
2567                                         Spacing, Subaddress->u.UserSpecified.Information);
2568                         }
2569                         break;
2570                 case 1: /* NSAP */
2571                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2572                                 Spacing, Subaddress->u.Nsap);
2573                         break;
2574                 default:
2575                         break;
2576                 }
2577         }
2578 }
2579 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2580
2581 #if defined(AST_MISDN_ENHANCEMENTS)
2582 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2583 {
2584         print_facility_PartyNumber(Level, &Address->Party, bc);
2585         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2586 }
2587 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2588
2589 #if defined(AST_MISDN_ENHANCEMENTS)
2590 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2591 {
2592         const char *Spacing;
2593
2594         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2595         chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2596         switch (Presented->Type) {
2597         case 0: /* presentationAllowedNumber */
2598                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2599                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2600                 break;
2601         case 1: /* presentationRestricted */
2602                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2603                 break;
2604         case 2: /* numberNotAvailableDueToInterworking */
2605                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2606                 break;
2607         case 3: /* presentationRestrictedNumber */
2608                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2609                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2610                 break;
2611         default:
2612                 break;
2613         }
2614 }
2615 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2616
2617 #if defined(AST_MISDN_ENHANCEMENTS)
2618 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2619 {
2620         const char *Spacing;
2621
2622         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2623         chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2624         print_facility_PartyNumber(Level, &Address->Party, bc);
2625         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2626 }
2627 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2628
2629 #if defined(AST_MISDN_ENHANCEMENTS)
2630 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2631 {
2632         const char *Spacing;
2633
2634         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2635         chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2636         switch (Presented->Type) {
2637         case 0: /* presentationAllowedAddress */
2638                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2639                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2640                 break;
2641         case 1: /* presentationRestricted */
2642                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2643                 break;
2644         case 2: /* numberNotAvailableDueToInterworking */
2645                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2646                 break;
2647         case 3: /* presentationRestrictedAddress */
2648                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2649                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2650                 break;
2651         default:
2652                 break;
2653         }
2654 }
2655 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2656
2657 #if defined(AST_MISDN_ENHANCEMENTS)
2658 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2659 {
2660         const char *Spacing;
2661
2662         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2663         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2664         if (Q931ie->Bc.Length) {
2665                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2666         }
2667         if (Q931ie->Hlc.Length) {
2668                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2669         }
2670         if (Q931ie->Llc.Length) {
2671                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2672         }
2673 }
2674 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2675
2676 #if defined(AST_MISDN_ENHANCEMENTS)
2677 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2678 {
2679         const char *Spacing;
2680
2681         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2682         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2683         if (Q931ie->Bc.Length) {
2684                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2685         }
2686         if (Q931ie->Hlc.Length) {
2687                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2688         }
2689         if (Q931ie->Llc.Length) {
2690                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2691         }
2692         if (Q931ie->UserInfo.Length) {
2693                 chan_misdn_log(1, bc->port, " -->%s  UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2694         }
2695 }
2696 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2697
2698 #if defined(AST_MISDN_ENHANCEMENTS)
2699 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2700 {
2701         const char *Spacing;
2702
2703         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2704         chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2705                 Spacing, CallInfo->CCBSReference);
2706         chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2707         print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2708         print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2709         if (CallInfo->SubaddressOfA.Length) {
2710                 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2711                 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2712         }
2713 }
2714 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2715
2716 #if defined(AST_MISDN_ENHANCEMENTS)
2717 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2718 {
2719         const char *Spacing;
2720
2721         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2722         if (Party->LengthOfNumber) {
2723                 print_facility_PartyNumber(Level, Party, bc);
2724         } else {
2725                 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2726         }
2727 }
2728 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2729
2730 #if defined(AST_MISDN_ENHANCEMENTS)
2731 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2732 {
2733         const char *Spacing;
2734
2735         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2736         chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2737                 Spacing,
2738                 ForwardingRecord->Procedure,
2739                 ForwardingRecord->BasicService);
2740         chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2741         print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2742         chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2743         print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2744 }
2745 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2746
2747 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
2748 {
2749 #if defined(AST_MISDN_ENHANCEMENTS)
2750         unsigned Index;
2751 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2752
2753         switch (fac->Function) {
2754 #if defined(AST_MISDN_ENHANCEMENTS)
2755         case Fac_ActivationDiversion:
2756                 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2757                         fac->u.ActivationDiversion.InvokeID);
2758                 switch (fac->u.ActivationDiversion.ComponentType) {
2759                 case FacComponent_Invoke:
2760                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2761                                 fac->u.ActivationDiversion.Component.Invoke.Procedure,
2762                                 fac->u.ActivationDiversion.Component.Invoke.BasicService);
2763                         chan_misdn_log(1, bc->port, " -->   ForwardedTo:\n");
2764                         print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2765                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2766                         print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2767                         break;
2768                 case FacComponent_Result:
2769                         chan_misdn_log(1, bc->port, " -->  Result\n");
2770                         break;
2771                 default:
2772                         break;
2773                 }
2774                 break;
2775         case Fac_DeactivationDiversion:
2776                 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2777                         fac->u.DeactivationDiversion.InvokeID);
2778                 switch (fac->u.DeactivationDiversion.ComponentType) {
2779                 case FacComponent_Invoke:
2780                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2781                                 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2782                                 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2783                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2784                         print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2785                         break;
2786                 case FacComponent_Result:
2787                         chan_misdn_log(1, bc->port, " -->  Result\n");
2788                         break;
2789                 default:
2790                         break;
2791                 }
2792                 break;
2793         case Fac_ActivationStatusNotificationDiv:
2794                 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2795                         fac->u.ActivationStatusNotificationDiv.InvokeID,
2796                         fac->u.ActivationStatusNotificationDiv.Procedure,
2797                         fac->u.ActivationStatusNotificationDiv.BasicService);
2798                 chan_misdn_log(1, bc->port, " -->  ForwardedTo:\n");
2799                 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2800                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2801                 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2802                 break;
2803         case Fac_DeactivationStatusNotificationDiv:
2804                 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2805                         fac->u.DeactivationStatusNotificationDiv.InvokeID,
2806                         fac->u.DeactivationStatusNotificationDiv.Procedure,
2807                         fac->u.DeactivationStatusNotificationDiv.BasicService);
2808                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2809                 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2810                 break;
2811         case Fac_InterrogationDiversion:
2812                 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2813                         fac->u.InterrogationDiversion.InvokeID);
2814                 switch (fac->u.InterrogationDiversion.ComponentType) {
2815                 case FacComponent_Invoke:
2816                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2817                                 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2818                                 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2819                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2820                         print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2821                         break;
2822                 case FacComponent_Result:
2823                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2824                         if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2825                                 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2826                                         chan_misdn_log(1, bc->port, " -->   IntResult[%d]:\n", Index);
2827                                         print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2828                                 }
2829                         }
2830                         break;
2831                 default:
2832                         break;
2833                 }
2834                 break;
2835         case Fac_DiversionInformation:
2836                 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2837                         fac->u.DiversionInformation.InvokeID,
2838                         fac->u.DiversionInformation.DiversionReason,
2839                         fac->u.DiversionInformation.BasicService);
2840                 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2841                         chan_misdn_log(1, bc->port, " -->  ServedUserSubaddress:\n");
2842                         print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2843                 }
2844                 if (fac->u.DiversionInformation.CallingAddressPresent) {
2845                         chan_misdn_log(1, bc->port, " -->  CallingAddress:\n");
2846                         print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2847                 }
2848                 if (fac->u.DiversionInformation.OriginalCalledPresent) {
2849                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2850                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2851                 }
2852                 if (fac->u.DiversionInformation.LastDivertingPresent) {
2853                         chan_misdn_log(1, bc->port, " -->  LastDivertingNr:\n");
2854                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2855                 }
2856                 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2857                         chan_misdn_log(1, bc->port, " -->  LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2858                 }
2859                 if (fac->u.DiversionInformation.UserInfo.Length) {
2860                         chan_misdn_log(1, bc->port, " -->  UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2861                 }
2862                 break;
2863         case Fac_CallDeflection:
2864                 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2865                         fac->u.CallDeflection.InvokeID);
2866                 switch (fac->u.CallDeflection.ComponentType) {
2867                 case FacComponent_Invoke:
2868                         chan_misdn_log(1, bc->port, " -->  Invoke:\n");
2869                         if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2870                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
2871                                         fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2872                         }
2873                         chan_misdn_log(1, bc->port, " -->   DeflectionAddress:\n");
2874                         print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2875                         break;
2876                 case FacComponent_Result:
2877                         chan_misdn_log(1, bc->port, " -->  Result\n");
2878                         break;
2879                 default:
2880                         break;
2881                 }
2882                 break;
2883         case Fac_CallRerouteing:
2884                 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2885                         fac->u.CallRerouteing.InvokeID);
2886                 switch (fac->u.CallRerouteing.ComponentType) {
2887                 case FacComponent_Invoke:
2888                         chan_misdn_log(1, bc->port, " -->  Invoke: Reason:%d Counter:%d\n",
2889                                 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2890                                 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2891                         chan_misdn_log(1, bc->port, " -->   CalledAddress:\n");
2892                         print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2893                         print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2894                         chan_misdn_log(1, bc->port, " -->   LastReroutingNr:\n");
2895                         print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2896                         chan_misdn_log(1, bc->port, " -->   SubscriptionOption:%d\n",
2897                                 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2898                         if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2899                                 chan_misdn_log(1, bc->port, " -->   CallingParty:\n");
2900                                 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2901                         }
2902                         break;
2903                 case FacComponent_Result:
2904                         chan_misdn_log(1, bc->port, " -->  Result\n");
2905                         break;
2906                 default:
2907                         break;
2908                 }
2909                 break;
2910         case Fac_InterrogateServedUserNumbers:
2911                 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2912                         fac->u.InterrogateServedUserNumbers.InvokeID);
2913                 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2914                 case FacComponent_Invoke:
2915                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
2916                         break;
2917                 case FacComponent_Result:
2918                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2919                         if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2920                                 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2921                                         chan_misdn_log(1, bc->port, " -->   ServedUserNr[%d]:\n", Index);
2922                                         print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2923                                 }
2924                         }
2925                         break;
2926                 default:
2927                         break;
2928                 }
2929                 break;
2930         case Fac_DivertingLegInformation1:
2931                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2932                         fac->u.DivertingLegInformation1.InvokeID,
2933                         fac->u.DivertingLegInformation1.DiversionReason,
2934                         fac->u.DivertingLegInformation1.SubscriptionOption);
2935                 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2936                         chan_misdn_log(1, bc->port, " -->  DivertedToNr:\n");
2937                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2938                 }
2939                 break;
2940         case Fac_DivertingLegInformation2:
2941                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2942                         fac->u.DivertingLegInformation2.InvokeID,
2943                         fac->u.DivertingLegInformation2.DiversionReason,
2944                         fac->u.DivertingLegInformation2.DiversionCounter);
2945                 if (fac->u.DivertingLegInformation2.DivertingPresent) {
2946                         chan_misdn_log(1, bc->port, " -->  DivertingNr:\n");
2947                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2948                 }
2949                 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2950                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2951                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2952                 }
2953                 break;
2954         case Fac_DivertingLegInformation3:
2955                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2956                         fac->u.DivertingLegInformation3.InvokeID,
2957                         fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2958                 break;
2959
2960 #else   /* !defined(AST_MISDN_ENHANCEMENTS) */
2961
2962         case Fac_CD:
2963                 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2964                         fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2965                 break;
2966 #endif  /* !defined(AST_MISDN_ENHANCEMENTS) */
2967         case Fac_AOCDCurrency:
2968                 if (fac->u.AOCDcur.chargeNotAvailable) {
2969                         chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2970                 } else if (fac->u.AOCDcur.freeOfCharge) {
2971                         chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2972                 } else if (fac->u.AOCDchu.billingId >= 0) {
2973                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2974                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2975                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2976                 } else {
2977                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2978                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2979                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2980                 }
2981                 break;
2982         case Fac_AOCDChargingUnit:
2983                 if (fac->u.AOCDchu.chargeNotAvailable) {
2984                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
2985                 } else if (fac->u.AOCDchu.freeOfCharge) {
2986                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
2987                 } else if (fac->u.AOCDchu.billingId >= 0) {
2988                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
2989                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
2990                 } else {
2991                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
2992                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
2993                 }
2994                 break;
2995 #if defined(AST_MISDN_ENHANCEMENTS)
2996         case Fac_ERROR:
2997                 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
2998                         fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
2999                 break;
3000         case Fac_RESULT:
3001                 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
3002                         fac->u.RESULT.InvokeID);
3003                 break;
3004         case Fac_REJECT:
3005                 if (fac->u.REJECT.InvokeIDPresent) {
3006                         chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
3007                                 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
3008                 } else {
3009                         chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
3010                                 fac->u.REJECT.Code);
3011                 }
3012                 break;
3013         case Fac_EctExecute:
3014                 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3015                         fac->u.EctExecute.InvokeID);
3016                 break;
3017         case Fac_ExplicitEctExecute:
3018                 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3019                         fac->u.ExplicitEctExecute.InvokeID,
3020                         fac->u.ExplicitEctExecute.LinkID);
3021                 break;
3022         case Fac_RequestSubaddress:
3023                 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3024                         fac->u.RequestSubaddress.InvokeID);
3025                 break;
3026         case Fac_SubaddressTransfer:
3027                 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3028                         fac->u.SubaddressTransfer.InvokeID);
3029                 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3030                 break;
3031         case Fac_EctLinkIdRequest:
3032                 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3033                         fac->u.EctLinkIdRequest.InvokeID);
3034                 switch (fac->u.EctLinkIdRequest.ComponentType) {
3035                 case FacComponent_Invoke:
3036                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3037                         break;
3038                 case FacComponent_Result:
3039                         chan_misdn_log(1, bc->port, " -->  Result: LinkID:%d\n",
3040                                 fac->u.EctLinkIdRequest.Component.Result.LinkID);
3041                         break;
3042                 default:
3043                         break;
3044                 }
3045                 break;
3046         case Fac_EctInform:
3047                 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3048                         fac->u.EctInform.InvokeID,
3049                         fac->u.EctInform.Status);
3050                 if (fac->u.EctInform.RedirectionPresent) {
3051                         chan_misdn_log(1, bc->port, " -->  Redirection Number\n");
3052                         print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3053                 }
3054                 break;
3055         case Fac_EctLoopTest:
3056                 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3057                         fac->u.EctLoopTest.InvokeID);
3058                 switch (fac->u.EctLoopTest.ComponentType) {
3059                 case FacComponent_Invoke:
3060                         chan_misdn_log(1, bc->port, " -->  Invoke: CallTransferID:%d\n",
3061                                 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3062                         break;
3063                 case FacComponent_Result:
3064                         chan_misdn_log(1, bc->port, " -->  Result: LoopResult:%d\n",
3065                                 fac->u.EctLoopTest.Component.Result.LoopResult);
3066                         break;
3067                 default:
3068                         break;
3069                 }
3070                 break;
3071         case Fac_StatusRequest:
3072                 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3073                         fac->u.StatusRequest.InvokeID);
3074                 switch (fac->u.StatusRequest.ComponentType) {
3075                 case FacComponent_Invoke:
3076                         chan_misdn_log(1, bc->port, " -->  Invoke: Compatibility:%d\n",
3077                                 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3078                         break;
3079                 case FacComponent_Result:
3080                         chan_misdn_log(1, bc->port, " -->  Result: Status:%d\n",
3081                                 fac->u.StatusRequest.Component.Result.Status);
3082                         break;
3083                 default:
3084                         break;
3085                 }
3086                 break;
3087         case Fac_CallInfoRetain:
3088                 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3089                         fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3090                 break;
3091         case Fac_CCBSDeactivate:
3092                 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3093                         fac->u.CCBSDeactivate.InvokeID);
3094                 switch (fac->u.CCBSDeactivate.ComponentType) {
3095                 case FacComponent_Invoke:
3096                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d\n",
3097                                 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3098                         break;
3099                 case FacComponent_Result:
3100                         chan_misdn_log(1, bc->port, " -->  Result\n");
3101                         break;
3102                 default:
3103                         break;
3104                 }
3105                 break;
3106         case Fac_CCBSErase:
3107                 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3108                         fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3109                         fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3110                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3111                 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3112                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3113                 break;
3114         case Fac_CCBSRemoteUserFree:
3115                 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3116                         fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3117                         fac->u.CCBSRemoteUserFree.RecallMode);
3118                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3119                 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3120                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3121                 break;
3122         case Fac_CCBSCall:
3123                 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3124                         fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3125                 break;
3126         case Fac_CCBSStatusRequest:
3127                 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3128                         fac->u.CCBSStatusRequest.InvokeID);
3129                 switch (fac->u.CCBSStatusRequest.ComponentType) {
3130                 case FacComponent_Invoke:
3131                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d RecallMode:%d\n",
3132                                 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3133                                 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3134                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3135                         break;
3136                 case FacComponent_Result:
3137                         chan_misdn_log(1, bc->port, " -->  Result: Free:%d\n",
3138                                 fac->u.CCBSStatusRequest.Component.Result.Free);
3139                         break;
3140                 default:
3141                         break;
3142                 }
3143                 break;
3144         case Fac_CCBSBFree:
3145                 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3146                         fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3147                         fac->u.CCBSBFree.RecallMode);
3148                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3149                 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3150                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3151                 break;
3152         case Fac_EraseCallLinkageID:
3153                 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3154                         fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3155                 break;
3156         case Fac_CCBSStopAlerting:
3157                 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3158                         fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3159                 break;
3160         case Fac_CCBSRequest:
3161                 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3162                         fac->u.CCBSRequest.InvokeID);
3163                 switch (fac->u.CCBSRequest.ComponentType) {
3164                 case FacComponent_Invoke:
3165                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3166                                 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3167                         break;
3168                 case FacComponent_Result:
3169                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3170                                 fac->u.CCBSRequest.Component.Result.CCBSReference,
3171                                 fac->u.CCBSRequest.Component.Result.RecallMode);
3172                         break;
3173                 default:
3174                         break;
3175                 }
3176                 break;
3177         case Fac_CCBSInterrogate:
3178                 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3179                         fac->u.CCBSInterrogate.InvokeID);
3180                 switch (fac->u.CCBSInterrogate.ComponentType) {
3181                 case FacComponent_Invoke:
3182                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3183                         if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3184                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3185                                         fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3186                         }
3187                         if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3188                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3189                                 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3190                         }
3191                         break;
3192                 case FacComponent_Result:
3193                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3194                                 fac->u.CCBSInterrogate.Component.Result.RecallMode);
3195                         if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3196                                 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3197                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3198                                         print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3199                                 }
3200                         }
3201                         break;
3202                 default:
3203                         break;
3204                 }
3205                 break;
3206         case Fac_CCNRRequest:
3207                 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3208                         fac->u.CCNRRequest.InvokeID);
3209                 switch (fac->u.CCNRRequest.ComponentType) {
3210                 case FacComponent_Invoke:
3211                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3212                                 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3213                         break;
3214                 case FacComponent_Result:
3215                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3216                                 fac->u.CCNRRequest.Component.Result.CCBSReference,
3217                                 fac->u.CCNRRequest.Component.Result.RecallMode);
3218                         break;
3219                 default:
3220                         break;
3221                 }
3222                 break;
3223         case Fac_CCNRInterrogate:
3224                 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3225                         fac->u.CCNRInterrogate.InvokeID);
3226                 switch (fac->u.CCNRInterrogate.ComponentType) {
3227                 case FacComponent_Invoke:
3228                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3229                         if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3230                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3231                                         fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3232                         }
3233                         if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3234                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3235                                 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3236                         }
3237                         break;
3238                 case FacComponent_Result:
3239                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3240                                 fac->u.CCNRInterrogate.Component.Result.RecallMode);
3241                         if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3242                                 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3243                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3244                                         print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3245                                 }
3246                         }
3247                         break;
3248                 default:
3249                         break;
3250                 }
3251                 break;
3252         case Fac_CCBS_T_Call:
3253                 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3254                         fac->u.CCBS_T_Call.InvokeID);
3255                 break;
3256         case Fac_CCBS_T_Suspend:
3257                 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3258                         fac->u.CCBS_T_Suspend.InvokeID);
3259                 break;
3260         case Fac_CCBS_T_Resume:
3261                 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3262                         fac->u.CCBS_T_Resume.InvokeID);
3263                 break;
3264         case Fac_CCBS_T_RemoteUserFree:
3265                 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3266                         fac->u.CCBS_T_RemoteUserFree.InvokeID);
3267                 break;
3268         case Fac_CCBS_T_Available:
3269                 chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3270                         fac->u.CCBS_T_Available.InvokeID);
3271                 break;
3272         case Fac_CCBS_T_Request:
3273                 chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
3274                         fac->u.CCBS_T_Request.InvokeID);
3275                 switch (fac->u.CCBS_T_Request.ComponentType) {
3276                 case FacComponent_Invoke:
3277                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3278                         chan_misdn_log(1, bc->port, " -->   DestinationAddress:\n");
3279                         print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
3280                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
3281                         if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
3282                                 chan_misdn_log(1, bc->port, " -->   RetentionSupported:1\n");
3283                         }
3284                         if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3285                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
3286                                         fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
3287                         }
3288                         if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3289                                 chan_misdn_log(1, bc->port, " -->   OriginatingAddress:\n");
3290                                 print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
3291                         }
3292                         break;
3293                 case FacComponent_Result:
3294                         chan_misdn_log(1, bc->port, " -->  Result: RetentionSupported:%d\n",
3295                                 fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
3296                         break;
3297                 default:
3298                         break;
3299                 }
3300                 break;
3301         case Fac_CCNR_T_Request:
3302                 chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
3303                         fac->u.CCNR_T_Request.InvokeID);
3304                 switch (fac->u.CCNR_T_Request.ComponentType) {
3305                 case FacComponent_Invoke:
3306                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3307                         chan_misdn_log(1, bc->port, " -->   DestinationAddress:\n");
3308                         print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
3309                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
3310                         if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
3311                                 chan_misdn_log(1, bc->port, " -->   RetentionSupported:1\n");
3312                         }
3313                         if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3314                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
3315                                         fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
3316                         }
3317                         if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
3318                                 chan_misdn_log(1, bc->port, " -->   OriginatingAddress:\n");
3319                                 print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
3320                         }
3321                         break;
3322                 case FacComponent_Result:
3323                         chan_misdn_log(1, bc->port, " -->  Result: RetentionSupported:%d\n",
3324                                 fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
3325                         break;
3326                 default:
3327                         break;
3328                 }
3329                 break;
3330 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
3331         case Fac_None:
3332                 /* No facility so print nothing */
3333                 break;
3334         default:
3335                 chan_misdn_log(1, bc->port, " --> unknown facility\n");
3336                 break;
3337         }
3338 }
3339
3340 static void print_bearer(struct misdn_bchannel *bc)
3341 {
3342         chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
3343
3344         switch(bc->law) {
3345         case INFO_CODEC_ALAW:
3346                 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
3347                 break;
3348         case INFO_CODEC_ULAW:
3349                 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
3350                 break;
3351         }
3352 }
3353
3354 /*!
3355  * \internal
3356  * \brief Prefix a string to another string in place.
3357  *
3358  * \param str_prefix String to prefix to the main string.
3359  * \param str_main String to get the prefix added to it.
3360  * \param size Buffer size of the main string (Includes null terminator).
3361  *
3362  * \note The str_main buffer size must be greater than one.
3363  *
3364  * \return Nothing
3365  */
3366 static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
3367 {
3368         size_t len_over;
3369         size_t len_total;
3370         size_t len_main;
3371         size_t len_prefix;
3372
3373         len_prefix = strlen(str_prefix);
3374         if (!len_prefix) {
3375                 /* There is no prefix to prepend. */
3376                 return;
3377         }
3378         len_main = strlen(str_main);
3379         len_total = len_prefix + len_main;
3380         if (size <= len_total) {
3381                 /* We need to truncate since the buffer is too small. */
3382                 len_over = len_total + 1 - size;
3383                 if (len_over <= len_main) {
3384                         len_main -= len_over;
3385                 } else {
3386                         len_over -= len_main;
3387                         len_main = 0;
3388                         len_prefix -= len_over;
3389                 }
3390         }
3391         if (len_main) {
3392                 memmove(str_main + len_prefix, str_main, len_main);
3393         }
3394         memcpy(str_main, str_prefix, len_prefix);
3395         str_main[len_prefix + len_main] = '\0';
3396 }
3397
3398 /*!
3399  * \internal
3400  * \brief Add a configured prefix to the given number.
3401  *
3402  * \param port Logical port number
3403  * \param number_type Type-of-number passed in.
3404  * \param number Given number string to add prefix
3405  * \param size Buffer size number string occupies.
3406  *
3407  * \return Nothing
3408  */
3409 static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
3410 {
3411         enum misdn_cfg_elements type_prefix;
3412         char num_prefix[MISDN_MAX_NUMBER_LEN];
3413
3414         /* Get prefix string. */
3415         switch (number_type) {
3416         case NUMTYPE_UNKNOWN:
3417                 type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
3418                 break;
3419         case NUMTYPE_INTERNATIONAL:
3420                 type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
3421                 break;
3422         case NUMTYPE_NATIONAL:
3423                 type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
3424                 break;
3425         case NUMTYPE_NETWORK_SPECIFIC:
3426                 type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
3427                 break;
3428         case NUMTYPE_SUBSCRIBER:
3429                 type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
3430                 break;
3431         case NUMTYPE_ABBREVIATED:
3432                 type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
3433                 break;
3434         default:
3435                 /* Type-of-number does not have a prefix that can be added. */
3436                 return;
3437         }
3438         misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
3439
3440         misdn_prefix_string(num_prefix, number, size);
3441 }
3442
3443 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
3444 {
3445         char buf[128];
3446
3447         if (!bc->AOCD_need_export || !ast) {
3448                 return;
3449         }
3450
3451         if (originator == ORG_AST) {
3452                 ast = ast_bridged_channel(ast);
3453                 if (!ast) {
3454                         return;
3455                 }
3456         }
3457
3458         switch (bc->AOCDtype) {
3459         case Fac_AOCDCurrency:
3460                 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
3461                 if (bc->AOCD.currency.chargeNotAvailable) {
3462                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
3463                 } else {
3464                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
3465                         if (bc->AOCD.currency.freeOfCharge) {
3466                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
3467                         } else {
3468                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
3469                                 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
3470                                         pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
3471                                         if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
3472                                                 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
3473                                         }
3474                                 }
3475                         }
3476                 }
3477                 break;
3478         case Fac_AOCDChargingUnit:
3479                 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
3480                 if (bc->AOCD.chargingUnit.chargeNotAvailable) {
3481                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
3482                 } else {
3483                         pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
3484                         if (bc->AOCD.chargingUnit.freeOfCharge) {
3485                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
3486                         } else {
3487                                 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
3488                                 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
3489                                         pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
3490                                         if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
3491                                                 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
3492                                         }
3493                                 }
3494                         }
3495                 }
3496                 break;
3497         default:
3498                 break;
3499         }
3500
3501         bc->AOCD_need_export = 0;
3502 }
3503
3504 /*************** Helpers END *************/
3505
3506 static void sighandler(int sig)
3507 {
3508 }
3509
3510 static void *misdn_tasks_thread_func(void *data)
3511 {
3512         int wait;
3513         struct sigaction sa;
3514
3515         sa.sa_handler = sighandler;
3516         sa.sa_flags = SA_NODEFER;
3517         sigemptyset(&sa.sa_mask);
3518         sigaddset(&sa.sa_mask, SIGUSR1);
3519         sigaction(SIGUSR1, &sa, NULL);
3520
3521         sem_post((sem_t *)data);
3522
3523         while (1) {
3524                 wait = ast_sched_wait(misdn_tasks);
3525                 if (wait < 0) {
3526                         wait = 8000;
3527                 }
3528                 if (poll(NULL, 0, wait) < 0) {
3529                         chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
3530                 }
3531                 ast_sched_runq(misdn_tasks);
3532         }
3533         return NULL;
3534 }
3535
3536 static void misdn_tasks_init(void)
3537 {
3538         sem_t blocker;
3539         int i = 5;
3540
3541         if (sem_init(&blocker, 0, 0)) {
3542                 perror("chan_misdn: Failed to initialize semaphore!");
3543                 exit(1);
3544         }
3545
3546         chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
3547
3548         misdn_tasks = ast_sched_context_create();
3549         pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
3550
3551         while (sem_wait(&blocker) && --i) {
3552         }
3553         sem_destroy(&blocker);
3554 }
3555
3556 static void misdn_tasks_destroy(void)
3557 {
3558         if (misdn_tasks) {
3559                 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
3560                 if (pthread_cancel(misdn_tasks_thread) == 0) {
3561                         cb_log(4, 0, "Joining misdn_tasks thread\n");
3562                         pthread_join(misdn_tasks_thread, NULL);
3563                 }
3564                 ast_sched_context_destroy(misdn_tasks);
3565         }
3566 }
3567
3568 static inline void misdn_tasks_wakeup(void)
3569 {
3570         pthread_kill(misdn_tasks_thread, SIGUSR1);
3571 }
3572
3573 static inline int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
3574 {
3575         int task_id;
3576
3577         if (!misdn_tasks) {
3578                 misdn_tasks_init();
3579         }
3580         task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
3581         misdn_tasks_wakeup();
3582
3583         return task_id;
3584 }
3585
3586 static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
3587 {
3588         return _misdn_tasks_add_variable(timeout, callback, data, 0);
3589 }
3590
3591 static int misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data)
3592 {
3593         return _misdn_tasks_add_variable(timeout, callback, data, 1);
3594 }
3595
3596 static void misdn_tasks_remove(int task_id)
3597 {
3598         AST_SCHED_DEL(misdn_tasks, task_id);
3599 }
3600
3601 static int misdn_l1_task(const void *vdata)
3602 {
3603         const int *data = vdata;
3604
3605         misdn_lib_isdn_l1watcher(*data);
3606         chan_misdn_log(5, *data, "L1watcher timeout\n");
3607         return 1;
3608 }
3609
3610 static int misdn_overlap_dial_task(const void *data)
3611 {
3612         struct timeval tv_end, tv_now;
3613         int diff;
3614         struct chan_list *ch = (struct chan_list *) data;
3615         char *dad;
3616
3617         chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
3618
3619         if (ch->state != MISDN_WAITING4DIGS) {
3620                 ch->overlap_dial_task = -1;
3621                 return 0;
3622         }
3623
3624         ast_mutex_lock(&ch->overlap_tv_lock);
3625         tv_end = ch->overlap_tv;
3626         ast_mutex_unlock(&ch->overlap_tv_lock);
3627
3628         tv_end.tv_sec += ch->overlap_dial;
3629         tv_now = ast_tvnow();
3630
3631         diff = ast_tvdiff_ms(tv_end, tv_now);
3632         if (100 < diff) {
3633                 return diff;
3634         }
3635
3636         /* if we are 100ms near the timeout, we are satisfied.. */
3637         stop_indicate(ch);
3638
3639         if (ast_strlen_zero(ch->bc->dialed.number)) {
3640                 dad = "s";
3641                 ast_channel_exten_set(ch->ast, dad);
3642         } else {
3643                 dad = ch->bc->dialed.number;
3644         }
3645
3646         if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
3647                 ch->state = MISDN_DIALING;
3648                 if (pbx_start_chan(ch) < 0) {
3649                         chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
3650                         goto misdn_overlap_dial_task_disconnect;
3651                 }
3652         } else {
3653 misdn_overlap_dial_task_disconnect:
3654                 hanguptone_indicate(ch);
3655                 ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
3656                 ch->state = MISDN_CLEANING;
3657                 misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
3658         }
3659         ch->overlap_dial_task = -1;
3660         return 0;
3661 }
3662
3663 static void send_digit_to_chan(struct chan_list *cl, char digit)
3664 {
3665         static const char * const dtmf_tones[] = {
3666 /* *INDENT-OFF* */
3667                 "!941+1336/100,!0/100", /* 0 */
3668                 "!697+1209/100,!0/100", /* 1 */
3669                 "!697+1336/100,!0/100", /* 2 */
3670                 "!697+1477/100,!0/100", /* 3 */
3671                 "!770+1209/100,!0/100", /* 4 */
3672                 "!770+1336/100,!0/100", /* 5 */
3673                 "!770+1477/100,!0/100", /* 6 */
3674                 "!852+1209/100,!0/100", /* 7 */
3675                 "!852+1336/100,!0/100", /* 8 */
3676                 "!852+1477/100,!0/100", /* 9 */
3677                 "!697+1633/100,!0/100", /* A */
3678                 "!770+1633/100,!0/100", /* B */
3679                 "!852+1633/100,!0/100", /* C */
3680                 "!941+1633/100,!0/100", /* D */
3681                 "!941+1209/100,!0/100", /* * */
3682                 "!941+1477/100,!0/100", /* # */
3683 /* *INDENT-ON* */
3684         };
3685         struct ast_channel *chan = cl->ast;
3686
3687         if (digit >= '0' && digit <='9') {
3688                 ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
3689         } else if (digit >= 'A' && digit <= 'D') {
3690                 ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
3691         } else if (digit == '*') {
3692                 ast_playtones_start(chan, 0, dtmf_tones[14], 0);
3693         } else if (digit == '#') {
3694                 ast_playtones_start(chan, 0, dtmf_tones[15], 0);
3695         } else {
3696                 /* not handled */
3697                 ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast_channel_name(chan));
3698         }
3699 }
3700
3701 /*** CLI HANDLING ***/
3702 static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3703 {
3704         int level;
3705
3706         switch (cmd) {
3707         case CLI_INIT:
3708                 e->command = "misdn set debug [on|off]";
3709                 e->usage =
3710                         "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
3711                         "       Set the debug level of the mISDN channel.\n";
3712                 return NULL;
3713         case CLI_GENERATE:
3714                 return complete_debug_port(a);
3715         }
3716
3717         if (a->argc < 4 || a->argc > 7) {
3718                 return CLI_SHOWUSAGE;
3719         }
3720
3721         if (!strcasecmp(a->argv[3], "on")) {
3722                 level = 1;
3723         } else if (!strcasecmp(a->argv[3], "off")) {
3724                 level = 0;
3725         } else if (isdigit(a->argv[3][0])) {
3726                 level = atoi(a->argv[3]);
3727         } else {
3728                 return CLI_SHOWUSAGE;
3729         }
3730
3731         switch (a->argc) {
3732         case 4:
3733         case 5:
3734                 {
3735                         int i;
3736                         int only = 0;
3737                         if (a->argc == 5) {
3738                                 if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
3739                                         return CLI_SHOWUSAGE;
3740                                 } else {
3741                                         only = 1;
3742                                 }
3743                         }
3744
3745                         for (i = 0; i <= max_ports; i++) {
3746                                 misdn_debug[i] = level;
3747                                 misdn_debug_only[i] = only;
3748                         }
3749                         ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
3750                 }
3751                 break;
3752         case 6:
3753         case 7:
3754                 {
3755                         int port;
3756                         if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
3757                                 return CLI_SHOWUSAGE;
3758                         port = atoi(a->argv[5]);
3759                         if (port <= 0 || port > max_ports) {
3760                                 switch (max_ports) {
3761                                 case 0:
3762                                         ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
3763                                         break;
3764                                 case 1:
3765                                         ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
3766                                         break;
3767                                 default:
3768                                         ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
3769                                 }
3770                                 return 0;
3771                         }
3772                         if (a->argc == 7) {
3773                                 if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
3774                            &nb