channel locking: Add locking for channel snapshot creation
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2006, Christian Richter
5  *
6  * Christian Richter <crich@beronet.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  *
18  */
19
20 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  *
25  * \author Christian Richter <crich@beronet.com>
26  *
27  * MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31
32 /*! \li \ref chan_misdn.c uses the configuration file \ref misdn.conf
33  * \addtogroup configuration_file
34  */
35
36 /*! \page misdn.conf misdn.conf
37  * \verbinclude misdn.conf.sample
38  */
39
40 /*!
41  * \note
42  * To use the CCBS/CCNR supplementary service feature and other
43  * supplementary services using FACILITY messages requires a
44  * modified version of mISDN.
45  *
46  * \note
47  * The latest modified mISDN v1.1.x based version is available at:
48  * http://svn.digium.com/svn/thirdparty/mISDN/trunk
49  * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
50  *
51  * \note
52  * Taged versions of the modified mISDN code are available under:
53  * http://svn.digium.com/svn/thirdparty/mISDN/tags
54  * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
55  */
56
57 /* Define to enable cli commands to generate canned CCBS messages. */
58 // #define CCBS_TEST_MESSAGES   1
59
60 /*
61  * XXX The mISDN channel driver needs its native bridge code
62  * converted to the new bridge technology scheme.  The
63  * chan_dahdi native bridge code can be used as an example.  It
64  * is unlikely that this will ever get done.  Support for this
65  * channel driver is dwindling because the supported version of
66  * mISDN does not support newer kernels.
67  *
68  * Without native bridge support, the following config file
69  * parameters have no effect: bridging.
70  *
71  * The existing native bridge code is marked with the
72  * mISDN_NATIVE_BRIDGING conditional.
73  */
74
75 /*** MODULEINFO
76         <depend>isdnnet</depend>
77         <depend>misdn</depend>
78         <depend>suppserv</depend>
79         <support_level>extended</support_level>
80  ***/
81
82 #include "asterisk.h"
83
84 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
85
86 #include <pthread.h>
87 #include <sys/socket.h>
88 #include <sys/time.h>
89 #include <arpa/inet.h>
90 #include <fcntl.h>
91 #include <sys/ioctl.h>
92 #include <signal.h>
93 #include <sys/file.h>
94 #include <semaphore.h>
95 #include <ctype.h>
96 #include <time.h>
97
98 #include "asterisk/channel.h"
99 #include "asterisk/config.h"
100 #include "asterisk/module.h"
101 #include "asterisk/pbx.h"
102 #include "asterisk/io.h"
103 #include "asterisk/frame.h"
104 #include "asterisk/translate.h"
105 #include "asterisk/cli.h"
106 #include "asterisk/musiconhold.h"
107 #include "asterisk/dsp.h"
108 #include "asterisk/file.h"
109 #include "asterisk/callerid.h"
110 #include "asterisk/indications.h"
111 #include "asterisk/app.h"
112 #include "asterisk/features.h"
113 #include "asterisk/term.h"
114 #include "asterisk/sched.h"
115 #include "asterisk/stringfields.h"
116 #include "asterisk/abstract_jb.h"
117 #include "asterisk/causes.h"
118 #include "asterisk/format.h"
119 #include "asterisk/format_cap.h"
120 #include "asterisk/features_config.h"
121 #include "asterisk/bridge.h"
122 #include "asterisk/pickup.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)), (obj))
372 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
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 char *linkedid, 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 /*! \brief Only alaw and mulaw is allowed for now */
695 static struct ast_format prefformat; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
696
697 static int *misdn_debug;
698 static int *misdn_debug_only;
699 static int max_ports;
700
701 static int *misdn_in_calls;
702 static int *misdn_out_calls;
703
704 /*!
705  * \brief Global channel call record list head.
706  */
707 static struct chan_list *cl_te=NULL;
708 static ast_mutex_t cl_te_lock;
709
710 static enum event_response_e
711 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
712
713 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
714
715 static void cl_queue_chan(struct chan_list *chan);
716
717 static int dialtone_indicate(struct chan_list *cl);
718 static void hanguptone_indicate(struct chan_list *cl);
719 static int stop_indicate(struct chan_list *cl);
720
721 static int start_bc_tones(struct chan_list *cl);
722 static int stop_bc_tones(struct chan_list *cl);
723 static void release_chan_early(struct chan_list *ch);
724 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
725
726 #if defined(AST_MISDN_ENHANCEMENTS)
727 static const char misdn_command_name[] = "misdn_command";
728 static int misdn_command_exec(struct ast_channel *chan, const char *data);
729 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
730 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
731 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
732 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
733
734 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
735
736 void debug_numtype(int port, int numtype, char *type);
737
738 int add_out_calls(int port);
739 int add_in_calls(int port);
740
741
742 #ifdef MISDN_1_2
743 static int update_pipeline_config(struct misdn_bchannel *bc);
744 #else
745 static int update_ec_config(struct misdn_bchannel *bc);
746 #endif
747
748
749
750 /*************** Helpers *****************/
751
752 static int misdn_chan_is_valid(struct chan_list *ch)
753 {
754         struct chan_list *list;
755
756         ast_mutex_lock(&cl_te_lock);
757         for (list = cl_te; list; list = list->next) {
758                 if (list == ch) {
759                         ast_mutex_unlock(&cl_te_lock);
760                         return 1;
761                 }
762         }
763         ast_mutex_unlock(&cl_te_lock);
764
765         return 0;
766 }
767
768 #if defined(mISDN_NATIVE_BRIDGING)
769 /*! Returns a reference to the found chan_list. */
770 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
771 {
772         struct chan_list *tmp;
773
774         ast_mutex_lock(&cl_te_lock);
775         for (tmp = cl_te; tmp; tmp = tmp->next) {
776                 if (tmp->ast == ast) {
777                         chan_list_ref(tmp, "Found chan_list by ast");
778                         ast_mutex_unlock(&cl_te_lock);
779                         return tmp;
780                 }
781         }
782         ast_mutex_unlock(&cl_te_lock);
783
784         return NULL;
785 }
786 #endif  /* defined(mISDN_NATIVE_BRIDGING) */
787
788 /*! Returns a reference to the found chan_list. */
789 static struct chan_list *get_chan_by_ast_name(const char *name)
790 {
791         struct chan_list *tmp;
792
793         ast_mutex_lock(&cl_te_lock);
794         for (tmp = cl_te; tmp; tmp = tmp->next) {
795                 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
796                         chan_list_ref(tmp, "Found chan_list by ast name");
797                         ast_mutex_unlock(&cl_te_lock);
798                         return tmp;
799                 }
800         }
801         ast_mutex_unlock(&cl_te_lock);
802
803         return NULL;
804 }
805
806 #if defined(AST_MISDN_ENHANCEMENTS)
807 /*!
808  * \internal
809  * \brief Destroy the misdn_cc_ds_info datastore payload
810  *
811  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
812  *
813  * \details
814  * Since the payload is a reference to an astobj2 object, we just decrement its
815  * reference count.  Before doing so, we NULL out the channel pointer inside of
816  * the misdn_cc_caller instance.  This function will be called in one of two
817  * cases.  In both cases, we no longer need the channel pointer:
818  *
819  *  - The original channel that initialized call completion services, the same
820  *    channel that is stored here, has been destroyed early.  This could happen
821  *    if it transferred the mISDN channel, for example.
822  *
823  *  - The mISDN channel that had this datastore inherited on to it is now being
824  *    destroyed.  If this is the case, then the call completion events have
825  *    already occurred and the appropriate channel variables have already been
826  *    set on the original channel that requested call completion services.
827  *
828  * \return Nothing
829  */
830 static void misdn_cc_ds_destroy(void *data)
831 {
832         struct misdn_cc_caller *cc_caller = data;
833
834         ao2_lock(cc_caller);
835         cc_caller->chan = NULL;
836         ao2_unlock(cc_caller);
837
838         ao2_ref(cc_caller, -1);
839 }
840 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
841
842 #if defined(AST_MISDN_ENHANCEMENTS)
843 /*!
844  * \internal
845  * \brief Duplicate the misdn_cc_ds_info datastore payload
846  *
847  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
848  *
849  * \details
850  * All we need to do is bump the reference count and return the same instance.
851  *
852  * \return A reference to an instance of a misdn_cc_caller
853  */
854 static void *misdn_cc_ds_duplicate(void *data)
855 {
856         struct misdn_cc_caller *cc_caller = data;
857
858         ao2_ref(cc_caller, +1);
859
860         return cc_caller;
861 }
862 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
863
864 #if defined(AST_MISDN_ENHANCEMENTS)
865 static const struct ast_datastore_info misdn_cc_ds_info = {
866         .type      = "misdn_cc",
867         .destroy   = misdn_cc_ds_destroy,
868         .duplicate = misdn_cc_ds_duplicate,
869 };
870 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
871
872 #if defined(AST_MISDN_ENHANCEMENTS)
873 /*!
874  * \internal
875  * \brief Set a channel var on the peer channel for call completion services
876  *
877  * \param[in] peer The peer that initialized call completion services
878  * \param[in] var The variable name to set
879  * \param[in] value The variable value to set
880  *
881  * This function may be called from outside of the channel thread.  It handles
882  * the fact that the peer channel may be hung up and destroyed at any time.
883  *
884  * \return nothing
885  */
886 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
887         const char *value)
888 {
889         ao2_lock(peer);
890
891         /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
892         while (peer->chan && ast_channel_trylock(peer->chan)) {
893                 ao2_unlock(peer);
894                 sched_yield();
895                 ao2_lock(peer);
896         }
897
898         if (peer->chan) {
899                 pbx_builtin_setvar_helper(peer->chan, var, value);
900                 ast_channel_unlock(peer->chan);
901         }
902
903         ao2_unlock(peer);
904 }
905 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
906
907 #if defined(AST_MISDN_ENHANCEMENTS)
908 /*!
909  * \internal
910  * \brief Get a reference to the CC caller if it exists
911  */
912 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
913 {
914         struct ast_datastore *datastore;
915         struct misdn_cc_caller *cc_caller;
916
917         ast_channel_lock(chan);
918
919         if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
920                 ast_channel_unlock(chan);
921                 return NULL;
922         }
923
924         ao2_ref(datastore->data, +1);
925         cc_caller = datastore->data;
926
927         ast_channel_unlock(chan);
928
929         return cc_caller;
930 }
931 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
932
933 #if defined(AST_MISDN_ENHANCEMENTS)
934 /*!
935  * \internal
936  * \brief Find the call completion record given the record id.
937  *
938  * \param record_id
939  *
940  * \retval pointer to found call completion record
941  * \retval NULL if not found
942  *
943  * \note Assumes the misdn_cc_records_db lock is already obtained.
944  */
945 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
946 {
947         struct misdn_cc_record *current;
948
949         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
950                 if (current->record_id == record_id) {
951                         /* Found the record */
952                         break;
953                 }
954         }
955
956         return current;
957 }
958 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
959
960 #if defined(AST_MISDN_ENHANCEMENTS)
961 /*!
962  * \internal
963  * \brief Find the call completion record given the port and call linkage id.
964  *
965  * \param port Logical port number
966  * \param linkage_id Call linkage ID number from switch.
967  *
968  * \retval pointer to found call completion record
969  * \retval NULL if not found
970  *
971  * \note Assumes the misdn_cc_records_db lock is already obtained.
972  */
973 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
974 {
975         struct misdn_cc_record *current;
976
977         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
978                 if (current->port == port
979                         && !current->ptp
980                         && current->mode.ptmp.linkage_id == linkage_id) {
981                         /* Found the record */
982                         break;
983                 }
984         }
985
986         return current;
987 }
988 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
989
990 #if defined(AST_MISDN_ENHANCEMENTS)
991 /*!
992  * \internal
993  * \brief Find the call completion record given the port and outstanding invocation id.
994  *
995  * \param port Logical port number
996  * \param invoke_id Outstanding message invocation ID number.
997  *
998  * \retval pointer to found call completion record
999  * \retval NULL if not found
1000  *
1001  * \note Assumes the misdn_cc_records_db lock is already obtained.
1002  */
1003 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
1004 {
1005         struct misdn_cc_record *current;
1006
1007         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1008                 if (current->outstanding_message
1009                         && current->invoke_id == invoke_id
1010                         && current->port == port) {
1011                         /* Found the record */
1012                         break;
1013                 }
1014         }
1015
1016         return current;
1017 }
1018 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1019
1020 #if defined(AST_MISDN_ENHANCEMENTS)
1021 /*!
1022  * \internal
1023  * \brief Find the call completion record given the port and CCBS reference id.
1024  *
1025  * \param port Logical port number
1026  * \param reference_id CCBS reference ID number from switch.
1027  *
1028  * \retval pointer to found call completion record
1029  * \retval NULL if not found
1030  *
1031  * \note Assumes the misdn_cc_records_db lock is already obtained.
1032  */
1033 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1034 {
1035         struct misdn_cc_record *current;
1036
1037         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1038                 if (current->activated
1039                         && current->port == port
1040                         && !current->ptp
1041                         && current->mode.ptmp.reference_id == reference_id) {
1042                         /* Found the record */
1043                         break;
1044                 }
1045         }
1046
1047         return current;
1048 }
1049 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1050
1051 #if defined(AST_MISDN_ENHANCEMENTS)
1052 /*!
1053  * \internal
1054  * \brief Find the call completion record given the B channel pointer
1055  *
1056  * \param bc B channel control structure pointer.
1057  *
1058  * \retval pointer to found call completion record
1059  * \retval NULL if not found
1060  *
1061  * \note Assumes the misdn_cc_records_db lock is already obtained.
1062  */
1063 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1064 {
1065         struct misdn_cc_record *current;
1066
1067         if (bc) {
1068                 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1069                         if (current->ptp
1070                                 && current->mode.ptp.bc == bc) {
1071                                 /* Found the record */
1072                                 break;
1073                         }
1074                 }
1075         } else {
1076                 current = NULL;
1077         }
1078
1079         return current;
1080 }
1081 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1082
1083 #if defined(AST_MISDN_ENHANCEMENTS)
1084 /*!
1085  * \internal
1086  * \brief Delete the given call completion record
1087  *
1088  * \param doomed Call completion record to destroy
1089  *
1090  * \return Nothing
1091  *
1092  * \note Assumes the misdn_cc_records_db lock is already obtained.
1093  */
1094 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1095 {
1096         struct misdn_cc_record *current;
1097
1098         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1099                 if (current == doomed) {
1100                         AST_LIST_REMOVE_CURRENT(list);
1101                         ast_free(current);
1102                         return;
1103                 }
1104         }
1105         AST_LIST_TRAVERSE_SAFE_END;
1106
1107         /* The doomed node is not in the call completion database */
1108 }
1109 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1110
1111 #if defined(AST_MISDN_ENHANCEMENTS)
1112 /*!
1113  * \internal
1114  * \brief Delete all old call completion records
1115  *
1116  * \return Nothing
1117  *
1118  * \note Assumes the misdn_cc_records_db lock is already obtained.
1119  */
1120 static void misdn_cc_remove_old(void)
1121 {
1122         struct misdn_cc_record *current;
1123         time_t now;
1124
1125         now = time(NULL);
1126         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1127                 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1128                         if (current->ptp && current->mode.ptp.bc) {
1129                                 /* Close the old call-completion signaling link */
1130                                 current->mode.ptp.bc->fac_out.Function = Fac_None;
1131                                 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1132                                 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1133                         }
1134
1135                         /* Remove the old call completion record */
1136                         AST_LIST_REMOVE_CURRENT(list);
1137                         ast_free(current);
1138                 }
1139         }
1140         AST_LIST_TRAVERSE_SAFE_END;
1141 }
1142 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1143
1144 #if defined(AST_MISDN_ENHANCEMENTS)
1145 /*!
1146  * \internal
1147  * \brief Allocate the next record id.
1148  *
1149  * \retval New record id on success.
1150  * \retval -1 on error.
1151  *
1152  * \note Assumes the misdn_cc_records_db lock is already obtained.
1153  */
1154 static long misdn_cc_record_id_new(void)
1155 {
1156         long record_id;
1157         long first_id;
1158
1159         record_id = ++misdn_cc_record_id;
1160         first_id = record_id;
1161         while (misdn_cc_find_by_id(record_id)) {
1162                 record_id = ++misdn_cc_record_id;
1163                 if (record_id == first_id) {
1164                         /*
1165                          * We have a resource leak.
1166                          * We should never need to allocate 64k records.
1167                          */
1168                         chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1169                         record_id = -1;
1170                         break;
1171                 }
1172         }
1173
1174         return record_id;
1175 }
1176 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1177
1178 #if defined(AST_MISDN_ENHANCEMENTS)
1179 /*!
1180  * \internal
1181  * \brief Create a new call completion record
1182  *
1183  * \retval pointer to new call completion record
1184  * \retval NULL if failed
1185  *
1186  * \note Assumes the misdn_cc_records_db lock is already obtained.
1187  */
1188 static struct misdn_cc_record *misdn_cc_new(void)
1189 {
1190         struct misdn_cc_record *cc_record;
1191         long record_id;
1192
1193         misdn_cc_remove_old();
1194
1195         cc_record = ast_calloc(1, sizeof(*cc_record));
1196         if (cc_record) {
1197                 record_id = misdn_cc_record_id_new();
1198                 if (record_id < 0) {
1199                         ast_free(cc_record);
1200                         return NULL;
1201                 }
1202
1203                 /* Initialize the new record */
1204                 cc_record->record_id = record_id;
1205                 cc_record->port = -1;/* Invalid port so it will never be found this way */
1206                 cc_record->invoke_id = ++misdn_invoke_id;
1207                 cc_record->party_a_free = 1;/* Default User-A as free */
1208                 cc_record->error_code = FacError_None;
1209                 cc_record->reject_code = FacReject_None;
1210                 cc_record->time_created = time(NULL);
1211
1212                 /* Insert the new record into the database */
1213                 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1214         }
1215         return cc_record;
1216 }
1217 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1218
1219 #if defined(AST_MISDN_ENHANCEMENTS)
1220 /*!
1221  * \internal
1222  * \brief Destroy the call completion record database
1223  *
1224  * \return Nothing
1225  */
1226 static void misdn_cc_destroy(void)
1227 {
1228         struct misdn_cc_record *current;
1229
1230         while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1231                 /* Do a misdn_cc_delete(current) inline */
1232                 ast_free(current);
1233         }
1234 }
1235 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1236
1237 #if defined(AST_MISDN_ENHANCEMENTS)
1238 /*!
1239  * \internal
1240  * \brief Initialize the call completion record database
1241  *
1242  * \return Nothing
1243  */
1244 static void misdn_cc_init(void)
1245 {
1246         misdn_cc_record_id = 0;
1247 }
1248 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1249
1250 #if defined(AST_MISDN_ENHANCEMENTS)
1251 /*!
1252  * \internal
1253  * \brief Check the status of an outstanding invocation request.
1254  *
1255  * \param data Points to an integer containing the call completion record id.
1256  *
1257  * \retval 0 if got a response.
1258  * \retval -1 if no response yet.
1259  */
1260 static int misdn_cc_response_check(void *data)
1261 {
1262         int not_responded;
1263         struct misdn_cc_record *cc_record;
1264
1265         AST_LIST_LOCK(&misdn_cc_records_db);
1266         cc_record = misdn_cc_find_by_id(*(long *) data);
1267         if (cc_record) {
1268                 if (cc_record->outstanding_message) {
1269                         not_responded = -1;
1270                 } else {
1271                         not_responded = 0;
1272                 }
1273         } else {
1274                 /* No record so there is no response to check. */
1275                 not_responded = 0;
1276         }
1277         AST_LIST_UNLOCK(&misdn_cc_records_db);
1278
1279         return not_responded;
1280 }
1281 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1282
1283 #if defined(AST_MISDN_ENHANCEMENTS)
1284 /*!
1285  * \internal
1286  * \brief Wait for a response from the switch for an outstanding
1287  * invocation request.
1288  *
1289  * \param chan Asterisk channel to operate upon.
1290  * \param wait_seconds Number of seconds to wait
1291  * \param record_id Call completion record ID.
1292  *
1293  * \return Nothing
1294  */
1295 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1296 {
1297         unsigned count;
1298
1299         for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1300                 /* Sleep in 500 ms increments */
1301                 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1302                         /* We got hung up or our response came in. */
1303                         break;
1304                 }
1305         }
1306 }
1307 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1308
1309 #if defined(AST_MISDN_ENHANCEMENTS)
1310 /*!
1311  * \internal
1312  * \brief Convert the mISDN reject code to a string
1313  *
1314  * \param code mISDN reject code.
1315  *
1316  * \return The mISDN reject code as a string
1317  */
1318 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1319 {
1320         static const struct {
1321                 enum FacRejectCode code;
1322                 char *name;
1323         } arr[] = {
1324 /* *INDENT-OFF* */
1325                 { FacReject_None,                           "No reject occurred" },
1326                 { FacReject_Unknown,                        "Unknown reject code" },
1327
1328                 { FacReject_Gen_UnrecognizedComponent,      "General: Unrecognized Component" },
1329                 { FacReject_Gen_MistypedComponent,          "General: Mistyped Component" },
1330                 { FacReject_Gen_BadlyStructuredComponent,   "General: Badly Structured Component" },
1331
1332                 { FacReject_Inv_DuplicateInvocation,        "Invoke: Duplicate Invocation" },
1333                 { FacReject_Inv_UnrecognizedOperation,      "Invoke: Unrecognized Operation" },
1334                 { FacReject_Inv_MistypedArgument,           "Invoke: Mistyped Argument" },
1335                 { FacReject_Inv_ResourceLimitation,         "Invoke: Resource Limitation" },
1336                 { FacReject_Inv_InitiatorReleasing,         "Invoke: Initiator Releasing" },
1337                 { FacReject_Inv_UnrecognizedLinkedID,       "Invoke: Unrecognized Linked ID" },
1338                 { FacReject_Inv_LinkedResponseUnexpected,   "Invoke: Linked Response Unexpected" },
1339                 { FacReject_Inv_UnexpectedChildOperation,   "Invoke: Unexpected Child Operation" },
1340
1341                 { FacReject_Res_UnrecognizedInvocation,     "Result: Unrecognized Invocation" },
1342                 { FacReject_Res_ResultResponseUnexpected,   "Result: Result Response Unexpected" },
1343                 { FacReject_Res_MistypedResult,             "Result: Mistyped Result" },
1344
1345                 { FacReject_Err_UnrecognizedInvocation,     "Error: Unrecognized Invocation" },
1346                 { FacReject_Err_ErrorResponseUnexpected,    "Error: Error Response Unexpected" },
1347                 { FacReject_Err_UnrecognizedError,          "Error: Unrecognized Error" },
1348                 { FacReject_Err_UnexpectedError,            "Error: Unexpected Error" },
1349                 { FacReject_Err_MistypedParameter,          "Error: Mistyped Parameter" },
1350 /* *INDENT-ON* */
1351         };
1352
1353         unsigned index;
1354
1355         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1356                 if (arr[index].code == code) {
1357                         return arr[index].name;
1358                 }
1359         }
1360
1361         return "unknown";
1362 }
1363 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1364
1365 #if defined(AST_MISDN_ENHANCEMENTS)
1366 /*!
1367  * \internal
1368  * \brief Convert the mISDN error code to a string
1369  *
1370  * \param code mISDN error code.
1371  *
1372  * \return The mISDN error code as a string
1373  */
1374 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1375 {
1376         static const struct {
1377                 enum FacErrorCode code;
1378                 char *name;
1379         } arr[] = {
1380 /* *INDENT-OFF* */
1381                 { FacError_None,                            "No error occurred" },
1382                 { FacError_Unknown,                         "Unknown OID error code" },
1383
1384                 { FacError_Gen_NotSubscribed,               "General: Not Subscribed" },
1385                 { FacError_Gen_NotAvailable,                "General: Not Available" },
1386                 { FacError_Gen_NotImplemented,              "General: Not Implemented" },
1387                 { FacError_Gen_InvalidServedUserNr,         "General: Invalid Served User Number" },
1388                 { FacError_Gen_InvalidCallState,            "General: Invalid Call State" },
1389                 { FacError_Gen_BasicServiceNotProvided,     "General: Basic Service Not Provided" },
1390                 { FacError_Gen_NotIncomingCall,             "General: Not Incoming Call" },
1391                 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1392                 { FacError_Gen_ResourceUnavailable,         "General: Resource Unavailable" },
1393
1394                 { FacError_Div_InvalidDivertedToNr,         "Diversion: Invalid Diverted To Number" },
1395                 { FacError_Div_SpecialServiceNr,            "Diversion: Special Service Number" },
1396                 { FacError_Div_DiversionToServedUserNr,     "Diversion: Diversion To Served User Number" },
1397                 { FacError_Div_IncomingCallAccepted,        "Diversion: Incoming Call Accepted" },
1398                 { FacError_Div_NumberOfDiversionsExceeded,  "Diversion: Number Of Diversions Exceeded" },
1399                 { FacError_Div_NotActivated,                "Diversion: Not Activated" },
1400                 { FacError_Div_RequestAlreadyAccepted,      "Diversion: Request Already Accepted" },
1401
1402                 { FacError_AOC_NoChargingInfoAvailable,     "AOC: No Charging Info Available" },
1403
1404                 { FacError_CCBS_InvalidCallLinkageID,       "CCBS: Invalid Call Linkage ID" },
1405                 { FacError_CCBS_InvalidCCBSReference,       "CCBS: Invalid CCBS Reference" },
1406                 { FacError_CCBS_LongTermDenial,             "CCBS: Long Term Denial" },
1407                 { FacError_CCBS_ShortTermDenial,            "CCBS: Short Term Denial" },
1408                 { FacError_CCBS_IsAlreadyActivated,         "CCBS: Is Already Activated" },
1409                 { FacError_CCBS_AlreadyAccepted,            "CCBS: Already Accepted" },
1410                 { FacError_CCBS_OutgoingCCBSQueueFull,      "CCBS: Outgoing CCBS Queue Full" },
1411                 { FacError_CCBS_CallFailureReasonNotBusy,   "CCBS: Call Failure Reason Not Busy" },
1412                 { FacError_CCBS_NotReadyForCall,            "CCBS: Not Ready For Call" },
1413
1414                 { FacError_CCBS_T_LongTermDenial,           "CCBS-T: Long Term Denial" },
1415                 { FacError_CCBS_T_ShortTermDenial,          "CCBS-T: Short Term Denial" },
1416
1417                 { FacError_ECT_LinkIdNotAssignedByNetwork,  "ECT: Link ID Not Assigned By Network" },
1418 /* *INDENT-ON* */
1419         };
1420
1421         unsigned index;
1422
1423         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1424                 if (arr[index].code == code) {
1425                         return arr[index].name;
1426                 }
1427         }
1428
1429         return "unknown";
1430 }
1431 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1432
1433 #if defined(AST_MISDN_ENHANCEMENTS)
1434 /*!
1435  * \internal
1436  * \brief Convert mISDN redirecting reason to diversion reason.
1437  *
1438  * \param reason mISDN redirecting reason code.
1439  *
1440  * \return Supported diversion reason code.
1441  */
1442 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1443 {
1444         unsigned diversion_reason;
1445
1446         switch (reason) {
1447         case mISDN_REDIRECTING_REASON_CALL_FWD:
1448                 diversion_reason = 1;/* cfu */
1449                 break;
1450         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
1451                 diversion_reason = 2;/* cfb */
1452                 break;
1453         case mISDN_REDIRECTING_REASON_NO_REPLY:
1454                 diversion_reason = 3;/* cfnr */
1455                 break;
1456         default:
1457                 diversion_reason = 0;/* unknown */
1458                 break;
1459         }
1460
1461         return diversion_reason;
1462 }
1463 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1464
1465 #if defined(AST_MISDN_ENHANCEMENTS)
1466 /*!
1467  * \internal
1468  * \brief Convert diversion reason to mISDN redirecting reason
1469  *
1470  * \param diversion_reason Diversion reason to convert
1471  *
1472  * \return Supported redirecting reason code.
1473  */
1474 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1475 {
1476         enum mISDN_REDIRECTING_REASON reason;
1477
1478         switch (diversion_reason) {
1479         case 1:/* cfu */
1480                 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
1481                 break;
1482         case 2:/* cfb */
1483                 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
1484                 break;
1485         case 3:/* cfnr */
1486                 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
1487                 break;
1488         default:
1489                 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
1490                 break;
1491         }
1492
1493         return reason;
1494 }
1495 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1496
1497 #if defined(AST_MISDN_ENHANCEMENTS)
1498 /*!
1499  * \internal
1500  * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1501  *
1502  * \param presentation mISDN presentation to convert
1503  * \param number_present TRUE if the number is present
1504  *
1505  * \return PresentedNumberUnscreened type
1506  */
1507 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1508 {
1509         unsigned type;
1510
1511         switch (presentation) {
1512         case 0:/* allowed */
1513                 if (number_present) {
1514                         type = 0;/* presentationAllowedNumber */
1515                 } else {
1516                         type = 2;/* numberNotAvailableDueToInterworking */
1517                 }
1518                 break;
1519         case 1:/* restricted */
1520                 if (number_present) {
1521                         type = 3;/* presentationRestrictedNumber */
1522                 } else {
1523                         type = 1;/* presentationRestricted */
1524                 }
1525                 break;
1526         default:
1527                 type = 2;/* numberNotAvailableDueToInterworking */
1528                 break;
1529         }
1530
1531         return type;
1532 }
1533 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1534
1535 #if defined(AST_MISDN_ENHANCEMENTS)
1536 /*!
1537  * \internal
1538  * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1539  *
1540  * \param type PresentedNumberUnscreened type
1541  *
1542  * \return mISDN presentation
1543  */
1544 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1545 {
1546         int presentation;
1547
1548         switch (type) {
1549         default:
1550         case 0:/* presentationAllowedNumber */
1551                 presentation = 0;/* allowed */
1552                 break;
1553
1554         case 1:/* presentationRestricted */
1555         case 3:/* presentationRestrictedNumber */
1556                 presentation = 1;/* restricted */
1557                 break;
1558
1559         case 2:/* numberNotAvailableDueToInterworking */
1560                 presentation = 2;/* unavailable */
1561                 break;
1562         }
1563
1564         return presentation;
1565 }
1566 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1567
1568 #if defined(AST_MISDN_ENHANCEMENTS)
1569 /*!
1570  * \internal
1571  * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1572  *
1573  * \param number_plan mISDN numbering plan
1574  *
1575  * \return PartyNumber numbering plan
1576  */
1577 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1578 {
1579         unsigned party_plan;
1580
1581         switch (number_plan) {
1582         default:
1583         case NUMPLAN_UNKNOWN:
1584                 party_plan = 0;/* unknown */
1585                 break;
1586
1587         case NUMPLAN_ISDN:
1588                 party_plan = 1;/* public */
1589                 break;
1590
1591         case NUMPLAN_DATA:
1592                 party_plan = 3;/* data */
1593                 break;
1594
1595         case NUMPLAN_TELEX:
1596                 party_plan = 4;/* telex */
1597                 break;
1598
1599         case NUMPLAN_NATIONAL:
1600                 party_plan = 8;/* nationalStandard */
1601                 break;
1602
1603         case NUMPLAN_PRIVATE:
1604                 party_plan = 5;/* private */
1605                 break;
1606         }
1607
1608         return party_plan;
1609 }
1610 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1611
1612 #if defined(AST_MISDN_ENHANCEMENTS)
1613 /*!
1614  * \internal
1615  * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1616  *
1617  * \param party_plan PartyNumber numbering plan
1618  *
1619  * \return mISDN numbering plan
1620  */
1621 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1622 {
1623         enum mISDN_NUMBER_PLAN number_plan;
1624
1625         switch (party_plan) {
1626         default:
1627         case 0:/* unknown */
1628                 number_plan = NUMPLAN_UNKNOWN;
1629                 break;
1630         case 1:/* public */
1631                 number_plan = NUMPLAN_ISDN;
1632                 break;
1633         case 3:/* data */
1634                 number_plan = NUMPLAN_DATA;
1635                 break;
1636         case 4:/* telex */
1637                 number_plan = NUMPLAN_TELEX;
1638                 break;
1639         case 8:/* nationalStandard */
1640                 number_plan = NUMPLAN_NATIONAL;
1641                 break;
1642         case 5:/* private */
1643                 number_plan = NUMPLAN_PRIVATE;
1644                 break;
1645         }
1646
1647         return number_plan;
1648 }
1649 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1650
1651 #if defined(AST_MISDN_ENHANCEMENTS)
1652 /*!
1653  * \internal
1654  * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1655  *
1656  * \param ton mISDN type-of-number
1657  *
1658  * \return PartyNumber public type-of-number
1659  */
1660 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1661 {
1662         unsigned party_ton;
1663
1664         switch (ton) {
1665         default:
1666         case NUMTYPE_UNKNOWN:
1667                 party_ton = 0;/* unknown */
1668                 break;
1669
1670         case NUMTYPE_INTERNATIONAL:
1671                 party_ton = 1;/* internationalNumber */
1672                 break;
1673
1674         case NUMTYPE_NATIONAL:
1675                 party_ton = 2;/* nationalNumber */
1676                 break;
1677
1678         case NUMTYPE_NETWORK_SPECIFIC:
1679                 party_ton = 3;/* networkSpecificNumber */
1680                 break;
1681
1682         case NUMTYPE_SUBSCRIBER:
1683                 party_ton = 4;/* subscriberNumber */
1684                 break;
1685
1686         case NUMTYPE_ABBREVIATED:
1687                 party_ton = 6;/* abbreviatedNumber */
1688                 break;
1689         }
1690
1691         return party_ton;
1692 }
1693 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1694
1695 #if defined(AST_MISDN_ENHANCEMENTS)
1696 /*!
1697  * \internal
1698  * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1699  *
1700  * \param party_ton PartyNumber public type-of-number
1701  *
1702  * \return mISDN type-of-number
1703  */
1704 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1705 {
1706         enum mISDN_NUMBER_TYPE ton;
1707
1708         switch (party_ton) {
1709         default:
1710         case 0:/* unknown */
1711                 ton = NUMTYPE_UNKNOWN;
1712                 break;
1713
1714         case 1:/* internationalNumber */
1715                 ton = NUMTYPE_INTERNATIONAL;
1716                 break;
1717
1718         case 2:/* nationalNumber */
1719                 ton = NUMTYPE_NATIONAL;
1720                 break;
1721
1722         case 3:/* networkSpecificNumber */
1723                 ton = NUMTYPE_NETWORK_SPECIFIC;
1724                 break;
1725
1726         case 4:/* subscriberNumber */
1727                 ton = NUMTYPE_SUBSCRIBER;
1728                 break;
1729
1730         case 6:/* abbreviatedNumber */
1731                 ton = NUMTYPE_ABBREVIATED;
1732                 break;
1733         }
1734
1735         return ton;
1736 }
1737 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1738
1739 #if defined(AST_MISDN_ENHANCEMENTS)
1740 /*!
1741  * \internal
1742  * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1743  *
1744  * \param ton mISDN type-of-number
1745  *
1746  * \return PartyNumber private type-of-number
1747  */
1748 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1749 {
1750         unsigned party_ton;
1751
1752         switch (ton) {
1753         default:
1754         case NUMTYPE_UNKNOWN:
1755                 party_ton = 0;/* unknown */
1756                 break;
1757
1758         case NUMTYPE_INTERNATIONAL:
1759                 party_ton = 1;/* level2RegionalNumber */
1760                 break;
1761
1762         case NUMTYPE_NATIONAL:
1763                 party_ton = 2;/* level1RegionalNumber */
1764                 break;
1765
1766         case NUMTYPE_NETWORK_SPECIFIC:
1767                 party_ton = 3;/* pTNSpecificNumber */
1768                 break;
1769
1770         case NUMTYPE_SUBSCRIBER:
1771                 party_ton = 4;/* localNumber */
1772                 break;
1773
1774         case NUMTYPE_ABBREVIATED:
1775                 party_ton = 6;/* abbreviatedNumber */
1776                 break;
1777         }
1778
1779         return party_ton;
1780 }
1781 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1782
1783 #if defined(AST_MISDN_ENHANCEMENTS)
1784 /*!
1785  * \internal
1786  * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1787  *
1788  * \param party_ton PartyNumber private type-of-number
1789  *
1790  * \return mISDN type-of-number
1791  */
1792 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1793 {
1794         enum mISDN_NUMBER_TYPE ton;
1795
1796         switch (party_ton) {
1797         default:
1798         case 0:/* unknown */
1799                 ton = NUMTYPE_UNKNOWN;
1800                 break;
1801
1802         case 1:/* level2RegionalNumber */
1803                 ton = NUMTYPE_INTERNATIONAL;
1804                 break;
1805
1806         case 2:/* level1RegionalNumber */
1807                 ton = NUMTYPE_NATIONAL;
1808                 break;
1809
1810         case 3:/* pTNSpecificNumber */
1811                 ton = NUMTYPE_NETWORK_SPECIFIC;
1812                 break;
1813
1814         case 4:/* localNumber */
1815                 ton = NUMTYPE_SUBSCRIBER;
1816                 break;
1817
1818         case 6:/* abbreviatedNumber */
1819                 ton = NUMTYPE_ABBREVIATED;
1820                 break;
1821         }
1822
1823         return ton;
1824 }
1825 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1826
1827 /*!
1828  * \internal
1829  * \brief Convert the mISDN type of number code to a string
1830  *
1831  * \param number_type mISDN type of number code.
1832  *
1833  * \return The mISDN type of number code as a string
1834  */
1835 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1836 {
1837         const char *str;
1838
1839         switch (number_type) {
1840         default:
1841         case NUMTYPE_UNKNOWN:
1842                 str = "Unknown";
1843                 break;
1844
1845         case NUMTYPE_INTERNATIONAL:
1846                 str = "International";
1847                 break;
1848
1849         case NUMTYPE_NATIONAL:
1850                 str = "National";
1851                 break;
1852
1853         case NUMTYPE_NETWORK_SPECIFIC:
1854                 str = "Network Specific";
1855                 break;
1856
1857         case NUMTYPE_SUBSCRIBER:
1858                 str = "Subscriber";
1859                 break;
1860
1861         case NUMTYPE_ABBREVIATED:
1862                 str = "Abbreviated";
1863                 break;
1864         }
1865
1866         return str;
1867 }
1868
1869 /*!
1870  * \internal
1871  * \brief Convert the mISDN type of number code to Asterisk type of number code
1872  *
1873  * \param number_type mISDN type of number code.
1874  *
1875  * \return Asterisk type of number code
1876  */
1877 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1878 {
1879         int ast_number_type;
1880
1881         switch (number_type) {
1882         default:
1883         case NUMTYPE_UNKNOWN:
1884                 ast_number_type = NUMTYPE_UNKNOWN << 4;
1885                 break;
1886
1887         case NUMTYPE_INTERNATIONAL:
1888                 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1889                 break;
1890
1891         case NUMTYPE_NATIONAL:
1892                 ast_number_type = NUMTYPE_NATIONAL << 4;
1893                 break;
1894
1895         case NUMTYPE_NETWORK_SPECIFIC:
1896                 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1897                 break;
1898
1899         case NUMTYPE_SUBSCRIBER:
1900                 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1901                 break;
1902
1903         case NUMTYPE_ABBREVIATED:
1904                 ast_number_type = NUMTYPE_ABBREVIATED << 4;
1905                 break;
1906         }
1907
1908         return ast_number_type;
1909 }
1910
1911 /*!
1912  * \internal
1913  * \brief Convert the Asterisk type of number code to mISDN type of number code
1914  *
1915  * \param ast_number_type Asterisk type of number code.
1916  *
1917  * \return mISDN type of number code
1918  */
1919 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1920 {
1921         enum mISDN_NUMBER_TYPE number_type;
1922
1923         switch ((ast_number_type >> 4) & 0x07) {
1924         default:
1925         case NUMTYPE_UNKNOWN:
1926                 number_type = NUMTYPE_UNKNOWN;
1927                 break;
1928
1929         case NUMTYPE_INTERNATIONAL:
1930                 number_type = NUMTYPE_INTERNATIONAL;
1931                 break;
1932
1933         case NUMTYPE_NATIONAL:
1934                 number_type = NUMTYPE_NATIONAL;
1935                 break;
1936
1937         case NUMTYPE_NETWORK_SPECIFIC:
1938                 number_type = NUMTYPE_NETWORK_SPECIFIC;
1939                 break;
1940
1941         case NUMTYPE_SUBSCRIBER:
1942                 number_type = NUMTYPE_SUBSCRIBER;
1943                 break;
1944
1945         case NUMTYPE_ABBREVIATED:
1946                 number_type = NUMTYPE_ABBREVIATED;
1947                 break;
1948         }
1949
1950         return number_type;
1951 }
1952
1953 /*!
1954  * \internal
1955  * \brief Convert the mISDN numbering plan code to a string
1956  *
1957  * \param number_plan mISDN numbering plan code.
1958  *
1959  * \return The mISDN numbering plan code as a string
1960  */
1961 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1962 {
1963         const char *str;
1964
1965         switch (number_plan) {
1966         default:
1967         case NUMPLAN_UNKNOWN:
1968                 str = "Unknown";
1969                 break;
1970
1971         case NUMPLAN_ISDN:
1972                 str = "ISDN";
1973                 break;
1974
1975         case NUMPLAN_DATA:
1976                 str = "Data";
1977                 break;
1978
1979         case NUMPLAN_TELEX:
1980                 str = "Telex";
1981                 break;
1982
1983         case NUMPLAN_NATIONAL:
1984                 str = "National";
1985                 break;
1986
1987         case NUMPLAN_PRIVATE:
1988                 str = "Private";
1989                 break;
1990         }
1991
1992         return str;
1993 }
1994
1995 /*!
1996  * \internal
1997  * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1998  *
1999  * \param number_plan mISDN numbering plan code.
2000  *
2001  * \return Asterisk numbering plan code
2002  */
2003 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
2004 {
2005         int ast_number_plan;
2006
2007         switch (number_plan) {
2008         default:
2009         case NUMPLAN_UNKNOWN:
2010                 ast_number_plan = NUMPLAN_UNKNOWN;
2011                 break;
2012
2013         case NUMPLAN_ISDN:
2014                 ast_number_plan = NUMPLAN_ISDN;
2015                 break;
2016
2017         case NUMPLAN_DATA:
2018                 ast_number_plan = NUMPLAN_DATA;
2019                 break;
2020
2021         case NUMPLAN_TELEX:
2022                 ast_number_plan = NUMPLAN_TELEX;
2023                 break;
2024
2025         case NUMPLAN_NATIONAL:
2026                 ast_number_plan = NUMPLAN_NATIONAL;
2027                 break;
2028
2029         case NUMPLAN_PRIVATE:
2030                 ast_number_plan = NUMPLAN_PRIVATE;
2031                 break;
2032         }
2033
2034         return ast_number_plan;
2035 }
2036
2037 /*!
2038  * \internal
2039  * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2040  *
2041  * \param ast_number_plan Asterisk numbering plan code.
2042  *
2043  * \return mISDN numbering plan code
2044  */
2045 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2046 {
2047         enum mISDN_NUMBER_PLAN number_plan;
2048
2049         switch (ast_number_plan & 0x0F) {
2050         default:
2051         case NUMPLAN_UNKNOWN:
2052                 number_plan = NUMPLAN_UNKNOWN;
2053                 break;
2054
2055         case NUMPLAN_ISDN:
2056                 number_plan = NUMPLAN_ISDN;
2057                 break;
2058
2059         case NUMPLAN_DATA:
2060                 number_plan = NUMPLAN_DATA;
2061                 break;
2062
2063         case NUMPLAN_TELEX:
2064                 number_plan = NUMPLAN_TELEX;
2065                 break;
2066
2067         case NUMPLAN_NATIONAL:
2068                 number_plan = NUMPLAN_NATIONAL;
2069                 break;
2070
2071         case NUMPLAN_PRIVATE:
2072                 number_plan = NUMPLAN_PRIVATE;
2073                 break;
2074         }
2075
2076         return number_plan;
2077 }
2078
2079 /*!
2080  * \internal
2081  * \brief Convert the mISDN presentation code to a string
2082  *
2083  * \param presentation mISDN number presentation restriction code.
2084  *
2085  * \return The mISDN presentation code as a string
2086  */
2087 static const char *misdn_to_str_pres(int presentation)
2088 {
2089         const char *str;
2090
2091         switch (presentation) {
2092         case 0:
2093                 str = "Allowed";
2094                 break;
2095
2096         case 1:
2097                 str = "Restricted";
2098                 break;
2099
2100         case 2:
2101                 str = "Unavailable";
2102                 break;
2103
2104         default:
2105                 str = "Unknown";
2106                 break;
2107         }
2108
2109         return str;
2110 }
2111
2112 /*!
2113  * \internal
2114  * \brief Convert the mISDN presentation code to Asterisk presentation code
2115  *
2116  * \param presentation mISDN number presentation restriction code.
2117  *
2118  * \return Asterisk presentation code
2119  */
2120 static int misdn_to_ast_pres(int presentation)
2121 {
2122         switch (presentation) {
2123         default:
2124         case 0:
2125                 presentation = AST_PRES_ALLOWED;
2126                 break;
2127
2128         case 1:
2129                 presentation = AST_PRES_RESTRICTED;
2130                 break;
2131
2132         case 2:
2133                 presentation = AST_PRES_UNAVAILABLE;
2134                 break;
2135         }
2136
2137         return presentation;
2138 }
2139
2140 /*!
2141  * \internal
2142  * \brief Convert the Asterisk presentation code to mISDN presentation code
2143  *
2144  * \param presentation Asterisk number presentation restriction code.
2145  *
2146  * \return mISDN presentation code
2147  */
2148 static int ast_to_misdn_pres(int presentation)
2149 {
2150         switch (presentation & AST_PRES_RESTRICTION) {
2151         default:
2152         case AST_PRES_ALLOWED:
2153                 presentation = 0;
2154                 break;
2155
2156         case AST_PRES_RESTRICTED:
2157                 presentation = 1;
2158                 break;
2159
2160         case AST_PRES_UNAVAILABLE:
2161                 presentation = 2;
2162                 break;
2163         }
2164
2165         return presentation;
2166 }
2167
2168 /*!
2169  * \internal
2170  * \brief Convert the mISDN screening code to a string
2171  *
2172  * \param screening mISDN number screening code.
2173  *
2174  * \return The mISDN screening code as a string
2175  */
2176 static const char *misdn_to_str_screen(int screening)
2177 {
2178         const char *str;
2179
2180         switch (screening) {
2181         case 0:
2182                 str = "Unscreened";
2183                 break;
2184
2185         case 1:
2186                 str = "Passed Screen";
2187                 break;
2188
2189         case 2:
2190                 str = "Failed Screen";
2191                 break;
2192
2193         case 3:
2194                 str = "Network Number";
2195                 break;
2196
2197         default:
2198                 str = "Unknown";
2199                 break;
2200         }
2201
2202         return str;
2203 }
2204
2205 /*!
2206  * \internal
2207  * \brief Convert the mISDN screening code to Asterisk screening code
2208  *
2209  * \param screening mISDN number screening code.
2210  *
2211  * \return Asterisk screening code
2212  */
2213 static int misdn_to_ast_screen(int screening)
2214 {
2215         switch (screening) {
2216         default:
2217         case 0:
2218                 screening = AST_PRES_USER_NUMBER_UNSCREENED;
2219                 break;
2220
2221         case 1:
2222                 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
2223                 break;
2224
2225         case 2:
2226                 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
2227                 break;
2228
2229         case 3:
2230                 screening = AST_PRES_NETWORK_NUMBER;
2231                 break;
2232         }
2233
2234         return screening;
2235 }
2236
2237 /*!
2238  * \internal
2239  * \brief Convert the Asterisk screening code to mISDN screening code
2240  *
2241  * \param screening Asterisk number screening code.
2242  *
2243  * \return mISDN screening code
2244  */
2245 static int ast_to_misdn_screen(int screening)
2246 {
2247         switch (screening & AST_PRES_NUMBER_TYPE) {
2248         default:
2249         case AST_PRES_USER_NUMBER_UNSCREENED:
2250                 screening = 0;
2251                 break;
2252
2253         case AST_PRES_USER_NUMBER_PASSED_SCREEN:
2254                 screening = 1;
2255                 break;
2256
2257         case AST_PRES_USER_NUMBER_FAILED_SCREEN:
2258                 screening = 2;
2259                 break;
2260
2261         case AST_PRES_NETWORK_NUMBER:
2262                 screening = 3;
2263                 break;
2264         }
2265
2266         return screening;
2267 }
2268
2269 /*!
2270  * \internal
2271  * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2272  *
2273  * \param ast Asterisk redirecting reason code.
2274  *
2275  * \return mISDN reason code
2276  */
2277 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
2278 {
2279         unsigned index;
2280
2281         static const struct misdn_reasons {
2282                 enum AST_REDIRECTING_REASON ast;
2283                 enum mISDN_REDIRECTING_REASON q931;
2284         } misdn_reason_table[] = {
2285         /* *INDENT-OFF* */
2286                 { AST_REDIRECTING_REASON_UNKNOWN,        mISDN_REDIRECTING_REASON_UNKNOWN },
2287                 { AST_REDIRECTING_REASON_USER_BUSY,      mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
2288                 { AST_REDIRECTING_REASON_NO_ANSWER,      mISDN_REDIRECTING_REASON_NO_REPLY },
2289                 { AST_REDIRECTING_REASON_UNAVAILABLE,    mISDN_REDIRECTING_REASON_NO_REPLY },
2290                 { AST_REDIRECTING_REASON_UNCONDITIONAL,  mISDN_REDIRECTING_REASON_CALL_FWD },
2291                 { AST_REDIRECTING_REASON_TIME_OF_DAY,    mISDN_REDIRECTING_REASON_UNKNOWN },
2292                 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2293                 { AST_REDIRECTING_REASON_DEFLECTION,     mISDN_REDIRECTING_REASON_DEFLECTION },
2294                 { AST_REDIRECTING_REASON_FOLLOW_ME,      mISDN_REDIRECTING_REASON_UNKNOWN },
2295                 { AST_REDIRECTING_REASON_OUT_OF_ORDER,   mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
2296                 { AST_REDIRECTING_REASON_AWAY,           mISDN_REDIRECTING_REASON_UNKNOWN },
2297                 { AST_REDIRECTING_REASON_CALL_FWD_DTE,   mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
2298         /* *INDENT-ON* */
2299         };
2300
2301         for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2302                 if (misdn_reason_table[index].ast == ast) {
2303                         return misdn_reason_table[index].q931;
2304                 }
2305         }
2306         return mISDN_REDIRECTING_REASON_UNKNOWN;
2307 }
2308
2309 /*!
2310  * \internal
2311  * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2312  *
2313  * \param q931 mISDN redirecting reason code.
2314  *
2315  * \return Asterisk redirecting reason code
2316  */
2317 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
2318 {
2319         enum AST_REDIRECTING_REASON ast;
2320
2321         switch (q931) {
2322         default:
2323         case mISDN_REDIRECTING_REASON_UNKNOWN:
2324                 ast = AST_REDIRECTING_REASON_UNKNOWN;
2325                 break;
2326
2327         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
2328                 ast = AST_REDIRECTING_REASON_USER_BUSY;
2329                 break;
2330
2331         case mISDN_REDIRECTING_REASON_NO_REPLY:
2332                 ast = AST_REDIRECTING_REASON_NO_ANSWER;
2333                 break;
2334
2335         case mISDN_REDIRECTING_REASON_DEFLECTION:
2336                 ast = AST_REDIRECTING_REASON_DEFLECTION;
2337                 break;
2338
2339         case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
2340                 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
2341                 break;
2342
2343         case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
2344                 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
2345                 break;
2346
2347         case mISDN_REDIRECTING_REASON_CALL_FWD:
2348                 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
2349                 break;
2350         }
2351
2352         return ast;
2353 }
2354
2355
2356
2357 struct allowed_bearers {
2358         char *name;         /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2359         char *display;      /*!< Bearer capability displayable name */
2360         int cap;            /*!< SETUP message bearer capability field code value */
2361         int deprecated;     /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2362 };
2363
2364 /* *INDENT-OFF* */
2365 static const struct allowed_bearers allowed_bearers_array[] = {
2366         /* Name,                      Displayable Name       Bearer Capability,                    Deprecated */
2367         { "speech",                  "Speech",               INFO_CAPABILITY_SPEECH,               0 },
2368         { "3_1khz",                  "3.1KHz Audio",         INFO_CAPABILITY_AUDIO_3_1K,           0 },
2369         { "digital_unrestricted",    "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2370         { "digital_restricted",      "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   0 },
2371         { "digital_restriced",       "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   1 }, /* Allow misspelling for backwards compatibility */
2372         { "video",                   "Video",                INFO_CAPABILITY_VIDEO,                0 }
2373 };
2374 /* *INDENT-ON* */
2375
2376 static const char *bearer2str(int cap)
2377 {
2378         unsigned index;
2379
2380         for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2381                 if (allowed_bearers_array[index].cap == cap) {
2382                         return allowed_bearers_array[index].display;
2383                 }
2384         }
2385
2386         return "Unknown Bearer";
2387 }
2388
2389 #if defined(AST_MISDN_ENHANCEMENTS)
2390 /*!
2391  * \internal
2392  * \brief Fill in facility PartyNumber information
2393  *
2394  * \param party PartyNumber structure to fill in.
2395  * \param id Information to put in PartyNumber structure.
2396  *
2397  * \return Nothing
2398  */
2399 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2400 {
2401         ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2402         party->LengthOfNumber = strlen((char *) party->Number);
2403         party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2404         switch (party->Type) {
2405         case 1:/* public */
2406                 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2407                 break;
2408         case 5:/* private */
2409                 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2410                 break;
2411         default:
2412                 party->TypeOfNumber = 0;/* Don't care */
2413                 break;
2414         }
2415 }
2416 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2417
2418 #if defined(AST_MISDN_ENHANCEMENTS)
2419 /*!
2420  * \internal
2421  * \brief Extract the information from PartyNumber
2422  *
2423  * \param id Where to put extracted PartyNumber information
2424  * \param party PartyNumber information to extract
2425  *
2426  * \return Nothing
2427  */
2428 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2429 {
2430         if (party->LengthOfNumber) {
2431                 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2432                 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2433                 switch (party->Type) {
2434                 case 1:/* public */
2435                         id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2436                         break;
2437                 case 5:/* private */
2438                         id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2439                         break;
2440                 default:
2441                         id->number_type = NUMTYPE_UNKNOWN;
2442                         break;
2443                 }
2444         } else {
2445                 /* Number not present */
2446                 id->number_type = NUMTYPE_UNKNOWN;
2447                 id->number_plan = NUMPLAN_ISDN;
2448                 id->number[0] = 0;
2449         }
2450 }
2451 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2452
2453 #if defined(AST_MISDN_ENHANCEMENTS)
2454 /*!
2455  * \internal
2456  * \brief Fill in facility Address information
2457  *
2458  * \param Address Address structure to fill in.
2459  * \param id Information to put in Address structure.
2460  *
2461  * \return Nothing
2462  */
2463 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2464 {
2465         misdn_PartyNumber_fill(&Address->Party, id);
2466
2467         /* Subaddresses are not supported yet */
2468         Address->Subaddress.Length = 0;
2469 }
2470 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2471
2472 #if defined(AST_MISDN_ENHANCEMENTS)
2473 /*!
2474  * \internal
2475  * \brief Fill in facility PresentedNumberUnscreened information
2476  *
2477  * \param presented PresentedNumberUnscreened structure to fill in.
2478  * \param id Information to put in PresentedNumberUnscreened structure.
2479  *
2480  * \return Nothing
2481  */
2482 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2483 {
2484         presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2485         misdn_PartyNumber_fill(&presented->Unscreened, id);
2486 }
2487 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2488
2489 #if defined(AST_MISDN_ENHANCEMENTS)
2490 /*!
2491  * \internal
2492  * \brief Extract the information from PartyNumber
2493  *
2494  * \param id Where to put extracted PresentedNumberUnscreened information
2495  * \param presented PresentedNumberUnscreened information to extract
2496  *
2497  * \return Nothing
2498  */
2499 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2500 {
2501         id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2502         id->screening = 0;/* unscreened */
2503         switch (presented->Type) {
2504         case 0:/* presentationAllowedNumber */
2505         case 3:/* presentationRestrictedNumber */
2506                 misdn_PartyNumber_extract(id, &presented->Unscreened);
2507                 break;
2508         case 1:/* presentationRestricted */
2509         case 2:/* numberNotAvailableDueToInterworking */
2510         default:
2511                 /* Number not present (And uninitialized so do not even look at it!) */
2512                 id->number_type = NUMTYPE_UNKNOWN;
2513                 id->number_plan = NUMPLAN_ISDN;
2514                 id->number[0] = 0;
2515                 break;
2516         }
2517 }
2518 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2519
2520 #if defined(AST_MISDN_ENHANCEMENTS)
2521 static const char Level_Spacing[] = "          ";/* Work for up to 10 levels */
2522 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2523
2524 #if defined(AST_MISDN_ENHANCEMENTS)
2525 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2526 {
2527         if (Party->LengthOfNumber) {
2528                 const char *Spacing;
2529
2530                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2531                 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2532                         Spacing, Party->Type);
2533                 switch (Party->Type) {
2534                 case 0: /* Unknown PartyNumber */
2535                         chan_misdn_log(1, bc->port, " -->%s  Unknown: %s\n",
2536                                 Spacing, Party->Number);
2537                         break;
2538                 case 1: /* Public PartyNumber */
2539                         chan_misdn_log(1, bc->port, " -->%s  Public TON:%d %s\n",
2540                                 Spacing, Party->TypeOfNumber, Party->Number);
2541                         break;
2542                 case 2: /* NSAP encoded PartyNumber */
2543                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2544                                 Spacing, Party->Number);
2545                         break;
2546                 case 3: /* Data PartyNumber (Not used) */
2547                         chan_misdn_log(1, bc->port, " -->%s  Data: %s\n",
2548                                 Spacing, Party->Number);
2549                         break;
2550                 case 4: /* Telex PartyNumber (Not used) */
2551                         chan_misdn_log(1, bc->port, " -->%s  Telex: %s\n",
2552                                 Spacing, Party->Number);
2553                         break;
2554                 case 5: /* Private PartyNumber */
2555                         chan_misdn_log(1, bc->port, " -->%s  Private TON:%d %s\n",
2556                                 Spacing, Party->TypeOfNumber, Party->Number);
2557                         break;
2558                 case 8: /* National Standard PartyNumber (Not used) */
2559                         chan_misdn_log(1, bc->port, " -->%s  National: %s\n",
2560                                 Spacing, Party->Number);
2561                         break;
2562                 default:
2563                         break;
2564                 }
2565         }
2566 }
2567 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2568
2569 #if defined(AST_MISDN_ENHANCEMENTS)
2570 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2571 {
2572         if (Subaddress->Length) {
2573                 const char *Spacing;
2574
2575                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2576                 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2577                         Spacing, Subaddress->Type);
2578                 switch (Subaddress->Type) {
2579                 case 0: /* UserSpecified */
2580                         if (Subaddress->u.UserSpecified.OddCountPresent) {
2581                                 chan_misdn_log(1, bc->port, " -->%s  User BCD OddCount:%d NumOctets:%d\n",
2582                                         Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2583                         } else {
2584                                 chan_misdn_log(1, bc->port, " -->%s  User: %s\n",
2585                                         Spacing, Subaddress->u.UserSpecified.Information);
2586                         }
2587                         break;
2588                 case 1: /* NSAP */
2589                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2590                                 Spacing, Subaddress->u.Nsap);
2591                         break;
2592                 default:
2593                         break;
2594                 }
2595         }
2596 }
2597 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2598
2599 #if defined(AST_MISDN_ENHANCEMENTS)
2600 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2601 {
2602         print_facility_PartyNumber(Level, &Address->Party, bc);
2603         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2604 }
2605 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2606
2607 #if defined(AST_MISDN_ENHANCEMENTS)
2608 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2609 {
2610         const char *Spacing;
2611
2612         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2613         chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2614         switch (Presented->Type) {
2615         case 0: /* presentationAllowedNumber */
2616                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2617                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2618                 break;
2619         case 1: /* presentationRestricted */
2620                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2621                 break;
2622         case 2: /* numberNotAvailableDueToInterworking */
2623                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2624                 break;
2625         case 3: /* presentationRestrictedNumber */
2626                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2627                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2628                 break;
2629         default:
2630                 break;
2631         }
2632 }
2633 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2634
2635 #if defined(AST_MISDN_ENHANCEMENTS)
2636 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2637 {
2638         const char *Spacing;
2639
2640         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2641         chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2642         print_facility_PartyNumber(Level, &Address->Party, bc);
2643         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2644 }
2645 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2646
2647 #if defined(AST_MISDN_ENHANCEMENTS)
2648 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2649 {
2650         const char *Spacing;
2651
2652         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2653         chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2654         switch (Presented->Type) {
2655         case 0: /* presentationAllowedAddress */
2656                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2657                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2658                 break;
2659         case 1: /* presentationRestricted */
2660                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2661                 break;
2662         case 2: /* numberNotAvailableDueToInterworking */
2663                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2664                 break;
2665         case 3: /* presentationRestrictedAddress */
2666                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2667                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2668                 break;
2669         default:
2670                 break;
2671         }
2672 }
2673 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2674
2675 #if defined(AST_MISDN_ENHANCEMENTS)
2676 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2677 {
2678         const char *Spacing;
2679
2680         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2681         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2682         if (Q931ie->Bc.Length) {
2683                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2684         }
2685         if (Q931ie->Hlc.Length) {
2686                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2687         }
2688         if (Q931ie->Llc.Length) {
2689                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2690         }
2691 }
2692 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2693
2694 #if defined(AST_MISDN_ENHANCEMENTS)
2695 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2696 {
2697         const char *Spacing;
2698
2699         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2700         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2701         if (Q931ie->Bc.Length) {
2702                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2703         }
2704         if (Q931ie->Hlc.Length) {
2705                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2706         }
2707         if (Q931ie->Llc.Length) {
2708                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2709         }
2710         if (Q931ie->UserInfo.Length) {
2711                 chan_misdn_log(1, bc->port, " -->%s  UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2712         }
2713 }
2714 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2715
2716 #if defined(AST_MISDN_ENHANCEMENTS)
2717 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2718 {
2719         const char *Spacing;
2720
2721         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2722         chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2723                 Spacing, CallInfo->CCBSReference);
2724         chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2725         print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2726         print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2727         if (CallInfo->SubaddressOfA.Length) {
2728                 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2729                 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2730         }
2731 }
2732 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2733
2734 #if defined(AST_MISDN_ENHANCEMENTS)
2735 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2736 {
2737         const char *Spacing;
2738
2739         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2740         if (Party->LengthOfNumber) {
2741                 print_facility_PartyNumber(Level, Party, bc);
2742         } else {
2743                 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2744         }
2745 }
2746 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2747
2748 #if defined(AST_MISDN_ENHANCEMENTS)
2749 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2750 {
2751         const char *Spacing;
2752
2753         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2754         chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2755                 Spacing,
2756                 ForwardingRecord->Procedure,
2757                 ForwardingRecord->BasicService);
2758         chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2759         print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2760         chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2761         print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2762 }
2763 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2764
2765 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
2766 {
2767 #if defined(AST_MISDN_ENHANCEMENTS)
2768         unsigned Index;
2769 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2770
2771         switch (fac->Function) {
2772 #if defined(AST_MISDN_ENHANCEMENTS)
2773         case Fac_ActivationDiversion:
2774                 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2775                         fac->u.ActivationDiversion.InvokeID);
2776                 switch (fac->u.ActivationDiversion.ComponentType) {
2777                 case FacComponent_Invoke:
2778                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2779                                 fac->u.ActivationDiversion.Component.Invoke.Procedure,
2780                                 fac->u.ActivationDiversion.Component.Invoke.BasicService);
2781                         chan_misdn_log(1, bc->port, " -->   ForwardedTo:\n");
2782                         print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2783                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2784                         print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2785                         break;
2786                 case FacComponent_Result:
2787                         chan_misdn_log(1, bc->port, " -->  Result\n");
2788                         break;
2789                 default:
2790                         break;
2791                 }
2792                 break;
2793         case Fac_DeactivationDiversion:
2794                 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2795                         fac->u.DeactivationDiversion.InvokeID);
2796                 switch (fac->u.DeactivationDiversion.ComponentType) {
2797                 case FacComponent_Invoke:
2798                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2799                                 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2800                                 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2801                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2802                         print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2803                         break;
2804                 case FacComponent_Result:
2805                         chan_misdn_log(1, bc->port, " -->  Result\n");
2806                         break;
2807                 default:
2808                         break;
2809                 }
2810                 break;
2811         case Fac_ActivationStatusNotificationDiv:
2812                 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2813                         fac->u.ActivationStatusNotificationDiv.InvokeID,
2814                         fac->u.ActivationStatusNotificationDiv.Procedure,
2815                         fac->u.ActivationStatusNotificationDiv.BasicService);
2816                 chan_misdn_log(1, bc->port, " -->  ForwardedTo:\n");
2817                 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2818                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2819                 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2820                 break;
2821         case Fac_DeactivationStatusNotificationDiv:
2822                 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2823                         fac->u.DeactivationStatusNotificationDiv.InvokeID,
2824                         fac->u.DeactivationStatusNotificationDiv.Procedure,
2825                         fac->u.DeactivationStatusNotificationDiv.BasicService);
2826                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2827                 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2828                 break;
2829         case Fac_InterrogationDiversion:
2830                 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2831                         fac->u.InterrogationDiversion.InvokeID);
2832                 switch (fac->u.InterrogationDiversion.ComponentType) {
2833                 case FacComponent_Invoke:
2834                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2835                                 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2836                                 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2837                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2838                         print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2839                         break;
2840                 case FacComponent_Result:
2841                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2842                         if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2843                                 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2844                                         chan_misdn_log(1, bc->port, " -->   IntResult[%d]:\n", Index);
2845                                         print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2846                                 }
2847                         }
2848                         break;
2849                 default:
2850                         break;
2851                 }
2852                 break;
2853         case Fac_DiversionInformation:
2854                 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2855                         fac->u.DiversionInformation.InvokeID,
2856                         fac->u.DiversionInformation.DiversionReason,
2857                         fac->u.DiversionInformation.BasicService);
2858                 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2859                         chan_misdn_log(1, bc->port, " -->  ServedUserSubaddress:\n");
2860                         print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2861                 }
2862                 if (fac->u.DiversionInformation.CallingAddressPresent) {
2863                         chan_misdn_log(1, bc->port, " -->  CallingAddress:\n");
2864                         print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2865                 }
2866                 if (fac->u.DiversionInformation.OriginalCalledPresent) {
2867                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2868                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2869                 }
2870                 if (fac->u.DiversionInformation.LastDivertingPresent) {
2871                         chan_misdn_log(1, bc->port, " -->  LastDivertingNr:\n");
2872                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2873                 }
2874                 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2875                         chan_misdn_log(1, bc->port, " -->  LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2876                 }
2877                 if (fac->u.DiversionInformation.UserInfo.Length) {
2878                         chan_misdn_log(1, bc->port, " -->  UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2879                 }
2880                 break;
2881         case Fac_CallDeflection:
2882                 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2883                         fac->u.CallDeflection.InvokeID);
2884                 switch (fac->u.CallDeflection.ComponentType) {
2885                 case FacComponent_Invoke:
2886                         chan_misdn_log(1, bc->port, " -->  Invoke:\n");
2887                         if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2888                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
2889                                         fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2890                         }
2891                         chan_misdn_log(1, bc->port, " -->   DeflectionAddress:\n");
2892                         print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2893                         break;
2894                 case FacComponent_Result:
2895                         chan_misdn_log(1, bc->port, " -->  Result\n");
2896                         break;
2897                 default:
2898                         break;
2899                 }
2900                 break;
2901         case Fac_CallRerouteing:
2902                 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2903                         fac->u.CallRerouteing.InvokeID);
2904                 switch (fac->u.CallRerouteing.ComponentType) {
2905                 case FacComponent_Invoke:
2906                         chan_misdn_log(1, bc->port, " -->  Invoke: Reason:%d Counter:%d\n",
2907                                 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2908                                 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2909                         chan_misdn_log(1, bc->port, " -->   CalledAddress:\n");
2910                         print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2911                         print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2912                         chan_misdn_log(1, bc->port, " -->   LastReroutingNr:\n");
2913                         print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2914                         chan_misdn_log(1, bc->port, " -->   SubscriptionOption:%d\n",
2915                                 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2916                         if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2917                                 chan_misdn_log(1, bc->port, " -->   CallingParty:\n");
2918                                 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2919                         }
2920                         break;
2921                 case FacComponent_Result:
2922                         chan_misdn_log(1, bc->port, " -->  Result\n");
2923                         break;
2924                 default:
2925                         break;
2926                 }
2927                 break;
2928         case Fac_InterrogateServedUserNumbers:
2929                 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2930                         fac->u.InterrogateServedUserNumbers.InvokeID);
2931                 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2932                 case FacComponent_Invoke:
2933                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
2934                         break;
2935                 case FacComponent_Result:
2936                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2937                         if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2938                                 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2939                                         chan_misdn_log(1, bc->port, " -->   ServedUserNr[%d]:\n", Index);
2940                                         print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2941                                 }
2942                         }
2943                         break;
2944                 default:
2945                         break;
2946                 }
2947                 break;
2948         case Fac_DivertingLegInformation1:
2949                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2950                         fac->u.DivertingLegInformation1.InvokeID,
2951                         fac->u.DivertingLegInformation1.DiversionReason,
2952                         fac->u.DivertingLegInformation1.SubscriptionOption);
2953                 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2954                         chan_misdn_log(1, bc->port, " -->  DivertedToNr:\n");
2955                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2956                 }
2957                 break;
2958         case Fac_DivertingLegInformation2:
2959                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2960                         fac->u.DivertingLegInformation2.InvokeID,
2961                         fac->u.DivertingLegInformation2.DiversionReason,
2962                         fac->u.DivertingLegInformation2.DiversionCounter);
2963                 if (fac->u.DivertingLegInformation2.DivertingPresent) {
2964                         chan_misdn_log(1, bc->port, " -->  DivertingNr:\n");
2965                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2966                 }
2967                 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2968                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2969                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2970                 }
2971                 break;
2972         case Fac_DivertingLegInformation3:
2973                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2974                         fac->u.DivertingLegInformation3.InvokeID,
2975                         fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2976                 break;
2977
2978 #else   /* !defined(AST_MISDN_ENHANCEMENTS) */
2979
2980         case Fac_CD:
2981                 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2982                         fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2983                 break;
2984 #endif  /* !defined(AST_MISDN_ENHANCEMENTS) */
2985         case Fac_AOCDCurrency:
2986                 if (fac->u.AOCDcur.chargeNotAvailable) {
2987                         chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2988                 } else if (fac->u.AOCDcur.freeOfCharge) {
2989                         chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2990                 } else if (fac->u.AOCDchu.billingId >= 0) {
2991                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2992                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2993                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2994                 } else {
2995                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2996                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2997                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2998                 }
2999                 break;
3000         case Fac_AOCDChargingUnit:
3001                 if (fac->u.AOCDchu.chargeNotAvailable) {
3002                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
3003                 } else if (fac->u.AOCDchu.freeOfCharge) {
3004                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
3005                 } else if (fac->u.AOCDchu.billingId >= 0) {
3006                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
3007                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
3008                 } else {
3009                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
3010                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
3011                 }
3012                 break;
3013 #if defined(AST_MISDN_ENHANCEMENTS)
3014         case Fac_ERROR:
3015                 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
3016                         fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
3017                 break;
3018         case Fac_RESULT:
3019                 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
3020                         fac->u.RESULT.InvokeID);
3021                 break;
3022         case Fac_REJECT:
3023                 if (fac->u.REJECT.InvokeIDPresent) {
3024                         chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
3025                                 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
3026                 } else {
3027                         chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
3028                                 fac->u.REJECT.Code);
3029                 }
3030                 break;
3031         case Fac_EctExecute:
3032                 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3033                         fac->u.EctExecute.InvokeID);
3034                 break;
3035         case Fac_ExplicitEctExecute:
3036                 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3037                         fac->u.ExplicitEctExecute.InvokeID,
3038                         fac->u.ExplicitEctExecute.LinkID);
3039                 break;
3040         case Fac_RequestSubaddress:
3041                 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3042                         fac->u.RequestSubaddress.InvokeID);
3043                 break;
3044         case Fac_SubaddressTransfer:
3045                 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3046                         fac->u.SubaddressTransfer.InvokeID);
3047                 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3048                 break;
3049         case Fac_EctLinkIdRequest:
3050                 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3051                         fac->u.EctLinkIdRequest.InvokeID);
3052                 switch (fac->u.EctLinkIdRequest.ComponentType) {
3053                 case FacComponent_Invoke:
3054                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3055                         break;
3056                 case FacComponent_Result:
3057                         chan_misdn_log(1, bc->port, " -->  Result: LinkID:%d\n",
3058                                 fac->u.EctLinkIdRequest.Component.Result.LinkID);
3059                         break;
3060                 default:
3061                         break;
3062                 }
3063                 break;
3064         case Fac_EctInform:
3065                 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3066                         fac->u.EctInform.InvokeID,
3067                         fac->u.EctInform.Status);
3068                 if (fac->u.EctInform.RedirectionPresent) {
3069                         chan_misdn_log(1, bc->port, " -->  Redirection Number\n");
3070                         print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3071                 }
3072                 break;
3073         case Fac_EctLoopTest:
3074                 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3075                         fac->u.EctLoopTest.InvokeID);
3076                 switch (fac->u.EctLoopTest.ComponentType) {
3077                 case FacComponent_Invoke:
3078                         chan_misdn_log(1, bc->port, " -->  Invoke: CallTransferID:%d\n",
3079                                 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3080                         break;
3081                 case FacComponent_Result:
3082                         chan_misdn_log(1, bc->port, " -->  Result: LoopResult:%d\n",
3083                                 fac->u.EctLoopTest.Component.Result.LoopResult);
3084                         break;
3085                 default:
3086                         break;
3087                 }
3088                 break;
3089         case Fac_StatusRequest:
3090                 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3091                         fac->u.StatusRequest.InvokeID);
3092                 switch (fac->u.StatusRequest.ComponentType) {
3093                 case FacComponent_Invoke:
3094                         chan_misdn_log(1, bc->port, " -->  Invoke: Compatibility:%d\n",
3095                                 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3096                         break;
3097                 case FacComponent_Result:
3098                         chan_misdn_log(1, bc->port, " -->  Result: Status:%d\n",
3099                                 fac->u.StatusRequest.Component.Result.Status);
3100                         break;
3101                 default:
3102                         break;
3103                 }
3104                 break;
3105         case Fac_CallInfoRetain:
3106                 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3107                         fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3108                 break;
3109         case Fac_CCBSDeactivate:
3110                 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3111                         fac->u.CCBSDeactivate.InvokeID);
3112                 switch (fac->u.CCBSDeactivate.ComponentType) {
3113                 case FacComponent_Invoke:
3114                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d\n",
3115                                 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3116                         break;
3117                 case FacComponent_Result:
3118                         chan_misdn_log(1, bc->port, " -->  Result\n");
3119                         break;
3120                 default:
3121                         break;
3122                 }
3123                 break;
3124         case Fac_CCBSErase:
3125                 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3126                         fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3127                         fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3128                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3129                 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3130                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3131                 break;
3132         case Fac_CCBSRemoteUserFree:
3133                 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3134                         fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3135                         fac->u.CCBSRemoteUserFree.RecallMode);
3136                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3137                 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3138                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3139                 break;
3140         case Fac_CCBSCall:
3141                 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3142                         fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3143                 break;
3144         case Fac_CCBSStatusRequest:
3145                 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3146                         fac->u.CCBSStatusRequest.InvokeID);
3147                 switch (fac->u.CCBSStatusRequest.ComponentType) {
3148                 case FacComponent_Invoke:
3149                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d RecallMode:%d\n",
3150                                 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3151                                 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3152                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3153                         break;
3154                 case FacComponent_Result:
3155                         chan_misdn_log(1, bc->port, " -->  Result: Free:%d\n",
3156                                 fac->u.CCBSStatusRequest.Component.Result.Free);
3157                         break;
3158                 default:
3159                         break;
3160                 }
3161                 break;
3162         case Fac_CCBSBFree:
3163                 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3164                         fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3165                         fac->u.CCBSBFree.RecallMode);
3166                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3167                 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3168                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3169                 break;
3170         case Fac_EraseCallLinkageID:
3171                 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3172                         fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3173                 break;
3174         case Fac_CCBSStopAlerting:
3175                 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3176                         fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3177                 break;
3178         case Fac_CCBSRequest:
3179                 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3180                         fac->u.CCBSRequest.InvokeID);
3181                 switch (fac->u.CCBSRequest.ComponentType) {
3182                 case FacComponent_Invoke:
3183                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3184                                 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3185                         break;
3186                 case FacComponent_Result:
3187                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3188                                 fac->u.CCBSRequest.Component.Result.CCBSReference,
3189                                 fac->u.CCBSRequest.Component.Result.RecallMode);
3190                         break;
3191                 default:
3192                         break;
3193                 }
3194                 break;
3195         case Fac_CCBSInterrogate:
3196                 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3197                         fac->u.CCBSInterrogate.InvokeID);
3198                 switch (fac->u.CCBSInterrogate.ComponentType) {
3199                 case FacComponent_Invoke:
3200                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3201                         if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3202                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3203                                         fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3204                         }
3205                         if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3206                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3207                                 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3208                         }
3209                         break;
3210                 case FacComponent_Result:
3211                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3212                                 fac->u.CCBSInterrogate.Component.Result.RecallMode);
3213                         if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3214                                 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3215                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3216                                         print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3217                                 }
3218                         }
3219                         break;
3220                 default:
3221                         break;
3222                 }
3223                 break;
3224         case Fac_CCNRRequest:
3225                 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3226                         fac->u.CCNRRequest.InvokeID);
3227                 switch (fac->u.CCNRRequest.ComponentType) {
3228                 case FacComponent_Invoke:
3229                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3230                                 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3231                         break;
3232                 case FacComponent_Result:
3233                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3234                                 fac->u.CCNRRequest.Component.Result.CCBSReference,
3235                                 fac->u.CCNRRequest.Component.Result.RecallMode);
3236                         break;
3237                 default:
3238                         break;
3239                 }
3240                 break;
3241         case Fac_CCNRInterrogate:
3242                 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3243                         fac->u.CCNRInterrogate.InvokeID);
3244                 switch (fac->u.CCNRInterrogate.ComponentType) {
3245                 case FacComponent_Invoke:
3246                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3247                         if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3248                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3249                                         fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3250                         }
3251                         if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3252                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3253                                 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3254                         }
3255                         break;
3256                 case FacComponent_Result:
3257                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3258                                 fac->u.CCNRInterrogate.Component.Result.RecallMode);
3259                         if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3260                                 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3261                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3262                                         print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3263                                 }
3264                         }
3265                         break;
3266                 default:
3267                         break;
3268                 }
3269                 break;
3270         case Fac_CCBS_T_Call:
3271                 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3272                         fac->u.CCBS_T_Call.InvokeID);
3273                 break;
3274         case Fac_CCBS_T_Suspend:
3275                 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3276                         fac->u.CCBS_T_Suspend.InvokeID);
3277                 break;
3278         case Fac_CCBS_T_Resume:
3279                 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3280                         fac->u.CCBS_T_Resume.InvokeID);
3281                 break;
3282         case Fac_CCBS_T_RemoteUserFree:
3283                 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3284                         fac->u.CCBS_T_RemoteUserFree.InvokeID);
3285                 break;
3286