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