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