#include "asterisk.h"
#include <values.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
#include "asterisk/event.h"
#include "asterisk/devicestate.h"
#include "asterisk/paths.h"

Go to the source code of this file.
Data Structures | |
| struct | dahdi_chan_conf |
| Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More... | |
| struct | dahdi_distRings |
| struct | dahdi_pvt |
| struct | dahdi_subchannel |
| struct | distRingData |
| struct | mwi_thread_data |
| struct | mwisend_info |
| struct | ringContextData |
Defines | |
| #define | ASCII_BYTES_PER_CHAR 80 |
| #define | AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
| #define | CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
| #define | CALLPROGRESS_FAX_INCOMING 4 |
| #define | CALLPROGRESS_FAX_OUTGOING 2 |
| #define | CALLPROGRESS_PROGRESS 1 |
| #define | CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
| #define | CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
| #define | CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CHAN_PSEUDO -2 |
| #define | CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define | CONF_USER_REAL (1 << 0) |
| #define | CONF_USER_THIRDCALL (1 << 1) |
| #define | DEFAULT_CIDRINGS 1 |
| Typically, how many rings before we should send Caller*ID. | |
| #define | DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
| #define | END_SILENCE_LEN 400 |
| #define | FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define | FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define | GET_CHANNEL(p) ((p)->channel) |
| #define | HANGUP 1 |
| #define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
| #define | HEADER_MS 50 |
| #define | ISTRUNK(p) |
| #define | MASK_AVAIL (1 << 0) |
| #define | MASK_INUSE (1 << 1) |
| #define | MAX_CHANLIST_LEN 80 |
| #define | MAX_SLAVES 4 |
| #define | MIN_MS_SINCE_FLASH ( (2000) ) |
| #define | NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
| Signaling types that need to use MF detection should be placed in this macro. | |
| #define | NUM_CADENCE_MAX 25 |
| #define | NUM_SPANS 32 |
| #define | POLARITY_IDLE 0 |
| #define | POLARITY_REV 1 |
| #define | PROC_DAHDI_OPT_NOCHAN (1 << 0) |
| #define | PROC_DAHDI_OPT_NOWARN (1 << 1) |
| #define | READ_SIZE 160 |
| #define | sig2str dahdi_sig2str |
| #define | SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
| #define | SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
| #define | SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
| #define | SIG_EM DAHDI_SIG_EM |
| #define | SIG_EM_E1 DAHDI_SIG_EM_E1 |
| #define | SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
| #define | SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
| #define | SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
| #define | SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
| #define | SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
| #define | SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
| #define | SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
| #define | SIG_FXOGS DAHDI_SIG_FXOGS |
| #define | SIG_FXOKS DAHDI_SIG_FXOKS |
| #define | SIG_FXOLS DAHDI_SIG_FXOLS |
| #define | SIG_FXSGS DAHDI_SIG_FXSGS |
| #define | SIG_FXSKS DAHDI_SIG_FXSKS |
| #define | SIG_FXSLS DAHDI_SIG_FXSLS |
| #define | SIG_MFCR2 DAHDI_SIG_CAS |
| #define | SIG_PRI DAHDI_SIG_CLEAR |
| #define | SIG_PRI_LIB_HANDLE_CASES |
| #define | SIG_SF DAHDI_SIG_SF |
| #define | SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
| #define | SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
| #define | SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
| #define | SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
| #define | SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
| #define | SMDI_MD_WAIT_TIMEOUT 1500 |
| #define | SUB_CALLWAIT 1 |
| #define | SUB_REAL 0 |
| #define | SUB_THREEWAY 2 |
| #define | TRAILER_MS 5 |
| #define | TRANSFER 0 |
Enumerations | |
| enum | DAHDI_IFLIST { DAHDI_IFLIST_NONE, DAHDI_IFLIST_MAIN } |
| enum | mwisend_states { MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE } |
Functions | |
| static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
| static void | __reg_module (void) |
| static int | __unload_module (void) |
| static void | __unreg_module (void) |
| static int | action_dahdidialoffhook (struct mansession *s, const struct message *m) |
| static int | action_dahdidndoff (struct mansession *s, const struct message *m) |
| static int | action_dahdidndon (struct mansession *s, const struct message *m) |
| static int | action_dahdirestart (struct mansession *s, const struct message *m) |
| static int | action_dahdishowchannels (struct mansession *s, const struct message *m) |
| static int | action_transfer (struct mansession *s, const struct message *m) |
| static int | action_transferhangup (struct mansession *s, const struct message *m) |
| static char * | alarm2str (int alm) |
| static int | alloc_sub (struct dahdi_pvt *p, int x) |
| static int | analog_lib_handles (int signalling, int radio, int oprmode) |
| static void * | analog_ss_thread (void *data) |
| static int | analog_tone_to_dahditone (enum analog_tone tone) |
| static int | analogsub_to_dahdisub (enum analog_sub analogsub) |
| static int | attempt_transfer (struct dahdi_pvt *p) |
| static int | available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched) |
| static int | build_channels (struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo) |
| static int | bump_gains (struct dahdi_pvt *p) |
| static int | calc_energy (const unsigned char *buf, int len, int law) |
| static int | check_for_conference (struct dahdi_pvt *p) |
| static int | conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel) |
| static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index) |
| static int | dahdi_answer (struct ast_channel *ast) |
| static enum ast_bridge_result | dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| static int | dahdi_call (struct ast_channel *ast, char *rdest, int timeout) |
| static int | dahdi_callwait (struct ast_channel *ast) |
| static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
| static void | dahdi_close (int fd) |
| static void | dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num) |
| static int | dahdi_confmute (struct dahdi_pvt *p, int muted) |
| static char * | dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_destroy_channel_bynum (int channel) |
| static int | dahdi_digit_begin (struct ast_channel *ast, char digit) |
| static int | dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static void | dahdi_disable_ec (struct dahdi_pvt *p) |
| static int | dahdi_dnd (struct dahdi_pvt *dahdichan, int flag) |
| enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel | |
| static void | dahdi_enable_ec (struct dahdi_pvt *p) |
| static struct ast_frame * | dahdi_exception (struct ast_channel *ast) |
| static int | dahdi_fake_event (struct dahdi_pvt *p, int mode) |
| static int | dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static int | dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) |
| static int | dahdi_func_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
| static int | dahdi_get_event (int fd) |
| Avoid the silly dahdi_getevent which ignores a bunch of events. | |
| static int | dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok) |
| static void | dahdi_handle_dtmfup (struct ast_channel *ast, int idx, struct ast_frame **dest) |
| static struct ast_frame * | dahdi_handle_event (struct ast_channel *ast) |
| static int | dahdi_hangup (struct ast_channel *ast) |
| static void | dahdi_iflist_extract (struct dahdi_pvt *pvt) |
| static void | dahdi_iflist_insert (struct dahdi_pvt *pvt) |
| static int | dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen) |
| static void | dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master) |
| static struct ast_channel * | dahdi_new (struct dahdi_pvt *, int, int, int, int, int, const char *) |
| static int | dahdi_open (char *fn) |
| static int | dahdi_queryoption (struct ast_channel *chan, int option, void *data, int *datalen) |
| static void | dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, void *data) |
| static struct ast_frame * | dahdi_read (struct ast_channel *ast) |
| static struct ast_channel * | dahdi_request (const char *type, int format, const struct ast_channel *requestor, void *data, int *cause) |
| static int | dahdi_restart (void) |
| static char * | dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_ring_phone (struct dahdi_pvt *p) |
| static int | dahdi_sendtext (struct ast_channel *c, const char *text) |
| static char * | dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_set_hook (int fd, int hs) |
| static char * | dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_setlinear (int dfd, int linear) |
| static int | dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen) |
| static char * | dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_sig2str (int sig) |
| static int | dahdi_sig_pri_lib_handles (int signaling) |
| static void | dahdi_softhangup_all (void) |
| static void | dahdi_train_ec (struct dahdi_pvt *p) |
| static void | dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock) |
| static int | dahdi_wait_event (int fd) |
| Avoid the silly dahdi_waitevent which ignores a bunch of events. | |
| static int | dahdi_wink (struct dahdi_pvt *p, int index) |
| static int | dahdi_write (struct ast_channel *ast, struct ast_frame *frame) |
| static enum analog_event | dahdievent_to_analogevent (int event) |
| static enum analog_sigtype | dahdisig_to_analogsig (int sig) |
| static void | destroy_all_channels (void) |
| static void | destroy_channel (struct dahdi_pvt *cur, int now) |
| static void | destroy_dahdi_pvt (struct dahdi_pvt *pvt) |
| static int | digit_to_dtmfindex (char digit) |
| static void | disable_dtmf_detect (struct dahdi_pvt *p) |
| static void * | do_monitor (void *data) |
| static int | drc_sample (int sample, float drc) |
| static struct dahdi_pvt * | duplicate_pseudo (struct dahdi_pvt *src) |
| static void | enable_dtmf_detect (struct dahdi_pvt *p) |
| static const char * | event2str (int event) |
| static void | fill_rxgain (struct dahdi_gains *g, float gain, float drc, int law) |
| static void | fill_txgain (struct dahdi_gains *g, float gain, float drc, int law) |
| static struct dahdi_pvt * | find_channel (int channel) |
| static int | get_alarms (struct dahdi_pvt *p) |
| static void | handle_alarms (struct dahdi_pvt *p, int alms) |
| static char * | handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static struct dahdi_pvt * | handle_init_event (struct dahdi_pvt *i, int event) |
| static int | has_voicemail (struct dahdi_pvt *p) |
| static int | isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c) |
| static int | isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out) |
| static int | load_module (void) |
| static struct dahdi_pvt * | mkintf (int channel, const struct dahdi_chan_conf *conf, int reloading) |
| static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
| static int | mwi_send_init (struct dahdi_pvt *pvt) |
| static int | mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read) |
| static int | mwi_send_process_event (struct dahdi_pvt *pvt, int event) |
| static void * | mwi_thread (void *data) |
| static void | my_all_subchannels_hungup (void *pvt) |
| static int | my_allocate_sub (void *pvt, enum analog_sub analogsub) |
| static int | my_callwait (void *pvt) |
| static void | my_cancel_cidspill (void *pvt) |
| static int | my_check_confirmanswer (void *pvt) |
| static int | my_check_for_conference (void *pvt) |
| static int | my_check_waitingfordt (void *pvt) |
| static int | my_complete_conference_update (void *pvt, int needconference) |
| static int | my_conf_add (void *pvt, enum analog_sub sub) |
| static int | my_conf_del (void *pvt, enum analog_sub sub) |
| static int | my_confmute (void *pvt, int mute) |
| static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear) |
| static void | my_decrease_ss_count (void) |
| static int | my_dial_digits (void *pvt, enum analog_sub sub, struct analog_dialoperation *dop) |
| static int | my_distinctive_ring (struct ast_channel *chan, void *pvt, int idx, int *ringdata) |
| static int | my_dsp_reset_and_flush_digits (void *pvt) |
| static int | my_dsp_set_digitmode (void *pvt, enum analog_dsp_digitmode mode) |
| static int | my_flash (void *pvt) |
| static void | my_get_and_handle_alarms (void *pvt) |
| static int | my_get_callerid (void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout) |
| static int | my_get_event (void *pvt) |
| static void * | my_get_sigpvt_bridged_channel (struct ast_channel *chan) |
| static int | my_get_sub_fd (void *pvt, enum analog_sub sub) |
| static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
| static void | my_handle_dtmfup (void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest) |
| static void | my_handle_notify_message (struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent) |
| static int | my_has_voicemail (void *pvt) |
| static void | my_increase_ss_count (void) |
| static int | my_is_dialing (void *pvt, enum analog_sub sub) |
| static int | my_is_off_hook (void *pvt) |
| static void | my_lock_private (void *pvt) |
| static struct ast_channel * | my_new_analog_ast_channel (void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor) |
| static int | my_off_hook (void *pvt) |
| static int | my_on_hook (void *pvt) |
| static int | my_play_tone (void *pvt, enum analog_sub sub, enum analog_tone tone) |
| static int | my_ring (void *pvt) |
| static int | my_send_callerid (void *pvt, int cwcid, struct ast_callerid *cid) |
| static void | my_set_cadence (void *pvt, int *cidrings, struct ast_channel *ast) |
| static void | my_set_confirmanswer (void *pvt, int flag) |
| static void | my_set_dialing (void *pvt, int flag) |
| static int | my_set_echocanceller (void *pvt, int enable) |
| static int | my_set_linear_mode (void *pvt, int idx, int linear_mode) |
| static void | my_set_pulsedial (void *pvt, int flag) |
| static void | my_set_ringtimeout (void *pvt, int ringt) |
| static void | my_set_waitingfordt (void *pvt, struct ast_channel *ast) |
| static int | my_start (void *pvt) |
| static int | my_start_cid_detect (void *pvt, int cid_signalling) |
| static int | my_stop_callwait (void *pvt) |
| static int | my_stop_cid_detect (void *pvt) |
| static void | my_swap_subchannels (void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b) |
| static int | my_train_echocanceller (void *pvt) |
| static int | my_unallocate_sub (void *pvt, enum analog_sub analogsub) |
| static void | my_unlock_private (void *pvt) |
| static int | my_wait_event (void *pvt) |
| static int | my_wink (void *pvt, enum analog_sub sub) |
| static void | notify_message (char *mailbox_full, int thereornot) |
| Send MWI state change. | |
| static int | parse_buffers_policy (const char *parse, int *num_buffers, int *policy) |
| static int | process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options) |
| static void | process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line) |
| static int | reload (void) |
| static int | reset_conf (struct dahdi_pvt *p) |
| static int | restart_monitor (void) |
| static int | restore_conference (struct dahdi_pvt *p) |
| static int | restore_gains (struct dahdi_pvt *p) |
| static int | revert_fax_buffers (struct dahdi_pvt *p, struct ast_channel *ast) |
| static int | save_conference (struct dahdi_pvt *p) |
| static int | send_callerid (struct dahdi_pvt *p) |
| static int | send_cwcidspill (struct dahdi_pvt *p) |
| static int | set_actual_gain (int fd, int chan, float rxgain, float txgain, float rxdrc, float txdrc, int law) |
| static int | set_actual_rxgain (int fd, int chan, float gain, float drc, int law) |
| static int | set_actual_txgain (int fd, int chan, float gain, float drc, int law) |
| static int | setup_dahdi (int reload) |
| static int | sigtype_to_signalling (int sigtype) |
| static void | swap_subs (struct dahdi_pvt *p, int a, int b) |
| static int | unalloc_sub (struct dahdi_pvt *p, int x) |
| static int | unload_module (void) |
| static int | update_conf (struct dahdi_pvt *p) |
| static void | wakeup_sub (struct dahdi_pvt *p, int a) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| struct { | |
| int alarm | |
| char * name | |
| } | alarms [] |
| static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
| static int | cidrings [NUM_CADENCE_MAX] |
| cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
| static const char | config [] = "chan_dahdi.conf" |
| static struct analog_callback | dahdi_analog_callbacks |
| static struct ast_cli_entry | dahdi_cli [] |
| static struct ast_channel_tech | dahdi_tech |
| static struct ast_jb_conf | default_jbconf |
| static char | defaultcic [64] = "" |
| static char | defaultozz [64] = "" |
| static int | distinctiveringaftercid = 0 |
| static int | dtmfcid_level = 256 |
| static const char *const | events [] |
| static int | firstdigittimeout = 16000 |
| Wait up to 16 seconds for first digit (FXO logic). | |
| static int | gendigittimeout = 8000 |
| How long to wait for following digits (FXO logic). | |
| static struct ast_jb_conf | global_jbconf |
| static int | ifcount = 0 |
| static struct dahdi_pvt * | ifend = NULL |
| static struct dahdi_pvt * | iflist = NULL |
| static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| Protect the interface list (of dahdi_pvt's). | |
| static const char *const | lbostr [] |
| static int | matchdigittimeout = 3000 |
| How long to wait for an extra digit, if there is an ambiguous match. | |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static int | mwilevel = 512 |
| static char | mwimonitornotify [PATH_MAX] = "" |
| static int | mwisend_rpas = 0 |
| static int | num_cadence = 4 |
| static int | num_restart_pending = 0 |
| static int | numbufs = 4 |
| static char | parkinglot [AST_MAX_EXTENSION] = "" |
| static char | progzone [10] = "" |
| static ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static int | ringt_base = DEFAULT_RINGT |
| Configured ring timeout base. | |
| static struct dahdi_pvt * | round_robin [32] |
| static ast_cond_t | ss_thread_complete |
| static int | ss_thread_count = 0 |
| static ast_mutex_t | ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static const char *const | subnames [] |
| static const char | tdesc [] = "DAHDI Telephony Driver" |
| static int | usedistinctiveringdetection = 0 |
| static int | user_has_defined_cadences = 0 |
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.
You need to install libraries before you attempt to compile and install the DAHDI channel.
Definition in file chan_dahdi.c.
| #define ASCII_BYTES_PER_CHAR 80 |
Referenced by dahdi_sendtext().
| #define AST_LAW | ( | p | ) | (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
Definition at line 297 of file chan_dahdi.c.
Referenced by analog_ss_thread(), dahdi_callwait(), dahdi_sendtext(), do_monitor(), mwi_send_init(), mwi_thread(), my_callwait(), my_get_callerid(), my_send_callerid(), and send_cwcidspill().
| #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 366 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), dahdi_queryoption(), dahdi_setoption(), my_handle_dtmfup(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
| #define CALLPROGRESS_FAX_OUTGOING 2 |
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 363 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and process_dahdi().
| #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
10,000 ms
Definition at line 502 of file chan_dahdi.c.
Referenced by dahdi_callwait(), and my_callwait().
| #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 501 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 397 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and my_set_waitingfordt().
| #define CHAN_PSEUDO -2 |
Definition at line 361 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), mkintf(), my_dsp_set_digitmode(), and process_dahdi().
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 660 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 661 of file chan_dahdi.c.
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Define if you want to check the hook state for an FXO (FXS signalled) interface before dialing on it. Certain FXO interfaces always think they're out of service with this method however.
Definition at line 295 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 505 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), gtalk_show_channels(), handle_cli_core_show_channeltypes(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_cli_keys_show(), handle_core_show_image_formats(), handle_show_calendar(), handle_show_calendars(), handle_show_routes(), handle_show_version_files(), jingle_show_channels(), show_channels_cb(), show_chanstats_cb(), sip_show_domains(), sip_show_inuse(), sip_show_mwi(), sip_show_registry(), sip_show_tcp(), and sip_show_users().
| #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), handle_show_calendar(), sip_show_channels(), sip_show_channelstats(), sip_show_inuse(), sip_show_registry(), and sip_show_tcp().
| #define GET_CHANNEL | ( | p | ) | ((p)->channel) |
Definition at line 1467 of file chan_dahdi.c.
Referenced by my_complete_conference_update(), and update_conf().
| #define HANGUP 1 |
Definition at line 14828 of file chan_dahdi.c.
Referenced by action_transferhangup(), and dahdi_fake_event().
| #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), and parse_setup_acknowledge().
| #define HEADER_MS 50 |
Referenced by dahdi_sendtext().
| #define ISTRUNK | ( | p | ) |
Value:
Definition at line 393 of file chan_dahdi.c.
Referenced by __analog_ss_thread(), analog_ss_thread(), and dahdi_indicate().
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 498 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 499 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 15645 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define MAX_SLAVES 4 |
Definition at line 663 of file chan_dahdi.c.
Referenced by dahdi_link(), dahdi_show_channel(), dahdi_unlink(), isslavenative(), my_complete_conference_update(), and update_conf().
| #define MIN_MS_SINCE_FLASH ( (2000) ) |
2000 ms
Definition at line 504 of file chan_dahdi.c.
Referenced by __analog_handle_event(), and dahdi_handle_event().
| #define NEED_MFDETECT | ( | p | ) | (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro.
Definition at line 301 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and dahdi_new().
| #define NUM_CADENCE_MAX 25 |
| #define NUM_SPANS 32 |
| #define POLARITY_IDLE 0 |
Definition at line 620 of file chan_dahdi.c.
Referenced by __analog_handle_event(), __analog_ss_thread(), analog_hangup(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
| #define POLARITY_REV 1 |
Definition at line 621 of file chan_dahdi.c.
Referenced by __analog_handle_event(), __analog_ss_thread(), analog_handle_init_event(), analog_ss_thread(), dahdi_handle_event(), and handle_init_event().
| #define PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 15699 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
| #define PROC_DAHDI_OPT_NOWARN (1 << 1) |
process_dahdi() - No warnings on non-existing cofiguration keywords
Definition at line 15701 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 496 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_callwait(), my_dahdi_write(), my_send_callerid(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 3863 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), analog_ss_thread(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
| #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 333 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 328 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 353 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 329 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 332 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 330 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 331 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 334 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 335 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 336 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 341 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 342 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 340 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 338 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), my_is_off_hook(), and process_dahdi().
| #define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 339 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), mkintf(), my_is_off_hook(), and process_dahdi().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 337 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), dahdisig_to_analogsig(), do_monitor(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 347 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), mkintf(), and process_dahdi().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 343 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_sig2str(), mkintf(), and process_dahdi().
| #define SIG_PRI_LIB_HANDLE_CASES |
Value:
SIG_PRI: \ case SIG_BRI: \ case SIG_BRI_PTMP
Definition at line 1469 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_bridge(), dahdi_confmute(), dahdi_digit_begin(), dahdi_enable_ec(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig_pri_lib_handles(), handle_init_event(), and mkintf().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 348 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 352 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 350 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), and mkintf().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 351 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), and mkintf().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 349 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 346 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SMDI_MD_WAIT_TIMEOUT 1500 |
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 616 of file chan_dahdi.c.
Referenced by analog_ss_thread(), analogsub_to_dahdisub(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), and dahdi_show_channel().
| #define SUB_REAL 0 |
Active call
Definition at line 615 of file chan_dahdi.c.
Referenced by __dahdi_exception(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), build_device(), bump_gains(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_func_write(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_restart(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), duplicate_pseudo(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), my_all_subchannels_hungup(), my_complete_conference_update(), my_flash(), my_get_callerid(), my_get_event(), my_is_off_hook(), my_off_hook(), my_set_cadence(), my_start(), my_start_cid_detect(), my_stop_cid_detect(), my_wait_event(), my_wink(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), revert_fax_buffers(), save_conference(), send_callerid(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), unistim_senddigit_end(), and update_conf().
| #define SUB_THREEWAY 2 |
Three-way call
Definition at line 617 of file chan_dahdi.c.
Referenced by analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), close_call(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
| #define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
| #define TRANSFER 0 |
Definition at line 14827 of file chan_dahdi.c.
Referenced by action_transfer(), dahdi_fake_event(), send_agent_complete(), and try_calling().
| enum DAHDI_IFLIST |
Specify the lists dahdi_pvt can be put in.
| DAHDI_IFLIST_NONE | The dahdi_pvt is not in any list. |
| DAHDI_IFLIST_MAIN | The dahdi_pvt is in the main interface list |
Definition at line 684 of file chan_dahdi.c.
00684 { 00685 DAHDI_IFLIST_NONE, /*!< The dahdi_pvt is not in any list. */ 00686 DAHDI_IFLIST_MAIN, /*!< The dahdi_pvt is in the main interface list */ 00687 #if defined(HAVE_PRI) 00688 DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */ 00689 #endif /* defined(HAVE_PRI) */ 00690 };
| enum mwisend_states |
| MWI_SEND_NULL | |
| MWI_SEND_SA | |
| MWI_SEND_SA_WAIT | |
| MWI_SEND_PAUSE | |
| MWI_SEND_SPILL | |
| MWI_SEND_CLEANUP | |
| MWI_SEND_DONE |
Definition at line 668 of file chan_dahdi.c.
00668 { 00669 MWI_SEND_NULL = 0, 00670 MWI_SEND_SA, 00671 MWI_SEND_SA_WAIT, 00672 MWI_SEND_PAUSE, 00673 MWI_SEND_SPILL, 00674 MWI_SEND_CLEANUP, 00675 MWI_SEND_DONE, 00676 } mwisend_states;
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7799 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cidcwexpire, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
Referenced by dahdi_exception(), and dahdi_read().
07800 { 07801 int res; 07802 int idx; 07803 struct ast_frame *f; 07804 int usedindex = -1; 07805 struct dahdi_pvt *p = ast->tech_pvt; 07806 07807 idx = dahdi_get_index(ast, p, 1); 07808 07809 p->subs[idx].f.frametype = AST_FRAME_NULL; 07810 p->subs[idx].f.datalen = 0; 07811 p->subs[idx].f.samples = 0; 07812 p->subs[idx].f.mallocd = 0; 07813 p->subs[idx].f.offset = 0; 07814 p->subs[idx].f.subclass = 0; 07815 p->subs[idx].f.delivery = ast_tv(0,0); 07816 p->subs[idx].f.src = "dahdi_exception"; 07817 p->subs[idx].f.data.ptr = NULL; 07818 07819 07820 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 07821 /* If nobody owns us, absorb the event appropriately, otherwise 07822 we loop indefinitely. This occurs when, during call waiting, the 07823 other end hangs up our channel so that it no longer exists, but we 07824 have neither FLASH'd nor ONHOOK'd to signify our desire to 07825 change to the other channel. */ 07826 if (p->fake_event) { 07827 res = p->fake_event; 07828 p->fake_event = 0; 07829 } else 07830 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 07831 /* Switch to real if there is one and this isn't something really silly... */ 07832 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 07833 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 07834 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 07835 p->owner = p->subs[SUB_REAL].owner; 07836 if (p->owner && ast_bridged_channel(p->owner)) 07837 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07838 p->subs[SUB_REAL].needunhold = 1; 07839 } 07840 switch (res) { 07841 case DAHDI_EVENT_ONHOOK: 07842 dahdi_disable_ec(p); 07843 if (p->owner) { 07844 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 07845 dahdi_ring_phone(p); 07846 p->callwaitingrepeat = 0; 07847 p->cidcwexpire = 0; 07848 } else 07849 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 07850 update_conf(p); 07851 break; 07852 case DAHDI_EVENT_RINGOFFHOOK: 07853 dahdi_enable_ec(p); 07854 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07855 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 07856 p->subs[SUB_REAL].needanswer = 1; 07857 p->dialing = 0; 07858 } 07859 break; 07860 case DAHDI_EVENT_HOOKCOMPLETE: 07861 case DAHDI_EVENT_RINGERON: 07862 case DAHDI_EVENT_RINGEROFF: 07863 /* Do nothing */ 07864 break; 07865 case DAHDI_EVENT_WINKFLASH: 07866 p->flashtime = ast_tvnow(); 07867 if (p->owner) { 07868 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 07869 if (p->owner->_state != AST_STATE_UP) { 07870 /* Answer if necessary */ 07871 usedindex = dahdi_get_index(p->owner, p, 0); 07872 if (usedindex > -1) { 07873 p->subs[usedindex].needanswer = 1; 07874 } 07875 ast_setstate(p->owner, AST_STATE_UP); 07876 } 07877 p->callwaitingrepeat = 0; 07878 p->cidcwexpire = 0; 07879 if (ast_bridged_channel(p->owner)) 07880 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07881 p->subs[SUB_REAL].needunhold = 1; 07882 } else 07883 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 07884 update_conf(p); 07885 break; 07886 default: 07887 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 07888 } 07889 f = &p->subs[idx].f; 07890 return f; 07891 } 07892 if (!(p->radio || (p->oprmode < 0))) 07893 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 07894 /* If it's not us, return NULL immediately */ 07895 if (ast != p->owner) { 07896 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 07897 f = &p->subs[idx].f; 07898 return f; 07899 } 07900 f = dahdi_handle_event(ast); 07901 07902 /* tell the cdr this zap device hung up */ 07903 if (f == NULL) { 07904 ast_set_hangupsource(ast, ast->name, 0); 07905 } 07906 07907 return f; 07908 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 17090 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 15494 of file chan_dahdi.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), destroy_all_channels(), iflock, dahdi_pvt::master, monlock, dahdi_pvt::next, and dahdi_pvt::owner.
Referenced by load_module(), and unload_module().
15495 { 15496 struct dahdi_pvt *p; 15497 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15498 int i, j; 15499 #endif 15500 15501 #ifdef HAVE_PRI 15502 for (i = 0; i < NUM_SPANS; i++) { 15503 if (pris[i].pri.master != AST_PTHREADT_NULL) 15504 pthread_cancel(pris[i].pri.master); 15505 } 15506 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15507 ast_unregister_application(dahdi_send_keypad_facility_app); 15508 #ifdef HAVE_PRI_PROG_W_CAUSE 15509 ast_unregister_application(dahdi_send_callrerouting_facility_app); 15510 #endif 15511 #endif 15512 #if defined(HAVE_SS7) 15513 for (i = 0; i < NUM_SPANS; i++) { 15514 if (linksets[i].master != AST_PTHREADT_NULL) 15515 pthread_cancel(linksets[i].master); 15516 } 15517 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15518 #endif 15519 #if defined(HAVE_OPENR2) 15520 dahdi_r2_destroy_links(); 15521 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 15522 ast_unregister_application(dahdi_accept_r2_call_app); 15523 #endif 15524 15525 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15526 ast_manager_unregister("DAHDIDialOffhook"); 15527 ast_manager_unregister("DAHDIHangup"); 15528 ast_manager_unregister("DAHDITransfer"); 15529 ast_manager_unregister("DAHDIDNDoff"); 15530 ast_manager_unregister("DAHDIDNDon"); 15531 ast_manager_unregister("DAHDIShowChannels"); 15532 ast_manager_unregister("DAHDIRestart"); 15533 ast_channel_unregister(&dahdi_tech); 15534 15535 /* Hangup all interfaces if they have an owner */ 15536 ast_mutex_lock(&iflock); 15537 for (p = iflist; p; p = p->next) { 15538 if (p->owner) 15539 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 15540 } 15541 ast_mutex_unlock(&iflock); 15542 15543 ast_mutex_lock(&monlock); 15544 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 15545 pthread_cancel(monitor_thread); 15546 pthread_kill(monitor_thread, SIGURG); 15547 pthread_join(monitor_thread, NULL); 15548 } 15549 monitor_thread = AST_PTHREADT_STOP; 15550 ast_mutex_unlock(&monlock); 15551 15552 destroy_all_channels(); 15553 15554 #if defined(HAVE_PRI) 15555 for (i = 0; i < NUM_SPANS; i++) { 15556 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) 15557 pthread_join(pris[i].pri.master, NULL); 15558 for (j = 0; j < NUM_DCHANS; j++) { 15559 dahdi_close_pri_fd(&(pris[i]), j); 15560 } 15561 } 15562 #endif 15563 15564 #if defined(HAVE_SS7) 15565 for (i = 0; i < NUM_SPANS; i++) { 15566 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 15567 pthread_join(linksets[i].master, NULL); 15568 for (j = 0; j < NUM_DCHANS; j++) { 15569 dahdi_close_ss7_fd(&(linksets[i]), j); 15570 } 15571 } 15572 #endif 15573 ast_cond_destroy(&ss_thread_complete); 15574 return 0; 15575 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 17090 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14936 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_queue_frame(), find_channel(), and dahdi_pvt::owner.
Referenced by load_module().
14937 { 14938 struct dahdi_pvt *p = NULL; 14939 const char *channel = astman_get_header(m, "DAHDIChannel"); 14940 const char *number = astman_get_header(m, "Number"); 14941 int i; 14942 14943 if (ast_strlen_zero(channel)) { 14944 astman_send_error(s, m, "No channel specified"); 14945 return 0; 14946 } 14947 if (ast_strlen_zero(number)) { 14948 astman_send_error(s, m, "No number specified"); 14949 return 0; 14950 } 14951 p = find_channel(atoi(channel)); 14952 if (!p) { 14953 astman_send_error(s, m, "No such channel"); 14954 return 0; 14955 } 14956 if (!p->owner) { 14957 astman_send_error(s, m, "Channel does not have it's owner"); 14958 return 0; 14959 } 14960 for (i = 0; i < strlen(number); i++) { 14961 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 14962 dahdi_queue_frame(p, &f, NULL); 14963 } 14964 astman_send_ack(s, m, "DAHDIDialOffhook"); 14965 return 0; 14966 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14879 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_dnd(), and find_channel().
Referenced by load_module().
14880 { 14881 struct dahdi_pvt *p = NULL; 14882 const char *channel = astman_get_header(m, "DAHDIChannel"); 14883 14884 if (ast_strlen_zero(channel)) { 14885 astman_send_error(s, m, "No channel specified"); 14886 return 0; 14887 } 14888 p = find_channel(atoi(channel)); 14889 if (!p) { 14890 astman_send_error(s, m, "No such channel"); 14891 return 0; 14892 } 14893 dahdi_dnd(p, 0); 14894 astman_send_ack(s, m, "DND Disabled"); 14895 return 0; 14896 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14860 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_dnd(), and find_channel().
Referenced by load_module().
14861 { 14862 struct dahdi_pvt *p = NULL; 14863 const char *channel = astman_get_header(m, "DAHDIChannel"); 14864 14865 if (ast_strlen_zero(channel)) { 14866 astman_send_error(s, m, "No channel specified"); 14867 return 0; 14868 } 14869 p = find_channel(atoi(channel)); 14870 if (!p) { 14871 astman_send_error(s, m, "No such channel"); 14872 return 0; 14873 } 14874 dahdi_dnd(p, 1); 14875 astman_send_ack(s, m, "DND Enabled"); 14876 return 0; 14877 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14196 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
14197 { 14198 if (dahdi_restart() != 0) { 14199 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 14200 return 1; 14201 } 14202 astman_send_ack(s, m, "DAHDIRestart: Success"); 14203 return 0; 14204 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14968 of file chan_dahdi.c.
References ast_channel::accountcode, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_dnd(), get_alarms(), iflock, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.
Referenced by load_module().
14969 { 14970 struct dahdi_pvt *tmp = NULL; 14971 const char *id = astman_get_header(m, "ActionID"); 14972 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 14973 char idText[256] = ""; 14974 int channels = 0; 14975 int dahdichanquery = -1; 14976 if (!ast_strlen_zero(dahdichannel)) { 14977 dahdichanquery = atoi(dahdichannel); 14978 } 14979 14980 astman_send_ack(s, m, "DAHDI channel status will follow"); 14981 if (!ast_strlen_zero(id)) 14982 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 14983 14984 ast_mutex_lock(&iflock); 14985 14986 for (tmp = iflist; tmp; tmp = tmp->next) { 14987 if (tmp->channel > 0) { 14988 int alm; 14989 14990 /* If a specific channel is queried for, only deliver status for that channel */ 14991 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 14992 continue; 14993 14994 alm = get_alarms(tmp); 14995 channels++; 14996 if (tmp->owner) { 14997 /* Add data if we have a current call */ 14998 astman_append(s, 14999 "Event: DAHDIShowChannels\r\n" 15000 "DAHDIChannel: %d\r\n" 15001 "Channel: %s\r\n" 15002 "Uniqueid: %s\r\n" 15003 "AccountCode: %s\r\n" 15004 "Signalling: %s\r\n" 15005 "SignallingCode: %d\r\n" 15006 "Context: %s\r\n" 15007 "DND: %s\r\n" 15008 "Alarm: %s\r\n" 15009 "%s" 15010 "\r\n", 15011 tmp->channel, 15012 tmp->owner->name, 15013 tmp->owner->uniqueid, 15014 tmp->owner->accountcode, 15015 sig2str(tmp->sig), 15016 tmp->sig, 15017 tmp->context, 15018 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15019 alarm2str(alm), idText); 15020 } else { 15021 astman_append(s, 15022 "Event: DAHDIShowChannels\r\n" 15023 "DAHDIChannel: %d\r\n" 15024 "Signalling: %s\r\n" 15025 "SignallingCode: %d\r\n" 15026 "Context: %s\r\n" 15027 "DND: %s\r\n" 15028 "Alarm: %s\r\n" 15029 "%s" 15030 "\r\n", 15031 tmp->channel, sig2str(tmp->sig), tmp->sig, 15032 tmp->context, 15033 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15034 alarm2str(alm), idText); 15035 } 15036 } 15037 } 15038 15039 ast_mutex_unlock(&iflock); 15040 15041 astman_append(s, 15042 "Event: DAHDIShowChannelsComplete\r\n" 15043 "%s" 15044 "Items: %d\r\n" 15045 "\r\n", 15046 idText, 15047 channels); 15048 return 0; 15049 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14898 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_fake_event(), find_channel(), and TRANSFER.
Referenced by load_module().
14899 { 14900 struct dahdi_pvt *p = NULL; 14901 const char *channel = astman_get_header(m, "DAHDIChannel"); 14902 14903 if (ast_strlen_zero(channel)) { 14904 astman_send_error(s, m, "No channel specified"); 14905 return 0; 14906 } 14907 p = find_channel(atoi(channel)); 14908 if (!p) { 14909 astman_send_error(s, m, "No such channel"); 14910 return 0; 14911 } 14912 dahdi_fake_event(p,TRANSFER); 14913 astman_send_ack(s, m, "DAHDITransfer"); 14914 return 0; 14915 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14917 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_fake_event(), find_channel(), and HANGUP.
Referenced by load_module().
14918 { 14919 struct dahdi_pvt *p = NULL; 14920 const char *channel = astman_get_header(m, "DAHDIChannel"); 14921 14922 if (ast_strlen_zero(channel)) { 14923 astman_send_error(s, m, "No channel specified"); 14924 return 0; 14925 } 14926 p = find_channel(atoi(channel)); 14927 if (!p) { 14928 astman_send_error(s, m, "No such channel"); 14929 return 0; 14930 } 14931 dahdi_fake_event(p,HANGUP); 14932 astman_send_ack(s, m, "DAHDIHangup"); 14933 return 0; 14934 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 3780 of file chan_dahdi.c.
References alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
03781 { 03782 int x; 03783 for (x = 0; x < ARRAY_LEN(alarms); x++) { 03784 if (alarms[x].alarm & alm) 03785 return alarms[x].name; 03786 } 03787 return alm ? "Unknown Alarm" : "No Alarm"; 03788 }
| static int alloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 3584 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), dahdi_open(), dahdi_subchannel::dfd, errno, LOG_WARNING, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().
03585 { 03586 struct dahdi_bufferinfo bi; 03587 int res; 03588 if (p->subs[x].dfd >= 0) { 03589 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 03590 return -1; 03591 } 03592 03593 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 03594 if (p->subs[x].dfd <= -1) { 03595 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 03596 return -1; 03597 } 03598 03599 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 03600 if (!res) { 03601 bi.txbufpolicy = p->buf_policy; 03602 bi.rxbufpolicy = p->buf_policy; 03603 bi.numbufs = p->buf_no; 03604 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 03605 if (res < 0) { 03606 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 03607 } 03608 } else 03609 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 03610 03611 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 03612 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 03613 dahdi_close_sub(p, x); 03614 p->subs[x].dfd = -1; 03615 return -1; 03616 } 03617 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 03618 return 0; 03619 }
| static int analog_lib_handles | ( | int | signalling, | |
| int | radio, | |||
| int | oprmode | |||
| ) | [static] |
Definition at line 3865 of file chan_dahdi.c.
References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_dnd(), dahdi_exception(), dahdi_fixup(), dahdi_hangup(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), mkintf(), and mwi_thread().
03866 { 03867 switch (signalling) { 03868 case SIG_FXOLS: 03869 case SIG_FXOGS: 03870 case SIG_FXOKS: 03871 case SIG_FXSLS: 03872 case SIG_FXSGS: 03873 case SIG_FXSKS: 03874 case SIG_EMWINK: 03875 case SIG_EM: 03876 case SIG_EM_E1: 03877 case SIG_FEATD: 03878 case SIG_FEATDMF: 03879 case SIG_E911: 03880 case SIG_FGC_CAMA: 03881 case SIG_FGC_CAMAMF: 03882 case SIG_FEATB: 03883 case SIG_SFWINK: 03884 case SIG_SF: 03885 case SIG_SF_FEATD: 03886 case SIG_SF_FEATDMF: 03887 case SIG_FEATDMF_TA: 03888 case SIG_SF_FEATB: 03889 break; 03890 default: 03891 /* The rest of the function should cover the remainder of signalling types */ 03892 return 0; 03893 } 03894 03895 if (radio) 03896 return 0; 03897 03898 if (oprmode) 03899 return 0; 03900 03901 return 1; 03902 }
| static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 8790 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_cond_signal(), AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FRAME_DTMF, ast_free, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_set_callerid(), ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, buf, bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, ast_frame::frametype, ast_smdi_md_message::fwd_st, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, my_getsigstr(), my_handle_notify_message(), ast_channel::name, name, NEED_MFDETECT, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.
Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and mwi_thread().
08791 { 08792 struct ast_channel *chan = data; 08793 struct dahdi_pvt *p = chan->tech_pvt; 08794 char exten[AST_MAX_EXTENSION] = ""; 08795 char exten2[AST_MAX_EXTENSION] = ""; 08796 unsigned char buf[256]; 08797 char dtmfcid[300]; 08798 char dtmfbuf[300]; 08799 struct callerid_state *cs = NULL; 08800 char *name = NULL, *number = NULL; 08801 int distMatches; 08802 int curRingData[3]; 08803 int receivedRingT; 08804 int counter1; 08805 int counter; 08806 int samples = 0; 08807 struct ast_smdi_md_message *smdi_msg = NULL; 08808 int flags = 0; 08809 int i; 08810 int timeout; 08811 int getforward = 0; 08812 char *s1, *s2; 08813 int len = 0; 08814 int res; 08815 int idx; 08816 08817 ast_mutex_lock(&ss_thread_lock); 08818 ss_thread_count++; 08819 ast_mutex_unlock(&ss_thread_lock); 08820 /* in the bizarre case where the channel has become a zombie before we 08821 even get started here, abort safely 08822 */ 08823 if (!p) { 08824 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 08825 ast_hangup(chan); 08826 goto quit; 08827 } 08828 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 08829 idx = dahdi_get_index(chan, p, 1); 08830 if (idx < 0) { 08831 ast_log(LOG_WARNING, "Huh?\n"); 08832 ast_hangup(chan); 08833 goto quit; 08834 } 08835 if (p->dsp) 08836 ast_dsp_digitreset(p->dsp); 08837 switch (p->sig) { 08838 case SIG_FEATD: 08839 case SIG_FEATDMF: 08840 case SIG_FEATDMF_TA: 08841 case SIG_E911: 08842 case SIG_FGC_CAMAMF: 08843 case SIG_FEATB: 08844 case SIG_EMWINK: 08845 case SIG_SF_FEATD: 08846 case SIG_SF_FEATDMF: 08847 case SIG_SF_FEATB: 08848 case SIG_SFWINK: 08849 if (dahdi_wink(p, idx)) 08850 goto quit; 08851 /* Fall through */ 08852 case SIG_EM: 08853 case SIG_EM_E1: 08854 case SIG_SF: 08855 case SIG_FGC_CAMA: 08856 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 08857 if (p->dsp) 08858 ast_dsp_digitreset(p->dsp); 08859 /* set digit mode appropriately */ 08860 if (p->dsp) { 08861 if (NEED_MFDETECT(p)) 08862 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 08863 else 08864 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 08865 } 08866 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 08867 /* Wait for the first digit only if immediate=no */ 08868 if (!p->immediate) 08869 /* Wait for the first digit (up to 5 seconds). */ 08870 res = ast_waitfordigit(chan, 5000); 08871 else 08872 res = 0; 08873 if (res > 0) { 08874 /* save first char */ 08875 dtmfbuf[0] = res; 08876 switch (p->sig) { 08877 case SIG_FEATD: 08878 case SIG_SF_FEATD: 08879 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 08880 if (res > 0) 08881 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 08882 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 08883 break; 08884 case SIG_FEATDMF_TA: 08885 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 08886 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 08887 if (dahdi_wink(p, idx)) goto quit; 08888 dtmfbuf[0] = 0; 08889 /* Wait for the first digit (up to 5 seconds). */ 08890 res = ast_waitfordigit(chan, 5000); 08891 if (res <= 0) break; 08892 dtmfbuf[0] = res; 08893 /* fall through intentionally */ 08894 case SIG_FEATDMF: 08895 case SIG_E911: 08896 case SIG_FGC_CAMAMF: 08897 case SIG_SF_FEATDMF: 08898 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 08899 /* if international caca, do it again to get real ANO */ 08900 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 08901 { 08902 if (dahdi_wink(p, idx)) goto quit; 08903 dtmfbuf[0] = 0; 08904 /* Wait for the first digit (up to 5 seconds). */ 08905 res = ast_waitfordigit(chan, 5000); 08906 if (res <= 0) break; 08907 dtmfbuf[0] = res; 08908 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 08909 } 08910 if (res > 0) { 08911 /* if E911, take off hook */ 08912 if (p->sig == SIG_E911) 08913 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08914 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 08915 } 08916 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 08917 break; 08918 case SIG_FEATB: 08919 case SIG_SF_FEATB: 08920 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 08921 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 08922 break; 08923 case SIG_EMWINK: 08924 /* if we received a '*', we are actually receiving Feature Group D 08925 dial syntax, so use that mode; otherwise, fall through to normal 08926 mode 08927 */ 08928 if (res == '*') { 08929 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 08930 if (res > 0) 08931 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 08932 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 08933 break; 08934 } 08935 default: 08936 /* If we got the first digit, get the rest */ 08937 len = 1; 08938 dtmfbuf[len] = '\0'; 08939 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 08940 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 08941 timeout = matchdigittimeout; 08942 } else { 08943 timeout = gendigittimeout; 08944 } 08945 res = ast_waitfordigit(chan, timeout); 08946 if (res < 0) { 08947 ast_debug(1, "waitfordigit returned < 0...\n"); 08948 ast_hangup(chan); 08949 goto quit; 08950 } else if (res) { 08951 dtmfbuf[len++] = res; 08952 dtmfbuf[len] = '\0'; 08953 } else { 08954 break; 08955 } 08956 } 08957 break; 08958 } 08959 } 08960 if (res == -1) { 08961 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 08962 ast_hangup(chan); 08963 goto quit; 08964 } else if (res < 0) { 08965 ast_debug(1, "Got hung up before digits finished\n"); 08966 ast_hangup(chan); 08967 goto quit; 08968 } 08969 08970 if (p->sig == SIG_FGC_CAMA) { 08971 char anibuf[100]; 08972 08973 if (ast_safe_sleep(chan,1000) == -1) { 08974 ast_hangup(chan); 08975 goto quit; 08976 } 08977 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08978 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 08979 res = my_getsigstr(chan, anibuf, "#", 10000); 08980 if ((res > 0) && (strlen(anibuf) > 2)) { 08981 if (anibuf[strlen(anibuf) - 1] == '#') 08982 anibuf[strlen(anibuf) - 1] = 0; 08983 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 08984 } 08985 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 08986 } 08987 08988 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 08989 if (ast_strlen_zero(exten)) 08990 ast_copy_string(exten, "s", sizeof(exten)); 08991 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 08992 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 08993 if (exten[0] == '*') { 08994 char *stringp=NULL; 08995 ast_copy_string(exten2, exten, sizeof(exten2)); 08996 /* Parse out extension and callerid */ 08997 stringp=exten2 +1; 08998 s1 = strsep(&stringp, "*"); 08999 s2 = strsep(&stringp, "*"); 09000 if (s2) { 09001 if (!ast_strlen_zero(p->cid_num)) 09002 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09003 else 09004 ast_set_callerid(chan, s1, NULL, s1); 09005 ast_copy_string(exten, s2, sizeof(exten)); 09006 } else 09007 ast_copy_string(exten, s1, sizeof(exten)); 09008 } else if (p->sig == SIG_FEATD) 09009 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 09010 } 09011 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 09012 if (exten[0] == '*') { 09013 char *stringp=NULL; 09014 ast_copy_string(exten2, exten, sizeof(exten2)); 09015 /* Parse out extension and callerid */ 09016 stringp=exten2 +1; 09017 s1 = strsep(&stringp, "#"); 09018 s2 = strsep(&stringp, "#"); 09019 if (s2) { 09020 if (!ast_strlen_zero(p->cid_num)) 09021 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09022 else 09023 if (*(s1 + 2)) 09024 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 09025 ast_copy_string(exten, s2 + 1, sizeof(exten)); 09026 } else 09027 ast_copy_string(exten, s1 + 2, sizeof(exten)); 09028 } else 09029 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 09030 } 09031 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 09032 if (exten[0] == '*') { 09033 char *stringp=NULL; 09034 ast_copy_string(exten2, exten, sizeof(exten2)); 09035 /* Parse out extension and callerid */ 09036 stringp=exten2 +1; 09037 s1 = strsep(&stringp, "#"); 09038 s2 = strsep(&stringp, "#"); 09039 if (s2 && (*(s2 + 1) == '0')) { 09040 if (*(s2 + 2)) 09041 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 09042 } 09043 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 09044 else ast_copy_string(exten, "911", sizeof(exten)); 09045 } else 09046 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 09047 } 09048 if (p->sig == SIG_FEATB) { 09049 if (exten[0] == '*') { 09050 char *stringp=NULL; 09051 ast_copy_string(exten2, exten, sizeof(exten2)); 09052 /* Parse out extension and callerid */ 09053 stringp=exten2 +1; 09054 s1 = strsep(&stringp, "#"); 09055 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 09056 } else 09057 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 09058 } 09059 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 09060 dahdi_wink(p, idx); 09061 /* some switches require a minimum guard time between 09062 the last FGD wink and something that answers 09063 immediately. This ensures it */ 09064 if (ast_safe_sleep(chan,100)) goto quit; 09065 } 09066 dahdi_enable_ec(p); 09067 if (NEED_MFDETECT(p)) { 09068 if (p->dsp) { 09069 if (!p->hardwaredtmf) 09070 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09071 else { 09072 ast_dsp_free(p->dsp); 09073 p->dsp = NULL; 09074 } 09075 } 09076 } 09077 09078 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 09079 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 09080 if (p->dsp) ast_dsp_digitreset(p->dsp); 09081 res = ast_pbx_run(chan); 09082 if (res) { 09083 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 09084 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09085 } 09086 goto quit; 09087 } else { 09088 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 09089 sleep(2); 09090 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 09091 if (res < 0) 09092 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 09093 else 09094 sleep(1); 09095 res = ast_streamfile(chan, "ss-noservice", chan->language); 09096 if (res >= 0) 09097 ast_waitstream(chan, ""); 09098 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09099 ast_hangup(chan); 09100 goto quit; 09101 } 09102 break; 09103 case SIG_FXOLS: 09104 case SIG_FXOGS: 09105 case SIG_FXOKS: 09106 /* Read the first digit */ 09107 timeout = firstdigittimeout; 09108 /* If starting a threeway call, never timeout on the first digit so someone 09109 can use flash-hook as a "hold" feature */ 09110 if (p->subs[SUB_THREEWAY].owner) 09111 timeout = 999999; 09112 while (len < AST_MAX_EXTENSION-1) { 09113 /* Read digit unless it's supposed to be immediate, in which case the 09114 only answer is 's' */ 09115 if (p->immediate) 09116 res = 's'; 09117 else 09118 res = ast_waitfordigit(chan, timeout); 09119 timeout = 0; 09120 if (res < 0) { 09121 ast_debug(1, "waitfordigit returned < 0...\n"); 09122 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09123 ast_hangup(chan); 09124 goto quit; 09125 } else if (res) { 09126 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 09127 exten[len++]=res; 09128 exten[len] = '\0'; 09129 } 09130 if (!ast_ignore_pattern(chan->context, exten)) 09131 tone_zone_play_tone(p->subs[idx].dfd, -1); 09132 else 09133 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 09134 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 09135 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 09136 if (getforward) { 09137 /* Record this as the forwarding extension */ 09138 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 09139 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 09140 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09141 if (res) 09142 break; 09143 usleep(500000); 09144 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09145 sleep(1); 09146 memset(exten, 0, sizeof(exten)); 09147 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 09148 len = 0; 09149 getforward = 0; 09150 } else { 09151 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09152 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 09153 if (!ast_strlen_zero(p->cid_num)) { 09154 if (!p->hidecallerid) 09155 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09156 else 09157 ast_set_callerid(chan, NULL, NULL, p->cid_num); 09158 } 09159 if (!ast_strlen_zero(p->cid_name)) { 09160 if (!p->hidecallerid) 09161 ast_set_callerid(chan, NULL, p->cid_name, NULL); 09162 } 09163 ast_setstate(chan, AST_STATE_RING); 09164 dahdi_enable_ec(p); 09165 res = ast_pbx_run(chan); 09166 if (res) { 09167 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 09168 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09169 } 09170 goto quit; 09171 } 09172 } else { 09173 /* It's a match, but they just typed a digit, and there is an ambiguous match, 09174 so just set the timeout to matchdigittimeout and wait some more */ 09175 timeout = matchdigittimeout; 09176 } 09177 } else if (res == 0) { 09178 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 09179 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09180 dahdi_wait_event(p->subs[idx].dfd); 09181 ast_hangup(chan); 09182 goto quit; 09183 } else if (p->callwaiting && !strcmp(exten, "*70")) { 09184 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 09185 /* Disable call waiting if enabled */ 09186 p->callwaiting = 0; 09187 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09188 if (res) { 09189 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 09190 chan->name, strerror(errno)); 09191 } 09192 len = 0; 09193 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 09194 memset(exten, 0, sizeof(exten)); 09195 timeout = firstdigittimeout; 09196 09197 } else if (!strcmp(exten,ast_pickup_ext())) { 09198 /* Scan all channels and see if there are any 09199 * ringing channels that have call groups 09200 * that equal this channels pickup group 09201 */ 09202 if (idx == SUB_REAL) { 09203 /* Switch us from Third call to Call Wait */ 09204 if (p->subs[SUB_THREEWAY].owner) { 09205 /* If you make a threeway call and the *8# a call, it should actually 09206 look like a callwait */ 09207 alloc_sub(p, SUB_CALLWAIT); 09208 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 09209 unalloc_sub(p, SUB_THREEWAY); 09210 } 09211 dahdi_enable_ec(p); 09212 if (ast_pickup_call(chan)) { 09213 ast_debug(1, "No call pickup possible...\n"); 09214 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09215 dahdi_wait_event(p->subs[idx].dfd); 09216 } 09217 ast_hangup(chan); 09218 goto quit; 09219 } else { 09220 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 09221 ast_hangup(chan); 09222 goto quit; 09223 } 09224 09225 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 09226 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 09227 /* Disable Caller*ID if enabled */ 09228 p->hidecallerid = 1; 09229 if (chan->cid.cid_num) 09230 ast_free(chan->cid.cid_num); 09231 chan->cid.cid_num = NULL; 09232 if (chan->cid.cid_name) 09233 ast_free(chan->cid.cid_name); 09234 chan->cid.cid_name = NULL; 09235 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09236 if (res) { 09237 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 09238 chan->name, strerror(errno)); 09239 } 09240 len = 0; 09241 memset(exten, 0, sizeof(exten)); 09242 timeout = firstdigittimeout; 09243 } else if (p->callreturn && !strcmp(exten, "*69")) { 09244 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09245 break; 09246 } else if (!strcmp(exten, "*78")) { 09247 dahdi_dnd(p, 1); 09248 /* Do not disturb */ 09249 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09250 getforward = 0; 09251 memset(exten, 0, sizeof(exten)); 09252 len = 0; 09253 } else if (!strcmp(exten, "*79")) { 09254 dahdi_dnd(p, 0); 09255 /* Do not disturb */ 09256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09257 getforward = 0; 09258 memset(exten, 0, sizeof(exten)); 09259 len = 0; 09260 } else if (p->cancallforward && !strcmp(exten, "*72")) { 09261 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09262 getforward = 1; 09263 memset(exten, 0, sizeof(exten)); 09264 len = 0; 09265 } else if (p->cancallforward && !strcmp(exten, "*73")) { 09266 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 09267 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09268 memset(p->call_forward, 0, sizeof(p->call_forward)); 09269 getforward = 0; 09270 memset(exten, 0, sizeof(exten)); 09271 len = 0; 09272 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 09273 p->subs[SUB_THREEWAY].owner && 09274 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 09275 /* This is a three way call, the main call being a real channel, 09276 and we're parking the first call. */ 09277 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 09278 ast_verb(3, "Parking call to '%s'\n", chan->name); 09279 break; 09280 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 09281 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 09282 /* Enable Caller*ID if enabled */ 09283 p->hidecallerid = 0; 09284 if (chan->cid.cid_num) 09285 ast_free(chan->cid.cid_num); 09286 chan->cid.cid_num = NULL; 09287 if (chan->cid.cid_name) 09288 ast_free(chan->cid.cid_name); 09289 chan->cid.cid_name = NULL; 09290 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 09291 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09292 if (res) { 09293 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 09294 chan->name, strerror(errno)); 09295 } 09296 len = 0; 09297 memset(exten, 0, sizeof(exten)); 09298 timeout = firstdigittimeout; 09299 } else if (!strcmp(exten, "*0")) { 09300 struct ast_channel *nbridge = 09301 p->subs[SUB_THREEWAY].owner; 09302 struct dahdi_pvt *pbridge = NULL; 09303 /* set up the private struct of the bridged one, if any */ 09304 if (nbridge && ast_bridged_channel(nbridge)) 09305 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 09306 if (nbridge && pbridge && 09307 (nbridge->tech == &dahdi_tech) && 09308 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 09309 ISTRUNK(pbridge)) { 09310 int func = DAHDI_FLASH; 09311 /* Clear out the dial buffer */ 09312 p->dop.dialstr[0] = '\0'; 09313 /* flash hookswitch */ 09314 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09315 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09316 nbridge->name, strerror(errno)); 09317 } 09318 swap_subs(p, SUB_REAL, SUB_THREEWAY); 09319 unalloc_sub(p, SUB_THREEWAY); 09320 p->owner = p->subs[SUB_REAL].owner; 09321 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 09322 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 09323 ast_hangup(chan); 09324 goto quit; 09325 } else { 09326 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09327 dahdi_wait_event(p->subs[idx].dfd); 09328 tone_zone_play_tone(p->subs[idx].dfd, -1); 09329 swap_subs(p, SUB_REAL, SUB_THREEWAY); 09330 unalloc_sub(p, SUB_THREEWAY); 09331 p->owner = p->subs[SUB_REAL].owner; 09332 ast_hangup(chan); 09333 goto quit; 09334 } 09335 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 09336 ((exten[0] != '*') || (strlen(exten) > 2))) { 09337 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context); 09338 break; 09339 } 09340 if (!timeout) 09341 timeout = gendigittimeout; 09342 if (len && !ast_ignore_pattern(chan->context, exten)) 09343 tone_zone_play_tone(p->subs[idx].dfd, -1); 09344 } 09345 break; 09346 case SIG_FXSLS: 09347 case SIG_FXSGS: 09348 case SIG_FXSKS: 09349 /* check for SMDI messages */ 09350 if (p->use_smdi && p->smdi_iface) { 09351 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 09352 09353 if (smdi_msg != NULL) { 09354 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 09355 09356 if (smdi_msg->type == 'B') 09357 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 09358 else if (smdi_msg->type == 'N') 09359 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 09360 09361 ast_debug(1, "Received SMDI message on %s\n", chan->name); 09362 } else { 09363 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 09364 } 09365 } 09366 09367 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 09368 number = smdi_msg->calling_st; 09369 09370 /* If we want caller id, we're in a prering state due to a polarity reversal 09371 * and we're set to use a polarity reversal to trigger the start of caller id, 09372 * grab the caller id and wait for ringing to start... */ 09373 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 09374 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 09375 /* If set to use DTMF CID signalling, listen for DTMF */ 09376 if (p->cid_signalling == CID_SIG_DTMF) { 09377 int k = 0; 09378 cs = NULL; 09379 ast_debug(1, "Receiving DTMF cid on " 09380 "channel %s\n", chan->name); 09381 dahdi_setlinear(p->subs[idx].dfd, 0); 09382 res = 2000; 09383 for (;;) { 09384 struct ast_frame *f; 09385 res = ast_waitfor(chan, res); 09386 if (res <= 0) { 09387 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 09388 "Exiting simple switch\n"); 09389 ast_hangup(chan); 09390 goto quit; 09391 } 09392 f = ast_read(chan); 09393 if (!f) 09394 break; 09395 if (f->frametype == AST_FRAME_DTMF) { 09396 dtmfbuf[k++] = f->subclass; 09397 ast_debug(1, "CID got digit '%c'\n", f->subclass); 09398 res = 2000; 09399 } 09400 ast_frfree(f); 09401 if (chan->_state == AST_STATE_RING || 09402 chan->_state == AST_STATE_RINGING) 09403 break; /* Got ring */ 09404 } 09405 dtmfbuf[k] = '\0'; 09406 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09407 /* Got cid and ring. */ 09408 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 09409 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 09410 ast_debug(1, "CID is '%s', flags %d\n", 09411 dtmfcid, flags); 09412 /* If first byte is NULL, we have no cid */ 09413 if (!ast_strlen_zero(dtmfcid)) 09414 number = dtmfcid; 09415 else 09416 number = NULL; 09417 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 09418 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 09419 cs = callerid_new(p->cid_signalling); 09420 if (cs) { 09421 samples = 0; 09422 #if 1 09423 bump_gains(p); 09424 #endif 09425 /* Take out of linear mode for Caller*ID processing */ 09426 dahdi_setlinear(p->subs[idx].dfd, 0); 09427 09428 /* First we wait and listen for the Caller*ID */ 09429 for (;;) { 09430 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 09431 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 09432 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 09433 callerid_free(cs); 09434 ast_hangup(chan); 09435 goto quit; 09436 } 09437 if (i & DAHDI_IOMUX_SIGEVENT) { 09438 res = dahdi_get_event(p->subs[idx].dfd); 09439 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 09440 09441 if (p->cid_signalling == CID_SIG_V23_JP) { 09442 if (res == DAHDI_EVENT_RINGBEGIN) { 09443 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09444 usleep(1); 09445 } 09446 } else { 09447 res = 0; 09448 break; 09449 } 09450 } else if (i & DAHDI_IOMUX_READ) { 09451 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 09452 if (res < 0) { 09453 if (errno != ELAST) { 09454 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 09455 callerid_free(cs); 09456 ast_hangup(chan); 09457 goto quit; 09458 } 09459 break; 09460 } 09461 samples += res; 09462 09463 if (p->cid_signalling == CID_SIG_V23_JP) { 09464 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 09465 } else { 09466 res = callerid_feed(cs, buf, res, AST_LAW(p)); 09467 } 09468 09469 if (res < 0) { 09470 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 09471 break; 09472 } else if (res) 09473 break; 09474 else if (samples > (8000 * 10)) 09475 break; 09476 } 09477 } 09478 if (res == 1) { 09479 callerid_get(cs, &name, &number, &flags); 09480 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 09481 } 09482 09483 if (p->cid_signalling == CID_SIG_V23_JP) { 09484 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09485 usleep(1); 09486 res = 4000; 09487 } else { 09488 09489 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 09490 res = 2000; 09491 } 09492 09493 for (;;) { 09494 struct ast_frame *f; 09495 res = ast_waitfor(chan, res); 09496 if (res <= 0) { 09497 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 09498 "Exiting simple switch\n"); 09499 ast_hangup(chan); 09500 goto quit; 09501 } 09502 if (!(f = ast_read(chan))) { 09503 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 09504 ast_hangup(chan); 09505 goto quit; 09506 } 09507 ast_frfree(f); 09508 if (chan->_state == AST_STATE_RING || 09509 chan->_state == AST_STATE_RINGING) 09510 break; /* Got ring */ 09511 } 09512 09513 /* We must have a ring by now, so, if configured, lets try to listen for 09514 * distinctive ringing */ 09515 if (p->usedistinctiveringdetection) { 09516 len = 0; 09517 distMatches = 0; 09518 /* Clear the current ring data array so we dont have old data in it. */ 09519 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 09520 curRingData[receivedRingT] = 0; 09521 receivedRingT = 0; 09522 counter = 0; 09523 counter1 = 0; 09524 /* Check to see if context is what it should be, if not set to be. */ 09525 if (strcmp(p->context,p->defcontext) != 0) { 09526 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 09527 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 09528 } 09529 09530 for (;;) { 09531 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 09532 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 09533 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 09534 callerid_free(cs); 09535 ast_hangup(chan); 09536 goto quit; 09537 } 09538 if (i & DAHDI_IOMUX_SIGEVENT) { 09539 res = dahdi_get_event(p->subs[idx].dfd); 09540 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 09541 res = 0; 09542 /* Let us detect distinctive ring */ 09543 09544 curRingData[receivedRingT] = p->ringt; 09545 09546 if (p->ringt < p->ringt_base/2) 09547 break; 09548 /* Increment the ringT counter so we can match it against 09549 values in chan_dahdi.conf for distinctive ring */ 09550 if (++receivedRingT == ARRAY_LEN(curRingData)) 09551 break; 09552 } else if (i & DAHDI_IOMUX_READ) { 09553 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 09554 if (res < 0) { 09555 if (errno != ELAST) { 09556 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 09557 callerid_free(cs); 09558 ast_hangup(chan); 09559 goto quit; 09560 } 09561 break; 09562 } 09563 if (p->ringt > 0) { 09564 if (!(--p->ringt)) { 09565 res = -1; 09566 break; 09567 } 09568 } 09569 } 09570 } 09571 /* this only shows up if you have n of the dring patterns filled in */ 09572 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 09573 for (counter = 0; counter < 3; counter++) { 09574 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 09575 channel */ 09576 distMatches = 0; 09577 for (counter1 = 0; counter1 < 3; counter1++) { 09578 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 09579 if (p->drings.ringnum[counter].ring[counter1] == -1) { 09580 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 09581 curRingData[counter1]); 09582 distMatches++; 09583 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 09584 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 09585 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 09586 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 09587 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 09588 distMatches++; 09589 } 09590 } 09591 09592 if (distMatches == 3) { 09593 /* The ring matches, set the context to whatever is for distinctive ring.. */ 09594 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 09595 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 09596 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 09597 break; 09598 } 09599 } 09600 } 09601 /* Restore linear mode (if appropriate) for Caller*ID processing */ 09602 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09603 #if 1 09604 restore_gains(p); 09605 #endif 09606 } else 09607 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 09608 } else { 09609 ast_log(LOG_WARNING, "Channel %s in prering " 09610 "state, but I have nothing to do. " 09611 "Terminating simple switch, should be " 09612 "restarted by the actual ring.\n", 09613 chan->name); 09614 ast_hangup(chan); 09615 goto quit; 09616 } 09617 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 09618 if (p->cid_signalling == CID_SIG_DTMF) { 09619 int k = 0; 09620 cs = NULL; 09621 dahdi_setlinear(p->subs[idx].dfd, 0); 09622 res = 2000; 09623 for (;;) { 09624 struct ast_frame *f; 09625 res = ast_waitfor(chan, res); 09626 if (res <= 0) { 09627 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 09628 "Exiting simple switch\n"); 09629 ast_hangup(chan); 09630 return NULL; 09631 } 09632 f = ast_read(chan); 09633 if (f->frametype == AST_FRAME_DTMF) { 09634 dtmfbuf[k++] = f->subclass; 09635 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 09636 res = 2000; 09637 } 09638 ast_frfree(f); 09639 09640 if (p->ringt_base == p->ringt) 09641 break; 09642 } 09643 dtmfbuf[k] = '\0'; 09644 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09645 /* Got cid and ring. */ 09646 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 09647 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 09648 dtmfcid, flags); 09649 /* If first byte is NULL, we have no cid */ 09650 if (!ast_strlen_zero(dtmfcid)) 09651 number = dtmfcid; 09652 else 09653 number = NULL; 09654 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 09655 } else { 09656 /* FSK Bell202 callerID */ 09657 cs = callerid_new(p->cid_signalling); 09658 if (cs) { 09659 #if 1 09660 bump_gains(p); 09661 #endif 09662 samples = 0; 09663 len = 0; 09664 distMatches = 0; 09665 /* Clear the current ring data array so we dont have old data in it. */ 09666 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 09667 curRingData[receivedRingT] = 0; 09668 receivedRingT = 0; 09669 counter = 0; 09670 counter1 = 0; 09671 /* Check to see if context is what it should be, if not set to be. */ 09672 if (strcmp(p->context,p->defcontext) != 0) { 09673 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 09674 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 09675 } 09676 09677 /* Take out of linear mode for Caller*ID processing */ 09678 dahdi_setlinear(p->subs[idx].dfd, 0); 09679 for (;;) { 09680 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 09681 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 09682 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 09683 callerid_free(cs); 09684 ast_hangup(chan); 09685 goto quit; 09686 } 09687 if (i & DAHDI_IOMUX_SIGEVENT) { 09688 res = dahdi_get_event(p->subs[idx].dfd); 09689 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 09690 /* If we get a PR event, they hung up while processing calerid */ 09691 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 09692 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 09693 p->polarity = POLARITY_IDLE; 09694 callerid_free(cs); 09695 ast_hangup(chan); 09696 goto quit; 09697 } 09698 res = 0; 09699 /* Let us detect callerid when the telco uses distinctive ring */ 09700 09701 curRingData[receivedRingT] = p->ringt; 09702 09703 if (p->ringt < p->ringt_base/2) 09704 break; 09705 /* Increment the ringT counter so we can match it against 09706 values in chan_dahdi.conf for distinctive ring */ 09707 if (++receivedRingT == ARRAY_LEN(curRingData)) 09708 break; 09709 } else if (i & DAHDI_IOMUX_READ) { 09710 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 09711 if (res < 0) { 09712 if (errno != ELAST) { 09713 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 09714 callerid_free(cs); 09715 ast_hangup(chan); 09716 goto quit; 09717 } 09718 break; 09719 } 09720 if (p->ringt > 0) { 09721 if (!(--p->ringt)) { 09722 res = -1; 09723 break; 09724 } 09725 } 09726 samples += res; 09727 res = callerid_feed(cs, buf, res, AST_LAW(p)); 09728 if (res < 0) { 09729 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 09730 break; 09731 } else if (res) 09732 break; 09733 else if (samples > (8000 * 10)) 09734 break; 09735 } 09736 } 09737 if (res == 1) { 09738 callerid_get(cs, &name, &number, &flags); 09739 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 09740 } 09741 if (distinctiveringaftercid == 1) { 09742 /* Clear the current ring data array so we dont have old data in it. */ 09743 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 09744 curRingData[receivedRingT] = 0; 09745 } 09746 receivedRingT = 0; 09747 ast_verb(3, "Detecting post-CID distinctive ring\n"); 09748 for (;;) { 09749 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 09750 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 09751 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 09752 callerid_free(cs); 09753 ast_hangup(chan); 09754 goto quit; 09755 } 09756 if (i & DAHDI_IOMUX_SIGEVENT) { 09757 res = dahdi_get_event(p->subs[idx].dfd); 09758 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 09759 res = 0; 09760 /* Let us detect callerid when the telco uses distinctive ring */ 09761 09762 curRingData[receivedRingT] = p->ringt; 09763 09764 if (p->ringt < p->ringt_base/2) 09765 break; 09766 /* Increment the ringT counter so we can match it against 09767 values in chan_dahdi.conf for distinctive ring */ 09768 if (++receivedRingT == ARRAY_LEN(curRingData)) 09769 break; 09770 } else if (i & DAHDI_IOMUX_READ) { 09771 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 09772 if (res < 0) { 09773 if (errno != ELAST) { 09774 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 09775 callerid_free(cs); 09776 ast_hangup(chan); 09777 goto quit; 09778 } 09779 break; 09780 } 09781 if (p->ringt > 0) { 09782 if (!(--p->ringt)) { 09783 res = -1; 09784 break; 09785 } 09786 } 09787 } 09788 } 09789 } 09790 if (p->usedistinctiveringdetection) { 09791 /* this only shows up if you have n of the dring patterns filled in */ 09792 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 09793 09794 for (counter = 0; counter < 3; counter++) { 09795 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 09796 channel */ 09797 /* this only shows up if you have n of the dring patterns filled in */ 09798 ast_verb(3, "Checking %d,%d,%d\n", 09799 p->drings.ringnum[counter].ring[0], 09800 p->drings.ringnum[counter].ring[1], 09801 p->drings.ringnum[counter].ring[2]); 09802 distMatches = 0; 09803 for (counter1 = 0; counter1 < 3; counter1++) { 09804 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 09805 if (p->drings.ringnum[counter].ring[counter1] == -1) { 09806 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 09807 curRingData[counter1]); 09808 distMatches++; 09809 } 09810 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 09811 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 09812 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 09813 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 09814 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 09815 distMatches++; 09816 } 09817 } 09818 if (distMatches == 3) { 09819 /* The ring matches, set the context to whatever is for distinctive ring.. */ 09820 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 09821 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 09822 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 09823 break; 09824 } 09825 } 09826 } 09827 /* Restore linear mode (if appropriate) for Caller*ID processing */ 09828 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09829 #if 1 09830 restore_gains(p); 09831 #endif 09832 if (res < 0) { 09833 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 09834 } 09835 } else 09836 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 09837 } 09838 } else 09839 cs = NULL; 09840 09841 if (number) 09842 ast_shrink_phone_number(number); 09843 ast_set_callerid(chan, number, name, number); 09844 09845 if (smdi_msg) 09846 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 09847 09848 if (cs) 09849 callerid_free(cs); 09850 09851 my_handle_notify_message(chan, p, flags, -1); 09852 09853 ast_setstate(chan, AST_STATE_RING); 09854 chan->rings = 1; 09855 p->ringt = p->ringt_base; 09856 res = ast_pbx_run(chan); 09857 if (res) { 09858 ast_hangup(chan); 09859 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 09860 } 09861 goto quit; 09862 default: 09863 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 09864 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09865 if (res < 0) 09866 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 09867 } 09868 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09869 if (res < 0) 09870 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 09871 ast_hangup(chan); 09872 quit: 09873 ast_mutex_lock(&ss_thread_lock); 09874 ss_thread_count--; 09875 ast_cond_signal(&ss_thread_complete); 09876 ast_mutex_unlock(&ss_thread_lock); 09877 return NULL; 09878 }
| static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1550 of file chan_dahdi.c.
References ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALRECALL, ANALOG_TONE_DIALTONE, ANALOG_TONE_INFO, ANALOG_TONE_RINGTONE, and ANALOG_TONE_STUTTER.
Referenced by my_play_tone().
01551 { 01552 switch (tone) { 01553 case ANALOG_TONE_RINGTONE: 01554 return DAHDI_TONE_RINGTONE; 01555 case ANALOG_TONE_STUTTER: 01556 return DAHDI_TONE_STUTTER; 01557 case ANALOG_TONE_CONGESTION: 01558 return DAHDI_TONE_CONGESTION; 01559 case ANALOG_TONE_DIALTONE: 01560 return DAHDI_TONE_DIALTONE; 01561 case ANALOG_TONE_DIALRECALL: 01562 return DAHDI_TONE_DIALRECALL; 01563 case ANALOG_TONE_INFO: 01564 return DAHDI_TONE_INFO; 01565 default: 01566 return -1; 01567 } 01568 }
| static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1570 of file chan_dahdi.c.
References ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, ast_log(), LOG_ERROR, SUB_CALLWAIT, SUB_REAL, and SUB_THREEWAY.
Referenced by my_allocate_sub(), my_conf_add(), my_conf_del(), my_dial_digits(), my_get_sub_fd(), my_handle_dtmfup(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().
01571 { 01572 int index; 01573 01574 switch (analogsub) { 01575 case ANALOG_SUB_REAL: 01576 index = SUB_REAL; 01577 break; 01578 case ANALOG_SUB_CALLWAIT: 01579 index = SUB_CALLWAIT; 01580 break; 01581 case ANALOG_SUB_THREEWAY: 01582 index = SUB_THREEWAY; 01583 break; 01584 default: 01585 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01586 index = SUB_REAL; 01587 } 01588 01589 return index; 01590 }
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6745 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_unlock, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, LOG_WARNING, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().
06746 { 06747 /* In order to transfer, we need at least one of the channels to 06748 actually be in a call bridge. We can't conference two applications 06749 together (but then, why would we want to?) */ 06750 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 06751 /* The three-way person we're about to transfer to could still be in MOH, so 06752 stop if now if appropriate */ 06753 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 06754 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 06755 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 06756 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 06757 } 06758 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 06759 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 06760 } 06761 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 06762 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 06763 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 06764 return -1; 06765 } 06766 /* Orphan the channel after releasing the lock */ 06767 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 06768 unalloc_sub(p, SUB_THREEWAY); 06769 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06770 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06771 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 06772 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 06773 } 06774 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 06775 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 06776 } 06777 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 06778 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 06779 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 06780 return -1; 06781 } 06782 /* Three-way is now the REAL */ 06783 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06784 ast_channel_unlock(p->subs[SUB_REAL].owner); 06785 unalloc_sub(p, SUB_THREEWAY); 06786 /* Tell the caller not to hangup */ 06787 return 1; 06788 } else { 06789 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 06790 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 06791 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 06792 return -1; 06793 } 06794 return 0; 06795 }
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | reason, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 11768 of file chan_dahdi.c.
References analog_available(), analog_lib_handles(), dahdi_pvt::channel, dahdi_pvt::group, dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, dahdi_pvt::oprmode, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, dahdi_pvt::sig, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, and dahdi_pvt::sig_pvt.
Referenced by __ast_string_field_ptr_build_va(), ast_logger_register_level(), and dahdi_request().
11769 { 11770 /* First, check group matching */ 11771 if (groupmatch) { 11772 if ((p->group & groupmatch) != groupmatch) 11773 return 0; 11774 *groupmatched = 1; 11775 } 11776 /* Check to see if we have a channel match */ 11777 if (channelmatch != -1) { 11778 if (p->channel != channelmatch) 11779 return 0; 11780 *channelmatched = 1; 11781 } 11782 11783 if (p->inalarm) 11784 return 0; 11785 11786 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 11787 return analog_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched); 11788 11789 #ifdef HAVE_PRI 11790 switch (p->sig) { 11791 case SIG_PRI_LIB_HANDLE_CASES: 11792 return sig_pri_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched); 11793 default: 11794 break; 11795 } 11796 #endif 11797 11798 if (p->locallyblocked || p->remotelyblocked) { 11799 return 0; 11800 } 11801 11802 /* If no owner definitely available */ 11803 if (!p->owner) { 11804 #ifdef HAVE_SS7 11805 /* Trust SS7 */ 11806 if (p->ss7) { 11807 if (p->ss7call) { 11808 return 0; 11809 } else { 11810 return 1; 11811 } 11812 } 11813 #endif 11814 #ifdef HAVE_OPENR2 11815 /* Trust MFC/R2 */ 11816 if (p->mfcr2) { 11817 if (p->mfcr2call) { 11818 return 0; 11819 } else { 11820 return 1; 11821 } 11822 } 11823 #endif 11824 return 1; 11825 } 11826 11827 return 0; 11828 }
| static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
| const char * | value, | |||
| int | reload, | |||
| int | lineno, | |||
| int * | found_pseudo | |||
| ) | [static] |
Definition at line 15593 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), dahdi_pvt::sig, sig2str, and strsep().
Referenced by process_dahdi().
15594 { 15595 char *c, *chan; 15596 int x, start, finish; 15597 struct dahdi_pvt *tmp; 15598 15599 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 15600 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 15601 return -1; 15602 } 15603 15604 c = ast_strdupa(value); 15605 15606 while ((chan = strsep(&c, ","))) { 15607 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 15608 /* Range */ 15609 } else if (sscanf(chan, "%30d", &start)) { 15610 /* Just one */ 15611 finish = start; 15612 } else if (!strcasecmp(chan, "pseudo")) { 15613 finish = start = CHAN_PSEUDO; 15614 if (found_pseudo) 15615 *found_pseudo = 1; 15616 } else { 15617 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 15618 return -1; 15619 } 15620 if (finish < start) { 15621 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 15622 x = finish; 15623 finish = start; 15624 start = x; 15625 } 15626 15627 for (x = start; x <= finish; x++) { 15628 tmp = mkintf(x, conf, reload); 15629 15630 if (tmp) { 15631 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 15632 } else { 15633 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 15634 (reload == 1) ? "reconfigure" : "register", value); 15635 return -1; 15636 } 15637 } 15638 } 15639 15640 return 0; 15641 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4324 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and dahdi_pvt::txgain.
Referenced by analog_ss_thread(), mwi_thread(), and my_start_cid_detect().
04325 { 04326 int res; 04327 04328 /* Bump receive gain by value stored in cid_rxgain */ 04329 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 04330 if (res) { 04331 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 04332 return -1; 04333 } 04334 04335 return 0; 04336 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 9886 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
09887 { 09888 int x; 09889 int sum = 0; 09890 09891 if (!len) 09892 return 0; 09893 09894 for (x = 0; x < len; x++) 09895 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 09896 09897 return sum / len; 09898 }
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6797 of file chan_dahdi.c.
References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), and my_check_for_conference().
06798 { 06799 struct dahdi_confinfo ci; 06800 /* Fine if we already have a master, etc */ 06801 if (p->master || (p->confno > -1)) 06802 return 0; 06803 memset(&ci, 0, sizeof(ci)); 06804 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 06805 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 06806 return 0; 06807 } 06808 /* If we have no master and don't have a confno, then 06809 if we're in a conference, it's probably a MeetMe room or 06810 some such, so don't let us 3-way out! */ 06811 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 06812 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 06813 return 1; 06814 } 06815 return 0; 06816 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | index, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 3904 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, and LOG_WARNING.
Referenced by my_complete_conference_update(), my_conf_add(), and update_conf().
03905 { 03906 /* If the conference already exists, and we're already in it 03907 don't bother doing anything */ 03908 struct dahdi_confinfo zi; 03909 03910 memset(&zi, 0, sizeof(zi)); 03911 zi.chan = 0; 03912 03913 if (slavechannel > 0) { 03914 /* If we have only one slave, do a digital mon */ 03915 zi.confmode = DAHDI_CONF_DIGITALMON; 03916 zi.confno = slavechannel; 03917 } else { 03918 if (!idx) { 03919 /* Real-side and pseudo-side both participate in conference */ 03920 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 03921 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 03922 } else 03923 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03924 zi.confno = p->confno; 03925 } 03926 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 03927 return 0; 03928 if (c->dfd < 0) 03929 return 0; 03930 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 03931 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 03932 return -1; 03933 } 03934 if (slavechannel < 1) { 03935 p->confno = zi.confno; 03936 } 03937 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 03938 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 03939 return 0; 03940 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | index | |||
| ) | [static] |
Definition at line 3953 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), and LOG_WARNING.
Referenced by dahdi_unlink(), my_conf_del(), and update_conf().
03954 { 03955 struct dahdi_confinfo zi; 03956 if (/* Can't delete if there's no dfd */ 03957 (c->dfd < 0) || 03958 /* Don't delete from the conference if it's not our conference */ 03959 !isourconf(p, c) 03960 /* Don't delete if we don't think it's conferenced at all (implied) */ 03961 ) return 0; 03962 memset(&zi, 0, sizeof(zi)); 03963 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 03964 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 03965 return -1; 03966 } 03967 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 03968 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 03969 return 0; 03970 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5780 of file chan_dahdi.c.
References analog_answer(), analog_lib_handles(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, dahdi_pvt::channel, dahdi_get_index(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, sig_pri_answer(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::span, SUB_REAL, and ast_channel::tech_pvt.
05781 { 05782 struct dahdi_pvt *p = ast->tech_pvt; 05783 int res = 0; 05784 int idx; 05785 ast_setstate(ast, AST_STATE_UP); 05786 ast_mutex_lock(&p->lock); 05787 idx = dahdi_get_index(ast, p, 0); 05788 if (idx < 0) 05789 idx = SUB_REAL; 05790 /* nothing to do if a radio channel */ 05791 if ((p->radio || (p->oprmode < 0))) { 05792 ast_mutex_unlock(&p->lock); 05793 return 0; 05794 } 05795 05796 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05797 res = analog_answer(p->sig_pvt, ast); 05798 ast_mutex_unlock(&p->lock); 05799 return res; 05800 } 05801 05802 switch (p->sig) { 05803 #ifdef HAVE_PRI 05804 case SIG_PRI_LIB_HANDLE_CASES: 05805 res = sig_pri_answer(p->sig_pvt, ast); 05806 ast_mutex_unlock(&p->lock); 05807 return res; 05808 #endif 05809 #ifdef HAVE_SS7 05810 case SIG_SS7: 05811 if (!ss7_grab(p, p->ss7)) { 05812 p->proceeding = 1; 05813 res = isup_anm(p->ss7->ss7, p->ss7call); 05814 ss7_rel(p->ss7); 05815 } else { 05816 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 05817 res = -1; 05818 } 05819 break; 05820 #endif 05821 #ifdef HAVE_OPENR2 05822 case SIG_MFCR2: 05823 if (!p->mfcr2_call_accepted) { 05824 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 05825 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 05826 p->mfcr2_answer_pending = 1; 05827 if (p->mfcr2_charge_calls) { 05828 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 05829 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 05830 } else { 05831 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 05832 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 05833 } 05834 } else { 05835 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 05836 dahdi_r2_answer(p); 05837 } 05838 break; 05839 #endif 05840 case 0: 05841 ast_mutex_unlock(&p->lock); 05842 return 0; 05843 default: 05844 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 05845 res = -1; 05846 } 05847 ast_mutex_unlock(&p->lock); 05848 return res; 05849 }
| static enum ast_bridge_result dahdi_bridge | ( | struct ast_channel * | c0, | |
| struct ast_channel * | c1, | |||
| int | flags, | |||
| struct ast_frame ** | fo, | |||
| struct ast_channel ** | rc, | |||
| int | timeoutms | |||
| ) | [static] |
Definition at line 6362 of file chan_dahdi.c.
References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::master, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, and update_conf().
06363 { 06364 struct ast_channel *who; 06365 struct dahdi_pvt *p0, *p1, *op0, *op1; 06366 struct dahdi_pvt *master = NULL, *slave = NULL; 06367 struct ast_frame *f; 06368 int inconf = 0; 06369 int nothingok = 1; 06370 int ofd0, ofd1; 06371 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 06372 int os0 = -1, os1 = -1; 06373 int priority = 0; 06374 struct ast_channel *oc0, *oc1; 06375 enum ast_bridge_result res; 06376 #ifdef PRI_2BCT 06377 q931_call *q931c0; 06378 q931_call *q931c1; 06379 #endif 06380 06381 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 06382 There is code below to handle it properly until DTMF is actually seen, 06383 but due to currently unresolved issues it's ignored... 06384 */ 06385 06386 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 06387 return AST_BRIDGE_FAILED_NOWARN; 06388 06389 ast_channel_lock(c0); 06390 while (ast_channel_trylock(c1)) { 06391 CHANNEL_DEADLOCK_AVOIDANCE(c0); 06392 } 06393 06394 p0 = c0->tech_pvt; 06395 p1 = c1->tech_pvt; 06396 /* cant do pseudo-channels here */ 06397 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 06398 ast_channel_unlock(c0); 06399 ast_channel_unlock(c1); 06400 return AST_BRIDGE_FAILED_NOWARN; 06401 } 06402 06403 oi0 = dahdi_get_index(c0, p0, 0); 06404 oi1 = dahdi_get_index(c1, p1, 0); 06405 if ((oi0 < 0) || (oi1 < 0)) { 06406 ast_channel_unlock(c0); 06407 ast_channel_unlock(c1); 06408 return AST_BRIDGE_FAILED; 06409 } 06410 06411 op0 = p0 = c0->tech_pvt; 06412 op1 = p1 = c1->tech_pvt; 06413 ofd0 = c0->fds[0]; 06414 ofd1 = c1->fds[0]; 06415 oc0 = p0->owner; 06416 oc1 = p1->owner; 06417 06418 if (ast_mutex_trylock(&p0->lock)) { 06419 /* Don't block, due to potential for deadlock */ 06420 ast_channel_unlock(c0); 06421 ast_channel_unlock(c1); 06422 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 06423 return AST_BRIDGE_RETRY; 06424 } 06425 if (ast_mutex_trylock(&p1->lock)) { 06426 /* Don't block, due to potential for deadlock */ 06427 ast_mutex_unlock(&p0->lock); 06428 ast_channel_unlock(c0); 06429 ast_channel_unlock(c1); 06430 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 06431 return AST_BRIDGE_RETRY; 06432 } 06433 06434 #if defined(HAVE_PRI) 06435 if ((dahdi_sig_pri_lib_handles(p0->sig) 06436 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 06437 || (dahdi_sig_pri_lib_handles(p1->sig) 06438 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 06439 /* 06440 * PRI nobch channels (hold and call waiting) are equivalent to 06441 * pseudo channels and cannot be done here. 06442 */ 06443 ast_mutex_unlock(&p0->lock); 06444 ast_mutex_unlock(&p1->lock); 06445 ast_channel_unlock(c0); 06446 ast_channel_unlock(c1); 06447 return AST_BRIDGE_FAILED_NOWARN; 06448 } 06449 #endif /* defined(HAVE_PRI) */ 06450 06451 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 06452 if (p0->owner && p1->owner) { 06453 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 06454 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 06455 master = p0; 06456 slave = p1; 06457 inconf = 1; 06458 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 06459 master = p1; 06460 slave = p0; 06461 inconf = 1; 06462 } else { 06463 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 06464 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 06465 p0->channel, 06466 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 06467 p0->subs[SUB_REAL].inthreeway, p0->channel, 06468 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 06469 p1->subs[SUB_REAL].inthreeway); 06470 } 06471 nothingok = 0; 06472 } 06473 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 06474 if (p1->subs[SUB_THREEWAY].inthreeway) { 06475 master = p1; 06476 slave = p0; 06477 nothingok = 0; 06478 } 06479 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 06480 if (p0->subs[SUB_THREEWAY].inthreeway) { 06481 master = p0; 06482 slave = p1; 06483 nothingok = 0; 06484 } 06485 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 06486 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 06487 don't put us in anything */ 06488 if (p1->subs[SUB_CALLWAIT].inthreeway) { 06489 master = p1; 06490 slave = p0; 06491 nothingok = 0; 06492 } 06493 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 06494 /* Same as previous */ 06495 if (p0->subs[SUB_CALLWAIT].inthreeway) { 06496 master = p0; 06497 slave = p1; 06498 nothingok = 0; 06499 } 06500 } 06501 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 06502 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 06503 if (master && slave) { 06504 /* Stop any tones, or play ringtone as appropriate. If they're bridged 06505 in an active threeway call with a channel that is ringing, we should 06506 indicate ringing. */ 06507 if ((oi1 == SUB_THREEWAY) && 06508 p1->subs[SUB_THREEWAY].inthreeway && 06509 p1->subs[SUB_REAL].owner && 06510 p1->subs[SUB_REAL].inthreeway && 06511 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 06512 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 06513 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 06514 os1 = p1->subs[SUB_REAL].owner->_state; 06515 } else { 06516 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 06517 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 06518 } 06519 if ((oi0 == SUB_THREEWAY) && 06520 p0->subs[SUB_THREEWAY].inthreeway && 06521 p0->subs[SUB_REAL].owner && 06522 p0->subs[SUB_REAL].inthreeway && 06523 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 06524 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 06525 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 06526 os0 = p0->subs[SUB_REAL].owner->_state; 06527 } else { 06528 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 06529 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 06530 } 06531 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 06532 if (!p0->echocanbridged || !p1->echocanbridged) { 06533 /* Disable echo cancellation if appropriate */ 06534 dahdi_disable_ec(p0); 06535 dahdi_disable_ec(p1); 06536 } 06537 } 06538 dahdi_link(slave, master); 06539 master->inconference = inconf; 06540 } else if (!nothingok) 06541 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 06542 06543 update_conf(p0); 06544 update_conf(p1); 06545 t0 = p0->subs[SUB_REAL].inthreeway; 06546 t1 = p1->subs[SUB_REAL].inthreeway; 06547 06548 ast_mutex_unlock(&p0->lock); 06549 ast_mutex_unlock(&p1->lock); 06550 06551 ast_channel_unlock(c0); 06552 ast_channel_unlock(c1); 06553 06554 /* Native bridge failed */ 06555 if ((!master || !slave) && !nothingok) { 06556 dahdi_enable_ec(p0); 06557 dahdi_enable_ec(p1); 06558 return AST_BRIDGE_FAILED; 06559 } 06560 06561 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 06562 06563 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 06564 disable_dtmf_detect(op0); 06565 06566 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 06567 disable_dtmf_detect(op1); 06568 06569 for (;;) { 06570 struct ast_channel *c0_priority[2] = {c0, c1}; 06571 struct ast_channel *c1_priority[2] = {c1, c0}; 06572 06573 /* Here's our main loop... Start by locking things, looking for private parts, 06574 and then balking if anything is wrong */ 06575 06576 ast_channel_lock(c0); 06577 while (ast_channel_trylock(c1)) { 06578 CHANNEL_DEADLOCK_AVOIDANCE(c0); 06579 } 06580 06581 p0 = c0->tech_pvt; 06582 p1 = c1->tech_pvt; 06583 06584 if (op0 == p0) 06585 i0 = dahdi_get_index(c0, p0, 1); 06586 if (op1 == p1) 06587 i1 = dahdi_get_index(c1, p1, 1); 06588 06589 ast_channel_unlock(c0); 06590 ast_channel_unlock(c1); 06591 06592 if (!timeoutms || 06593 (op0 != p0) || 06594 (op1 != p1) || 06595 (ofd0 != c0->fds[0]) || 06596 (ofd1 != c1->fds[0]) || 06597 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 06598 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 06599 (oc0 != p0->owner) || 06600 (oc1 != p1->owner) || 06601 (t0 != p0->subs[SUB_REAL].inthreeway) || 06602 (t1 != p1->subs[SUB_REAL].inthreeway) || 06603 (oi0 != i0) || 06604 (oi1 != i1)) { 06605 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 06606 op0->channel, oi0, op1->channel, oi1); 06607 res = AST_BRIDGE_RETRY; 06608 goto return_from_bridge; 06609 } 06610 06611 #ifdef PRI_2BCT 06612 switch (p0->sig) { 06613 case SIG_PRI_LIB_HANDLE_CASES: 06614 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 06615 break; 06616 default: 06617 q931c0 = NULL; 06618 break; 06619 } 06620 switch (p1->sig) { 06621 case SIG_PRI_LIB_HANDLE_CASES: 06622 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 06623 break; 06624 default: 06625 q931c1 = NULL; 06626 break; 06627 } 06628 if (q931c0 && q931c1 && p0->transfer && p1->transfer) { 06629 pri_channel_bridge(q931c0, q931c1); 06630 } 06631 #endif 06632 06633 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 06634 if (!who) { 06635 ast_debug(1, "Ooh, empty read...\n"); 06636 continue; 06637 } 06638 f = ast_read(who); 06639 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 06640 *fo = f; 06641 *rc = who; 06642 res = AST_BRIDGE_COMPLETE; 06643 goto return_from_bridge; 06644 } 06645 if (f->frametype == AST_FRAME_DTMF) { 06646 if ((who == c0) && p0->pulsedial) { 06647 ast_write(c1, f); 06648 } else if ((who == c1) && p1->pulsedial) { 06649 ast_write(c0, f); 06650 } else { 06651 *fo = f; 06652 *rc = who; 06653 res = AST_BRIDGE_COMPLETE; 06654 goto return_from_bridge; 06655 } 06656 } 06657 ast_frfree(f); 06658 06659 /* Swap who gets priority */ 06660 priority = !priority; 06661 } 06662 06663 return_from_bridge: 06664 if (op0 == p0) 06665 dahdi_enable_ec(p0); 06666 06667 if (op1 == p1) 06668 dahdi_enable_ec(p1); 06669 06670 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 06671 enable_dtmf_detect(op0); 06672 06673 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 06674 enable_dtmf_detect(op1); 06675 06676 dahdi_unlink(slave, master, 1); 06677 06678 return res; 06679 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 4566 of file chan_dahdi.c.
References ast_channel::_state, analog_call(), analog_lib_handles(), ast_party_connected_line::ani2, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::connected, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pvt::digital, errno, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, ast_channel::name, dahdi_subchannel::needbusy, ast_party_id::number, ast_party_id::number_presentation, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, pbx_builtin_getvar_helper(), dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_gain(), dahdi_pvt::sig, SIG_MFCR2, sig_pri_call(), dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callingpres, and dahdi_pvt::waitingfordt.
04567 { 04568 struct dahdi_pvt *p = ast->tech_pvt; 04569 int x, res, mysig; 04570 char dest[256]; /* must be same length as p->dialdest */ 04571 #ifdef HAVE_SS7 04572 char *c, *l; 04573 #endif 04574 ast_mutex_lock(&p->lock); 04575 ast_copy_string(dest, rdest, sizeof(dest)); 04576 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 04577 if ((ast->_state == AST_STATE_BUSY)) { 04578 p->subs[SUB_REAL].needbusy = 1; 04579 ast_mutex_unlock(&p->lock); 04580 return 0; 04581 } 04582 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 04583 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 04584 ast_mutex_unlock(&p->lock); 04585 return -1; 04586 } 04587 p->waitingfordt.tv_sec = 0; 04588 p->dialednone = 0; 04589 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 04590 { 04591 /* Special pseudo -- automatically up */ 04592 ast_setstate(ast, AST_STATE_UP); 04593 ast_mutex_unlock(&p->lock); 04594 return 0; 04595 } 04596 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 04597 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 04598 if (res) 04599 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 04600 p->outgoing = 1; 04601 04602 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 04603 04604 #ifdef HAVE_PRI 04605 if (dahdi_sig_pri_lib_handles(p->sig)) { 04606 struct dahdi_params ps; 04607 04608 memset(&ps, 0, sizeof(ps)); 04609 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) { 04610 ast_log(LOG_ERROR, "Could not get params\n"); 04611 } 04612 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW); 04613 ast_mutex_unlock(&p->lock); 04614 return res; 04615 } 04616 #endif 04617 04618 /* If this is analog signalling we can exit here */ 04619 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 04620 p->callwaitrings = 0; 04621 res = analog_call(p->sig_pvt, ast, rdest, timeout); 04622 ast_mutex_unlock(&p->lock); 04623 return res; 04624 } 04625 04626 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 04627 switch (mysig) { 04628 case 0: 04629 /* Special pseudo -- automatically up*/ 04630 ast_setstate(ast, AST_STATE_UP); 04631 break; 04632 case SIG_SS7: 04633 case SIG_MFCR2: 04634 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 04635 p->dialdest[0] = '\0'; 04636 p->dialing = 1; 04637 break; 04638 default: 04639 ast_debug(1, "not yet implemented\n"); 04640 ast_mutex_unlock(&p->lock); 04641 return -1; 04642 } 04643 04644 #if defined(HAVE_SS7) 04645 if (p->ss7) { 04646 char ss7_called_nai; 04647 int called_nai_strip; 04648 char ss7_calling_nai; 04649 int calling_nai_strip; 04650 const char *charge_str = NULL; 04651 const char *gen_address = NULL; 04652 const char *gen_digits = NULL; 04653 const char *gen_dig_type = NULL; 04654 const char *gen_dig_scheme = NULL; 04655 const char *gen_name = NULL; 04656 const char *jip_digits = NULL; 04657 const char *lspi_ident = NULL; 04658 const char *rlt_flag = NULL; 04659 const char *call_ref_id = NULL; 04660 const char *call_ref_pc = NULL; 04661 const char *send_far = NULL; 04662 04663 c = strchr(dest, '/'); 04664 if (c) { 04665 c++; 04666 } else { 04667 c = ""; 04668 } 04669 if (strlen(c) < p->stripmsd) { 04670 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 04671 ast_mutex_unlock(&p->lock); 04672 return -1; 04673 } 04674 04675 if (!p->hidecallerid) { 04676 l = ast->connected.id.number; 04677 } else { 04678 l = NULL; 04679 } 04680 04681 if (ss7_grab(p, p->ss7)) { 04682 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 04683 ast_mutex_unlock(&p->lock); 04684 return -1; 04685 } 04686 p->digital = IS_DIGITAL(ast->transfercapability); 04687 p->ss7call = isup_new_call(p->ss7->ss7); 04688 04689 if (!p->ss7call) { 04690 ss7_rel(p->ss7); 04691 ast_mutex_unlock(&p->lock); 04692 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 04693 return -1; 04694 } 04695 04696 called_nai_strip = 0; 04697 ss7_called_nai = p->ss7->called_nai; 04698 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 04699 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 04700 called_nai_strip = strlen(p->ss7->internationalprefix); 04701 ss7_called_nai = SS7_NAI_INTERNATIONAL; 04702 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 04703 called_nai_strip = strlen(p->ss7->nationalprefix); 04704 ss7_called_nai = SS7_NAI_NATIONAL; 04705 } else { 04706 ss7_called_nai = SS7_NAI_SUBSCRIBER; 04707 } 04708 } 04709 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 04710 04711 calling_nai_strip = 0; 04712 ss7_calling_nai = p->ss7->calling_nai; 04713 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 04714 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 04715 calling_nai_strip = strlen(p->ss7->internationalprefix); 04716 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 04717 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 04718 calling_nai_strip = strlen(p->ss7->nationalprefix); 04719 ss7_calling_nai = SS7_NAI_NATIONAL; 04720 } else { 04721 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 04722 } 04723 } 04724 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 04725 p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 04726 p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED ); 04727 04728 isup_set_oli(p->ss7call, ast->connected.ani2); 04729 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 04730 04731 ast_channel_lock(ast); 04732 /* Set the charge number if it is set */ 04733 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 04734 if (charge_str) 04735 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 04736 04737 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 04738 if (gen_address) 04739 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */ 04740 04741 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 04742 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 04743 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 04744 if (gen_digits) 04745 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 04746 04747 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 04748 if (gen_name) 04749 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 04750 04751 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 04752 if (jip_digits) 04753 isup_set_jip_digits(p->ss7call, jip_digits); 04754 04755 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 04756 if (lspi_ident) 04757 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 04758 04759 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 04760 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 04761 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 04762 } 04763 04764 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 04765 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 04766 if (call_ref_id && call_ref_pc) { 04767 isup_set_callref(p->ss7call, atoi(call_ref_id), 04768 call_ref_pc ? atoi(call_ref_pc) : 0); 04769 } 04770 04771 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 04772 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 04773 (isup_far(p->ss7->ss7, p->ss7call)); 04774 04775 ast_channel_unlock(ast); 04776 04777 isup_iam(p->ss7->ss7, p->ss7call); 04778 ast_setstate(ast, AST_STATE_DIALING); 04779 ss7_rel(p->ss7); 04780 } 04781 #endif /* defined(HAVE_SS7) */ 04782 04783 #ifdef HAVE_OPENR2 04784 if (p->mfcr2) { 04785 openr2_calling_party_category_t chancat; 04786 int callres = 0; 04787 char *c, *l; 04788 04789 c = strchr(dest, '/'); 04790 if (c) { 04791 c++; 04792 } else { 04793 c = ""; 04794 } 04795 if (!p->hidecallerid) { 04796 l = ast->cid.cid_num; 04797 } else { 04798 l = NULL; 04799 } 04800 if (strlen(c) < p->stripmsd) { 04801 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 04802 ast_mutex_unlock(&p->lock); 04803 return -1; 04804 } 04805 p->dialing = 1; 04806 ast_channel_lock(ast); 04807 chancat = dahdi_r2_get_channel_category(ast); 04808 ast_channel_unlock(ast); 04809 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 04810 if (-1 == callres) { 04811 ast_mutex_unlock(&p->lock); 04812 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 04813 return -1; 04814 } 04815 ast_setstate(ast, AST_STATE_DIALING); 04816 } 04817 #endif /* HAVE_OPENR2 */ 04818 ast_mutex_unlock(&p->lock); 04819 return 0; 04820 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4524 of file chan_dahdi.c.
References ast_free, ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_read().
04525 { 04526 struct dahdi_pvt *p = ast->tech_pvt; 04527 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 04528 if (p->cidspill) { 04529 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 04530 ast_free(p->cidspill); 04531 } 04532 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 04533 return -1; 04534 save_conference(p); 04535 /* Silence */ 04536 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 04537 if (!p->callwaitrings && p->callwaitingcallerid) { 04538 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 04539 p->callwaitcas = 1; 04540 p->cidlen = 2400 + 680 + READ_SIZE * 4; 04541 } else { 04542 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 04543 p->callwaitcas = 0; 04544 p->cidlen = 2400 + READ_SIZE * 4; 04545 } 04546 p->cidpos = 0; 04547 send_callerid(p); 04548 04549 return 0; 04550 }
| static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static, read] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 1310 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, and DEFAULT_CIDRINGS.
Referenced by process_dahdi(), and setup_dahdi().
01311 { 01312 /* recall that if a field is not included here it is initialized 01313 * to 0 or equivalent 01314 */ 01315 struct dahdi_chan_conf conf = { 01316 #ifdef HAVE_PRI 01317 .pri.pri = { 01318 .nsf = PRI_NSF_NONE, 01319 .switchtype = PRI_SWITCH_NI2, 01320 .dialplan = PRI_UNKNOWN + 1, 01321 .localdialplan = PRI_NATIONAL_ISDN + 1, 01322 .nodetype = PRI_CPE, 01323 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01324 01325 .minunused = 2, 01326 .idleext = "", 01327 .idledial = "", 01328 .internationalprefix = "", 01329 .nationalprefix = "", 01330 .localprefix = "", 01331 .privateprefix = "", 01332 .unknownprefix = "", 01333 .resetinterval = -1, 01334 }, 01335 #endif 01336 #ifdef HAVE_SS7 01337 .ss7 = { 01338 .called_nai = SS7_NAI_NATIONAL, 01339 .calling_nai = SS7_NAI_NATIONAL, 01340 .internationalprefix = "", 01341 .nationalprefix = "", 01342 .subscriberprefix = "", 01343 .unknownprefix = "" 01344 }, 01345 #endif 01346 #ifdef HAVE_OPENR2 01347 .mfcr2 = { 01348 .variant = OR2_VAR_ITU, 01349 .mfback_timeout = -1, 01350 .metering_pulse_timeout = -1, 01351 .max_ani = 10, 01352 .max_dnis = 4, 01353 .get_ani_first = -1, 01354 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01355 .skip_category_request = -1, 01356 #endif 01357 .call_files = 0, 01358 .allow_collect_calls = 0, 01359 .charge_calls = 1, 01360 .accept_on_offer = 1, 01361 .forced_release = 0, 01362 .double_answer = 0, 01363 .immediate_accept = -1, 01364 .logdir = "", 01365 .r2proto_file = "", 01366 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01367 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01368 }, 01369 #endif 01370 .chan = { 01371 .context = "default", 01372 .cid_num = "", 01373 .cid_name = "", 01374 .mohinterpret = "default", 01375 .mohsuggest = "", 01376 .parkinglot = "", 01377 .transfertobusy = 1, 01378 01379 .cid_signalling = CID_SIG_BELL, 01380 .cid_start = CID_START_RING, 01381 .dahditrcallerid = 0, 01382 .use_callerid = 1, 01383 .sig = -1, 01384 .outsigmod = -1, 01385 01386 .cid_rxgain = +5.0, 01387 01388 .tonezone = -1, 01389 01390 .echocancel.head.tap_length = 1, 01391 01392 .busycount = 3, 01393 01394 .accountcode = "", 01395 01396 .mailbox = "", 01397 01398 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01399 .mwisend_fsk = 1, 01400 #endif 01401 .polarityonanswerdelay = 600, 01402 01403 .sendcalleridafter = DEFAULT_CIDRINGS, 01404 01405 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01406 .buf_no = numbufs, 01407 .usefaxbuffers = 0, 01408 }, 01409 .timing = { 01410 .prewinktime = -1, 01411 .preflashtime = -1, 01412 .winktime = -1, 01413 .flashtime = -1, 01414 .starttime = -1, 01415 .rxwinktime = -1, 01416 .rxflashtime = -1, 01417 .debouncetime = -1 01418 }, 01419 .is_sig_auto = 1, 01420 .smdi_port = "/dev/ttyS0", 01421 }; 01422 01423 return conf; 01424 }
| static void dahdi_close | ( | int | fd | ) | [static] |
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 3556 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().
03557 { 03558 dahdi_close(chan_pvt->subs[sub_num].dfd); 03559 chan_pvt->subs[sub_num].dfd = -1; 03560 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 4368 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmfup().
04369 { 04370 int x, res; 04371 04372 x = muted; 04373 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04374 switch (p->sig) { 04375 #if defined(HAVE_PRI) 04376 case SIG_PRI_LIB_HANDLE_CASES: 04377 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04378 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 04379 break; 04380 } 04381 /* Fall through */ 04382 #endif /* defined(HAVE_PRI) */ 04383 #if defined(HAVE_SS7) 04384 case SIG_SS7: 04385 #endif /* defined(HAVE_SS7) */ 04386 { 04387 int y = 1; 04388 04389 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 04390 if (res) 04391 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 04392 p->channel, strerror(errno)); 04393 } 04394 break; 04395 default: 04396 break; 04397 } 04398 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04399 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 04400 if (res < 0) 04401 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 04402 return res; 04403 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14005 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.
14006 { 14007 int channel; 14008 int ret; 14009 switch (cmd) { 14010 case CLI_INIT: 14011 e->command = "dahdi destroy channel"; 14012 e->usage = 14013 "Usage: dahdi destroy channel <chan num>\n" 14014 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 14015 return NULL; 14016 case CLI_GENERATE: 14017 return NULL; 14018 } 14019 if (a->argc != 4) 14020 return CLI_SHOWUSAGE; 14021 14022 channel = atoi(a->argv[3]); 14023 ret = dahdi_destroy_channel_bynum(channel); 14024 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 14025 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 10230 of file chan_dahdi.c.
References ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, iflock, dahdi_pvt::next, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and do_monitor().
10231 { 10232 struct dahdi_pvt *cur; 10233 10234 ast_mutex_lock(&iflock); 10235 for (cur = iflist; cur; cur = cur->next) { 10236 if (cur->channel == channel) { 10237 int x = DAHDI_FLASH; 10238 10239 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 10240 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 10241 10242 destroy_channel(cur, 1); 10243 ast_mutex_unlock(&iflock); 10244 ast_module_unref(ast_module_info->self); 10245 return RESULT_SUCCESS; 10246 } 10247 } 10248 ast_mutex_unlock(&iflock); 10249 return RESULT_FAILURE; 10250 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 3654 of file chan_dahdi.c.
References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, sig_pri_digit_begin(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
03655 { 03656 struct dahdi_pvt *pvt; 03657 int idx; 03658 int dtmf = -1; 03659 int res; 03660 03661 pvt = chan->tech_pvt; 03662 03663 ast_mutex_lock(&pvt->lock); 03664 03665 idx = dahdi_get_index(chan, pvt, 0); 03666 03667 if ((idx != SUB_REAL) || !pvt->owner) 03668 goto out; 03669 03670 #ifdef HAVE_PRI 03671 switch (pvt->sig) { 03672 case SIG_PRI_LIB_HANDLE_CASES: 03673 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 03674 if (!res) 03675 goto out; 03676 break; 03677 default: 03678 break; 03679 } 03680 #endif 03681 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 03682 goto out; 03683 03684 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 03685 struct dahdi_dialoperation zo = { 03686 .op = DAHDI_DIAL_OP_APPEND, 03687 }; 03688 03689 zo.dialstr[0] = 'T'; 03690 zo.dialstr[1] = digit; 03691 zo.dialstr[2] = '\0'; 03692 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 03693 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 03694 else 03695 pvt->dialing = 1; 03696 } else { 03697 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 03698 pvt->dialing = 1; 03699 pvt->begindigit = digit; 03700 } 03701 03702 out: 03703 ast_mutex_unlock(&pvt->lock); 03704 03705 return 0; 03706 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 3708 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
03709 { 03710 struct dahdi_pvt *pvt; 03711 int res = 0; 03712 int idx; 03713 int x; 03714 03715 pvt = chan->tech_pvt; 03716 03717 ast_mutex_lock(&pvt->lock); 03718 03719 idx = dahdi_get_index(chan, pvt, 0); 03720 03721 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 03722 goto out; 03723 03724 #ifdef HAVE_PRI 03725 /* This means that the digit was already sent via PRI signalling */ 03726 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 03727 goto out; 03728 } 03729 #endif 03730 03731 if (pvt->begindigit) { 03732 x = -1; 03733 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 03734 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 03735 pvt->dialing = 0; 03736 pvt->begindigit = 0; 03737 } 03738 03739 out: 03740 ast_mutex_unlock(&pvt->lock); 03741 03742 return res; 03743 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4158 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().
04159 { 04160 int res; 04161 04162 if (p->echocanon) { 04163 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04164 04165 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04166 04167 if (res) 04168 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04169 else 04170 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 04171 } 04172 04173 p->echocanon = 0; 04174 }
| static int dahdi_dnd | ( | struct dahdi_pvt * | dahdichan, | |
| int | flag | |||
| ) | [static] |
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
| dahdichan | "Physical" DAHDI channel (e.g: DAHDI/5) | |
| on | 1 to enable, 0 to disable, -1 return dnd value |
Definition at line 8767 of file chan_dahdi.c.
References analog_dnd(), analog_lib_handles(), ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, and dahdi_pvt::sig_pvt.
Referenced by action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), analog_ss_thread(), dahdi_set_dnd(), and dahdi_show_channel().
08768 { 08769 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 08770 return analog_dnd(dahdichan->sig_pvt, flag); 08771 } 08772 08773 if (flag == -1) { 08774 return dahdichan->dnd; 08775 } 08776 08777 /* Do not disturb */ 08778 dahdichan->dnd = flag; 08779 ast_verb(3, "%s DND on channel %d\n", 08780 flag? "Enabled" : "Disabled", 08781 dahdichan->channel); 08782 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 08783 "Channel: DAHDI/%d\r\n" 08784 "Status: %s\r\n", dahdichan->channel, 08785 flag? "enabled" : "disabled"); 08786 08787 return 0; 08788 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4086 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_bridge(), dahdi_func_write(), dahdi_handle_event(), dahdi_indicate(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().
04087 { 04088 int res; 04089 if (!p) 04090 return; 04091 if (p->echocanon) { 04092 ast_debug(1, "Echo cancellation already on\n"); 04093 return; 04094 } 04095 if (p->digital) { 04096 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04097 return; 04098 } 04099 if (p->echocancel.head.tap_length) { 04100 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04101 switch (p->sig) { 04102 #if defined(HAVE_PRI) 04103 case SIG_PRI_LIB_HANDLE_CASES: 04104 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04105 /* 04106 * PRI nobch pseudo channel. Does not need ec anyway. 04107 * Does not handle ioctl(DAHDI_AUDIOMODE) 04108 */ 04109 return; 04110 } 04111 /* Fall through */ 04112 #endif /* defined(HAVE_PRI) */ 04113 #if defined(HAVE_SS7) 04114 case SIG_SS7: 04115 #endif /* defined(HAVE_SS7) */ 04116 { 04117 int x = 1; 04118 04119 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04120 if (res) 04121 ast_log(LOG_WARNING, 04122 "Unable to enable audio mode on channel %d (%s)\n", 04123 p->channel, strerror(errno)); 04124 } 04125 break; 04126 default: 04127 break; 04128 } 04129 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04130 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04131 if (res) { 04132 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04133 } else { 04134 p->echocanon = 1; 04135 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04136 } 04137 } else 04138 ast_debug(1, "No echo cancellation requested\n"); 04139 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7910 of file chan_dahdi.c.
References __dahdi_exception(), analog_exception(), analog_lib_handles(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.
07911 { 07912 struct dahdi_pvt *p = ast->tech_pvt; 07913 struct ast_frame *f; 07914 ast_mutex_lock(&p->lock); 07915 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07916 struct analog_pvt *analog_p = p->sig_pvt; 07917 f = analog_exception(analog_p, ast); 07918 } else { 07919 f = __dahdi_exception(ast); 07920 } 07921 ast_mutex_unlock(&p->lock); 07922 return f; 07923 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 14830 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, LOG_WARNING, ast_channel::name, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
14831 { 14832 if (p) { 14833 switch (mode) { 14834 case TRANSFER: 14835 p->fake_event = DAHDI_EVENT_WINKFLASH; 14836 break; 14837 case HANGUP: 14838 p->fake_event = DAHDI_EVENT_ONHOOK; 14839 break; 14840 default: 14841 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 14842 } 14843 } 14844 return 0; 14845 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 6681 of file chan_dahdi.c.
References ast_channel::_state, analog_fixup(), analog_lib_handles(), AST_CONTROL_RINGING, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_sig_pri_lib_handles(), dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
06682 { 06683 struct dahdi_pvt *p = newchan->tech_pvt; 06684 int x; 06685 ast_mutex_lock(&p->lock); 06686 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 06687 if (p->owner == oldchan) { 06688 p->owner = newchan; 06689 } 06690 for (x = 0; x < 3; x++) 06691 if (p->subs[x].owner == oldchan) { 06692 if (!x) 06693 dahdi_unlink(NULL, p, 0); 06694 p->subs[x].owner = newchan; 06695 } 06696 if (newchan->_state == AST_STATE_RINGING) 06697 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 06698 06699 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06700 analog_fixup(oldchan, newchan, p->sig_pvt); 06701 } 06702 #ifdef HAVE_PRI 06703 else if (dahdi_sig_pri_lib_handles(p->sig)) { 06704 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 06705 } 06706 #endif 06707 06708 update_conf(p); 06709 ast_mutex_unlock(&p->lock); 06710 return 0; 06711 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 6132 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, ast_channel::tech_pvt, and dahdi_pvt::txgain.
06133 { 06134 struct dahdi_pvt *p = chan->tech_pvt; 06135 int res = 0; 06136 06137 if (!strcasecmp(data, "rxgain")) { 06138 ast_mutex_lock(&p->lock); 06139 snprintf(buf, len, "%f", p->rxgain); 06140 ast_mutex_unlock(&p->lock); 06141 } else if (!strcasecmp(data, "txgain")) { 06142 ast_mutex_lock(&p->lock); 06143 snprintf(buf, len, "%f", p->txgain); 06144 ast_mutex_unlock(&p->lock); 06145 #if defined(HAVE_PRI) 06146 #if defined(HAVE_PRI_REVERSE_CHARGE) 06147 } else if (!strcasecmp(data, "reversecharge")) { 06148 ast_mutex_lock(&p->lock); 06149 switch (p->sig) { 06150 case SIG_PRI_LIB_HANDLE_CASES: 06151 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 06152 break; 06153 default: 06154 *buf = '\0'; 06155 res = -1; 06156 break; 06157 } 06158 ast_mutex_unlock(&p->lock); 06159 #endif 06160 #if defined(HAVE_PRI_SETUP_KEYPAD) 06161 } else if (!strcasecmp(data, "keypad_digits")) { 06162 ast_mutex_lock(&p->lock); 06163 switch (p->sig) { 06164 case SIG_PRI_LIB_HANDLE_CASES: 06165 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 06166 len); 06167 break; 06168 default: 06169 *buf = '\0'; 06170 res = -1; 06171 break; 06172 } 06173 ast_mutex_unlock(&p->lock); 06174 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 06175 #endif /* defined(HAVE_PRI) */ 06176 } else { 06177 *buf = '\0'; 06178 res = -1; 06179 } 06180 06181 return res; 06182 }
| static int dahdi_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 6214 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
06215 { 06216 struct dahdi_pvt *p = chan->tech_pvt; 06217 int res = 0; 06218 06219 if (!strcasecmp(data, "buffers")) { 06220 int num_bufs, policy; 06221 06222 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 06223 struct dahdi_bufferinfo bi = { 06224 .txbufpolicy = policy, 06225 .rxbufpolicy = policy, 06226 .bufsize = p->bufsize, 06227 .numbufs = num_bufs, 06228 }; 06229 int bpres; 06230 06231 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06232 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 06233 } else { 06234 p->bufferoverrideinuse = 1; 06235 } 06236 } else { 06237 res = -1; 06238 } 06239 } else if (!strcasecmp(data, "echocan_mode")) { 06240 if (!strcasecmp(value, "on")) { 06241 ast_mutex_lock(&p->lock); 06242 dahdi_enable_ec(p); 06243 ast_mutex_unlock(&p->lock); 06244 } else if (!strcasecmp(value, "off")) { 06245 ast_mutex_lock(&p->lock); 06246 dahdi_disable_ec(p); 06247 ast_mutex_unlock(&p->lock); 06248 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 06249 } else if (!strcasecmp(value, "fax")) { 06250 int blah = 1; 06251 06252 ast_mutex_lock(&p->lock); 06253 if (!p->echocanon) { 06254 dahdi_enable_ec(p); 06255 } 06256 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 06257 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 06258 } 06259 ast_mutex_unlock(&p->lock); 06260 } else if (!strcasecmp(value, "voice")) { 06261 int blah = 0; 06262 06263 ast_mutex_lock(&p->lock); 06264 if (!p->echocanon) { 06265 dahdi_enable_ec(p); 06266 } 06267 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 06268 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 06269 } 06270 ast_mutex_unlock(&p->lock); 06271 #endif 06272 } else { 06273 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 06274 res = -1; 06275 } 06276 } else { 06277 res = -1; 06278 } 06279 06280 return res; 06281 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 475 of file chan_dahdi.c.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), do_monitor(), mwi_thread(), my_distinctive_ring(), my_get_callerid(), and my_get_event().
00476 { 00477 int j; 00478 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00479 return -1; 00480 return j; 00481 }
| static int dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok | |||
| ) | [static] |
Definition at line 2952 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_subchannel::owner, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_answer(), dahdi_bridge(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), and dahdi_write().
02953 { 02954 int res; 02955 if (p->subs[SUB_REAL].owner == ast) 02956 res = 0; 02957 else if (p->subs[SUB_CALLWAIT].owner == ast) 02958 res = 1; 02959 else if (p->subs[SUB_THREEWAY].owner == ast) 02960 res = 2; 02961 else { 02962 res = -1; 02963 if (!nullok) 02964 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 02965 } 02966 return res; 02967 }
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 6850 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::usefaxbuffers.
Referenced by dahdi_handle_event(), and dahdi_read().
06851 { 06852 struct dahdi_pvt *p = ast->tech_pvt; 06853 struct ast_frame *f = *dest; 06854 06855 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 06856 06857 if (p->confirmanswer) { 06858 ast_debug(1, "Confirm answer on %s!\n", ast->name); 06859 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 06860 of a DTMF digit */ 06861 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06862 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 06863 *dest = &p->subs[idx].f; 06864 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 06865 p->confirmanswer = 0; 06866 } else if (p->callwaitcas) { 06867 if ((f->subclass == 'A') || (f->subclass == 'D')) { 06868 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 06869 if (p->cidspill) 06870 ast_free(p->cidspill); 06871 send_cwcidspill(p); 06872 } 06873 p->callwaitcas = 0; 06874 p->subs[idx].f.frametype = AST_FRAME_NULL; 06875 p->subs[idx].f.subclass = 0; 06876 *dest = &p->subs[idx].f; 06877 } else if (f->subclass == 'f') { 06878 /* Fax tone -- Handle and return NULL */ 06879 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 06880 /* If faxbuffers are configured, use them for the fax transmission */ 06881 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 06882 struct dahdi_bufferinfo bi = { 06883 .txbufpolicy = p->faxbuf_policy, 06884 .bufsize = p->bufsize, 06885 .numbufs = p->faxbuf_no 06886 }; 06887 int res; 06888 06889 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06890 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 06891 } else { 06892 p->bufferoverrideinuse = 1; 06893 } 06894 } 06895 p->faxhandled = 1; 06896 p->callprogress &= ~CALLPROGRESS_FAX; 06897 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06898 ast_dsp_set_features(p->dsp, p->dsp_features); 06899 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 06900 if (strcmp(ast->exten, "fax")) { 06901 const char *target_context = S_OR(ast->macrocontext, ast->context); 06902 06903 /* We need to unlock 'ast' here because ast_exists_extension has the 06904 * potential to start autoservice on the channel. Such action is prone 06905 * to deadlock. 06906 */ 06907 ast_mutex_unlock(&p->lock); 06908 ast_channel_unlock(ast); 06909 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 06910 ast_channel_lock(ast); 06911 ast_mutex_lock(&p->lock); 06912 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 06913 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 06914 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 06915 if (ast_async_goto(ast, target_context, "fax", 1)) 06916 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 06917 } else { 06918 ast_channel_lock(ast); 06919 ast_mutex_lock(&p->lock); 06920 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 06921 } 06922 } else { 06923 ast_debug(1, "Already in a fax extension, not redirecting\n"); 06924 } 06925 } else { 06926 ast_debug(1, "Fax already handled\n"); 06927 } 06928 dahdi_confmute(p, 0); 06929 p->subs[idx].f.frametype = AST_FRAME_NULL; 06930 p->subs[idx].f.subclass = 0; 06931 *dest = &p->subs[idx].f; 06932 } 06933 }
| static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6946 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, ast_channel::cdr, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_sig_pri_lib_handles(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, dahdi_subchannel::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_chan_alarm_notify(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ast_frame::src, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
06947 { 06948 int res, x; 06949 int idx, mysig; 06950 char *c; 06951 struct dahdi_pvt *p = ast->tech_pvt; 06952 pthread_t threadid; 06953 struct ast_channel *chan; 06954 struct ast_frame *f; 06955 06956 idx = dahdi_get_index(ast, p, 0); 06957 mysig = p->sig; 06958 if (p->outsigmod > -1) 06959 mysig = p->outsigmod; 06960 p->subs[idx].f.frametype = AST_FRAME_NULL; 06961 p->subs[idx].f.subclass = 0; 06962 p->subs[idx].f.datalen = 0; 06963 p->subs[idx].f.samples = 0; 06964 p->subs[idx].f.mallocd = 0; 06965 p->subs[idx].f.offset = 0; 06966 p->subs[idx].f.src = "dahdi_handle_event"; 06967 p->subs[idx].f.data.ptr = NULL; 06968 f = &p->subs[idx].f; 06969 06970 if (idx < 0) 06971 return &p->subs[idx].f; 06972 if (p->fake_event) { 06973 res = p->fake_event; 06974 p->fake_event = 0; 06975 } else 06976 res = dahdi_get_event(p->subs[idx].dfd); 06977 06978 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 06979 06980 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 06981 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 06982 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 06983 #ifdef HAVE_PRI 06984 if (dahdi_sig_pri_lib_handles(p->sig) 06985 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding 06986 && p->pri 06987 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 06988 /* absorb event */ 06989 } else { 06990 #endif 06991 dahdi_confmute(p, 0); 06992 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 06993 p->subs[idx].f.subclass = res & 0xff; 06994 #ifdef HAVE_PRI 06995 } 06996 #endif 06997 dahdi_handle_dtmfup(ast, idx, &f); 06998 return f; 06999 } 07000 07001 if (res & DAHDI_EVENT_DTMFDOWN) { 07002 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07003 /* Mute conference */ 07004 dahdi_confmute(p, 1); 07005 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07006 p->subs[idx].f.subclass = res & 0xff; 07007 return &p->subs[idx].f; 07008 } 07009 07010 switch (res) { 07011 case DAHDI_EVENT_EC_DISABLED: 07012 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07013 p->echocanon = 0; 07014 break; 07015 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07016 case DAHDI_EVENT_TX_CED_DETECTED: 07017 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 07018 break; 07019 case DAHDI_EVENT_RX_CED_DETECTED: 07020 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 07021 break; 07022 case DAHDI_EVENT_EC_NLP_DISABLED: 07023 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 07024 break; 07025 case DAHDI_EVENT_EC_NLP_ENABLED: 07026 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 07027 break; 07028 #endif 07029 case DAHDI_EVENT_BITSCHANGED: 07030 #ifdef HAVE_OPENR2 07031 if (p->sig != SIG_MFCR2) { 07032 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07033 } else { 07034 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 07035 openr2_chan_handle_cas(p->r2chan); 07036 } 07037 #else 07038 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07039 #endif 07040 case DAHDI_EVENT_PULSE_START: 07041 /* Stop tone if there's a pulse start and the PBX isn't started */ 07042 if (!ast->pbx) 07043 tone_zone_play_tone(p->subs[idx].dfd, -1); 07044 break; 07045 case DAHDI_EVENT_DIALCOMPLETE: 07046 #ifdef HAVE_OPENR2 07047 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 07048 /* we don't need to do anything for this event for R2 signaling 07049 if the call is being setup */ 07050 break; 07051 } 07052 #endif 07053 if (p->inalarm) break; 07054 if ((p->radio || (p->oprmode < 0))) break; 07055 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 07056 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 07057 return NULL; 07058 } 07059 if (!x) { /* if not still dialing in driver */ 07060 dahdi_enable_ec(p); 07061 if (p->echobreak) { 07062 dahdi_train_ec(p); 07063 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 07064 p->dop.op = DAHDI_DIAL_OP_REPLACE; 07065 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07066 p->echobreak = 0; 07067 } else { 07068 p->dialing = 0; 07069 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 07070 /* if thru with dialing after offhook */ 07071 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 07072 ast_setstate(ast, AST_STATE_UP); 07073 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07074 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 07075 break; 07076 } else { /* if to state wait for offhook to dial rest */ 07077 /* we now wait for off hook */ 07078 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 07079 } 07080 } 07081 if (ast->_state == AST_STATE_DIALING) { 07082 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 07083 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 07084 } else if (p->confirmanswer || (!p->dialednone 07085 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 07086 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 07087 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 07088 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 07089 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 07090 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 07091 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 07092 || (mysig == SIG_SF_FEATB)))) { 07093 ast_setstate(ast, AST_STATE_RINGING); 07094 } else if (!p->answeronpolarityswitch) { 07095 ast_setstate(ast, AST_STATE_UP); 07096 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07097 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 07098 /* If aops=0 and hops=1, this is necessary */ 07099 p->polarity = POLARITY_REV; 07100 } else { 07101 /* Start clean, so we can catch the change to REV polarity when party answers */ 07102 p->polarity = POLARITY_IDLE; 07103 } 07104 } 07105 } 07106 } 07107 break; 07108 case DAHDI_EVENT_ALARM: 07109 #ifdef HAVE_PRI 07110 switch (p->sig) { 07111 case SIG_PRI_LIB_HANDLE_CASES: 07112 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 07113 break; 07114 default: 07115 break; 07116 } 07117 #endif 07118 p->inalarm = 1; 07119 res = get_alarms(p); 07120 handle_alarms(p, res); 07121 #ifdef HAVE_PRI 07122 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 07123 /* fall through intentionally */ 07124 } else { 07125 break; 07126 } 07127 #endif 07128 #ifdef HAVE_SS7 07129 if (p->sig == SIG_SS7) 07130 break; 07131 #endif 07132 #ifdef HAVE_OPENR2 07133 if (p->sig == SIG_MFCR2) 07134 break; 07135 #endif 07136 case DAHDI_EVENT_ONHOOK: 07137 if (p->radio) { 07138 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07139 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 07140 break; 07141 } 07142 if (p->oprmode < 0) 07143 { 07144 if (p->oprmode != -1) break; 07145 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 07146 { 07147 /* Make sure it starts ringing */ 07148 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 07149 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 07150 save_conference(p->oprpeer); 07151 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07152 } 07153 break; 07154 } 07155 switch (p->sig) { 07156 case SIG_FXOLS: 07157 case SIG_FXOGS: 07158 case SIG_FXOKS: 07159 /* Check for some special conditions regarding call waiting */ 07160 if (idx == SUB_REAL) { 07161 /* The normal line was hung up */ 07162 if (p->subs[SUB_CALLWAIT].owner) { 07163 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 07164 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 07165 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 07166 unalloc_sub(p, SUB_CALLWAIT); 07167 #if 0 07168 p->subs[idx].needanswer = 0; 07169 p->subs[idx].needringing = 0; 07170 #endif 07171 p->callwaitingrepeat = 0; 07172 p->cidcwexpire = 0; 07173 p->owner = NULL; 07174 /* Don't start streaming audio yet if the incoming call isn't up yet */ 07175 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 07176 p->dialing = 1; 07177 dahdi_ring_phone(p); 07178 } else if (p->subs[SUB_THREEWAY].owner) { 07179 unsigned int mssinceflash; 07180 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 07181 the private structure -- not especially easy or clean */ 07182 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 07183 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 07184 DLA_UNLOCK(&p->lock); 07185 CHANNEL_DEADLOCK_AVOIDANCE(ast); 07186 /* We can grab ast and p in that order, without worry. We should make sure 07187 nothing seriously bad has happened though like some sort of bizarre double 07188 masquerade! */ 07189 DLA_LOCK(&p->lock); 07190 if (p->owner != ast) { 07191 ast_log(LOG_WARNING, "This isn't good...\n"); 07192 return NULL; 07193 } 07194 } 07195 if (!p->subs[SUB_THREEWAY].owner) { 07196 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 07197 return NULL; 07198 } 07199 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 07200 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 07201 if (mssinceflash < MIN_MS_SINCE_FLASH) { 07202 /* It hasn't been long enough since the last flashook. This is probably a bounce on 07203 hanging up. Hangup both channels now */ 07204 if (p->subs[SUB_THREEWAY].owner) 07205 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 07206 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07207 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 07208 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07209 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 07210 if (p->transfer) { 07211 /* In any case this isn't a threeway call anymore */ 07212 p->subs[SUB_REAL].inthreeway = 0; 07213 p->subs[SUB_THREEWAY].inthreeway = 0; 07214 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 07215 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 07216 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07217 /* Swap subs and dis-own channel */ 07218 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07219 p->owner = NULL; 07220 /* Ring the phone */ 07221 dahdi_ring_phone(p); 07222 } else { 07223 if ((res = attempt_transfer(p)) < 0) { 07224 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07225 if (p->subs[SUB_THREEWAY].owner) 07226 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07227 } else if (res) { 07228 /* Don't actually hang up at this point */ 07229 if (p->subs[SUB_THREEWAY].owner) 07230 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07231 break; 07232 } 07233 } 07234 } else { 07235 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07236 if (p->subs[SUB_THREEWAY].owner) 07237 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07238 } 07239 } else { 07240 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07241 /* Swap subs and dis-own channel */ 07242 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07243 p->owner = NULL; 07244 /* Ring the phone */ 07245 dahdi_ring_phone(p); 07246 } 07247 } 07248 } else { 07249 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 07250 } 07251 /* Fall through */ 07252 default: 07253 dahdi_disable_ec(p); 07254 return NULL; 07255 } 07256 break; 07257 case DAHDI_EVENT_RINGOFFHOOK: 07258 if (p->inalarm) break; 07259 if (p->oprmode < 0) 07260 { 07261 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 07262 { 07263 /* Make sure it stops ringing */ 07264 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 07265 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 07266 restore_conference(p->oprpeer); 07267 } 07268 break; 07269 } 07270 if (p->radio) 07271 { 07272 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07273 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 07274 break; 07275 } 07276 /* for E911, its supposed to wait for offhook then dial 07277 the second half of the dial string */ 07278 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 07279 c = strchr(p->dialdest, '/'); 07280 if (c) 07281 c++; 07282 else 07283 c = p->dialdest; 07284 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 07285 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 07286 if (strlen(p->dop.dialstr) > 4) { 07287 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 07288 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 07289 p->echorest[sizeof(p->echorest) - 1] = '\0'; 07290 p->echobreak = 1; 07291 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 07292 } else 07293 p->echobreak = 0; 07294 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 07295 int saveerr = errno; 07296 07297 x = DAHDI_ONHOOK; 07298 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07299 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 07300 return NULL; 07301 } 07302 p->dialing = 1; 07303 return &p->subs[idx].f; 07304 } 07305 switch (p->sig) { 07306 case SIG_FXOLS: 07307 case SIG_FXOGS: 07308 case SIG_FXOKS: 07309 switch (ast->_state) { 07310 case AST_STATE_RINGING: 07311 dahdi_enable_ec(p); 07312 dahdi_train_ec(p); 07313 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07314 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 07315 /* Make sure it stops ringing */ 07316 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 07317 ast_debug(1, "channel %d answered\n", p->channel); 07318 if (p->cidspill) { 07319 /* Cancel any running CallerID spill */ 07320 ast_free(p->cidspill); 07321 p->cidspill = NULL; 07322 } 07323 p->dialing = 0; 07324 p->callwaitcas = 0; 07325 if (p->confirmanswer) { 07326 /* Ignore answer if "confirm answer" is enabled */ 07327 p->subs[idx].f.frametype = AST_FRAME_NULL; 07328 p->subs[idx].f.subclass = 0; 07329 } else if (!ast_strlen_zero(p->dop.dialstr)) { 07330 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 07331 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07332 if (res < 0) { 07333 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 07334 p->dop.dialstr[0] = '\0'; 07335 return NULL; 07336 } else { 07337 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 07338 p->subs[idx].f.frametype = AST_FRAME_NULL; 07339 p->subs[idx].f.subclass = 0; 07340 p->dialing = 1; 07341 } 07342 p->dop.dialstr[0] = '\0'; 07343 ast_setstate(ast, AST_STATE_DIALING); 07344 } else 07345 ast_setstate(ast, AST_STATE_UP); 07346 return &p->subs[idx].f; 07347 case AST_STATE_DOWN: 07348 ast_setstate(ast, AST_STATE_RING); 07349 ast->rings = 1; 07350 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07351 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 07352 ast_debug(1, "channel %d picked up\n", p->channel); 07353 return &p->subs[idx].f; 07354 case AST_STATE_UP: 07355 /* Make sure it stops ringing */ 07356 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 07357 /* Okay -- probably call waiting*/ 07358 if (ast_bridged_channel(p->owner)) 07359 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07360 p->subs[idx].needunhold = 1; 07361 break; 07362 case AST_STATE_RESERVED: 07363 /* Start up dialtone */ 07364 if (has_voicemail(p)) 07365 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07366 else 07367 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07368 break; 07369 default: 07370 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 07371 } 07372 break; 07373 case SIG_FXSLS: 07374 case SIG_FXSGS: 07375 case SIG_FXSKS: 07376 if (ast->_state == AST_STATE_RING) { 07377 p->ringt = p->ringt_base; 07378 } 07379 07380 /* If we get a ring then we cannot be in 07381 * reversed polarity. So we reset to idle */ 07382 ast_debug(1, "Setting IDLE polarity due " 07383 "to ring. Old polarity was %d\n", 07384 p->polarity); 07385 p->polarity = POLARITY_IDLE; 07386 07387 /* Fall through */ 07388 case SIG_EM: 07389 case SIG_EM_E1: 07390 case SIG_EMWINK: 07391 case SIG_FEATD: 07392 case SIG_FEATDMF: 07393 case SIG_FEATDMF_TA: 07394 case SIG_E911: 07395 case SIG_FGC_CAMA: 07396 case SIG_FGC_CAMAMF: 07397 case SIG_FEATB: 07398 case SIG_SF: 07399 case SIG_SFWINK: 07400 case SIG_SF_FEATD: 07401 case SIG_SF_FEATDMF: 07402 case SIG_SF_FEATB: 07403 if (ast->_state == AST_STATE_PRERING) 07404 ast_setstate(ast, AST_STATE_RING); 07405 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 07406 ast_debug(1, "Ring detected\n"); 07407 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07408 p->subs[idx].f.subclass = AST_CONTROL_RING; 07409 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 07410 ast_debug(1, "Line answered\n"); 07411 if (p->confirmanswer) { 07412 p->subs[idx].f.frametype = AST_FRAME_NULL; 07413 p->subs[idx].f.subclass = 0; 07414 } else { 07415 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07416 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 07417 ast_setstate(ast, AST_STATE_UP); 07418 } 07419 } else if (ast->_state != AST_STATE_RING) 07420 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 07421 break; 07422 default: 07423 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 07424 } 07425 break; 07426 case DAHDI_EVENT_RINGBEGIN: 07427 switch (p->sig) { 07428 case SIG_FXSLS: 07429 case SIG_FXSGS: 07430 case SIG_FXSKS: 07431 if (ast->_state == AST_STATE_RING) { 07432 p->ringt = p->ringt_base; 07433 } 07434 break; 07435 } 07436 break; 07437 case DAHDI_EVENT_RINGERON: 07438 break; 07439 case DAHDI_EVENT_NOALARM: 07440 #ifdef HAVE_PRI 07441 switch (p->sig) { 07442 case SIG_PRI_LIB_HANDLE_CASES: 07443 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 07444 break; 07445 default: 07446 break; 07447 } 07448 #endif 07449 p->inalarm = 0; 07450 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 07451 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07452 "Channel: %d\r\n", p->channel); 07453 break; 07454 case DAHDI_EVENT_WINKFLASH: 07455 if (p->inalarm) break; 07456 if (p->radio) break; 07457 if (p->oprmode < 0) break; 07458 if (p->oprmode > 1) 07459 { 07460 struct dahdi_params par; 07461 07462 memset(&par, 0, sizeof(par)); 07463 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 07464 { 07465 if (!par.rxisoffhook) 07466 { 07467 /* Make sure it stops ringing */ 07468 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 07469 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 07470 save_conference(p); 07471 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07472 } 07473 } 07474 break; 07475 } 07476 /* Remember last time we got a flash-hook */ 07477 p->flashtime = ast_tvnow(); 07478 switch (mysig) { 07479 case SIG_FXOLS: 07480 case SIG_FXOGS: 07481 case SIG_FXOKS: 07482 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 07483 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 07484 p->callwaitcas = 0; 07485 07486 if (idx != SUB_REAL) { 07487 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 07488 goto winkflashdone; 07489 } 07490 07491 if (p->subs[SUB_CALLWAIT].owner) { 07492 /* Swap to call-wait */ 07493 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 07494 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 07495 p->owner = p->subs[SUB_REAL].owner; 07496 ast_debug(1, "Making %s the new owner\n", p->owner->name); 07497 if (p->owner->_state == AST_STATE_RINGING) { 07498 ast_setstate(p->owner, AST_STATE_UP); 07499 p->subs[SUB_REAL].needanswer = 1; 07500 } 07501 p->callwaitingrepeat = 0; 07502 p->cidcwexpire = 0; 07503 /* Start music on hold if appropriate */ 07504 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 07505 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 07506 S_OR(p->mohsuggest, NULL), 07507 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 07508 } 07509 p->subs[SUB_CALLWAIT].needhold = 1; 07510 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07511 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 07512 S_OR(p->mohsuggest, NULL), 07513 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 07514 } 07515 p->subs[SUB_REAL].needunhold = 1; 07516 } else if (!p->subs[SUB_THREEWAY].owner) { 07517 if (!p->threewaycalling) { 07518 /* Just send a flash if no 3-way calling */ 07519 p->subs[SUB_REAL].needflash = 1; 07520 goto winkflashdone; 07521 } else if (!check_for_conference(p)) { 07522 char cid_num[256]; 07523 char cid_name[256]; 07524 07525 cid_num[0] = 0; 07526 cid_name[0] = 0; 07527 if (p->dahditrcallerid && p->owner) { 07528 if (p->owner->cid.cid_num) 07529 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 07530 if (p->owner->cid.cid_name) 07531 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 07532 } 07533 /* XXX This section needs much more error checking!!! XXX */ 07534 /* Start a 3-way call if feasible */ 07535 if (!((ast->pbx) || 07536 (ast->_state == AST_STATE_UP) || 07537 (ast->_state == AST_STATE_RING))) { 07538 ast_debug(1, "Flash when call not up or ringing\n"); 07539 goto winkflashdone; 07540 } 07541 if (alloc_sub(p, SUB_THREEWAY)) { 07542 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 07543 goto winkflashdone; 07544 } 07545 /* Make new channel */ 07546 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0, 0); 07547 if (p->dahditrcallerid) { 07548 if (!p->origcid_num) 07549 p->origcid_num = ast_strdup(p->cid_num); 07550 if (!p->origcid_name) 07551 p->origcid_name = ast_strdup(p->cid_name); 07552 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 07553 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 07554 } 07555 /* Swap things around between the three-way and real call */ 07556 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07557 /* Disable echo canceller for better dialing */ 07558 dahdi_disable_ec(p); 07559 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 07560 if (res) 07561 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 07562 p->owner = chan; 07563 if (!chan) { 07564 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 07565 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 07566 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 07567 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07568 dahdi_enable_ec(p); 07569 ast_hangup(chan); 07570 } else { 07571 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 07572 int way3bridge = 0, cdr3way = 0; 07573 07574 if (!other) { 07575 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 07576 } else 07577 way3bridge = 1; 07578 07579 if (p->subs[SUB_THREEWAY].owner->cdr) 07580 cdr3way = 1; 07581 07582 ast_verb(3, "Started three way call on channel %d\n", p->channel); 07583 07584 /* Start music on hold if appropriate */ 07585 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07586 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 07587 S_OR(p->mohsuggest, NULL), 07588 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 07589 } 07590 p->subs[SUB_THREEWAY].needhold = 1; 07591 } 07592 } 07593 } else { 07594 /* Already have a 3 way call */ 07595 if (p->subs[SUB_THREEWAY].inthreeway) { 07596 /* Call is already up, drop the last person */ 07597 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 07598 /* If the primary call isn't answered yet, use it */ 07599 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 07600 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 07601 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07602 p->owner = p->subs[SUB_REAL].owner; 07603 } 07604 /* Drop the last call and stop the conference */ 07605 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 07606 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07607 p->subs[SUB_REAL].inthreeway = 0; 07608 p->subs[SUB_THREEWAY].inthreeway = 0; 07609 } else { 07610 /* Lets see what we're up to */ 07611 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 07612 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 07613 int otherindex = SUB_THREEWAY; 07614 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 07615 int way3bridge = 0, cdr3way = 0; 07616 07617 if (!other) { 07618 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 07619 } else 07620 way3bridge = 1; 07621 07622 if (p->subs[SUB_THREEWAY].owner->cdr) 07623 cdr3way = 1; 07624 07625 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 07626 /* Put them in the threeway, and flip */ 07627 p->subs[SUB_THREEWAY].inthreeway = 1; 07628 p->subs[SUB_REAL].inthreeway = 1; 07629 if (ast->_state == AST_STATE_UP) { 07630 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07631 otherindex = SUB_REAL; 07632 } 07633 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 07634 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 07635 p->subs[otherindex].needunhold = 1; 07636 p->owner = p->subs[SUB_REAL].owner; 07637 if (ast->_state == AST_STATE_RINGING) { 07638 ast_debug(1, "Enabling ringtone on real and threeway\n"); 07639 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07640 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07641 } 07642 } else { 07643 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 07644 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07645 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07646 p->owner = p->subs[SUB_REAL].owner; 07647 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 07648 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07649 p->subs[SUB_REAL].needunhold = 1; 07650 dahdi_enable_ec(p); 07651 } 07652 } 07653 } 07654 winkflashdone: 07655 update_conf(p); 07656 break; 07657 case SIG_EM: 07658 case SIG_EM_E1: 07659 case SIG_FEATD: 07660 case SIG_SF: 07661 case SIG_SFWINK: 07662 case SIG_SF_FEATD: 07663 case SIG_FXSLS: 07664 case SIG_FXSGS: 07665 if (p->dialing) 07666 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 07667 else 07668 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 07669 break; 07670 case SIG_FEATDMF_TA: 07671 switch (p->whichwink) { 07672 case 0: 07673 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 07674 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 07675 break; 07676 case 1: 07677 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 07678 break; 07679 case 2: 07680 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 07681 return NULL; 07682 } 07683 p->whichwink++; 07684 /* Fall through */ 07685 case SIG_FEATDMF: 07686 case SIG_E911: 07687 case SIG_FGC_CAMAMF: 07688 case SIG_FGC_CAMA: 07689 case SIG_FEATB: 07690 case SIG_SF_FEATDMF: 07691 case SIG_SF_FEATB: 07692 case SIG_EMWINK: 07693 /* FGD MF and EMWINK *Must* wait for wink */ 07694 if (!ast_strlen_zero(p->dop.dialstr)) { 07695 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07696 if (res < 0) { 07697 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 07698 p->dop.dialstr[0] = '\0'; 07699 return NULL; 07700 } else 07701 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 07702 } 07703 p->dop.dialstr[0] = '\0'; 07704 break; 07705 default: 07706 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 07707 } 07708 break; 07709 case DAHDI_EVENT_HOOKCOMPLETE: 07710 if (p->inalarm) break; 07711 if ((p->radio || (p->oprmode < 0))) break; 07712 if (p->waitingfordt.tv_sec) break; 07713 switch (mysig) { 07714 case SIG_FXSLS: /* only interesting for FXS */ 07715 case SIG_FXSGS: 07716 case SIG_FXSKS: 07717 case SIG_EM: 07718 case SIG_EM_E1: 07719 case SIG_EMWINK: 07720 case SIG_FEATD: 07721 case SIG_SF: 07722 case SIG_SFWINK: 07723 case SIG_SF_FEATD: 07724 if (!ast_strlen_zero(p->dop.dialstr)) { 07725 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07726 if (res < 0) { 07727 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 07728 p->dop.dialstr[0] = '\0'; 07729 return NULL; 07730 } else 07731 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 07732 } 07733 p->dop.dialstr[0] = '\0'; 07734 p->dop.op = DAHDI_DIAL_OP_REPLACE; 07735 break; 07736 case SIG_FEATDMF: 07737 case SIG_FEATDMF_TA: 07738 case SIG_E911: 07739 case SIG_FGC_CAMA: 07740 case SIG_FGC_CAMAMF: 07741 case SIG_FEATB: 07742 case SIG_SF_FEATDMF: 07743 case SIG_SF_FEATB: 07744 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 07745 break; 07746 default: 07747 break; 07748 } 07749 break; 07750 case DAHDI_EVENT_POLARITY: 07751 /* 07752