2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2004 - 2006, Christian Richter
6 * Christian Richter <crich@beronet.com>
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.
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.
23 * \brief the chan_misdn channel driver for Asterisk
25 * \author Christian Richter <crich@beronet.com>
27 * MISDN http://www.misdn.org/
29 * \ingroup channel_drivers
32 /*! \li \ref chan_misdn.c uses the configuration file \ref misdn.conf
33 * \addtogroup configuration_file
36 /*! \page misdn.conf misdn.conf
37 * \verbinclude misdn.conf.sample
42 * To use the CCBS/CCNR supplementary service feature and other
43 * supplementary services using FACILITY messages requires a
44 * modified version of mISDN.
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
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
57 /* Define to enable cli commands to generate canned CCBS messages. */
58 // #define CCBS_TEST_MESSAGES 1
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.
68 * Without native bridge support, the following config file
69 * parameters have no effect: bridging.
71 * The existing native bridge code is marked with the
72 * mISDN_NATIVE_BRIDGING conditional.
76 <depend>isdnnet</depend>
77 <depend>misdn</depend>
78 <depend>suppserv</depend>
79 <support_level>extended</support_level>
84 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
87 #include <sys/socket.h>
89 #include <arpa/inet.h>
91 #include <sys/ioctl.h>
94 #include <semaphore.h>
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"
124 #include "chan_misdn_config.h"
125 #include "isdn_lib.h"
127 static char global_tracefile[BUFFERSIZE + 1];
129 static int g_config_initialized = 0;
143 /*! \brief allocates the jb-structure and initialize the elements */
144 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
146 /*! \brief frees the data and destroys the given jitterbuffer struct */
147 void misdn_jb_destroy(struct misdn_jb *jb);
149 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
150 error (buffer overrun). */
151 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
153 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
154 available data is returned and the return value indicates the number
156 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
158 static char *complete_ch(struct ast_cli_args *a);
159 static char *complete_debug_port(struct ast_cli_args *a);
160 static char *complete_show_config(struct ast_cli_args *a);
162 /* BEGIN: chan_misdn.h */
164 #if defined(AST_MISDN_ENHANCEMENTS)
166 * This timeout duration is to clean up any call completion records that
167 * are forgotten about by the switch.
169 #define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60) /* seconds */
171 #define MISDN_CC_REQUEST_WAIT_MAX 5 /* seconds */
174 * \brief Caller that initialized call completion services
177 * This data is the payload for a datastore that is put on the channel that
178 * initializes call completion services. This datastore is set to be inherited
179 * by the outbound mISDN channel. When one of these channels hangs up, the
180 * channel pointer will be set to NULL. That way, we can ensure that we do not
181 * touch this channel after it gets destroyed.
183 struct misdn_cc_caller {
184 /*! \brief The channel that initialized call completion services */
185 struct ast_channel *chan;
188 struct misdn_cc_notify {
189 /*! \brief Dialplan: Notify extension priority */
192 /*! \brief Dialplan: Notify extension context */
193 char context[AST_MAX_CONTEXT];
195 /*! \brief Dialplan: Notify extension number (User-A) */
196 char exten[AST_MAX_EXTENSION];
199 /*! \brief mISDN call completion record */
200 struct misdn_cc_record {
201 /*! \brief Call completion record linked list */
202 AST_LIST_ENTRY(misdn_cc_record) list;
204 /*! \brief Time the record was created. */
207 /*! \brief MISDN_CC_RECORD_ID value */
211 * \brief Logical Layer 1 port associated with this
212 * call completion record
216 /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
219 /*! \brief Mode specific parameters */
221 /*! \brief point-to-point specific parameters. */
224 * \brief Call-completion signaling link.
225 * NULL if signaling link not established.
227 struct misdn_bchannel *bc;
230 * \brief TRUE if we requested the request retention option
233 int requested_retention;
236 * \brief TRUE if the request retention option is enabled.
238 int retention_enabled;
241 /*! \brief point-to-multi-point specific parameters. */
243 /*! \brief CallLinkageID (valid when port determined) */
246 /*! \breif CCBSReference (valid when activated is TRUE) */
249 /*! \brief globalRecall(0), specificRecall(1) */
254 /*! \brief TRUE if call completion activated */
257 /*! \brief Outstanding message ID (valid when outstanding_message) */
260 /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
261 int outstanding_message;
263 /*! \brief TRUE if activation has been requested */
264 int activation_requested;
267 * \brief TRUE if User-A is free
268 * \note PTMP - Used to answer CCBSStatusRequest.
269 * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
273 /*! \brief Error code received from last outstanding message. */
274 enum FacErrorCode error_code;
276 /*! \brief Reject code received from last outstanding message. */
277 enum FacRejectCode reject_code;
280 * \brief Saved struct misdn_bchannel call information when
281 * attempted to call User-B
284 /*! \brief User-A caller id information */
285 struct misdn_party_id caller;
287 /*! \brief User-B number information */
288 struct misdn_party_dialing dialed;
290 /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
291 struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
293 /*! \brief SETUP message bearer capability field code value */
296 /*! \brief TRUE if call made in digital HDLC mode */
300 /*! \brief Dialplan location to indicate User-B free and User-A is free */
301 struct misdn_cc_notify remote_user_free;
303 /*! \brief Dialplan location to indicate User-B free and User-A is busy */
304 struct misdn_cc_notify b_free;
307 /*! \brief mISDN call completion record database */
308 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
309 /*! \brief Next call completion record ID to use */
310 static __u16 misdn_cc_record_id;
311 /*! \brief Next invoke ID to use */
312 static __s16 misdn_invoke_id;
314 static const char misdn_no_response_from_network[] = "No response from network";
315 static const char misdn_cc_record_not_found[] = "Call completion record not found";
317 /* mISDN channel variable names */
318 #define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
319 #define MISDN_CC_STATUS "MISDN_CC_STATUS"
320 #define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
321 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
323 static ast_mutex_t release_lock;
325 enum misdn_chan_state {
326 MISDN_NOTHING = 0, /*!< at beginning */
327 MISDN_WAITING4DIGS, /*!< when waiting for info */
328 MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
329 MISDN_INCOMING_SETUP, /*!< for incoming setup */
330 MISDN_DIALING, /*!< when pbx_start */
331 MISDN_PROGRESS, /*!< we have progress */
332 MISDN_PROCEEDING, /*!< we have progress */
333 MISDN_CALLING, /*!< when misdn_call is called */
334 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
335 MISDN_ALERTING, /*!< when Alerting */
336 MISDN_BUSY, /*!< when BUSY */
337 MISDN_CONNECTED, /*!< when connected */
338 MISDN_DISCONNECTED, /*!< when connected */
339 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
342 /*! Asterisk created the channel (outgoing call) */
344 /*! mISDN created the channel (incoming call) */
347 enum misdn_hold_state {
348 MISDN_HOLD_IDLE, /*!< HOLD not active */
349 MISDN_HOLD_ACTIVE, /*!< Call is held */
350 MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
351 MISDN_HOLD_DISCONNECT, /*!< Held call is being disconnected */
355 * \brief Call HOLD state.
357 enum misdn_hold_state state;
359 * \brief Logical port the channel call record is HELD on
360 * because the B channel is no longer associated.
365 * \brief Original B channel number the HELD call was using.
366 * \note Used only for debug display messages.
371 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
372 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
375 * \brief Channel call record structure
379 * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
381 char allowed_bearers[BUFFERSIZE + 1];
384 * \brief State of the channel
386 enum misdn_chan_state state;
389 * \brief TRUE if a hangup needs to be queued
390 * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
392 int need_queue_hangup;
395 * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
400 * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
405 * \brief Who originally created this channel. ORG_AST or ORG_MISDN
410 * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
411 * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
413 int noautorespond_on_setup;
415 int norxtone; /*!< Boolean assigned values but the value is not used. */
418 * \brief TRUE if we are not to generate tones (Playtones)
423 * \brief TRUE if echo canceller is enabled. Value is toggled.
428 * \brief TRUE if you want to send Tone Indications to an incoming
429 * ISDN channel on a TE Port.
430 * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
432 int incoming_early_audio;
435 * \brief TRUE if DTMF digits are to be passed inband only.
436 * \note It is settable by the misdn_set_opt() application.
441 * \brief Pipe file descriptor handles array.
442 * Read from pipe[0], write to pipe[1]
447 * \brief Read buffer for inbound audio from pipe[0]
449 char ast_rd_buf[4096];
452 * \brief Inbound audio frame returned by misdn_read().
454 struct ast_frame frame;
457 * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
458 * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
459 * \note It is settable by the misdn_set_opt() application.
464 * \brief Number of seconds to detect a Fax machine when detection enabled.
465 * \note 0 disables the timeout.
466 * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
468 int faxdetect_timeout;
471 * \brief Starting time of fax detection with timeout when nonzero.
473 struct timeval faxdetect_tv;
476 * \brief TRUE if a fax has been detected.
481 * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
482 * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
487 * \brief Jitterbuffer length
488 * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
493 * \brief Jitterbuffer upper threshold
494 * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
496 int jb_upper_threshold;
499 * \brief Allocated jitterbuffer controller
500 * \note misdn_jb_init() creates the jitterbuffer.
501 * \note Must use misdn_jb_destroy() to clean up.
506 * \brief Allocated DSP controller
507 * \note ast_dsp_new() creates the DSP controller.
508 * \note Must use ast_dsp_free() to clean up.
513 * \brief Associated Asterisk channel structure.
515 struct ast_channel * ast;
518 * \brief Associated B channel structure.
520 struct misdn_bchannel *bc;
522 #if defined(AST_MISDN_ENHANCEMENTS)
524 * \brief Peer channel for which call completion was initialized.
526 struct misdn_cc_caller *peer;
528 /*! \brief Associated call completion record ID (-1 if not associated) */
530 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
533 * \brief HELD channel call information
535 struct hold_info hold;
538 * \brief From associated B channel: Layer 3 process ID
539 * \note Used to find the HELD channel call record when retrieving a call.
544 * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
545 * \note Used only for debug display messages.
550 * \brief Incoming call dialplan context identifier.
551 * \note The "context" string read in from /etc/asterisk/misdn.conf
553 char context[AST_MAX_CONTEXT];
556 * \brief The configured music-on-hold class to use for this call.
557 * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
559 char mohinterpret[MAX_MUSICCLASS];
562 * \brief Number of outgoing audio frames dropped since last debug gripe message.
564 int dropped_frame_cnt;
567 * \brief TRUE if we must do the ringback tones.
568 * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
573 * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
574 * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
579 * \brief Tone zone sound used for dialtone generation.
580 * \note Used as a boolean. Non-NULL to prod generation if enabled.
582 struct ast_tone_zone_sound *ts;
585 * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
586 * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
591 * \brief Overlap dialing timeout Task ID. -1 if not running.
593 int overlap_dial_task;
596 * \brief overlap_tv access lock.
598 ast_mutex_t overlap_tv_lock;
601 * \brief Overlap timer start time. Timer restarted for every digit received.
603 struct timeval overlap_tv;
606 * \brief Next channel call record in the list.
608 struct chan_list *next;
615 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
616 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
617 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
623 struct robin_list *next;
624 struct robin_list *prev;
626 static struct robin_list *robin = NULL;
629 static void free_robin_list(void)
631 struct robin_list *r;
632 struct robin_list *next;
634 for (r = robin, robin = NULL; r; r = next) {
641 static struct robin_list *get_robin_position(char *group)
643 struct robin_list *new;
644 struct robin_list *iter = robin;
645 for (; iter; iter = iter->next) {
646 if (!strcasecmp(iter->group, group)) {
650 new = ast_calloc(1, sizeof(*new));
654 new->group = ast_strdup(group);
669 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
670 static struct ast_sched_context *misdn_tasks = NULL;
671 static pthread_t misdn_tasks_thread;
673 static int *misdn_ports;
675 static void chan_misdn_log(int level, int port, char *tmpl, ...)
676 __attribute__((format(printf, 3, 4)));
678 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c);
679 static void send_digit_to_chan(struct chan_list *cl, char digit);
681 static int pbx_start_chan(struct chan_list *ch);
683 #define MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast)
684 #define MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value)
686 #include "asterisk/strings.h"
688 /* #define MISDN_DEBUG 1 */
690 static const char misdn_type[] = "mISDN";
692 static int tracing = 0;
694 /*! \brief Only alaw and mulaw is allowed for now */
695 static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
697 static int *misdn_debug;
698 static int *misdn_debug_only;
699 static int max_ports;
701 static int *misdn_in_calls;
702 static int *misdn_out_calls;
705 * \brief Global channel call record list head.
707 static struct chan_list *cl_te=NULL;
708 static ast_mutex_t cl_te_lock;
710 static enum event_response_e
711 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
713 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
715 static void cl_queue_chan(struct chan_list *chan);
717 static int dialtone_indicate(struct chan_list *cl);
718 static void hanguptone_indicate(struct chan_list *cl);
719 static int stop_indicate(struct chan_list *cl);
721 static int start_bc_tones(struct chan_list *cl);
722 static int stop_bc_tones(struct chan_list *cl);
723 static void release_chan_early(struct chan_list *ch);
724 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
726 #if defined(AST_MISDN_ENHANCEMENTS)
727 static const char misdn_command_name[] = "misdn_command";
728 static int misdn_command_exec(struct ast_channel *chan, const char *data);
729 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
730 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
731 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
732 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
734 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
736 void debug_numtype(int port, int numtype, char *type);
738 int add_out_calls(int port);
739 int add_in_calls(int port);
743 static int update_pipeline_config(struct misdn_bchannel *bc);
745 static int update_ec_config(struct misdn_bchannel *bc);
750 /*************** Helpers *****************/
752 static int misdn_chan_is_valid(struct chan_list *ch)
754 struct chan_list *list;
756 ast_mutex_lock(&cl_te_lock);
757 for (list = cl_te; list; list = list->next) {
759 ast_mutex_unlock(&cl_te_lock);
763 ast_mutex_unlock(&cl_te_lock);
768 #if defined(mISDN_NATIVE_BRIDGING)
769 /*! Returns a reference to the found chan_list. */
770 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
772 struct chan_list *tmp;
774 ast_mutex_lock(&cl_te_lock);
775 for (tmp = cl_te; tmp; tmp = tmp->next) {
776 if (tmp->ast == ast) {
777 chan_list_ref(tmp, "Found chan_list by ast");
778 ast_mutex_unlock(&cl_te_lock);
782 ast_mutex_unlock(&cl_te_lock);
786 #endif /* defined(mISDN_NATIVE_BRIDGING) */
788 /*! Returns a reference to the found chan_list. */
789 static struct chan_list *get_chan_by_ast_name(const char *name)
791 struct chan_list *tmp;
793 ast_mutex_lock(&cl_te_lock);
794 for (tmp = cl_te; tmp; tmp = tmp->next) {
795 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
796 chan_list_ref(tmp, "Found chan_list by ast name");
797 ast_mutex_unlock(&cl_te_lock);
801 ast_mutex_unlock(&cl_te_lock);
806 #if defined(AST_MISDN_ENHANCEMENTS)
809 * \brief Destroy the misdn_cc_ds_info datastore payload
811 * \param[in] data the datastore payload, a reference to an misdn_cc_caller
814 * Since the payload is a reference to an astobj2 object, we just decrement its
815 * reference count. Before doing so, we NULL out the channel pointer inside of
816 * the misdn_cc_caller instance. This function will be called in one of two
817 * cases. In both cases, we no longer need the channel pointer:
819 * - The original channel that initialized call completion services, the same
820 * channel that is stored here, has been destroyed early. This could happen
821 * if it transferred the mISDN channel, for example.
823 * - The mISDN channel that had this datastore inherited on to it is now being
824 * destroyed. If this is the case, then the call completion events have
825 * already occurred and the appropriate channel variables have already been
826 * set on the original channel that requested call completion services.
830 static void misdn_cc_ds_destroy(void *data)
832 struct misdn_cc_caller *cc_caller = data;
835 cc_caller->chan = NULL;
836 ao2_unlock(cc_caller);
838 ao2_ref(cc_caller, -1);
840 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
842 #if defined(AST_MISDN_ENHANCEMENTS)
845 * \brief Duplicate the misdn_cc_ds_info datastore payload
847 * \param[in] data the datastore payload, a reference to an misdn_cc_caller
850 * All we need to do is bump the reference count and return the same instance.
852 * \return A reference to an instance of a misdn_cc_caller
854 static void *misdn_cc_ds_duplicate(void *data)
856 struct misdn_cc_caller *cc_caller = data;
858 ao2_ref(cc_caller, +1);
862 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
864 #if defined(AST_MISDN_ENHANCEMENTS)
865 static const struct ast_datastore_info misdn_cc_ds_info = {
867 .destroy = misdn_cc_ds_destroy,
868 .duplicate = misdn_cc_ds_duplicate,
870 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
872 #if defined(AST_MISDN_ENHANCEMENTS)
875 * \brief Set a channel var on the peer channel for call completion services
877 * \param[in] peer The peer that initialized call completion services
878 * \param[in] var The variable name to set
879 * \param[in] value The variable value to set
881 * This function may be called from outside of the channel thread. It handles
882 * the fact that the peer channel may be hung up and destroyed at any time.
886 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
891 /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
892 while (peer->chan && ast_channel_trylock(peer->chan)) {
899 pbx_builtin_setvar_helper(peer->chan, var, value);
900 ast_channel_unlock(peer->chan);
905 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
907 #if defined(AST_MISDN_ENHANCEMENTS)
910 * \brief Get a reference to the CC caller if it exists
912 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
914 struct ast_datastore *datastore;
915 struct misdn_cc_caller *cc_caller;
917 ast_channel_lock(chan);
919 if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
920 ast_channel_unlock(chan);
924 ao2_ref(datastore->data, +1);
925 cc_caller = datastore->data;
927 ast_channel_unlock(chan);
931 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
933 #if defined(AST_MISDN_ENHANCEMENTS)
936 * \brief Find the call completion record given the record id.
940 * \retval pointer to found call completion record
941 * \retval NULL if not found
943 * \note Assumes the misdn_cc_records_db lock is already obtained.
945 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
947 struct misdn_cc_record *current;
949 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
950 if (current->record_id == record_id) {
951 /* Found the record */
958 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
960 #if defined(AST_MISDN_ENHANCEMENTS)
963 * \brief Find the call completion record given the port and call linkage id.
965 * \param port Logical port number
966 * \param linkage_id Call linkage ID number from switch.
968 * \retval pointer to found call completion record
969 * \retval NULL if not found
971 * \note Assumes the misdn_cc_records_db lock is already obtained.
973 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
975 struct misdn_cc_record *current;
977 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
978 if (current->port == port
980 && current->mode.ptmp.linkage_id == linkage_id) {
981 /* Found the record */
988 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
990 #if defined(AST_MISDN_ENHANCEMENTS)
993 * \brief Find the call completion record given the port and outstanding invocation id.
995 * \param port Logical port number
996 * \param invoke_id Outstanding message invocation ID number.
998 * \retval pointer to found call completion record
999 * \retval NULL if not found
1001 * \note Assumes the misdn_cc_records_db lock is already obtained.
1003 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
1005 struct misdn_cc_record *current;
1007 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1008 if (current->outstanding_message
1009 && current->invoke_id == invoke_id
1010 && current->port == port) {
1011 /* Found the record */
1018 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1020 #if defined(AST_MISDN_ENHANCEMENTS)
1023 * \brief Find the call completion record given the port and CCBS reference id.
1025 * \param port Logical port number
1026 * \param reference_id CCBS reference ID number from switch.
1028 * \retval pointer to found call completion record
1029 * \retval NULL if not found
1031 * \note Assumes the misdn_cc_records_db lock is already obtained.
1033 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1035 struct misdn_cc_record *current;
1037 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1038 if (current->activated
1039 && current->port == port
1041 && current->mode.ptmp.reference_id == reference_id) {
1042 /* Found the record */
1049 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1051 #if defined(AST_MISDN_ENHANCEMENTS)
1054 * \brief Find the call completion record given the B channel pointer
1056 * \param bc B channel control structure pointer.
1058 * \retval pointer to found call completion record
1059 * \retval NULL if not found
1061 * \note Assumes the misdn_cc_records_db lock is already obtained.
1063 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1065 struct misdn_cc_record *current;
1068 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1070 && current->mode.ptp.bc == bc) {
1071 /* Found the record */
1081 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1083 #if defined(AST_MISDN_ENHANCEMENTS)
1086 * \brief Delete the given call completion record
1088 * \param doomed Call completion record to destroy
1092 * \note Assumes the misdn_cc_records_db lock is already obtained.
1094 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1096 struct misdn_cc_record *current;
1098 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1099 if (current == doomed) {
1100 AST_LIST_REMOVE_CURRENT(list);
1105 AST_LIST_TRAVERSE_SAFE_END;
1107 /* The doomed node is not in the call completion database */
1109 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1111 #if defined(AST_MISDN_ENHANCEMENTS)
1114 * \brief Delete all old call completion records
1118 * \note Assumes the misdn_cc_records_db lock is already obtained.
1120 static void misdn_cc_remove_old(void)
1122 struct misdn_cc_record *current;
1126 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1127 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1128 if (current->ptp && current->mode.ptp.bc) {
1129 /* Close the old call-completion signaling link */
1130 current->mode.ptp.bc->fac_out.Function = Fac_None;
1131 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1132 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1135 /* Remove the old call completion record */
1136 AST_LIST_REMOVE_CURRENT(list);
1140 AST_LIST_TRAVERSE_SAFE_END;
1142 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1144 #if defined(AST_MISDN_ENHANCEMENTS)
1147 * \brief Allocate the next record id.
1149 * \retval New record id on success.
1150 * \retval -1 on error.
1152 * \note Assumes the misdn_cc_records_db lock is already obtained.
1154 static long misdn_cc_record_id_new(void)
1159 record_id = ++misdn_cc_record_id;
1160 first_id = record_id;
1161 while (misdn_cc_find_by_id(record_id)) {
1162 record_id = ++misdn_cc_record_id;
1163 if (record_id == first_id) {
1165 * We have a resource leak.
1166 * We should never need to allocate 64k records.
1168 chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1176 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1178 #if defined(AST_MISDN_ENHANCEMENTS)
1181 * \brief Create a new call completion record
1183 * \retval pointer to new call completion record
1184 * \retval NULL if failed
1186 * \note Assumes the misdn_cc_records_db lock is already obtained.
1188 static struct misdn_cc_record *misdn_cc_new(void)
1190 struct misdn_cc_record *cc_record;
1193 misdn_cc_remove_old();
1195 cc_record = ast_calloc(1, sizeof(*cc_record));
1197 record_id = misdn_cc_record_id_new();
1198 if (record_id < 0) {
1199 ast_free(cc_record);
1203 /* Initialize the new record */
1204 cc_record->record_id = record_id;
1205 cc_record->port = -1;/* Invalid port so it will never be found this way */
1206 cc_record->invoke_id = ++misdn_invoke_id;
1207 cc_record->party_a_free = 1;/* Default User-A as free */
1208 cc_record->error_code = FacError_None;
1209 cc_record->reject_code = FacReject_None;
1210 cc_record->time_created = time(NULL);
1212 /* Insert the new record into the database */
1213 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1217 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1219 #if defined(AST_MISDN_ENHANCEMENTS)
1222 * \brief Destroy the call completion record database
1226 static void misdn_cc_destroy(void)
1228 struct misdn_cc_record *current;
1230 while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1231 /* Do a misdn_cc_delete(current) inline */
1235 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1237 #if defined(AST_MISDN_ENHANCEMENTS)
1240 * \brief Initialize the call completion record database
1244 static void misdn_cc_init(void)
1246 misdn_cc_record_id = 0;
1248 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1250 #if defined(AST_MISDN_ENHANCEMENTS)
1253 * \brief Check the status of an outstanding invocation request.
1255 * \param data Points to an integer containing the call completion record id.
1257 * \retval 0 if got a response.
1258 * \retval -1 if no response yet.
1260 static int misdn_cc_response_check(void *data)
1263 struct misdn_cc_record *cc_record;
1265 AST_LIST_LOCK(&misdn_cc_records_db);
1266 cc_record = misdn_cc_find_by_id(*(long *) data);
1268 if (cc_record->outstanding_message) {
1274 /* No record so there is no response to check. */
1277 AST_LIST_UNLOCK(&misdn_cc_records_db);
1279 return not_responded;
1281 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1283 #if defined(AST_MISDN_ENHANCEMENTS)
1286 * \brief Wait for a response from the switch for an outstanding
1287 * invocation request.
1289 * \param chan Asterisk channel to operate upon.
1290 * \param wait_seconds Number of seconds to wait
1291 * \param record_id Call completion record ID.
1295 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1299 for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1300 /* Sleep in 500 ms increments */
1301 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1302 /* We got hung up or our response came in. */
1307 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1309 #if defined(AST_MISDN_ENHANCEMENTS)
1312 * \brief Convert the mISDN reject code to a string
1314 * \param code mISDN reject code.
1316 * \return The mISDN reject code as a string
1318 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1320 static const struct {
1321 enum FacRejectCode code;
1325 { FacReject_None, "No reject occurred" },
1326 { FacReject_Unknown, "Unknown reject code" },
1328 { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
1329 { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
1330 { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
1332 { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
1333 { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
1334 { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
1335 { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
1336 { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
1337 { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
1338 { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
1339 { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
1341 { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
1342 { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
1343 { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
1345 { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
1346 { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
1347 { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
1348 { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
1349 { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
1355 for (index = 0; index < ARRAY_LEN(arr); ++index) {
1356 if (arr[index].code == code) {
1357 return arr[index].name;
1363 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1365 #if defined(AST_MISDN_ENHANCEMENTS)
1368 * \brief Convert the mISDN error code to a string
1370 * \param code mISDN error code.
1372 * \return The mISDN error code as a string
1374 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1376 static const struct {
1377 enum FacErrorCode code;
1381 { FacError_None, "No error occurred" },
1382 { FacError_Unknown, "Unknown OID error code" },
1384 { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
1385 { FacError_Gen_NotAvailable, "General: Not Available" },
1386 { FacError_Gen_NotImplemented, "General: Not Implemented" },
1387 { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
1388 { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
1389 { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
1390 { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
1391 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1392 { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
1394 { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
1395 { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
1396 { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
1397 { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
1398 { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
1399 { FacError_Div_NotActivated, "Diversion: Not Activated" },
1400 { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
1402 { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
1404 { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
1405 { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
1406 { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
1407 { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
1408 { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
1409 { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
1410 { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
1411 { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
1412 { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
1414 { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
1415 { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
1417 { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
1423 for (index = 0; index < ARRAY_LEN(arr); ++index) {
1424 if (arr[index].code == code) {
1425 return arr[index].name;
1431 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1433 #if defined(AST_MISDN_ENHANCEMENTS)
1436 * \brief Convert mISDN redirecting reason to diversion reason.
1438 * \param reason mISDN redirecting reason code.
1440 * \return Supported diversion reason code.
1442 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1444 unsigned diversion_reason;
1447 case mISDN_REDIRECTING_REASON_CALL_FWD:
1448 diversion_reason = 1;/* cfu */
1450 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
1451 diversion_reason = 2;/* cfb */
1453 case mISDN_REDIRECTING_REASON_NO_REPLY:
1454 diversion_reason = 3;/* cfnr */
1457 diversion_reason = 0;/* unknown */
1461 return diversion_reason;
1463 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1465 #if defined(AST_MISDN_ENHANCEMENTS)
1468 * \brief Convert diversion reason to mISDN redirecting reason
1470 * \param diversion_reason Diversion reason to convert
1472 * \return Supported redirecting reason code.
1474 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1476 enum mISDN_REDIRECTING_REASON reason;
1478 switch (diversion_reason) {
1480 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
1483 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
1486 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
1489 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
1495 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1497 #if defined(AST_MISDN_ENHANCEMENTS)
1500 * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1502 * \param presentation mISDN presentation to convert
1503 * \param number_present TRUE if the number is present
1505 * \return PresentedNumberUnscreened type
1507 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1511 switch (presentation) {
1512 case 0:/* allowed */
1513 if (number_present) {
1514 type = 0;/* presentationAllowedNumber */
1516 type = 2;/* numberNotAvailableDueToInterworking */
1519 case 1:/* restricted */
1520 if (number_present) {
1521 type = 3;/* presentationRestrictedNumber */
1523 type = 1;/* presentationRestricted */
1527 type = 2;/* numberNotAvailableDueToInterworking */
1533 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1535 #if defined(AST_MISDN_ENHANCEMENTS)
1538 * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1540 * \param type PresentedNumberUnscreened type
1542 * \return mISDN presentation
1544 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1550 case 0:/* presentationAllowedNumber */
1551 presentation = 0;/* allowed */
1554 case 1:/* presentationRestricted */
1555 case 3:/* presentationRestrictedNumber */
1556 presentation = 1;/* restricted */
1559 case 2:/* numberNotAvailableDueToInterworking */
1560 presentation = 2;/* unavailable */
1564 return presentation;
1566 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1568 #if defined(AST_MISDN_ENHANCEMENTS)
1571 * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1573 * \param number_plan mISDN numbering plan
1575 * \return PartyNumber numbering plan
1577 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1579 unsigned party_plan;
1581 switch (number_plan) {
1583 case NUMPLAN_UNKNOWN:
1584 party_plan = 0;/* unknown */
1588 party_plan = 1;/* public */
1592 party_plan = 3;/* data */
1596 party_plan = 4;/* telex */
1599 case NUMPLAN_NATIONAL:
1600 party_plan = 8;/* nationalStandard */
1603 case NUMPLAN_PRIVATE:
1604 party_plan = 5;/* private */
1610 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1612 #if defined(AST_MISDN_ENHANCEMENTS)
1615 * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1617 * \param party_plan PartyNumber numbering plan
1619 * \return mISDN numbering plan
1621 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1623 enum mISDN_NUMBER_PLAN number_plan;
1625 switch (party_plan) {
1627 case 0:/* unknown */
1628 number_plan = NUMPLAN_UNKNOWN;
1631 number_plan = NUMPLAN_ISDN;
1634 number_plan = NUMPLAN_DATA;
1637 number_plan = NUMPLAN_TELEX;
1639 case 8:/* nationalStandard */
1640 number_plan = NUMPLAN_NATIONAL;
1642 case 5:/* private */
1643 number_plan = NUMPLAN_PRIVATE;
1649 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1651 #if defined(AST_MISDN_ENHANCEMENTS)
1654 * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1656 * \param ton mISDN type-of-number
1658 * \return PartyNumber public type-of-number
1660 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1666 case NUMTYPE_UNKNOWN:
1667 party_ton = 0;/* unknown */
1670 case NUMTYPE_INTERNATIONAL:
1671 party_ton = 1;/* internationalNumber */
1674 case NUMTYPE_NATIONAL:
1675 party_ton = 2;/* nationalNumber */
1678 case NUMTYPE_NETWORK_SPECIFIC:
1679 party_ton = 3;/* networkSpecificNumber */
1682 case NUMTYPE_SUBSCRIBER:
1683 party_ton = 4;/* subscriberNumber */
1686 case NUMTYPE_ABBREVIATED:
1687 party_ton = 6;/* abbreviatedNumber */
1693 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1695 #if defined(AST_MISDN_ENHANCEMENTS)
1698 * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1700 * \param party_ton PartyNumber public type-of-number
1702 * \return mISDN type-of-number
1704 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1706 enum mISDN_NUMBER_TYPE ton;
1708 switch (party_ton) {
1710 case 0:/* unknown */
1711 ton = NUMTYPE_UNKNOWN;
1714 case 1:/* internationalNumber */
1715 ton = NUMTYPE_INTERNATIONAL;
1718 case 2:/* nationalNumber */
1719 ton = NUMTYPE_NATIONAL;
1722 case 3:/* networkSpecificNumber */
1723 ton = NUMTYPE_NETWORK_SPECIFIC;
1726 case 4:/* subscriberNumber */
1727 ton = NUMTYPE_SUBSCRIBER;
1730 case 6:/* abbreviatedNumber */
1731 ton = NUMTYPE_ABBREVIATED;
1737 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1739 #if defined(AST_MISDN_ENHANCEMENTS)
1742 * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1744 * \param ton mISDN type-of-number
1746 * \return PartyNumber private type-of-number
1748 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1754 case NUMTYPE_UNKNOWN:
1755 party_ton = 0;/* unknown */
1758 case NUMTYPE_INTERNATIONAL:
1759 party_ton = 1;/* level2RegionalNumber */
1762 case NUMTYPE_NATIONAL:
1763 party_ton = 2;/* level1RegionalNumber */
1766 case NUMTYPE_NETWORK_SPECIFIC:
1767 party_ton = 3;/* pTNSpecificNumber */
1770 case NUMTYPE_SUBSCRIBER:
1771 party_ton = 4;/* localNumber */
1774 case NUMTYPE_ABBREVIATED:
1775 party_ton = 6;/* abbreviatedNumber */
1781 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1783 #if defined(AST_MISDN_ENHANCEMENTS)
1786 * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1788 * \param party_ton PartyNumber private type-of-number
1790 * \return mISDN type-of-number
1792 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1794 enum mISDN_NUMBER_TYPE ton;
1796 switch (party_ton) {
1798 case 0:/* unknown */
1799 ton = NUMTYPE_UNKNOWN;
1802 case 1:/* level2RegionalNumber */
1803 ton = NUMTYPE_INTERNATIONAL;
1806 case 2:/* level1RegionalNumber */
1807 ton = NUMTYPE_NATIONAL;
1810 case 3:/* pTNSpecificNumber */
1811 ton = NUMTYPE_NETWORK_SPECIFIC;
1814 case 4:/* localNumber */
1815 ton = NUMTYPE_SUBSCRIBER;
1818 case 6:/* abbreviatedNumber */
1819 ton = NUMTYPE_ABBREVIATED;
1825 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1829 * \brief Convert the mISDN type of number code to a string
1831 * \param number_type mISDN type of number code.
1833 * \return The mISDN type of number code as a string
1835 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1839 switch (number_type) {
1841 case NUMTYPE_UNKNOWN:
1845 case NUMTYPE_INTERNATIONAL:
1846 str = "International";
1849 case NUMTYPE_NATIONAL:
1853 case NUMTYPE_NETWORK_SPECIFIC:
1854 str = "Network Specific";
1857 case NUMTYPE_SUBSCRIBER:
1861 case NUMTYPE_ABBREVIATED:
1862 str = "Abbreviated";
1871 * \brief Convert the mISDN type of number code to Asterisk type of number code
1873 * \param number_type mISDN type of number code.
1875 * \return Asterisk type of number code
1877 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1879 int ast_number_type;
1881 switch (number_type) {
1883 case NUMTYPE_UNKNOWN:
1884 ast_number_type = NUMTYPE_UNKNOWN << 4;
1887 case NUMTYPE_INTERNATIONAL:
1888 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1891 case NUMTYPE_NATIONAL:
1892 ast_number_type = NUMTYPE_NATIONAL << 4;
1895 case NUMTYPE_NETWORK_SPECIFIC:
1896 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1899 case NUMTYPE_SUBSCRIBER:
1900 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1903 case NUMTYPE_ABBREVIATED:
1904 ast_number_type = NUMTYPE_ABBREVIATED << 4;
1908 return ast_number_type;
1913 * \brief Convert the Asterisk type of number code to mISDN type of number code
1915 * \param ast_number_type Asterisk type of number code.
1917 * \return mISDN type of number code
1919 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1921 enum mISDN_NUMBER_TYPE number_type;
1923 switch ((ast_number_type >> 4) & 0x07) {
1925 case NUMTYPE_UNKNOWN:
1926 number_type = NUMTYPE_UNKNOWN;
1929 case NUMTYPE_INTERNATIONAL:
1930 number_type = NUMTYPE_INTERNATIONAL;
1933 case NUMTYPE_NATIONAL:
1934 number_type = NUMTYPE_NATIONAL;
1937 case NUMTYPE_NETWORK_SPECIFIC:
1938 number_type = NUMTYPE_NETWORK_SPECIFIC;
1941 case NUMTYPE_SUBSCRIBER:
1942 number_type = NUMTYPE_SUBSCRIBER;
1945 case NUMTYPE_ABBREVIATED:
1946 number_type = NUMTYPE_ABBREVIATED;
1955 * \brief Convert the mISDN numbering plan code to a string
1957 * \param number_plan mISDN numbering plan code.
1959 * \return The mISDN numbering plan code as a string
1961 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1965 switch (number_plan) {
1967 case NUMPLAN_UNKNOWN:
1983 case NUMPLAN_NATIONAL:
1987 case NUMPLAN_PRIVATE:
1997 * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1999 * \param number_plan mISDN numbering plan code.
2001 * \return Asterisk numbering plan code
2003 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
2005 int ast_number_plan;
2007 switch (number_plan) {
2009 case NUMPLAN_UNKNOWN:
2010 ast_number_plan = NUMPLAN_UNKNOWN;
2014 ast_number_plan = NUMPLAN_ISDN;
2018 ast_number_plan = NUMPLAN_DATA;
2022 ast_number_plan = NUMPLAN_TELEX;
2025 case NUMPLAN_NATIONAL:
2026 ast_number_plan = NUMPLAN_NATIONAL;
2029 case NUMPLAN_PRIVATE:
2030 ast_number_plan = NUMPLAN_PRIVATE;
2034 return ast_number_plan;
2039 * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2041 * \param ast_number_plan Asterisk numbering plan code.
2043 * \return mISDN numbering plan code
2045 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2047 enum mISDN_NUMBER_PLAN number_plan;
2049 switch (ast_number_plan & 0x0F) {
2051 case NUMPLAN_UNKNOWN:
2052 number_plan = NUMPLAN_UNKNOWN;
2056 number_plan = NUMPLAN_ISDN;
2060 number_plan = NUMPLAN_DATA;
2064 number_plan = NUMPLAN_TELEX;
2067 case NUMPLAN_NATIONAL:
2068 number_plan = NUMPLAN_NATIONAL;
2071 case NUMPLAN_PRIVATE:
2072 number_plan = NUMPLAN_PRIVATE;
2081 * \brief Convert the mISDN presentation code to a string
2083 * \param presentation mISDN number presentation restriction code.
2085 * \return The mISDN presentation code as a string
2087 static const char *misdn_to_str_pres(int presentation)
2091 switch (presentation) {
2101 str = "Unavailable";
2114 * \brief Convert the mISDN presentation code to Asterisk presentation code
2116 * \param presentation mISDN number presentation restriction code.
2118 * \return Asterisk presentation code
2120 static int misdn_to_ast_pres(int presentation)
2122 switch (presentation) {
2125 presentation = AST_PRES_ALLOWED;
2129 presentation = AST_PRES_RESTRICTED;
2133 presentation = AST_PRES_UNAVAILABLE;
2137 return presentation;
2142 * \brief Convert the Asterisk presentation code to mISDN presentation code
2144 * \param presentation Asterisk number presentation restriction code.
2146 * \return mISDN presentation code
2148 static int ast_to_misdn_pres(int presentation)
2150 switch (presentation & AST_PRES_RESTRICTION) {
2152 case AST_PRES_ALLOWED:
2156 case AST_PRES_RESTRICTED:
2160 case AST_PRES_UNAVAILABLE:
2165 return presentation;
2170 * \brief Convert the mISDN screening code to a string
2172 * \param screening mISDN number screening code.
2174 * \return The mISDN screening code as a string
2176 static const char *misdn_to_str_screen(int screening)
2180 switch (screening) {
2186 str = "Passed Screen";
2190 str = "Failed Screen";
2194 str = "Network Number";
2207 * \brief Convert the mISDN screening code to Asterisk screening code
2209 * \param screening mISDN number screening code.
2211 * \return Asterisk screening code
2213 static int misdn_to_ast_screen(int screening)
2215 switch (screening) {
2218 screening = AST_PRES_USER_NUMBER_UNSCREENED;
2222 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
2226 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
2230 screening = AST_PRES_NETWORK_NUMBER;
2239 * \brief Convert the Asterisk screening code to mISDN screening code
2241 * \param screening Asterisk number screening code.
2243 * \return mISDN screening code
2245 static int ast_to_misdn_screen(int screening)
2247 switch (screening & AST_PRES_NUMBER_TYPE) {
2249 case AST_PRES_USER_NUMBER_UNSCREENED:
2253 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
2257 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
2261 case AST_PRES_NETWORK_NUMBER:
2271 * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2273 * \param ast Asterisk redirecting reason code.
2275 * \return mISDN reason code
2277 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
2281 static const struct misdn_reasons {
2282 enum AST_REDIRECTING_REASON ast;
2283 enum mISDN_REDIRECTING_REASON q931;
2284 } misdn_reason_table[] = {
2286 { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
2287 { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
2288 { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
2289 { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
2290 { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
2291 { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2292 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2293 { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
2294 { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
2295 { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
2296 { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2297 { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
2301 for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2302 if (misdn_reason_table[index].ast == ast) {
2303 return misdn_reason_table[index].q931;
2306 return mISDN_REDIRECTING_REASON_UNKNOWN;
2311 * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2313 * \param q931 mISDN redirecting reason code.
2315 * \return Asterisk redirecting reason code
2317 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
2319 enum AST_REDIRECTING_REASON ast;
2323 case mISDN_REDIRECTING_REASON_UNKNOWN:
2324 ast = AST_REDIRECTING_REASON_UNKNOWN;
2327 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
2328 ast = AST_REDIRECTING_REASON_USER_BUSY;
2331 case mISDN_REDIRECTING_REASON_NO_REPLY:
2332 ast = AST_REDIRECTING_REASON_NO_ANSWER;
2335 case mISDN_REDIRECTING_REASON_DEFLECTION:
2336 ast = AST_REDIRECTING_REASON_DEFLECTION;
2339 case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
2340 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
2343 case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
2344 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
2347 case mISDN_REDIRECTING_REASON_CALL_FWD:
2348 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
2357 struct allowed_bearers {
2358 char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2359 char *display; /*!< Bearer capability displayable name */
2360 int cap; /*!< SETUP message bearer capability field code value */
2361 int deprecated; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2365 static const struct allowed_bearers allowed_bearers_array[] = {
2366 /* Name, Displayable Name Bearer Capability, Deprecated */
2367 { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
2368 { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
2369 { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2370 { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
2371 { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 }, /* Allow misspelling for backwards compatibility */
2372 { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
2376 static const char *bearer2str(int cap)
2380 for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2381 if (allowed_bearers_array[index].cap == cap) {
2382 return allowed_bearers_array[index].display;
2386 return "Unknown Bearer";
2389 #if defined(AST_MISDN_ENHANCEMENTS)
2392 * \brief Fill in facility PartyNumber information
2394 * \param party PartyNumber structure to fill in.
2395 * \param id Information to put in PartyNumber structure.
2399 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2401 ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2402 party->LengthOfNumber = strlen((char *) party->Number);
2403 party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2404 switch (party->Type) {
2406 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2408 case 5:/* private */
2409 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2412 party->TypeOfNumber = 0;/* Don't care */
2416 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2418 #if defined(AST_MISDN_ENHANCEMENTS)
2421 * \brief Extract the information from PartyNumber
2423 * \param id Where to put extracted PartyNumber information
2424 * \param party PartyNumber information to extract
2428 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2430 if (party->LengthOfNumber) {
2431 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2432 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2433 switch (party->Type) {
2435 id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2437 case 5:/* private */
2438 id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2441 id->number_type = NUMTYPE_UNKNOWN;
2445 /* Number not present */
2446 id->number_type = NUMTYPE_UNKNOWN;
2447 id->number_plan = NUMPLAN_ISDN;
2451 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2453 #if defined(AST_MISDN_ENHANCEMENTS)
2456 * \brief Fill in facility Address information
2458 * \param Address Address structure to fill in.
2459 * \param id Information to put in Address structure.
2463 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2465 misdn_PartyNumber_fill(&Address->Party, id);
2467 /* Subaddresses are not supported yet */
2468 Address->Subaddress.Length = 0;
2470 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2472 #if defined(AST_MISDN_ENHANCEMENTS)
2475 * \brief Fill in facility PresentedNumberUnscreened information
2477 * \param presented PresentedNumberUnscreened structure to fill in.
2478 * \param id Information to put in PresentedNumberUnscreened structure.
2482 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2484 presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2485 misdn_PartyNumber_fill(&presented->Unscreened, id);
2487 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2489 #if defined(AST_MISDN_ENHANCEMENTS)
2492 * \brief Extract the information from PartyNumber
2494 * \param id Where to put extracted PresentedNumberUnscreened information
2495 * \param presented PresentedNumberUnscreened information to extract
2499 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2501 id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2502 id->screening = 0;/* unscreened */
2503 switch (presented->Type) {
2504 case 0:/* presentationAllowedNumber */
2505 case 3:/* presentationRestrictedNumber */
2506 misdn_PartyNumber_extract(id, &presented->Unscreened);
2508 case 1:/* presentationRestricted */
2509 case 2:/* numberNotAvailableDueToInterworking */
2511 /* Number not present (And uninitialized so do not even look at it!) */
2512 id->number_type = NUMTYPE_UNKNOWN;
2513 id->number_plan = NUMPLAN_ISDN;
2518 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2520 #if defined(AST_MISDN_ENHANCEMENTS)
2521 static const char Level_Spacing[] = " ";/* Work for up to 10 levels */
2522 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2524 #if defined(AST_MISDN_ENHANCEMENTS)
2525 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2527 if (Party->LengthOfNumber) {
2528 const char *Spacing;
2530 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2531 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2532 Spacing, Party->Type);
2533 switch (Party->Type) {
2534 case 0: /* Unknown PartyNumber */
2535 chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
2536 Spacing, Party->Number);
2538 case 1: /* Public PartyNumber */
2539 chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
2540 Spacing, Party->TypeOfNumber, Party->Number);
2542 case 2: /* NSAP encoded PartyNumber */
2543 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2544 Spacing, Party->Number);
2546 case 3: /* Data PartyNumber (Not used) */
2547 chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
2548 Spacing, Party->Number);
2550 case 4: /* Telex PartyNumber (Not used) */
2551 chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
2552 Spacing, Party->Number);
2554 case 5: /* Private PartyNumber */
2555 chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
2556 Spacing, Party->TypeOfNumber, Party->Number);
2558 case 8: /* National Standard PartyNumber (Not used) */
2559 chan_misdn_log(1, bc->port, " -->%s National: %s\n",
2560 Spacing, Party->Number);
2567 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2569 #if defined(AST_MISDN_ENHANCEMENTS)
2570 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2572 if (Subaddress->Length) {
2573 const char *Spacing;
2575 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2576 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2577 Spacing, Subaddress->Type);
2578 switch (Subaddress->Type) {
2579 case 0: /* UserSpecified */
2580 if (Subaddress->u.UserSpecified.OddCountPresent) {
2581 chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
2582 Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2584 chan_misdn_log(1, bc->port, " -->%s User: %s\n",
2585 Spacing, Subaddress->u.UserSpecified.Information);
2589 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2590 Spacing, Subaddress->u.Nsap);
2597 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2599 #if defined(AST_MISDN_ENHANCEMENTS)
2600 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2602 print_facility_PartyNumber(Level, &Address->Party, bc);
2603 print_facility_Subaddress(Level, &Address->Subaddress, bc);
2605 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2607 #if defined(AST_MISDN_ENHANCEMENTS)
2608 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2610 const char *Spacing;
2612 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2613 chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2614 switch (Presented->Type) {
2615 case 0: /* presentationAllowedNumber */
2616 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2617 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2619 case 1: /* presentationRestricted */
2620 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2622 case 2: /* numberNotAvailableDueToInterworking */
2623 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2625 case 3: /* presentationRestrictedNumber */
2626 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2627 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2633 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2635 #if defined(AST_MISDN_ENHANCEMENTS)
2636 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2638 const char *Spacing;
2640 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2641 chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2642 print_facility_PartyNumber(Level, &Address->Party, bc);
2643 print_facility_Subaddress(Level, &Address->Subaddress, bc);
2645 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2647 #if defined(AST_MISDN_ENHANCEMENTS)
2648 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2650 const char *Spacing;
2652 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2653 chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2654 switch (Presented->Type) {
2655 case 0: /* presentationAllowedAddress */
2656 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2657 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2659 case 1: /* presentationRestricted */
2660 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2662 case 2: /* numberNotAvailableDueToInterworking */
2663 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2665 case 3: /* presentationRestrictedAddress */
2666 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2667 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2673 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2675 #if defined(AST_MISDN_ENHANCEMENTS)
2676 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2678 const char *Spacing;
2680 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2681 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2682 if (Q931ie->Bc.Length) {
2683 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2685 if (Q931ie->Hlc.Length) {
2686 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2688 if (Q931ie->Llc.Length) {
2689 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2692 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2694 #if defined(AST_MISDN_ENHANCEMENTS)
2695 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2697 const char *Spacing;
2699 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2700 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2701 if (Q931ie->Bc.Length) {
2702 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2704 if (Q931ie->Hlc.Length) {
2705 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2707 if (Q931ie->Llc.Length) {
2708 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2710 if (Q931ie->UserInfo.Length) {
2711 chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2714 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2716 #if defined(AST_MISDN_ENHANCEMENTS)
2717 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2719 const char *Spacing;
2721 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2722 chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2723 Spacing, CallInfo->CCBSReference);
2724 chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2725 print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2726 print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2727 if (CallInfo->SubaddressOfA.Length) {
2728 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2729 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2732 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2734 #if defined(AST_MISDN_ENHANCEMENTS)
2735 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2737 const char *Spacing;
2739 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2740 if (Party->LengthOfNumber) {
2741 print_facility_PartyNumber(Level, Party, bc);
2743 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2746 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2748 #if defined(AST_MISDN_ENHANCEMENTS)
2749 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2751 const char *Spacing;
2753 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2754 chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2756 ForwardingRecord->Procedure,
2757 ForwardingRecord->BasicService);
2758 chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2759 print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2760 chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2761 print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2763 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2765 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
2767 #if defined(AST_MISDN_ENHANCEMENTS)
2769 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2771 switch (fac->Function) {
2772 #if defined(AST_MISDN_ENHANCEMENTS)
2773 case Fac_ActivationDiversion:
2774 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2775 fac->u.ActivationDiversion.InvokeID);
2776 switch (fac->u.ActivationDiversion.ComponentType) {
2777 case FacComponent_Invoke:
2778 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2779 fac->u.ActivationDiversion.Component.Invoke.Procedure,
2780 fac->u.ActivationDiversion.Component.Invoke.BasicService);
2781 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2782 print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2783 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2784 print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2786 case FacComponent_Result:
2787 chan_misdn_log(1, bc->port, " --> Result\n");
2793 case Fac_DeactivationDiversion:
2794 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2795 fac->u.DeactivationDiversion.InvokeID);
2796 switch (fac->u.DeactivationDiversion.ComponentType) {
2797 case FacComponent_Invoke:
2798 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2799 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2800 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2801 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2802 print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2804 case FacComponent_Result:
2805 chan_misdn_log(1, bc->port, " --> Result\n");
2811 case Fac_ActivationStatusNotificationDiv:
2812 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2813 fac->u.ActivationStatusNotificationDiv.InvokeID,
2814 fac->u.ActivationStatusNotificationDiv.Procedure,
2815 fac->u.ActivationStatusNotificationDiv.BasicService);
2816 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2817 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2818 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2819 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2821 case Fac_DeactivationStatusNotificationDiv:
2822 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2823 fac->u.DeactivationStatusNotificationDiv.InvokeID,
2824 fac->u.DeactivationStatusNotificationDiv.Procedure,
2825 fac->u.DeactivationStatusNotificationDiv.BasicService);
2826 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2827 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2829 case Fac_InterrogationDiversion:
2830 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2831 fac->u.InterrogationDiversion.InvokeID);
2832 switch (fac->u.InterrogationDiversion.ComponentType) {
2833 case FacComponent_Invoke:
2834 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2835 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2836 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2837 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2838 print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2840 case FacComponent_Result:
2841 chan_misdn_log(1, bc->port, " --> Result:\n");
2842 if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2843 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2844 chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
2845 print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2853 case Fac_DiversionInformation:
2854 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2855 fac->u.DiversionInformation.InvokeID,
2856 fac->u.DiversionInformation.DiversionReason,
2857 fac->u.DiversionInformation.BasicService);
2858 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2859 chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
2860 print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2862 if (fac->u.DiversionInformation.CallingAddressPresent) {
2863 chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
2864 print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2866 if (fac->u.DiversionInformation.OriginalCalledPresent) {
2867 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2868 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2870 if (fac->u.DiversionInformation.LastDivertingPresent) {
2871 chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
2872 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2874 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2875 chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2877 if (fac->u.DiversionInformation.UserInfo.Length) {
2878 chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2881 case Fac_CallDeflection:
2882 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2883 fac->u.CallDeflection.InvokeID);
2884 switch (fac->u.CallDeflection.ComponentType) {
2885 case FacComponent_Invoke:
2886 chan_misdn_log(1, bc->port, " --> Invoke:\n");
2887 if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2888 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
2889 fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2891 chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
2892 print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2894 case FacComponent_Result:
2895 chan_misdn_log(1, bc->port, " --> Result\n");
2901 case Fac_CallRerouteing:
2902 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2903 fac->u.CallRerouteing.InvokeID);
2904 switch (fac->u.CallRerouteing.ComponentType) {
2905 case FacComponent_Invoke:
2906 chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
2907 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2908 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2909 chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
2910 print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2911 print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2912 chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
2913 print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2914 chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
2915 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2916 if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2917 chan_misdn_log(1, bc->port, " --> CallingParty:\n");
2918 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2921 case FacComponent_Result:
2922 chan_misdn_log(1, bc->port, " --> Result\n");
2928 case Fac_InterrogateServedUserNumbers:
2929 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2930 fac->u.InterrogateServedUserNumbers.InvokeID);
2931 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2932 case FacComponent_Invoke:
2933 chan_misdn_log(1, bc->port, " --> Invoke\n");
2935 case FacComponent_Result:
2936 chan_misdn_log(1, bc->port, " --> Result:\n");
2937 if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2938 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2939 chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
2940 print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2948 case Fac_DivertingLegInformation1:
2949 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2950 fac->u.DivertingLegInformation1.InvokeID,
2951 fac->u.DivertingLegInformation1.DiversionReason,
2952 fac->u.DivertingLegInformation1.SubscriptionOption);
2953 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2954 chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
2955 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2958 case Fac_DivertingLegInformation2:
2959 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2960 fac->u.DivertingLegInformation2.InvokeID,
2961 fac->u.DivertingLegInformation2.DiversionReason,
2962 fac->u.DivertingLegInformation2.DiversionCounter);
2963 if (fac->u.DivertingLegInformation2.DivertingPresent) {
2964 chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
2965 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2967 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2968 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2969 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2972 case Fac_DivertingLegInformation3:
2973 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2974 fac->u.DivertingLegInformation3.InvokeID,
2975 fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2978 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
2981 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2982 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2984 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
2985 case Fac_AOCDCurrency:
2986 if (fac->u.AOCDcur.chargeNotAvailable) {
2987 chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2988 } else if (fac->u.AOCDcur.freeOfCharge) {
2989 chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2990 } else if (fac->u.AOCDchu.billingId >= 0) {
2991 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2992 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2993 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2995 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2996 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2997 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
3000 case Fac_AOCDChargingUnit:
3001 if (fac->u.AOCDchu.chargeNotAvailable) {
3002 chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
3003 } else if (fac->u.AOCDchu.freeOfCharge) {
3004 chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
3005 } else if (fac->u.AOCDchu.billingId >= 0) {
3006 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
3007 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
3009 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
3010 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
3013 #if defined(AST_MISDN_ENHANCEMENTS)
3015 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
3016 fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
3019 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
3020 fac->u.RESULT.InvokeID);
3023 if (fac->u.REJECT.InvokeIDPresent) {
3024 chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
3025 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
3027 chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
3028 fac->u.REJECT.Code);
3031 case Fac_EctExecute:
3032 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3033 fac->u.EctExecute.InvokeID);
3035 case Fac_ExplicitEctExecute:
3036 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3037 fac->u.ExplicitEctExecute.InvokeID,
3038 fac->u.ExplicitEctExecute.LinkID);
3040 case Fac_RequestSubaddress:
3041 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3042 fac->u.RequestSubaddress.InvokeID);
3044 case Fac_SubaddressTransfer:
3045 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3046 fac->u.SubaddressTransfer.InvokeID);
3047 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3049 case Fac_EctLinkIdRequest:
3050 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3051 fac->u.EctLinkIdRequest.InvokeID);
3052 switch (fac->u.EctLinkIdRequest.ComponentType) {
3053 case FacComponent_Invoke:
3054 chan_misdn_log(1, bc->port, " --> Invoke\n");
3056 case FacComponent_Result:
3057 chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
3058 fac->u.EctLinkIdRequest.Component.Result.LinkID);
3065 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3066 fac->u.EctInform.InvokeID,
3067 fac->u.EctInform.Status);
3068 if (fac->u.EctInform.RedirectionPresent) {
3069 chan_misdn_log(1, bc->port, " --> Redirection Number\n");
3070 print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3073 case Fac_EctLoopTest:
3074 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3075 fac->u.EctLoopTest.InvokeID);
3076 switch (fac->u.EctLoopTest.ComponentType) {
3077 case FacComponent_Invoke:
3078 chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
3079 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3081 case FacComponent_Result:
3082 chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
3083 fac->u.EctLoopTest.Component.Result.LoopResult);
3089 case Fac_StatusRequest:
3090 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3091 fac->u.StatusRequest.InvokeID);
3092 switch (fac->u.StatusRequest.ComponentType) {
3093 case FacComponent_Invoke:
3094 chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
3095 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3097 case FacComponent_Result:
3098 chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
3099 fac->u.StatusRequest.Component.Result.Status);
3105 case Fac_CallInfoRetain:
3106 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3107 fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3109 case Fac_CCBSDeactivate:
3110 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3111 fac->u.CCBSDeactivate.InvokeID);
3112 switch (fac->u.CCBSDeactivate.ComponentType) {
3113 case FacComponent_Invoke:
3114 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
3115 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3117 case FacComponent_Result:
3118 chan_misdn_log(1, bc->port, " --> Result\n");
3125 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3126 fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3127 fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3128 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3129 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3130 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3132 case Fac_CCBSRemoteUserFree:
3133 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3134 fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3135 fac->u.CCBSRemoteUserFree.RecallMode);
3136 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3137 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3138 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3141 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3142 fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3144 case Fac_CCBSStatusRequest:
3145 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3146 fac->u.CCBSStatusRequest.InvokeID);
3147 switch (fac->u.CCBSStatusRequest.ComponentType) {
3148 case FacComponent_Invoke:
3149 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
3150 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3151 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3152 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3154 case FacComponent_Result:
3155 chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
3156 fac->u.CCBSStatusRequest.Component.Result.Free);
3163 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3164 fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3165 fac->u.CCBSBFree.RecallMode);
3166 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3167 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3168 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3170 case Fac_EraseCallLinkageID:
3171 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3172 fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3174 case Fac_CCBSStopAlerting:
3175 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3176 fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3178 case Fac_CCBSRequest:
3179 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3180 fac->u.CCBSRequest.InvokeID);
3181 switch (fac->u.CCBSRequest.ComponentType) {
3182 case FacComponent_Invoke:
3183 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3184 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3186 case FacComponent_Result:
3187 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3188 fac->u.CCBSRequest.Component.Result.CCBSReference,
3189 fac->u.CCBSRequest.Component.Result.RecallMode);
3195 case Fac_CCBSInterrogate:
3196 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3197 fac->u.CCBSInterrogate.InvokeID);
3198 switch (fac->u.CCBSInterrogate.ComponentType) {
3199 case FacComponent_Invoke:
3200 chan_misdn_log(1, bc->port, " --> Invoke\n");
3201 if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3202 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3203 fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3205 if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3206 chan_misdn_log(1, bc->port, " --> AParty\n");
3207 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3210 case FacComponent_Result:
3211 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3212 fac->u.CCBSInterrogate.Component.Result.RecallMode);
3213 if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3214 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3215 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3216 print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3224 case Fac_CCNRRequest:
3225 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3226 fac->u.CCNRRequest.InvokeID);
3227 switch (fac->u.CCNRRequest.ComponentType) {
3228 case FacComponent_Invoke:
3229 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3230 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3232 case FacComponent_Result:
3233 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3234 fac->u.CCNRRequest.Component.Result.CCBSReference,
3235 fac->u.CCNRRequest.Component.Result.RecallMode);
3241 case Fac_CCNRInterrogate:
3242 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3243 fac->u.CCNRInterrogate.InvokeID);
3244 switch (fac->u.CCNRInterrogate.ComponentType) {
3245 case FacComponent_Invoke:
3246 chan_misdn_log(1, bc->port, " --> Invoke\n");
3247 if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3248 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3249 fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3251 if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3252 chan_misdn_log(1, bc->port, " --> AParty\n");
3253 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3256 case FacComponent_Result:
3257 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3258 fac->u.CCNRInterrogate.Component.Result.RecallMode);
3259 if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3260 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3261 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3262 print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3270 case Fac_CCBS_T_Call:
3271 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3272 fac->u.CCBS_T_Call.InvokeID);
3274 case Fac_CCBS_T_Suspend:
3275 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3276 fac->u.CCBS_T_Suspend.InvokeID);
3278 case Fac_CCBS_T_Resume:
3279 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3280 fac->u.CCBS_T_Resume.InvokeID);
3282 case Fac_CCBS_T_RemoteUserFree:
3283 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3284 fac->u.CCBS_T_RemoteUserFree.InvokeID);
3286 case Fac_CCBS_T_Available:
3287 chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3288 fac->u.CCBS_T_Available.InvokeID);