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