diff options
author | Jeff Peeler <jpeeler@digium.com> | 2009-05-29 19:19:51 +0000 |
---|---|---|
committer | Jeff Peeler <jpeeler@digium.com> | 2009-05-29 19:19:51 +0000 |
commit | aaf5eb105ed55b7856dfd79b352a1669cb51d437 (patch) | |
tree | 0dda7e0de1ea9c2ef20bdf75cc315bd5292622cb /channels/sig_analog.h | |
parent | 161fdde84de3f836fbad7b0294d7f8fe39b2e1e1 (diff) |
New signaling module to handle analog operations in chan_dahdi
This branch splits all the analog signaling logic out of chan_dahdi.c into
sig_analog.c. Functionality in theory should not change at all. As noted
in the code, there is still some unused code remaining that will be cleaned
up in a later commit.
Review: https://reviewboard.asterisk.org/r/253/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@198088 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/sig_analog.h')
-rw-r--r-- | channels/sig_analog.h | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/channels/sig_analog.h b/channels/sig_analog.h new file mode 100644 index 000000000..91e154353 --- /dev/null +++ b/channels/sig_analog.h @@ -0,0 +1,329 @@ +#ifndef _SIG_ANALOG_H +#define _SIG_ANALOG_H +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2009, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Interface header for analog signaling module + * + * \author Matthew Fredrickson <creslin@digium.com> + */ + +#include "asterisk/channel.h" +#include "asterisk/frame.h" + +/* Signalling types supported */ +enum analog_sigtype { + ANALOG_SIG_NONE = -1, + ANALOG_SIG_FXOLS = 1, + ANALOG_SIG_FXOKS, + ANALOG_SIG_FXOGS, + ANALOG_SIG_FXSLS, + ANALOG_SIG_FXSKS, + ANALOG_SIG_FXSGS, + ANALOG_SIG_EMWINK, + ANALOG_SIG_EM, + ANALOG_SIG_EM_E1, + ANALOG_SIG_FEATD, + ANALOG_SIG_FEATDMF, + ANALOG_SIG_E911, + ANALOG_SIG_FGC_CAMA, + ANALOG_SIG_FGC_CAMAMF, + ANALOG_SIG_FEATB, + ANALOG_SIG_SFWINK, + ANALOG_SIG_SF, + ANALOG_SIG_SF_FEATD, + ANALOG_SIG_SF_FEATDMF, + ANALOG_SIG_FEATDMF_TA, + ANALOG_SIG_SF_FEATB, +}; + +enum analog_tone { + ANALOG_TONE_RINGTONE = 0, + ANALOG_TONE_STUTTER, + ANALOG_TONE_CONGESTION, + ANALOG_TONE_DIALTONE, + ANALOG_TONE_DIALRECALL, + ANALOG_TONE_INFO, +}; + +enum analog_event { + ANALOG_EVENT_NONE = 0, + ANALOG_EVENT_DIALCOMPLETE, + ANALOG_EVENT_WINKFLASH, + ANALOG_EVENT_ONHOOK, + ANALOG_EVENT_RINGOFFHOOK, + ANALOG_EVENT_ALARM, + ANALOG_EVENT_NOALARM, + ANALOG_EVENT_HOOKCOMPLETE, + ANALOG_EVENT_POLARITY, + ANALOG_EVENT_RINGERON, + ANALOG_EVENT_RINGEROFF, + ANALOG_EVENT_RINGBEGIN, + ANALOG_EVENT_PULSE_START, + ANALOG_EVENT_ERROR, + ANALOG_EVENT_NEONMWI_ACTIVE, + ANALOG_EVENT_NEONMWI_INACTIVE, +}; + +enum analog_sub { + ANALOG_SUB_REAL = 0, /*!< Active call */ + ANALOG_SUB_CALLWAIT, /*!< Call-Waiting call on hold */ + ANALOG_SUB_THREEWAY, /*!< Three-way call */ +}; + +enum analog_dsp_digitmode { + ANALOG_DIGITMODE_DTMF = 1, + ANALOG_DIGITMODE_MF, +}; + +enum analog_cid_start { + ANALOG_CID_START_POLARITY = 1, + ANALOG_CID_START_POLARITY_IN, + ANALOG_CID_START_RING, +}; + +#define ANALOG_MAX_CID 300 + +enum dialop { + ANALOG_DIAL_OP_REPLACE = 2, +}; + + +struct analog_dialoperation { + enum dialop op; + char dialstr[256]; +}; + +struct analog_callback { + /* Unlock the private in the signalling private structure. This is used for three way calling madness. */ + void (* const unlock_private)(void *pvt); + /* Lock the private in the signalling private structure. ... */ + void (* const lock_private)(void *pvt); + /* Function which is called back to handle any other DTMF up events that are received. Called by analog_handle_event. Why is this + * important to use, instead of just directly using events received before they are passed into the library? Because sometimes, + * (CWCID) the library absorbs DTMF events received. */ + void (* const handle_dtmfup)(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest); + + int (* const get_event)(void *pvt); + int (* const wait_event)(void *pvt); + int (* const is_off_hook)(void *pvt); + int (* const is_dialing)(void *pvt, enum analog_sub sub); + /* Start a trunk type signalling protocol (everything except phone ports basically */ + int (* const start)(void *pvt); + int (* const ring)(void *pvt); + int (* const flash)(void *pvt); + /*! \brief Set channel on hook */ + int (* const on_hook)(void *pvt); + /*! \brief Set channel off hook */ + int (* const off_hook)(void *pvt); + /* We're assuming that we're going to only wink on ANALOG_SUB_REAL - even though in the code there's an argument to the index + * function */ + int (* const wink)(void *pvt, enum analog_sub sub); + int (* const dial_digits)(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop); + int (* const send_fsk)(void *pvt, struct ast_channel *ast, char *fsk); + int (* const play_tone)(void *pvt, enum analog_sub sub, enum analog_tone tone); + + int (* const set_echocanceller)(void *pvt, int enable); + int (* const train_echocanceller)(void *pvt); + int (* const dsp_set_digitmode)(void *pvt, enum analog_dsp_digitmode mode); + int (* const dsp_reset_and_flush_digits)(void *pvt); + int (* const send_callerid)(void *pvt, int cwcid, struct ast_callerid *cid); + /* Returns 0 if CID received. Returns 1 if event received, and -1 if error. name and num are size ANALOG_MAX_CID */ + int (* const get_callerid)(void *pvt, char *name, char *num, enum analog_event *ev, size_t timeout); + /* Start CID detection */ + int (* const start_cid_detect)(void *pvt, int cid_signalling); + /* Stop CID detection */ + int (* const stop_cid_detect)(void *pvt); + + /* Play the CAS callwait tone on the REAL sub, then repeat after 10 seconds, and then stop */ + int (* const callwait)(void *pvt); + /* Stop playing any CAS call waiting announcement tones that might be running on the REAL sub */ + int (* const stop_callwait)(void *pvt); + + /* Bearer control related (non signalling) callbacks */ + int (* const allocate_sub)(void *pvt, enum analog_sub sub); + int (* const unallocate_sub)(void *pvt, enum analog_sub sub); + /*! This function is for swapping of the owners with the underlying subs. Typically it means you need to change the fds + * of the new owner to be the fds of the sub specified, for each of the two subs given */ + void (* const swap_subs)(void *pvt, enum analog_sub a, struct ast_channel *new_a_owner, enum analog_sub b, struct ast_channel *new_b_owner); + struct ast_channel * (* const new_ast_channel)(void *pvt, int state, int startpbx, enum analog_sub sub); + + /* Add the given sub to a conference */ + int (* const conf_add)(void *pvt, enum analog_sub sub); + /* Delete the given sub from any conference that might be running on the channels */ + int (* const conf_del)(void *pvt, enum analog_sub sub); + + /* If you would like to do any optimizations after the conference members have been added and removed, + * you can do so here */ + int (* const complete_conference_update)(void *pvt, int needconf); + + /* This is called when there are no more subchannels on the given private that are left up, + * for any cleanup or whatever else you would like to do. Called from analog_hangup() */ + void (* const all_subchannels_hungup)(void *pvt); + + int (* const has_voicemail)(void *pvt); + int (* const check_for_conference)(void *pvt); + void (* const handle_notify_message)(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent); + + /* callbacks for increasing and decreasing ss_thread_count, will handle locking and condition signal */ + void (* const increase_ss_count)(void); + void (* const decrease_ss_count)(void); +}; + + + +#define READ_SIZE 160 + +struct analog_subchannel { + struct ast_channel *owner; + struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */ + unsigned int needcallerid:1; + unsigned int inthreeway:1; + /* Have we allocated a subchannel yet or not */ + unsigned int allocd:1; +}; + +struct analog_pvt { + /* Analog signalling type used in this private */ + enum analog_sigtype sig; + /* To contain the private structure passed into the channel callbacks */ + void *chan_pvt; + /* Callbacks for various functions needed by the analog API */ + struct analog_callback *calls; + /* All members after this are giong to be transient, and most will probably change */ + struct ast_channel *owner; /*!< Our current active owner (if applicable) */ + + struct analog_subchannel subs[3]; /*!< Sub-channels */ + struct analog_dialoperation dop; + + /* XXX: Option Variables - Set by allocator of private structure */ + unsigned int answeronpolarityswitch:1; + unsigned int callreturn:1; + unsigned int cancallforward:1; + unsigned int canpark:1; + unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */ + unsigned int hanguponpolarityswitch:1; + unsigned int immediate:1; + unsigned int permcallwaiting:1; + unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */ + unsigned int pulse:1; + unsigned int threewaycalling:1; + unsigned int transfer:1; + unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */ + unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */ + + /* Not used for anything but log messages. Could be just the TCID */ + int channel; /*!< Channel Number or CRV */ + enum analog_sigtype outsigmod; + int echotraining; + int cid_signalling; /*!< Asterisk callerid type we're using */ + int polarityonanswerdelay; + int stripmsd; + enum analog_cid_start cid_start; + /* Number of rings to wait to send callerid on FXS. Set to 1 for US */ + int sendcalleridafter; + int callwaitingcallerid; + char mohsuggest[MAX_MUSICCLASS]; + char cid_num[AST_MAX_EXTENSION]; + char cid_name[AST_MAX_EXTENSION]; + + + /* XXX: All variables after this are internal */ + unsigned int callwaiting:1; + unsigned int dialednone:1; + unsigned int dialing:1; + unsigned int dnd:1; + unsigned int echobreak:1; + unsigned int hidecallerid:1; + unsigned int outgoing:1; + unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */ + + char callwait_num[AST_MAX_EXTENSION]; + char callwait_name[AST_MAX_EXTENSION]; + char lastcid_num[AST_MAX_EXTENSION]; + char lastcid_name[AST_MAX_EXTENSION]; + struct ast_callerid cid; + int cidrings; /*!< Which ring to deliver CID on */ + char echorest[20]; + int polarity; + struct timeval polaritydelaytv; + char dialdest[256]; + time_t guardtime; /*!< Must wait this much time before using for new call */ + struct timeval flashtime; /*!< Last flash-hook time */ + int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */ + char finaldial[64]; + char *origcid_num; /*!< malloced original callerid */ + char *origcid_name; /*!< malloced original callerid */ + char call_forward[AST_MAX_EXTENSION]; + + /* Ast channel to pass to __ss_analog_thread */ + void *ss_astchan; + + /* All variables after this are definitely going to be audited */ + unsigned int inalarm:1; // + unsigned int unknown_alarm:1;// + + int callwaitcas; + +#if 0 + int ringt; // + int ringt_base; +#endif +}; + +struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog_callback *c, void *private_data); + +void analog_free(struct analog_pvt *p); + +int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout); + +int analog_hangup(struct analog_pvt *p, struct ast_channel *ast); + +int analog_answer(struct analog_pvt *p, struct ast_channel *ast); + +struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast); + +struct ast_channel * analog_request(struct analog_pvt *p, int *callwait); + +int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched); + +int analog_handle_init_event(struct analog_pvt *i, int event); + +int analog_config_complete(struct analog_pvt *p); + +void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest); + +enum analog_cid_start analog_str_to_cidstart(const char *value); + +const char *analog_cidstart_to_str(enum analog_cid_start cid_start); + +enum analog_sigtype analog_str_to_sigtype(const char *name); + +const char *analog_sigtype_to_str(enum analog_sigtype sigtype); + +unsigned int analog_str_to_cidtype(const char *name); + +const char *analog_cidtype_to_str(unsigned int cid_type); + +int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *ast); + +int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp); + +#endif /* _SIG_ANSLOG_H */ |