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