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