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