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 * \extref MISDN http://www.misdn.org/
29 * \ingroup channel_drivers
34 * To use the CCBS/CCNR supplementary service feature and other
35 * supplementary services using FACILITY messages requires a
36 * modified version of mISDN.
39 * The latest modified mISDN v1.1.x based version is available at:
40 * http://svn.digium.com/svn/thirdparty/mISDN/trunk
41 * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
44 * Taged versions of the modified mISDN code are available under:
45 * http://svn.digium.com/svn/thirdparty/mISDN/tags
46 * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
49 /* Define to enable cli commands to generate canned CCBS messages. */
50 // #define CCBS_TEST_MESSAGES 1
53 <depend>isdnnet</depend>
54 <depend>misdn</depend>
55 <depend>suppserv</depend>
56 <support_level>extended</support_level>
60 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
63 #include <sys/socket.h>
65 #include <arpa/inet.h>
67 #include <sys/ioctl.h>
70 #include <semaphore.h>
74 #include "asterisk/channel.h"
75 #include "asterisk/config.h"
76 #include "asterisk/module.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/io.h"
79 #include "asterisk/frame.h"
80 #include "asterisk/translate.h"
81 #include "asterisk/cli.h"
82 #include "asterisk/musiconhold.h"
83 #include "asterisk/dsp.h"
84 #include "asterisk/file.h"
85 #include "asterisk/callerid.h"
86 #include "asterisk/indications.h"
87 #include "asterisk/app.h"
88 #include "asterisk/features.h"
89 #include "asterisk/term.h"
90 #include "asterisk/sched.h"
91 #include "asterisk/stringfields.h"
92 #include "asterisk/abstract_jb.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/format.h"
95 #include "asterisk/format_cap.h"
97 #include "chan_misdn_config.h"
100 static char global_tracefile[BUFFERSIZE + 1];
102 static int g_config_initialized = 0;
116 /*! \brief allocates the jb-structure and initialize the elements */
117 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
119 /*! \brief frees the data and destroys the given jitterbuffer struct */
120 void misdn_jb_destroy(struct misdn_jb *jb);
122 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
123 error (buffer overrun). */
124 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
126 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
127 available data is returned and the return value indicates the number
129 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
131 static char *complete_ch(struct ast_cli_args *a);
132 static char *complete_debug_port(struct ast_cli_args *a);
133 static char *complete_show_config(struct ast_cli_args *a);
135 /* BEGIN: chan_misdn.h */
137 #if defined(AST_MISDN_ENHANCEMENTS)
139 * This timeout duration is to clean up any call completion records that
140 * are forgotten about by the switch.
142 #define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60) /* seconds */
144 #define MISDN_CC_REQUEST_WAIT_MAX 5 /* seconds */
147 * \brief Caller that initialized call completion services
150 * This data is the payload for a datastore that is put on the channel that
151 * initializes call completion services. This datastore is set to be inherited
152 * by the outbound mISDN channel. When one of these channels hangs up, the
153 * channel pointer will be set to NULL. That way, we can ensure that we do not
154 * touch this channel after it gets destroyed.
156 struct misdn_cc_caller {
157 /*! \brief The channel that initialized call completion services */
158 struct ast_channel *chan;
161 struct misdn_cc_notify {
162 /*! \brief Dialplan: Notify extension priority */
165 /*! \brief Dialplan: Notify extension context */
166 char context[AST_MAX_CONTEXT];
168 /*! \brief Dialplan: Notify extension number (User-A) */
169 char exten[AST_MAX_EXTENSION];
172 /*! \brief mISDN call completion record */
173 struct misdn_cc_record {
174 /*! \brief Call completion record linked list */
175 AST_LIST_ENTRY(misdn_cc_record) list;
177 /*! \brief Time the record was created. */
180 /*! \brief MISDN_CC_RECORD_ID value */
184 * \brief Logical Layer 1 port associated with this
185 * call completion record
189 /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
192 /*! \brief Mode specific parameters */
194 /*! \brief point-to-point specific parameters. */
197 * \brief Call-completion signaling link.
198 * NULL if signaling link not established.
200 struct misdn_bchannel *bc;
203 * \brief TRUE if we requested the request retention option
206 int requested_retention;
209 * \brief TRUE if the request retention option is enabled.
211 int retention_enabled;
214 /*! \brief point-to-multi-point specific parameters. */
216 /*! \brief CallLinkageID (valid when port determined) */
219 /*! \breif CCBSReference (valid when activated is TRUE) */
222 /*! \brief globalRecall(0), specificRecall(1) */
227 /*! \brief TRUE if call completion activated */
230 /*! \brief Outstanding message ID (valid when outstanding_message) */
233 /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
234 int outstanding_message;
236 /*! \brief TRUE if activation has been requested */
237 int activation_requested;
240 * \brief TRUE if User-A is free
241 * \note PTMP - Used to answer CCBSStatusRequest.
242 * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
246 /*! \brief Error code received from last outstanding message. */
247 enum FacErrorCode error_code;
249 /*! \brief Reject code received from last outstanding message. */
250 enum FacRejectCode reject_code;
253 * \brief Saved struct misdn_bchannel call information when
254 * attempted to call User-B
257 /*! \brief User-A caller id information */
258 struct misdn_party_id caller;
260 /*! \brief User-B number information */
261 struct misdn_party_dialing dialed;
263 /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
264 struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
266 /*! \brief SETUP message bearer capability field code value */
269 /*! \brief TRUE if call made in digital HDLC mode */
273 /*! \brief Dialplan location to indicate User-B free and User-A is free */
274 struct misdn_cc_notify remote_user_free;
276 /*! \brief Dialplan location to indicate User-B free and User-A is busy */
277 struct misdn_cc_notify b_free;
280 /*! \brief mISDN call completion record database */
281 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
282 /*! \brief Next call completion record ID to use */
283 static __u16 misdn_cc_record_id;
284 /*! \brief Next invoke ID to use */
285 static __s16 misdn_invoke_id;
287 static const char misdn_no_response_from_network[] = "No response from network";
288 static const char misdn_cc_record_not_found[] = "Call completion record not found";
290 /* mISDN channel variable names */
291 #define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
292 #define MISDN_CC_STATUS "MISDN_CC_STATUS"
293 #define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
294 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
296 static ast_mutex_t release_lock;
298 enum misdn_chan_state {
299 MISDN_NOTHING = 0, /*!< at beginning */
300 MISDN_WAITING4DIGS, /*!< when waiting for info */
301 MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
302 MISDN_INCOMING_SETUP, /*!< for incoming setup */
303 MISDN_DIALING, /*!< when pbx_start */
304 MISDN_PROGRESS, /*!< we have progress */
305 MISDN_PROCEEDING, /*!< we have progress */
306 MISDN_CALLING, /*!< when misdn_call is called */
307 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
308 MISDN_ALERTING, /*!< when Alerting */
309 MISDN_BUSY, /*!< when BUSY */
310 MISDN_CONNECTED, /*!< when connected */
311 MISDN_DISCONNECTED, /*!< when connected */
312 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
315 /*! Asterisk created the channel (outgoing call) */
317 /*! mISDN created the channel (incoming call) */
320 enum misdn_hold_state {
321 MISDN_HOLD_IDLE, /*!< HOLD not active */
322 MISDN_HOLD_ACTIVE, /*!< Call is held */
323 MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
324 MISDN_HOLD_DISCONNECT, /*!< Held call is being disconnected */
328 * \brief Call HOLD state.
330 enum misdn_hold_state state;
332 * \brief Logical port the channel call record is HELD on
333 * because the B channel is no longer associated.
338 * \brief Original B channel number the HELD call was using.
339 * \note Used only for debug display messages.
344 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
345 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
348 * \brief Channel call record structure
352 * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
354 char allowed_bearers[BUFFERSIZE + 1];
357 * \brief State of the channel
359 enum misdn_chan_state state;
362 * \brief TRUE if a hangup needs to be queued
363 * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
365 int need_queue_hangup;
368 * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
373 * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
378 * \brief Who originally created this channel. ORG_AST or ORG_MISDN
383 * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
384 * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
386 int noautorespond_on_setup;
388 int norxtone; /*!< Boolean assigned values but the value is not used. */
391 * \brief TRUE if we are not to generate tones (Playtones)
396 * \brief TRUE if echo canceller is enabled. Value is toggled.
401 * \brief TRUE if you want to send Tone Indications to an incoming
402 * ISDN channel on a TE Port.
403 * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
405 int incoming_early_audio;
408 * \brief TRUE if DTMF digits are to be passed inband only.
409 * \note It is settable by the misdn_set_opt() application.
414 * \brief Pipe file descriptor handles array.
415 * Read from pipe[0], write to pipe[1]
420 * \brief Read buffer for inbound audio from pipe[0]
422 char ast_rd_buf[4096];
425 * \brief Inbound audio frame returned by misdn_read().
427 struct ast_frame frame;
430 * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
431 * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
432 * \note It is settable by the misdn_set_opt() application.
437 * \brief Number of seconds to detect a Fax machine when detection enabled.
438 * \note 0 disables the timeout.
439 * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
441 int faxdetect_timeout;
444 * \brief Starting time of fax detection with timeout when nonzero.
446 struct timeval faxdetect_tv;
449 * \brief TRUE if a fax has been detected.
454 * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
455 * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
460 * \brief Jitterbuffer length
461 * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
466 * \brief Jitterbuffer upper threshold
467 * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
469 int jb_upper_threshold;
472 * \brief Allocated jitterbuffer controller
473 * \note misdn_jb_init() creates the jitterbuffer.
474 * \note Must use misdn_jb_destroy() to clean up.
479 * \brief Allocated DSP controller
480 * \note ast_dsp_new() creates the DSP controller.
481 * \note Must use ast_dsp_free() to clean up.
486 * \brief Associated Asterisk channel structure.
488 struct ast_channel * ast;
491 * \brief Associated B channel structure.
493 struct misdn_bchannel *bc;
495 #if defined(AST_MISDN_ENHANCEMENTS)
497 * \brief Peer channel for which call completion was initialized.
499 struct misdn_cc_caller *peer;
501 /*! \brief Associated call completion record ID (-1 if not associated) */
503 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
506 * \brief HELD channel call information
508 struct hold_info hold;
511 * \brief From associated B channel: Layer 3 process ID
512 * \note Used to find the HELD channel call record when retrieving a call.
517 * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
518 * \note Used only for debug display messages.
523 * \brief Incoming call dialplan context identifier.
524 * \note The "context" string read in from /etc/asterisk/misdn.conf
526 char context[AST_MAX_CONTEXT];
529 * \brief The configured music-on-hold class to use for this call.
530 * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
532 char mohinterpret[MAX_MUSICCLASS];
535 * \brief Number of outgoing audio frames dropped since last debug gripe message.
537 int dropped_frame_cnt;
540 * \brief TRUE if we must do the ringback tones.
541 * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
546 * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
547 * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
552 * \brief Tone zone sound used for dialtone generation.
553 * \note Used as a boolean. Non-NULL to prod generation if enabled.
555 struct ast_tone_zone_sound *ts;
558 * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
559 * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
564 * \brief Overlap dialing timeout Task ID. -1 if not running.
566 int overlap_dial_task;
569 * \brief overlap_tv access lock.
571 ast_mutex_t overlap_tv_lock;
574 * \brief Overlap timer start time. Timer restarted for every digit received.
576 struct timeval overlap_tv;
579 * \brief Next channel call record in the list.
581 struct chan_list *next;
588 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
589 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
590 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
596 struct robin_list *next;
597 struct robin_list *prev;
599 static struct robin_list *robin = NULL;
602 static void free_robin_list(void)
604 struct robin_list *r;
605 struct robin_list *next;
607 for (r = robin, robin = NULL; r; r = next) {
614 static struct robin_list *get_robin_position(char *group)
616 struct robin_list *new;
617 struct robin_list *iter = robin;
618 for (; iter; iter = iter->next) {
619 if (!strcasecmp(iter->group, group)) {
623 new = ast_calloc(1, sizeof(*new));
627 new->group = ast_strdup(group);
642 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
643 static struct ast_sched_context *misdn_tasks = NULL;
644 static pthread_t misdn_tasks_thread;
646 static int *misdn_ports;
648 static void chan_misdn_log(int level, int port, char *tmpl, ...)
649 __attribute__((format(printf, 3, 4)));
651 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);
652 static void send_digit_to_chan(struct chan_list *cl, char digit);
654 static int pbx_start_chan(struct chan_list *ch);
656 #define MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast)
657 #define MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value)
659 #include "asterisk/strings.h"
661 /* #define MISDN_DEBUG 1 */
663 static const char misdn_type[] = "mISDN";
665 static int tracing = 0;
667 /*! \brief Only alaw and mulaw is allowed for now */
668 static struct ast_format prefformat; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
670 static int *misdn_debug;
671 static int *misdn_debug_only;
672 static int max_ports;
674 static int *misdn_in_calls;
675 static int *misdn_out_calls;
678 * \brief Global channel call record list head.
680 static struct chan_list *cl_te=NULL;
681 static ast_mutex_t cl_te_lock;
683 static enum event_response_e
684 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
686 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
688 static void cl_queue_chan(struct chan_list *chan);
690 static int dialtone_indicate(struct chan_list *cl);
691 static void hanguptone_indicate(struct chan_list *cl);
692 static int stop_indicate(struct chan_list *cl);
694 static int start_bc_tones(struct chan_list *cl);
695 static int stop_bc_tones(struct chan_list *cl);
696 static void release_chan_early(struct chan_list *ch);
697 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
699 #if defined(AST_MISDN_ENHANCEMENTS)
700 static const char misdn_command_name[] = "misdn_command";
701 static int misdn_command_exec(struct ast_channel *chan, const char *data);
702 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
703 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
704 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
705 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
707 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
709 void debug_numtype(int port, int numtype, char *type);
711 int add_out_calls(int port);
712 int add_in_calls(int port);
716 static int update_pipeline_config(struct misdn_bchannel *bc);
718 static int update_ec_config(struct misdn_bchannel *bc);
723 /*************** Helpers *****************/
725 static int misdn_chan_is_valid(struct chan_list *ch)
727 struct chan_list *list;
729 ast_mutex_lock(&cl_te_lock);
730 for (list = cl_te; list; list = list->next) {
732 ast_mutex_unlock(&cl_te_lock);
736 ast_mutex_unlock(&cl_te_lock);
741 /*! Returns a reference to the found chan_list. */
742 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
744 struct chan_list *tmp;
746 ast_mutex_lock(&cl_te_lock);
747 for (tmp = cl_te; tmp; tmp = tmp->next) {
748 if (tmp->ast == ast) {
749 chan_list_ref(tmp, "Found chan_list by ast");
750 ast_mutex_unlock(&cl_te_lock);
754 ast_mutex_unlock(&cl_te_lock);
759 /*! Returns a reference to the found chan_list. */
760 static struct chan_list *get_chan_by_ast_name(const char *name)
762 struct chan_list *tmp;
764 ast_mutex_lock(&cl_te_lock);
765 for (tmp = cl_te; tmp; tmp = tmp->next) {
766 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
767 chan_list_ref(tmp, "Found chan_list by ast name");
768 ast_mutex_unlock(&cl_te_lock);
772 ast_mutex_unlock(&cl_te_lock);
777 #if defined(AST_MISDN_ENHANCEMENTS)
780 * \brief Destroy the misdn_cc_ds_info datastore payload
782 * \param[in] data the datastore payload, a reference to an misdn_cc_caller
785 * Since the payload is a reference to an astobj2 object, we just decrement its
786 * reference count. Before doing so, we NULL out the channel pointer inside of
787 * the misdn_cc_caller instance. This function will be called in one of two
788 * cases. In both cases, we no longer need the channel pointer:
790 * - The original channel that initialized call completion services, the same
791 * channel that is stored here, has been destroyed early. This could happen
792 * if it transferred the mISDN channel, for example.
794 * - The mISDN channel that had this datastore inherited on to it is now being
795 * destroyed. If this is the case, then the call completion events have
796 * already occurred and the appropriate channel variables have already been
797 * set on the original channel that requested call completion services.
801 static void misdn_cc_ds_destroy(void *data)
803 struct misdn_cc_caller *cc_caller = data;
806 cc_caller->chan = NULL;
807 ao2_unlock(cc_caller);
809 ao2_ref(cc_caller, -1);
811 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
813 #if defined(AST_MISDN_ENHANCEMENTS)
816 * \brief Duplicate the misdn_cc_ds_info datastore payload
818 * \param[in] data the datastore payload, a reference to an misdn_cc_caller
821 * All we need to do is bump the reference count and return the same instance.
823 * \return A reference to an instance of a misdn_cc_caller
825 static void *misdn_cc_ds_duplicate(void *data)
827 struct misdn_cc_caller *cc_caller = data;
829 ao2_ref(cc_caller, +1);
833 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
835 #if defined(AST_MISDN_ENHANCEMENTS)
836 static const struct ast_datastore_info misdn_cc_ds_info = {
838 .destroy = misdn_cc_ds_destroy,
839 .duplicate = misdn_cc_ds_duplicate,
841 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
843 #if defined(AST_MISDN_ENHANCEMENTS)
846 * \brief Set a channel var on the peer channel for call completion services
848 * \param[in] peer The peer that initialized call completion services
849 * \param[in] var The variable name to set
850 * \param[in] value The variable value to set
852 * This function may be called from outside of the channel thread. It handles
853 * the fact that the peer channel may be hung up and destroyed at any time.
857 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
862 /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
863 while (peer->chan && ast_channel_trylock(peer->chan)) {
870 pbx_builtin_setvar_helper(peer->chan, var, value);
871 ast_channel_unlock(peer->chan);
876 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
878 #if defined(AST_MISDN_ENHANCEMENTS)
881 * \brief Get a reference to the CC caller if it exists
883 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
885 struct ast_datastore *datastore;
886 struct misdn_cc_caller *cc_caller;
888 ast_channel_lock(chan);
890 if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
891 ast_channel_unlock(chan);
895 ao2_ref(datastore->data, +1);
896 cc_caller = datastore->data;
898 ast_channel_unlock(chan);
902 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
904 #if defined(AST_MISDN_ENHANCEMENTS)
907 * \brief Find the call completion record given the record id.
911 * \retval pointer to found call completion record
912 * \retval NULL if not found
914 * \note Assumes the misdn_cc_records_db lock is already obtained.
916 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
918 struct misdn_cc_record *current;
920 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
921 if (current->record_id == record_id) {
922 /* Found the record */
929 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
931 #if defined(AST_MISDN_ENHANCEMENTS)
934 * \brief Find the call completion record given the port and call linkage id.
936 * \param port Logical port number
937 * \param linkage_id Call linkage ID number from switch.
939 * \retval pointer to found call completion record
940 * \retval NULL if not found
942 * \note Assumes the misdn_cc_records_db lock is already obtained.
944 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
946 struct misdn_cc_record *current;
948 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
949 if (current->port == port
951 && current->mode.ptmp.linkage_id == linkage_id) {
952 /* Found the record */
959 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
961 #if defined(AST_MISDN_ENHANCEMENTS)
964 * \brief Find the call completion record given the port and outstanding invocation id.
966 * \param port Logical port number
967 * \param invoke_id Outstanding message invocation ID number.
969 * \retval pointer to found call completion record
970 * \retval NULL if not found
972 * \note Assumes the misdn_cc_records_db lock is already obtained.
974 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
976 struct misdn_cc_record *current;
978 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
979 if (current->outstanding_message
980 && current->invoke_id == invoke_id
981 && current->port == port) {
982 /* Found the record */
989 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
991 #if defined(AST_MISDN_ENHANCEMENTS)
994 * \brief Find the call completion record given the port and CCBS reference id.
996 * \param port Logical port number
997 * \param reference_id CCBS reference ID number from switch.
999 * \retval pointer to found call completion record
1000 * \retval NULL if not found
1002 * \note Assumes the misdn_cc_records_db lock is already obtained.
1004 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1006 struct misdn_cc_record *current;
1008 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1009 if (current->activated
1010 && current->port == port
1012 && current->mode.ptmp.reference_id == reference_id) {
1013 /* Found the record */
1020 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1022 #if defined(AST_MISDN_ENHANCEMENTS)
1025 * \brief Find the call completion record given the B channel pointer
1027 * \param bc B channel control structure pointer.
1029 * \retval pointer to found call completion record
1030 * \retval NULL if not found
1032 * \note Assumes the misdn_cc_records_db lock is already obtained.
1034 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1036 struct misdn_cc_record *current;
1039 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1041 && current->mode.ptp.bc == bc) {
1042 /* Found the record */
1052 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1054 #if defined(AST_MISDN_ENHANCEMENTS)
1057 * \brief Delete the given call completion record
1059 * \param doomed Call completion record to destroy
1063 * \note Assumes the misdn_cc_records_db lock is already obtained.
1065 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1067 struct misdn_cc_record *current;
1069 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1070 if (current == doomed) {
1071 AST_LIST_REMOVE_CURRENT(list);
1076 AST_LIST_TRAVERSE_SAFE_END;
1078 /* The doomed node is not in the call completion database */
1080 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1082 #if defined(AST_MISDN_ENHANCEMENTS)
1085 * \brief Delete all old call completion records
1089 * \note Assumes the misdn_cc_records_db lock is already obtained.
1091 static void misdn_cc_remove_old(void)
1093 struct misdn_cc_record *current;
1097 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1098 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1099 if (current->ptp && current->mode.ptp.bc) {
1100 /* Close the old call-completion signaling link */
1101 current->mode.ptp.bc->fac_out.Function = Fac_None;
1102 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1103 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1106 /* Remove the old call completion record */
1107 AST_LIST_REMOVE_CURRENT(list);
1111 AST_LIST_TRAVERSE_SAFE_END;
1113 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1115 #if defined(AST_MISDN_ENHANCEMENTS)
1118 * \brief Allocate the next record id.
1120 * \retval New record id on success.
1121 * \retval -1 on error.
1123 * \note Assumes the misdn_cc_records_db lock is already obtained.
1125 static long misdn_cc_record_id_new(void)
1130 record_id = ++misdn_cc_record_id;
1131 first_id = record_id;
1132 while (misdn_cc_find_by_id(record_id)) {
1133 record_id = ++misdn_cc_record_id;
1134 if (record_id == first_id) {
1136 * We have a resource leak.
1137 * We should never need to allocate 64k records.
1139 chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1147 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1149 #if defined(AST_MISDN_ENHANCEMENTS)
1152 * \brief Create a new call completion record
1154 * \retval pointer to new call completion record
1155 * \retval NULL if failed
1157 * \note Assumes the misdn_cc_records_db lock is already obtained.
1159 static struct misdn_cc_record *misdn_cc_new(void)
1161 struct misdn_cc_record *cc_record;
1164 misdn_cc_remove_old();
1166 cc_record = ast_calloc(1, sizeof(*cc_record));
1168 record_id = misdn_cc_record_id_new();
1169 if (record_id < 0) {
1170 ast_free(cc_record);
1174 /* Initialize the new record */
1175 cc_record->record_id = record_id;
1176 cc_record->port = -1;/* Invalid port so it will never be found this way */
1177 cc_record->invoke_id = ++misdn_invoke_id;
1178 cc_record->party_a_free = 1;/* Default User-A as free */
1179 cc_record->error_code = FacError_None;
1180 cc_record->reject_code = FacReject_None;
1181 cc_record->time_created = time(NULL);
1183 /* Insert the new record into the database */
1184 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1188 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1190 #if defined(AST_MISDN_ENHANCEMENTS)
1193 * \brief Destroy the call completion record database
1197 static void misdn_cc_destroy(void)
1199 struct misdn_cc_record *current;
1201 while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1202 /* Do a misdn_cc_delete(current) inline */
1206 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1208 #if defined(AST_MISDN_ENHANCEMENTS)
1211 * \brief Initialize the call completion record database
1215 static void misdn_cc_init(void)
1217 misdn_cc_record_id = 0;
1219 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1221 #if defined(AST_MISDN_ENHANCEMENTS)
1224 * \brief Check the status of an outstanding invocation request.
1226 * \param data Points to an integer containing the call completion record id.
1228 * \retval 0 if got a response.
1229 * \retval -1 if no response yet.
1231 static int misdn_cc_response_check(void *data)
1234 struct misdn_cc_record *cc_record;
1236 AST_LIST_LOCK(&misdn_cc_records_db);
1237 cc_record = misdn_cc_find_by_id(*(long *) data);
1239 if (cc_record->outstanding_message) {
1245 /* No record so there is no response to check. */
1248 AST_LIST_UNLOCK(&misdn_cc_records_db);
1250 return not_responded;
1252 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1254 #if defined(AST_MISDN_ENHANCEMENTS)
1257 * \brief Wait for a response from the switch for an outstanding
1258 * invocation request.
1260 * \param chan Asterisk channel to operate upon.
1261 * \param wait_seconds Number of seconds to wait
1262 * \param record_id Call completion record ID.
1266 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1270 for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1271 /* Sleep in 500 ms increments */
1272 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1273 /* We got hung up or our response came in. */
1278 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1280 #if defined(AST_MISDN_ENHANCEMENTS)
1283 * \brief Convert the mISDN reject code to a string
1285 * \param code mISDN reject code.
1287 * \return The mISDN reject code as a string
1289 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1291 static const struct {
1292 enum FacRejectCode code;
1296 { FacReject_None, "No reject occurred" },
1297 { FacReject_Unknown, "Unknown reject code" },
1299 { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
1300 { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
1301 { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
1303 { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
1304 { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
1305 { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
1306 { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
1307 { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
1308 { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
1309 { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
1310 { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
1312 { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
1313 { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
1314 { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
1316 { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
1317 { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
1318 { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
1319 { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
1320 { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
1326 for (index = 0; index < ARRAY_LEN(arr); ++index) {
1327 if (arr[index].code == code) {
1328 return arr[index].name;
1334 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1336 #if defined(AST_MISDN_ENHANCEMENTS)
1339 * \brief Convert the mISDN error code to a string
1341 * \param code mISDN error code.
1343 * \return The mISDN error code as a string
1345 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1347 static const struct {
1348 enum FacErrorCode code;
1352 { FacError_None, "No error occurred" },
1353 { FacError_Unknown, "Unknown OID error code" },
1355 { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
1356 { FacError_Gen_NotAvailable, "General: Not Available" },
1357 { FacError_Gen_NotImplemented, "General: Not Implemented" },
1358 { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
1359 { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
1360 { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
1361 { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
1362 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1363 { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
1365 { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
1366 { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
1367 { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
1368 { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
1369 { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
1370 { FacError_Div_NotActivated, "Diversion: Not Activated" },
1371 { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
1373 { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
1375 { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
1376 { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
1377 { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
1378 { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
1379 { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
1380 { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
1381 { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
1382 { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
1383 { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
1385 { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
1386 { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
1388 { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
1394 for (index = 0; index < ARRAY_LEN(arr); ++index) {
1395 if (arr[index].code == code) {
1396 return arr[index].name;
1402 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1404 #if defined(AST_MISDN_ENHANCEMENTS)
1407 * \brief Convert mISDN redirecting reason to diversion reason.
1409 * \param reason mISDN redirecting reason code.
1411 * \return Supported diversion reason code.
1413 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1415 unsigned diversion_reason;
1418 case mISDN_REDIRECTING_REASON_CALL_FWD:
1419 diversion_reason = 1;/* cfu */
1421 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
1422 diversion_reason = 2;/* cfb */
1424 case mISDN_REDIRECTING_REASON_NO_REPLY:
1425 diversion_reason = 3;/* cfnr */
1428 diversion_reason = 0;/* unknown */
1432 return diversion_reason;
1434 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1436 #if defined(AST_MISDN_ENHANCEMENTS)
1439 * \brief Convert diversion reason to mISDN redirecting reason
1441 * \param diversion_reason Diversion reason to convert
1443 * \return Supported redirecting reason code.
1445 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1447 enum mISDN_REDIRECTING_REASON reason;
1449 switch (diversion_reason) {
1451 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
1454 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
1457 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
1460 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
1466 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1468 #if defined(AST_MISDN_ENHANCEMENTS)
1471 * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1473 * \param presentation mISDN presentation to convert
1474 * \param number_present TRUE if the number is present
1476 * \return PresentedNumberUnscreened type
1478 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1482 switch (presentation) {
1483 case 0:/* allowed */
1484 if (number_present) {
1485 type = 0;/* presentationAllowedNumber */
1487 type = 2;/* numberNotAvailableDueToInterworking */
1490 case 1:/* restricted */
1491 if (number_present) {
1492 type = 3;/* presentationRestrictedNumber */
1494 type = 1;/* presentationRestricted */
1498 type = 2;/* numberNotAvailableDueToInterworking */
1504 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1506 #if defined(AST_MISDN_ENHANCEMENTS)
1509 * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1511 * \param type PresentedNumberUnscreened type
1513 * \return mISDN presentation
1515 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1521 case 0:/* presentationAllowedNumber */
1522 presentation = 0;/* allowed */
1525 case 1:/* presentationRestricted */
1526 case 3:/* presentationRestrictedNumber */
1527 presentation = 1;/* restricted */
1530 case 2:/* numberNotAvailableDueToInterworking */
1531 presentation = 2;/* unavailable */
1535 return presentation;
1537 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1539 #if defined(AST_MISDN_ENHANCEMENTS)
1542 * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1544 * \param number_plan mISDN numbering plan
1546 * \return PartyNumber numbering plan
1548 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1550 unsigned party_plan;
1552 switch (number_plan) {
1554 case NUMPLAN_UNKNOWN:
1555 party_plan = 0;/* unknown */
1559 party_plan = 1;/* public */
1563 party_plan = 3;/* data */
1567 party_plan = 4;/* telex */
1570 case NUMPLAN_NATIONAL:
1571 party_plan = 8;/* nationalStandard */
1574 case NUMPLAN_PRIVATE:
1575 party_plan = 5;/* private */
1581 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1583 #if defined(AST_MISDN_ENHANCEMENTS)
1586 * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1588 * \param party_plan PartyNumber numbering plan
1590 * \return mISDN numbering plan
1592 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1594 enum mISDN_NUMBER_PLAN number_plan;
1596 switch (party_plan) {
1598 case 0:/* unknown */
1599 number_plan = NUMPLAN_UNKNOWN;
1602 number_plan = NUMPLAN_ISDN;
1605 number_plan = NUMPLAN_DATA;
1608 number_plan = NUMPLAN_TELEX;
1610 case 8:/* nationalStandard */
1611 number_plan = NUMPLAN_NATIONAL;
1613 case 5:/* private */
1614 number_plan = NUMPLAN_PRIVATE;
1620 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1622 #if defined(AST_MISDN_ENHANCEMENTS)
1625 * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1627 * \param ton mISDN type-of-number
1629 * \return PartyNumber public type-of-number
1631 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1637 case NUMTYPE_UNKNOWN:
1638 party_ton = 0;/* unknown */
1641 case NUMTYPE_INTERNATIONAL:
1642 party_ton = 1;/* internationalNumber */
1645 case NUMTYPE_NATIONAL:
1646 party_ton = 2;/* nationalNumber */
1649 case NUMTYPE_NETWORK_SPECIFIC:
1650 party_ton = 3;/* networkSpecificNumber */
1653 case NUMTYPE_SUBSCRIBER:
1654 party_ton = 4;/* subscriberNumber */
1657 case NUMTYPE_ABBREVIATED:
1658 party_ton = 6;/* abbreviatedNumber */
1664 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1666 #if defined(AST_MISDN_ENHANCEMENTS)
1669 * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1671 * \param party_ton PartyNumber public type-of-number
1673 * \return mISDN type-of-number
1675 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1677 enum mISDN_NUMBER_TYPE ton;
1679 switch (party_ton) {
1681 case 0:/* unknown */
1682 ton = NUMTYPE_UNKNOWN;
1685 case 1:/* internationalNumber */
1686 ton = NUMTYPE_INTERNATIONAL;
1689 case 2:/* nationalNumber */
1690 ton = NUMTYPE_NATIONAL;
1693 case 3:/* networkSpecificNumber */
1694 ton = NUMTYPE_NETWORK_SPECIFIC;
1697 case 4:/* subscriberNumber */
1698 ton = NUMTYPE_SUBSCRIBER;
1701 case 6:/* abbreviatedNumber */
1702 ton = NUMTYPE_ABBREVIATED;
1708 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1710 #if defined(AST_MISDN_ENHANCEMENTS)
1713 * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1715 * \param ton mISDN type-of-number
1717 * \return PartyNumber private type-of-number
1719 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1725 case NUMTYPE_UNKNOWN:
1726 party_ton = 0;/* unknown */
1729 case NUMTYPE_INTERNATIONAL:
1730 party_ton = 1;/* level2RegionalNumber */
1733 case NUMTYPE_NATIONAL:
1734 party_ton = 2;/* level1RegionalNumber */
1737 case NUMTYPE_NETWORK_SPECIFIC:
1738 party_ton = 3;/* pTNSpecificNumber */
1741 case NUMTYPE_SUBSCRIBER:
1742 party_ton = 4;/* localNumber */
1745 case NUMTYPE_ABBREVIATED:
1746 party_ton = 6;/* abbreviatedNumber */
1752 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1754 #if defined(AST_MISDN_ENHANCEMENTS)
1757 * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1759 * \param party_ton PartyNumber private type-of-number
1761 * \return mISDN type-of-number
1763 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1765 enum mISDN_NUMBER_TYPE ton;
1767 switch (party_ton) {
1769 case 0:/* unknown */
1770 ton = NUMTYPE_UNKNOWN;
1773 case 1:/* level2RegionalNumber */
1774 ton = NUMTYPE_INTERNATIONAL;
1777 case 2:/* level1RegionalNumber */
1778 ton = NUMTYPE_NATIONAL;
1781 case 3:/* pTNSpecificNumber */
1782 ton = NUMTYPE_NETWORK_SPECIFIC;
1785 case 4:/* localNumber */
1786 ton = NUMTYPE_SUBSCRIBER;
1789 case 6:/* abbreviatedNumber */
1790 ton = NUMTYPE_ABBREVIATED;
1796 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
1800 * \brief Convert the mISDN type of number code to a string
1802 * \param number_type mISDN type of number code.
1804 * \return The mISDN type of number code as a string
1806 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1810 switch (number_type) {
1812 case NUMTYPE_UNKNOWN:
1816 case NUMTYPE_INTERNATIONAL:
1817 str = "International";
1820 case NUMTYPE_NATIONAL:
1824 case NUMTYPE_NETWORK_SPECIFIC:
1825 str = "Network Specific";
1828 case NUMTYPE_SUBSCRIBER:
1832 case NUMTYPE_ABBREVIATED:
1833 str = "Abbreviated";
1842 * \brief Convert the mISDN type of number code to Asterisk type of number code
1844 * \param number_type mISDN type of number code.
1846 * \return Asterisk type of number code
1848 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1850 int ast_number_type;
1852 switch (number_type) {
1854 case NUMTYPE_UNKNOWN:
1855 ast_number_type = NUMTYPE_UNKNOWN << 4;
1858 case NUMTYPE_INTERNATIONAL:
1859 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1862 case NUMTYPE_NATIONAL:
1863 ast_number_type = NUMTYPE_NATIONAL << 4;
1866 case NUMTYPE_NETWORK_SPECIFIC:
1867 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1870 case NUMTYPE_SUBSCRIBER:
1871 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1874 case NUMTYPE_ABBREVIATED:
1875 ast_number_type = NUMTYPE_ABBREVIATED << 4;
1879 return ast_number_type;
1884 * \brief Convert the Asterisk type of number code to mISDN type of number code
1886 * \param ast_number_type Asterisk type of number code.
1888 * \return mISDN type of number code
1890 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1892 enum mISDN_NUMBER_TYPE number_type;
1894 switch ((ast_number_type >> 4) & 0x07) {
1896 case NUMTYPE_UNKNOWN:
1897 number_type = NUMTYPE_UNKNOWN;
1900 case NUMTYPE_INTERNATIONAL:
1901 number_type = NUMTYPE_INTERNATIONAL;
1904 case NUMTYPE_NATIONAL:
1905 number_type = NUMTYPE_NATIONAL;
1908 case NUMTYPE_NETWORK_SPECIFIC:
1909 number_type = NUMTYPE_NETWORK_SPECIFIC;
1912 case NUMTYPE_SUBSCRIBER:
1913 number_type = NUMTYPE_SUBSCRIBER;
1916 case NUMTYPE_ABBREVIATED:
1917 number_type = NUMTYPE_ABBREVIATED;
1926 * \brief Convert the mISDN numbering plan code to a string
1928 * \param number_plan mISDN numbering plan code.
1930 * \return The mISDN numbering plan code as a string
1932 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1936 switch (number_plan) {
1938 case NUMPLAN_UNKNOWN:
1954 case NUMPLAN_NATIONAL:
1958 case NUMPLAN_PRIVATE:
1968 * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1970 * \param number_plan mISDN numbering plan code.
1972 * \return Asterisk numbering plan code
1974 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
1976 int ast_number_plan;
1978 switch (number_plan) {
1980 case NUMPLAN_UNKNOWN:
1981 ast_number_plan = NUMPLAN_UNKNOWN;
1985 ast_number_plan = NUMPLAN_ISDN;
1989 ast_number_plan = NUMPLAN_DATA;
1993 ast_number_plan = NUMPLAN_TELEX;
1996 case NUMPLAN_NATIONAL:
1997 ast_number_plan = NUMPLAN_NATIONAL;
2000 case NUMPLAN_PRIVATE:
2001 ast_number_plan = NUMPLAN_PRIVATE;
2005 return ast_number_plan;
2010 * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2012 * \param ast_number_plan Asterisk numbering plan code.
2014 * \return mISDN numbering plan code
2016 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2018 enum mISDN_NUMBER_PLAN number_plan;
2020 switch (ast_number_plan & 0x0F) {
2022 case NUMPLAN_UNKNOWN:
2023 number_plan = NUMPLAN_UNKNOWN;
2027 number_plan = NUMPLAN_ISDN;
2031 number_plan = NUMPLAN_DATA;
2035 number_plan = NUMPLAN_TELEX;
2038 case NUMPLAN_NATIONAL:
2039 number_plan = NUMPLAN_NATIONAL;
2042 case NUMPLAN_PRIVATE:
2043 number_plan = NUMPLAN_PRIVATE;
2052 * \brief Convert the mISDN presentation code to a string
2054 * \param presentation mISDN number presentation restriction code.
2056 * \return The mISDN presentation code as a string
2058 static const char *misdn_to_str_pres(int presentation)
2062 switch (presentation) {
2072 str = "Unavailable";
2085 * \brief Convert the mISDN presentation code to Asterisk presentation code
2087 * \param presentation mISDN number presentation restriction code.
2089 * \return Asterisk presentation code
2091 static int misdn_to_ast_pres(int presentation)
2093 switch (presentation) {
2096 presentation = AST_PRES_ALLOWED;
2100 presentation = AST_PRES_RESTRICTED;
2104 presentation = AST_PRES_UNAVAILABLE;
2108 return presentation;
2113 * \brief Convert the Asterisk presentation code to mISDN presentation code
2115 * \param presentation Asterisk number presentation restriction code.
2117 * \return mISDN presentation code
2119 static int ast_to_misdn_pres(int presentation)
2121 switch (presentation & AST_PRES_RESTRICTION) {
2123 case AST_PRES_ALLOWED:
2127 case AST_PRES_RESTRICTED:
2131 case AST_PRES_UNAVAILABLE:
2136 return presentation;
2141 * \brief Convert the mISDN screening code to a string
2143 * \param screening mISDN number screening code.
2145 * \return The mISDN screening code as a string
2147 static const char *misdn_to_str_screen(int screening)
2151 switch (screening) {
2157 str = "Passed Screen";
2161 str = "Failed Screen";
2165 str = "Network Number";
2178 * \brief Convert the mISDN screening code to Asterisk screening code
2180 * \param screening mISDN number screening code.
2182 * \return Asterisk screening code
2184 static int misdn_to_ast_screen(int screening)
2186 switch (screening) {
2189 screening = AST_PRES_USER_NUMBER_UNSCREENED;
2193 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
2197 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
2201 screening = AST_PRES_NETWORK_NUMBER;
2210 * \brief Convert the Asterisk screening code to mISDN screening code
2212 * \param screening Asterisk number screening code.
2214 * \return mISDN screening code
2216 static int ast_to_misdn_screen(int screening)
2218 switch (screening & AST_PRES_NUMBER_TYPE) {
2220 case AST_PRES_USER_NUMBER_UNSCREENED:
2224 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
2228 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
2232 case AST_PRES_NETWORK_NUMBER:
2242 * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2244 * \param ast Asterisk redirecting reason code.
2246 * \return mISDN reason code
2248 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
2252 static const struct misdn_reasons {
2253 enum AST_REDIRECTING_REASON ast;
2254 enum mISDN_REDIRECTING_REASON q931;
2255 } misdn_reason_table[] = {
2257 { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
2258 { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
2259 { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
2260 { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
2261 { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
2262 { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2263 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2264 { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
2265 { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
2266 { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
2267 { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
2268 { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
2272 for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2273 if (misdn_reason_table[index].ast == ast) {
2274 return misdn_reason_table[index].q931;
2277 return mISDN_REDIRECTING_REASON_UNKNOWN;
2282 * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2284 * \param q931 mISDN redirecting reason code.
2286 * \return Asterisk redirecting reason code
2288 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
2290 enum AST_REDIRECTING_REASON ast;
2294 case mISDN_REDIRECTING_REASON_UNKNOWN:
2295 ast = AST_REDIRECTING_REASON_UNKNOWN;
2298 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
2299 ast = AST_REDIRECTING_REASON_USER_BUSY;
2302 case mISDN_REDIRECTING_REASON_NO_REPLY:
2303 ast = AST_REDIRECTING_REASON_NO_ANSWER;
2306 case mISDN_REDIRECTING_REASON_DEFLECTION:
2307 ast = AST_REDIRECTING_REASON_DEFLECTION;
2310 case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
2311 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
2314 case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
2315 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
2318 case mISDN_REDIRECTING_REASON_CALL_FWD:
2319 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
2328 struct allowed_bearers {
2329 char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2330 char *display; /*!< Bearer capability displayable name */
2331 int cap; /*!< SETUP message bearer capability field code value */
2332 int deprecated; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2336 static const struct allowed_bearers allowed_bearers_array[] = {
2337 /* Name, Displayable Name Bearer Capability, Deprecated */
2338 { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
2339 { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
2340 { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2341 { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
2342 { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 }, /* Allow misspelling for backwards compatibility */
2343 { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
2347 static const char *bearer2str(int cap)
2351 for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2352 if (allowed_bearers_array[index].cap == cap) {
2353 return allowed_bearers_array[index].display;
2357 return "Unknown Bearer";
2360 #if defined(AST_MISDN_ENHANCEMENTS)
2363 * \brief Fill in facility PartyNumber information
2365 * \param party PartyNumber structure to fill in.
2366 * \param id Information to put in PartyNumber structure.
2370 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2372 ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2373 party->LengthOfNumber = strlen((char *) party->Number);
2374 party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2375 switch (party->Type) {
2377 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2379 case 5:/* private */
2380 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2383 party->TypeOfNumber = 0;/* Don't care */
2387 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2389 #if defined(AST_MISDN_ENHANCEMENTS)
2392 * \brief Extract the information from PartyNumber
2394 * \param id Where to put extracted PartyNumber information
2395 * \param party PartyNumber information to extract
2399 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2401 if (party->LengthOfNumber) {
2402 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2403 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2404 switch (party->Type) {
2406 id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2408 case 5:/* private */
2409 id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2412 id->number_type = NUMTYPE_UNKNOWN;
2416 /* Number not present */
2417 id->number_type = NUMTYPE_UNKNOWN;
2418 id->number_plan = NUMPLAN_ISDN;
2422 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2424 #if defined(AST_MISDN_ENHANCEMENTS)
2427 * \brief Fill in facility Address information
2429 * \param Address Address structure to fill in.
2430 * \param id Information to put in Address structure.
2434 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2436 misdn_PartyNumber_fill(&Address->Party, id);
2438 /* Subaddresses are not supported yet */
2439 Address->Subaddress.Length = 0;
2441 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2443 #if defined(AST_MISDN_ENHANCEMENTS)
2446 * \brief Fill in facility PresentedNumberUnscreened information
2448 * \param presented PresentedNumberUnscreened structure to fill in.
2449 * \param id Information to put in PresentedNumberUnscreened structure.
2453 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2455 presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2456 misdn_PartyNumber_fill(&presented->Unscreened, id);
2458 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2460 #if defined(AST_MISDN_ENHANCEMENTS)
2463 * \brief Extract the information from PartyNumber
2465 * \param id Where to put extracted PresentedNumberUnscreened information
2466 * \param presented PresentedNumberUnscreened information to extract
2470 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2472 id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2473 id->screening = 0;/* unscreened */
2474 switch (presented->Type) {
2475 case 0:/* presentationAllowedNumber */
2476 case 3:/* presentationRestrictedNumber */
2477 misdn_PartyNumber_extract(id, &presented->Unscreened);
2479 case 1:/* presentationRestricted */
2480 case 2:/* numberNotAvailableDueToInterworking */
2482 /* Number not present (And uninitialized so do not even look at it!) */
2483 id->number_type = NUMTYPE_UNKNOWN;
2484 id->number_plan = NUMPLAN_ISDN;
2489 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2491 #if defined(AST_MISDN_ENHANCEMENTS)
2492 static const char Level_Spacing[] = " ";/* Work for up to 10 levels */
2493 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2495 #if defined(AST_MISDN_ENHANCEMENTS)
2496 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2498 if (Party->LengthOfNumber) {
2499 const char *Spacing;
2501 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2502 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2503 Spacing, Party->Type);
2504 switch (Party->Type) {
2505 case 0: /* Unknown PartyNumber */
2506 chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
2507 Spacing, Party->Number);
2509 case 1: /* Public PartyNumber */
2510 chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
2511 Spacing, Party->TypeOfNumber, Party->Number);
2513 case 2: /* NSAP encoded PartyNumber */
2514 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2515 Spacing, Party->Number);
2517 case 3: /* Data PartyNumber (Not used) */
2518 chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
2519 Spacing, Party->Number);
2521 case 4: /* Telex PartyNumber (Not used) */
2522 chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
2523 Spacing, Party->Number);
2525 case 5: /* Private PartyNumber */
2526 chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
2527 Spacing, Party->TypeOfNumber, Party->Number);
2529 case 8: /* National Standard PartyNumber (Not used) */
2530 chan_misdn_log(1, bc->port, " -->%s National: %s\n",
2531 Spacing, Party->Number);
2538 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2540 #if defined(AST_MISDN_ENHANCEMENTS)
2541 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2543 if (Subaddress->Length) {
2544 const char *Spacing;
2546 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2547 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2548 Spacing, Subaddress->Type);
2549 switch (Subaddress->Type) {
2550 case 0: /* UserSpecified */
2551 if (Subaddress->u.UserSpecified.OddCountPresent) {
2552 chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
2553 Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2555 chan_misdn_log(1, bc->port, " -->%s User: %s\n",
2556 Spacing, Subaddress->u.UserSpecified.Information);
2560 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
2561 Spacing, Subaddress->u.Nsap);
2568 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2570 #if defined(AST_MISDN_ENHANCEMENTS)
2571 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2573 print_facility_PartyNumber(Level, &Address->Party, bc);
2574 print_facility_Subaddress(Level, &Address->Subaddress, bc);
2576 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2578 #if defined(AST_MISDN_ENHANCEMENTS)
2579 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2581 const char *Spacing;
2583 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2584 chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2585 switch (Presented->Type) {
2586 case 0: /* presentationAllowedNumber */
2587 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2588 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2590 case 1: /* presentationRestricted */
2591 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2593 case 2: /* numberNotAvailableDueToInterworking */
2594 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2596 case 3: /* presentationRestrictedNumber */
2597 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2598 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2604 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2606 #if defined(AST_MISDN_ENHANCEMENTS)
2607 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2609 const char *Spacing;
2611 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2612 chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2613 print_facility_PartyNumber(Level, &Address->Party, bc);
2614 print_facility_Subaddress(Level, &Address->Subaddress, bc);
2616 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2618 #if defined(AST_MISDN_ENHANCEMENTS)
2619 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2621 const char *Spacing;
2623 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2624 chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2625 switch (Presented->Type) {
2626 case 0: /* presentationAllowedAddress */
2627 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
2628 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2630 case 1: /* presentationRestricted */
2631 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
2633 case 2: /* numberNotAvailableDueToInterworking */
2634 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
2636 case 3: /* presentationRestrictedAddress */
2637 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
2638 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2644 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2646 #if defined(AST_MISDN_ENHANCEMENTS)
2647 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2649 const char *Spacing;
2651 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2652 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2653 if (Q931ie->Bc.Length) {
2654 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2656 if (Q931ie->Hlc.Length) {
2657 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2659 if (Q931ie->Llc.Length) {
2660 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2663 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2665 #if defined(AST_MISDN_ENHANCEMENTS)
2666 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2668 const char *Spacing;
2670 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2671 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2672 if (Q931ie->Bc.Length) {
2673 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2675 if (Q931ie->Hlc.Length) {
2676 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2678 if (Q931ie->Llc.Length) {
2679 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2681 if (Q931ie->UserInfo.Length) {
2682 chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2685 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2687 #if defined(AST_MISDN_ENHANCEMENTS)
2688 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2690 const char *Spacing;
2692 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2693 chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2694 Spacing, CallInfo->CCBSReference);
2695 chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2696 print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2697 print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2698 if (CallInfo->SubaddressOfA.Length) {
2699 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2700 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2703 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2705 #if defined(AST_MISDN_ENHANCEMENTS)
2706 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2708 const char *Spacing;
2710 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2711 if (Party->LengthOfNumber) {
2712 print_facility_PartyNumber(Level, Party, bc);
2714 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2717 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2719 #if defined(AST_MISDN_ENHANCEMENTS)
2720 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2722 const char *Spacing;
2724 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2725 chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2727 ForwardingRecord->Procedure,
2728 ForwardingRecord->BasicService);
2729 chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2730 print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2731 chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2732 print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2734 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2736 static void print_facility(const struct FacParm *fac, const const struct misdn_bchannel *bc)
2738 #if defined(AST_MISDN_ENHANCEMENTS)
2740 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
2742 switch (fac->Function) {
2743 #if defined(AST_MISDN_ENHANCEMENTS)
2744 case Fac_ActivationDiversion:
2745 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2746 fac->u.ActivationDiversion.InvokeID);
2747 switch (fac->u.ActivationDiversion.ComponentType) {
2748 case FacComponent_Invoke:
2749 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2750 fac->u.ActivationDiversion.Component.Invoke.Procedure,
2751 fac->u.ActivationDiversion.Component.Invoke.BasicService);
2752 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2753 print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2754 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2755 print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2757 case FacComponent_Result:
2758 chan_misdn_log(1, bc->port, " --> Result\n");
2764 case Fac_DeactivationDiversion:
2765 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2766 fac->u.DeactivationDiversion.InvokeID);
2767 switch (fac->u.DeactivationDiversion.ComponentType) {
2768 case FacComponent_Invoke:
2769 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2770 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2771 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2772 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2773 print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2775 case FacComponent_Result:
2776 chan_misdn_log(1, bc->port, " --> Result\n");
2782 case Fac_ActivationStatusNotificationDiv:
2783 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2784 fac->u.ActivationStatusNotificationDiv.InvokeID,
2785 fac->u.ActivationStatusNotificationDiv.Procedure,
2786 fac->u.ActivationStatusNotificationDiv.BasicService);
2787 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
2788 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2789 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2790 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2792 case Fac_DeactivationStatusNotificationDiv:
2793 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2794 fac->u.DeactivationStatusNotificationDiv.InvokeID,
2795 fac->u.DeactivationStatusNotificationDiv.Procedure,
2796 fac->u.DeactivationStatusNotificationDiv.BasicService);
2797 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2798 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2800 case Fac_InterrogationDiversion:
2801 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2802 fac->u.InterrogationDiversion.InvokeID);
2803 switch (fac->u.InterrogationDiversion.ComponentType) {
2804 case FacComponent_Invoke:
2805 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
2806 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2807 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2808 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
2809 print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2811 case FacComponent_Result:
2812 chan_misdn_log(1, bc->port, " --> Result:\n");
2813 if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2814 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2815 chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
2816 print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2824 case Fac_DiversionInformation:
2825 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2826 fac->u.DiversionInformation.InvokeID,
2827 fac->u.DiversionInformation.DiversionReason,
2828 fac->u.DiversionInformation.BasicService);
2829 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2830 chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
2831 print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2833 if (fac->u.DiversionInformation.CallingAddressPresent) {
2834 chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
2835 print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2837 if (fac->u.DiversionInformation.OriginalCalledPresent) {
2838 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2839 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2841 if (fac->u.DiversionInformation.LastDivertingPresent) {
2842 chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
2843 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2845 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2846 chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2848 if (fac->u.DiversionInformation.UserInfo.Length) {
2849 chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2852 case Fac_CallDeflection:
2853 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2854 fac->u.CallDeflection.InvokeID);
2855 switch (fac->u.CallDeflection.ComponentType) {
2856 case FacComponent_Invoke:
2857 chan_misdn_log(1, bc->port, " --> Invoke:\n");
2858 if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2859 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
2860 fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2862 chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
2863 print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2865 case FacComponent_Result:
2866 chan_misdn_log(1, bc->port, " --> Result\n");
2872 case Fac_CallRerouteing:
2873 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2874 fac->u.CallRerouteing.InvokeID);
2875 switch (fac->u.CallRerouteing.ComponentType) {
2876 case FacComponent_Invoke:
2877 chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
2878 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2879 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2880 chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
2881 print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2882 print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2883 chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
2884 print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2885 chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
2886 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2887 if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2888 chan_misdn_log(1, bc->port, " --> CallingParty:\n");
2889 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2892 case FacComponent_Result:
2893 chan_misdn_log(1, bc->port, " --> Result\n");
2899 case Fac_InterrogateServedUserNumbers:
2900 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2901 fac->u.InterrogateServedUserNumbers.InvokeID);
2902 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2903 case FacComponent_Invoke:
2904 chan_misdn_log(1, bc->port, " --> Invoke\n");
2906 case FacComponent_Result:
2907 chan_misdn_log(1, bc->port, " --> Result:\n");
2908 if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2909 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2910 chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
2911 print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2919 case Fac_DivertingLegInformation1:
2920 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2921 fac->u.DivertingLegInformation1.InvokeID,
2922 fac->u.DivertingLegInformation1.DiversionReason,
2923 fac->u.DivertingLegInformation1.SubscriptionOption);
2924 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2925 chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
2926 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2929 case Fac_DivertingLegInformation2:
2930 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2931 fac->u.DivertingLegInformation2.InvokeID,
2932 fac->u.DivertingLegInformation2.DiversionReason,
2933 fac->u.DivertingLegInformation2.DiversionCounter);
2934 if (fac->u.DivertingLegInformation2.DivertingPresent) {
2935 chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
2936 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2938 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2939 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
2940 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2943 case Fac_DivertingLegInformation3:
2944 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2945 fac->u.DivertingLegInformation3.InvokeID,
2946 fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2949 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
2952 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2953 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2955 #endif /* !defined(AST_MISDN_ENHANCEMENTS) */
2956 case Fac_AOCDCurrency:
2957 if (fac->u.AOCDcur.chargeNotAvailable) {
2958 chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2959 } else if (fac->u.AOCDcur.freeOfCharge) {
2960 chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2961 } else if (fac->u.AOCDchu.billingId >= 0) {
2962 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2963 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2964 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2966 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2967 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2968 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2971 case Fac_AOCDChargingUnit:
2972 if (fac->u.AOCDchu.chargeNotAvailable) {
2973 chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
2974 } else if (fac->u.AOCDchu.freeOfCharge) {
2975 chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
2976 } else if (fac->u.AOCDchu.billingId >= 0) {
2977 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
2978 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
2980 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
2981 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
2984 #if defined(AST_MISDN_ENHANCEMENTS)
2986 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
2987 fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
2990 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
2991 fac->u.RESULT.InvokeID);
2994 if (fac->u.REJECT.InvokeIDPresent) {
2995 chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
2996 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
2998 chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
2999 fac->u.REJECT.Code);
3002 case Fac_EctExecute:
3003 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3004 fac->u.EctExecute.InvokeID);
3006 case Fac_ExplicitEctExecute:
3007 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3008 fac->u.ExplicitEctExecute.InvokeID,
3009 fac->u.ExplicitEctExecute.LinkID);
3011 case Fac_RequestSubaddress:
3012 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3013 fac->u.RequestSubaddress.InvokeID);
3015 case Fac_SubaddressTransfer:
3016 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3017 fac->u.SubaddressTransfer.InvokeID);
3018 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3020 case Fac_EctLinkIdRequest:
3021 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3022 fac->u.EctLinkIdRequest.InvokeID);
3023 switch (fac->u.EctLinkIdRequest.ComponentType) {
3024 case FacComponent_Invoke:
3025 chan_misdn_log(1, bc->port, " --> Invoke\n");
3027 case FacComponent_Result:
3028 chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
3029 fac->u.EctLinkIdRequest.Component.Result.LinkID);
3036 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3037 fac->u.EctInform.InvokeID,
3038 fac->u.EctInform.Status);
3039 if (fac->u.EctInform.RedirectionPresent) {
3040 chan_misdn_log(1, bc->port, " --> Redirection Number\n");
3041 print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3044 case Fac_EctLoopTest:
3045 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3046 fac->u.EctLoopTest.InvokeID);
3047 switch (fac->u.EctLoopTest.ComponentType) {
3048 case FacComponent_Invoke:
3049 chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
3050 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3052 case FacComponent_Result:
3053 chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
3054 fac->u.EctLoopTest.Component.Result.LoopResult);
3060 case Fac_StatusRequest:
3061 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3062 fac->u.StatusRequest.InvokeID);
3063 switch (fac->u.StatusRequest.ComponentType) {
3064 case FacComponent_Invoke:
3065 chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
3066 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3068 case FacComponent_Result:
3069 chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
3070 fac->u.StatusRequest.Component.Result.Status);
3076 case Fac_CallInfoRetain:
3077 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3078 fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3080 case Fac_CCBSDeactivate:
3081 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3082 fac->u.CCBSDeactivate.InvokeID);
3083 switch (fac->u.CCBSDeactivate.ComponentType) {
3084 case FacComponent_Invoke:
3085 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
3086 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3088 case FacComponent_Result:
3089 chan_misdn_log(1, bc->port, " --> Result\n");
3096 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3097 fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3098 fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3099 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3100 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3101 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3103 case Fac_CCBSRemoteUserFree:
3104 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3105 fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3106 fac->u.CCBSRemoteUserFree.RecallMode);
3107 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3108 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3109 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3112 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3113 fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3115 case Fac_CCBSStatusRequest:
3116 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3117 fac->u.CCBSStatusRequest.InvokeID);
3118 switch (fac->u.CCBSStatusRequest.ComponentType) {
3119 case FacComponent_Invoke:
3120 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
3121 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3122 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3123 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3125 case FacComponent_Result:
3126 chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
3127 fac->u.CCBSStatusRequest.Component.Result.Free);
3134 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3135 fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3136 fac->u.CCBSBFree.RecallMode);
3137 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
3138 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3139 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3141 case Fac_EraseCallLinkageID:
3142 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3143 fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3145 case Fac_CCBSStopAlerting:
3146 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3147 fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3149 case Fac_CCBSRequest:
3150 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3151 fac->u.CCBSRequest.InvokeID);
3152 switch (fac->u.CCBSRequest.ComponentType) {
3153 case FacComponent_Invoke:
3154 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3155 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3157 case FacComponent_Result:
3158 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3159 fac->u.CCBSRequest.Component.Result.CCBSReference,
3160 fac->u.CCBSRequest.Component.Result.RecallMode);
3166 case Fac_CCBSInterrogate:
3167 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3168 fac->u.CCBSInterrogate.InvokeID);
3169 switch (fac->u.CCBSInterrogate.ComponentType) {
3170 case FacComponent_Invoke:
3171 chan_misdn_log(1, bc->port, " --> Invoke\n");
3172 if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3173 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3174 fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3176 if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3177 chan_misdn_log(1, bc->port, " --> AParty\n");
3178 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3181 case FacComponent_Result:
3182 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3183 fac->u.CCBSInterrogate.Component.Result.RecallMode);
3184 if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3185 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3186 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3187 print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3195 case Fac_CCNRRequest:
3196 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3197 fac->u.CCNRRequest.InvokeID);
3198 switch (fac->u.CCNRRequest.ComponentType) {
3199 case FacComponent_Invoke:
3200 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
3201 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3203 case FacComponent_Result:
3204 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
3205 fac->u.CCNRRequest.Component.Result.CCBSReference,
3206 fac->u.CCNRRequest.Component.Result.RecallMode);
3212 case Fac_CCNRInterrogate:
3213 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3214 fac->u.CCNRInterrogate.InvokeID);
3215 switch (fac->u.CCNRInterrogate.ComponentType) {
3216 case FacComponent_Invoke:
3217 chan_misdn_log(1, bc->port, " --> Invoke\n");
3218 if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3219 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
3220 fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3222 if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3223 chan_misdn_log(1, bc->port, " --> AParty\n");
3224 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3227 case FacComponent_Result:
3228 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
3229 fac->u.CCNRInterrogate.Component.Result.RecallMode);
3230 if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3231 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3232 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
3233 print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3241 case Fac_CCBS_T_Call:
3242 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3243 fac->u.CCBS_T_Call.InvokeID);
3245 case Fac_CCBS_T_Suspend:
3246 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3247 fac->u.CCBS_T_Suspend.InvokeID);
3249 case Fac_CCBS_T_Resume:
3250 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3251 fac->u.CCBS_T_Resume.InvokeID);
3253 case Fac_CCBS_T_RemoteUserFree:
3254 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3255 fac->u.CCBS_T_RemoteUserFree.InvokeID);
3257 case Fac_CCBS_T_Available:
3258 chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3259 fac->u.CCBS_T_Available.InvokeID);
3261 case Fac_CCBS_T_Request:
3262 chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
3263 fac->u.CCBS_T_Request.InvokeID);
3264 switch (fac->u.CCBS_T_Request.ComponentType) {
3265 case FacComponent_Invoke:
3266 chan_misdn_log(1, bc->port, " --> Invoke\n");
3267 chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
3268 print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
3269 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
3270 if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
3271 chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
3273 if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3274 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
3275 fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);