DAHDI for Pseudo TDM. More...
#include "asterisk.h"#include <sys/signal.h>#include <sys/ioctl.h>#include <sys/stat.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"#include "asterisk/ccss.h"#include "asterisk/data.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_starting_point |
| 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 | CALLWAITING_SUPPRESS_SAMPLES ((100 * 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 | dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
| #define | DATA_EXPORT_DAHDI_PVT(MEMBER) |
| #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 %-15.15s %-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 %-15.15s %-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 | REPORT_CHANNEL_ALARMS 1 |
| #define | REPORT_SPAN_ALARMS 2 |
| #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 int | __unload_module (void) |
| static int | _dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line) |
| 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) |
| AST_DATA_STRUCTURE (dahdi_pvt, DATA_EXPORT_DAHDI_PVT) | |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DRIVER,.nonoptreq="res_smdi",) | |
| AST_MUTEX_DEFINE_STATIC (restart_lock) | |
| AST_MUTEX_DEFINE_STATIC (ss_thread_lock) | |
| AST_MUTEX_DEFINE_STATIC (monlock) | |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| AST_MUTEX_DEFINE_STATIC (iflock) | |
| Protect the interface list (of dahdi_pvt's). | |
| static int | attempt_transfer (struct dahdi_pvt *p) |
| static int | available (struct dahdi_pvt **pvt, int is_specific_channel) |
| 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, format_t law) |
| static int | canmatch_featurecode (const char *exten) |
| 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 struct ast_str * | create_channel_name (struct dahdi_pvt *i) |
| static void | dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan) |
| 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 int | dahdi_cc_callback (struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback) |
| Callback made when dial failed to get a channel out of dahdi_request(). | |
| static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
| static int | dahdi_channels_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| 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_devicestate (void *data) |
| 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 void | dahdi_handle_dtmf (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 void | dahdi_lock_sub_owner (struct dahdi_pvt *pvt, int sub_idx) |
| static struct ast_channel * | dahdi_new (struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid) |
| 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) |
| static struct ast_frame * | dahdi_read (struct ast_channel *ast) |
| static struct ast_channel * | dahdi_request (const char *type, format_t 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 int | dahdi_status_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| 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_version_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| 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 | deep_copy_dahdi_chan_conf (struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src) |
| 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 struct dahdi_pvt * | determine_starting_point (const char *data, struct dahdi_starting_point *param) |
| static int | device2chan (const char *subdir, int channel, char *path, int pathlen) |
| 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 struct dahdi_pvt * | find_channel_from_str (const char *channel) |
| static struct dahdi_pvt * | find_next_iface_in_span (struct dahdi_pvt *cur) |
| static int | get_alarms (struct dahdi_pvt *p) |
| static void | handle_alarms (struct dahdi_pvt *p, int alms) |
| static void | handle_clear_alarms (struct dahdi_pvt *p) |
| 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 | is_group_or_channel_match (struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched) |
| 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 | monitor_pfds_clean (void *arg) |
| 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 void | my_answer_polarityswitch (void *pvt) |
| 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_deadlock_avoidance_private (void *pvt) |
| 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 const char * | my_get_orig_dialstring (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_dtmf (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 void | my_hangup_polarityswitch (void *pvt) |
| static int | my_has_voicemail (void *pvt) |
| static int | my_have_progressdetect (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_party_caller *caller) |
| static void | my_set_alarm (void *pvt, int in_alarm) |
| static void | my_set_cadence (void *pvt, int *cid_rings, struct ast_channel *ast) |
| static void | my_set_callwaiting (void *pvt, int callwaiting_enable) |
| static void | my_set_confirmanswer (void *pvt, int flag) |
| static void | my_set_dialing (void *pvt, int is_dialing) |
| static int | my_set_echocanceller (void *pvt, int enable) |
| static void | my_set_inthreeway (void *pvt, enum analog_sub sub, int inthreeway) |
| static int | my_set_linear_mode (void *pvt, enum analog_sub sub, int linear_mode) |
| static void | my_set_needringing (void *pvt, int value) |
| static void | my_set_new_owner (void *pvt, struct ast_channel *new_owner) |
| static void | my_set_outgoing (void *pvt, int is_outgoing) |
| static void | my_set_polarity (void *pvt, int value) |
| 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 void | my_start_polarityswitch (void *pvt) |
| 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 char * | parse_spanchan (char *chanstr, char **subdir) |
| 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, float rxgain, float txgain, float rxdrc, float txdrc, int law) |
| static int | set_actual_rxgain (int fd, float gain, float drc, int law) |
| static int | set_actual_txgain (int fd, float gain, float drc, int law) |
| static int | setup_dahdi (int reload) |
| static int | setup_dahdi_int (int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf) |
| static int | sigtype_to_signalling (int sigtype) |
| static void | string_replace (char *str, int char1, int char2) |
| 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 | |
| struct { | |
| int alarm | |
| char * name | |
| } | alarms [] |
| static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
| 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_data_handler | dahdi_channels_data_provider |
| static struct ast_cli_entry | dahdi_cli [] |
| static struct ast_data_entry | dahdi_data_providers [] |
| static struct ast_data_handler | dahdi_status_data_provider |
| static struct ast_channel_tech | dahdi_tech |
| static struct ast_data_handler | dahdi_version_data_provider |
| 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 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 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 | progzone [10] = "" |
| static int | report_alarms = REPORT_CHANNEL_ALARMS |
| 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 const char *const | subnames [] |
| static const char | tdesc [] = "DAHDI Telephony Driver" |
| static int | usedistinctiveringdetection = 0 |
| static int | user_has_defined_cadences = 0 |
DAHDI for Pseudo TDM.
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 320 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 387 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmf(), my_handle_dtmf(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 386 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 385 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 384 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), my_have_progressdetect(), and process_dahdi().
| #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) |
10,000 ms
Definition at line 522 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 521 of file chan_dahdi.c.
| #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) |
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 417 of file chan_dahdi.c.
Referenced by dahdi_new().
| #define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 418 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), my_have_progressdetect(), and my_set_waitingfordt().
| #define CHAN_PSEUDO -2 |
Definition at line 382 of file chan_dahdi.c.
Referenced by build_channels(), create_channel_name(), dahdi_ami_channel_event(), dahdi_new(), dahdi_request(), determine_starting_point(), enable_dtmf_detect(), mkintf(), my_dsp_set_digitmode(), my_set_polarity(), and process_dahdi().
| #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 659 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 660 of file chan_dahdi.c.
| #define dahdi_get_index | ( | ast, | |||
| p, | |||||
| nullok | ) | _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
Definition at line 3777 of file chan_dahdi.c.
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().
| #define DATA_EXPORT_DAHDI_PVT | ( | MEMBER | ) |
Definition at line 1236 of file chan_dahdi.c.
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 318 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 526 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 %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_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_manager_show_settings(), 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 %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_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_manager_show_settings(), 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 1526 of file chan_dahdi.c.
Referenced by my_complete_conference_update(), and update_conf().
| #define HANGUP 1 |
Definition at line 16009 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_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_retrieve_acknowledge(), build_setup(), build_setup_acknowledge(), 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 | ) |
Definition at line 414 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 518 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 519 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 17037 of file chan_dahdi.c.
| #define MAX_SLAVES 4 |
Definition at line 662 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 525 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 324 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and dahdi_new().
| #define NUM_CADENCE_MAX 25 |
Definition at line 389 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_SPANS 32 |
Definition at line 379 of file chan_dahdi.c.
Referenced by destroy_all_channels().
| #define POLARITY_IDLE 0 |
Definition at line 619 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 620 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 17091 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi_int().
| #define PROC_DAHDI_OPT_NOWARN (1 << 1) |
process_dahdi() - No warnings on non-existing cofiguration keywords
Definition at line 17093 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi_int().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 516 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 REPORT_CHANNEL_ALARMS 1 |
Definition at line 439 of file chan_dahdi.c.
Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().
| #define REPORT_SPAN_ALARMS 2 |
Definition at line 440 of file chan_dahdi.c.
Referenced by handle_alarms(), handle_clear_alarms(), and process_dahdi().
| #define sig2str dahdi_sig2str |
Definition at line 4712 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) |
Definition at line 365 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), and process_dahdi().
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 366 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), mkintf(), and process_dahdi().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 354 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 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_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 374 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 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(), mkintf(), and process_dahdi().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
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_FEATD (0x0200000 | DAHDI_SIG_EM) |
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(), mkintf(), and process_dahdi().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
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_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 355 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 356 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 357 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 362 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 363 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 361 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 359 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 360 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 358 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 368 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), mkintf(), and process_dahdi().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 364 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_sig2str(), mkintf(), and process_dahdi().
| #define SIG_PRI_LIB_HANDLE_CASES |
SIG_PRI: \ case SIG_BRI: \ case SIG_BRI_PTMP
Definition at line 1528 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_new(), dahdi_request(), dahdi_sig_pri_lib_handles(), destroy_dahdi_pvt(), handle_init_event(), and mkintf().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 369 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 373 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 371 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 372 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 370 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 367 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_fixup(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), destroy_dahdi_pvt(), handle_init_event(), mkintf(), and process_dahdi().
| #define SMDI_MD_WAIT_TIMEOUT 1500 |
Definition at line 281 of file chan_dahdi.c.
Referenced by analog_ss_thread().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 615 of file chan_dahdi.c.
Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), and dahdi_show_channel().
| #define SUB_REAL 0 |
Active call
Definition at line 614 of file chan_dahdi.c.
Referenced by __dahdi_exception(), _dahdi_get_index(), 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_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_set_needringing(), my_set_polarity(), 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 616 of file chan_dahdi.c.
Referenced by _dahdi_get_index(), analog_ss_thread(), analogsub_to_dahdisub(), attempt_transfer(), close_call(), dahdi_bridge(), 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 16008 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 683 of file chan_dahdi.c.
00683 { 00684 DAHDI_IFLIST_NONE, /*!< The dahdi_pvt is not in any list. */ 00685 DAHDI_IFLIST_MAIN, /*!< The dahdi_pvt is in the main interface list */ 00686 #if defined(HAVE_PRI) 00687 DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */ 00688 #endif /* defined(HAVE_PRI) */ 00689 };
| 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 667 of file chan_dahdi.c.
00667 { 00668 MWI_SEND_NULL = 0, 00669 MWI_SEND_SA, 00670 MWI_SEND_SA_WAIT, 00671 MWI_SEND_PAUSE, 00672 MWI_SEND_SPILL, 00673 MWI_SEND_CLEANUP, 00674 MWI_SEND_DONE, 00675 } mwisend_states;
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8799 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_suppress_expire, 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, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_WARNING, ast_frame::mallocd, 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().
08800 { 08801 int res; 08802 int idx; 08803 struct ast_frame *f; 08804 int usedindex = -1; 08805 struct dahdi_pvt *p = ast->tech_pvt; 08806 08807 if ((idx = dahdi_get_index(ast, p, 0)) < 0) { 08808 idx = SUB_REAL; 08809 } 08810 08811 p->subs[idx].f.frametype = AST_FRAME_NULL; 08812 p->subs[idx].f.datalen = 0; 08813 p->subs[idx].f.samples = 0; 08814 p->subs[idx].f.mallocd = 0; 08815 p->subs[idx].f.offset = 0; 08816 p->subs[idx].f.subclass.integer = 0; 08817 p->subs[idx].f.delivery = ast_tv(0,0); 08818 p->subs[idx].f.src = "dahdi_exception"; 08819 p->subs[idx].f.data.ptr = NULL; 08820 08821 08822 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 08823 /* If nobody owns us, absorb the event appropriately, otherwise 08824 we loop indefinitely. This occurs when, during call waiting, the 08825 other end hangs up our channel so that it no longer exists, but we 08826 have neither FLASH'd nor ONHOOK'd to signify our desire to 08827 change to the other channel. */ 08828 if (p->fake_event) { 08829 res = p->fake_event; 08830 p->fake_event = 0; 08831 } else 08832 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 08833 /* Switch to real if there is one and this isn't something really silly... */ 08834 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 08835 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 08836 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 08837 p->owner = p->subs[SUB_REAL].owner; 08838 if (p->owner && ast_bridged_channel(p->owner)) 08839 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08840 p->subs[SUB_REAL].needunhold = 1; 08841 } 08842 switch (res) { 08843 case DAHDI_EVENT_ONHOOK: 08844 dahdi_disable_ec(p); 08845 if (p->owner) { 08846 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 08847 dahdi_ring_phone(p); 08848 p->callwaitingrepeat = 0; 08849 p->cidcwexpire = 0; 08850 p->cid_suppress_expire = 0; 08851 } else 08852 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08853 update_conf(p); 08854 break; 08855 case DAHDI_EVENT_RINGOFFHOOK: 08856 dahdi_enable_ec(p); 08857 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08858 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 08859 p->subs[SUB_REAL].needanswer = 1; 08860 p->dialing = 0; 08861 } 08862 break; 08863 case DAHDI_EVENT_HOOKCOMPLETE: 08864 case DAHDI_EVENT_RINGERON: 08865 case DAHDI_EVENT_RINGEROFF: 08866 /* Do nothing */ 08867 break; 08868 case DAHDI_EVENT_WINKFLASH: 08869 p->flashtime = ast_tvnow(); 08870 if (p->owner) { 08871 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 08872 if (p->owner->_state != AST_STATE_UP) { 08873 /* Answer if necessary */ 08874 usedindex = dahdi_get_index(p->owner, p, 0); 08875 if (usedindex > -1) { 08876 p->subs[usedindex].needanswer = 1; 08877 } 08878 ast_setstate(p->owner, AST_STATE_UP); 08879 } 08880 p->callwaitingrepeat = 0; 08881 p->cidcwexpire = 0; 08882 p->cid_suppress_expire = 0; 08883 if (ast_bridged_channel(p->owner)) 08884 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08885 p->subs[SUB_REAL].needunhold = 1; 08886 } else 08887 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08888 update_conf(p); 08889 break; 08890 default: 08891 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 08892 } 08893 f = &p->subs[idx].f; 08894 return f; 08895 } 08896 if (!(p->radio || (p->oprmode < 0))) 08897 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 08898 /* If it's not us, return NULL immediately */ 08899 if (ast != p->owner) { 08900 if (p->owner) { 08901 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 08902 } 08903 f = &p->subs[idx].f; 08904 return f; 08905 } 08906 08907 f = dahdi_handle_event(ast); 08908 if (!f) { 08909 const char *name = ast_strdupa(ast->name); 08910 08911 /* Tell the CDR this DAHDI device hung up */ 08912 ast_mutex_unlock(&p->lock); 08913 ast_channel_unlock(ast); 08914 ast_set_hangupsource(ast, name, 0); 08915 ast_channel_lock(ast); 08916 ast_mutex_lock(&p->lock); 08917 } 08918 return f; 08919 }
| static int __unload_module | ( | void | ) | [static] |
Definition at line 16831 of file chan_dahdi.c.
References ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_data_unregister, 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(), sig_ss7_linkset::master, sig_pri_span::master, dahdi_pvt::next, dahdi_pvt::owner, sig_pri_stop_pri(), sig_pri_unload(), and SIG_SS7_NUM_DCHANS.
Referenced by load_module(), and unload_module().
16832 { 16833 struct dahdi_pvt *p; 16834 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16835 int i, j; 16836 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16837 16838 #ifdef HAVE_PRI 16839 for (i = 0; i < NUM_SPANS; i++) { 16840 if (pris[i].pri.master != AST_PTHREADT_NULL) { 16841 pthread_cancel(pris[i].pri.master); 16842 pthread_kill(pris[i].pri.master, SIGURG); 16843 } 16844 } 16845 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 16846 ast_unregister_application(dahdi_send_keypad_facility_app); 16847 #ifdef HAVE_PRI_PROG_W_CAUSE 16848 ast_unregister_application(dahdi_send_callrerouting_facility_app); 16849 #endif 16850 #endif 16851 #if defined(HAVE_SS7) 16852 for (i = 0; i < NUM_SPANS; i++) { 16853 if (linksets[i].ss7.master != AST_PTHREADT_NULL) { 16854 pthread_cancel(linksets[i].ss7.master); 16855 pthread_kill(linksets[i].ss7.master, SIGURG); 16856 } 16857 } 16858 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 16859 #endif /* defined(HAVE_SS7) */ 16860 #if defined(HAVE_OPENR2) 16861 dahdi_r2_destroy_links(); 16862 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 16863 ast_unregister_application(dahdi_accept_r2_call_app); 16864 #endif 16865 16866 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 16867 ast_manager_unregister("DAHDIDialOffhook"); 16868 ast_manager_unregister("DAHDIHangup"); 16869 ast_manager_unregister("DAHDITransfer"); 16870 ast_manager_unregister("DAHDIDNDoff"); 16871 ast_manager_unregister("DAHDIDNDon"); 16872 ast_manager_unregister("DAHDIShowChannels"); 16873 ast_manager_unregister("DAHDIRestart"); 16874 ast_data_unregister(NULL); 16875 ast_channel_unregister(&dahdi_tech); 16876 16877 /* Hangup all interfaces if they have an owner */ 16878 ast_mutex_lock(&iflock); 16879 for (p = iflist; p; p = p->next) { 16880 if (p->owner) 16881 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 16882 } 16883 ast_mutex_unlock(&iflock); 16884 16885 ast_mutex_lock(&monlock); 16886 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 16887 pthread_cancel(monitor_thread); 16888 pthread_kill(monitor_thread, SIGURG); 16889 pthread_join(monitor_thread, NULL); 16890 } 16891 monitor_thread = AST_PTHREADT_STOP; 16892 ast_mutex_unlock(&monlock); 16893 16894 destroy_all_channels(); 16895 16896 #if defined(HAVE_PRI) 16897 for (i = 0; i < NUM_SPANS; i++) { 16898 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 16899 pthread_join(pris[i].pri.master, NULL); 16900 } 16901 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) { 16902 dahdi_close_pri_fd(&(pris[i]), j); 16903 } 16904 sig_pri_stop_pri(&pris[i].pri); 16905 } 16906 #if defined(HAVE_PRI_CCSS) 16907 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks); 16908 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks); 16909 #endif /* defined(HAVE_PRI_CCSS) */ 16910 sig_pri_unload(); 16911 #endif 16912 16913 #if defined(HAVE_SS7) 16914 for (i = 0; i < NUM_SPANS; i++) { 16915 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 16916 pthread_join(linksets[i].ss7.master, NULL); 16917 } 16918 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) { 16919 dahdi_close_ss7_fd(&(linksets[i]), j); 16920 } 16921 } 16922 #endif /* defined(HAVE_SS7) */ 16923 ast_cond_destroy(&ss_thread_complete); 16924 return 0; 16925 }
| static int _dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok, | |||
| const char * | fname, | |||
| unsigned long | line | |||
| ) | [static] |
Definition at line 3778 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_subchannel::owner, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
03779 { 03780 int res; 03781 if (p->subs[SUB_REAL].owner == ast) 03782 res = 0; 03783 else if (p->subs[SUB_CALLWAIT].owner == ast) 03784 res = 1; 03785 else if (p->subs[SUB_THREEWAY].owner == ast) 03786 res = 2; 03787 else { 03788 res = -1; 03789 if (!nullok) 03790 ast_log(LOG_WARNING, 03791 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 03792 ast ? ast->name : "", p->channel, fname, line); 03793 } 03794 return res; 03795 }
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16146 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_from_str(), and dahdi_pvt::owner.
Referenced by load_module().
16147 { 16148 struct dahdi_pvt *p; 16149 const char *channel = astman_get_header(m, "DAHDIChannel"); 16150 const char *number = astman_get_header(m, "Number"); 16151 int i; 16152 16153 if (ast_strlen_zero(channel)) { 16154 astman_send_error(s, m, "No channel specified"); 16155 return 0; 16156 } 16157 if (ast_strlen_zero(number)) { 16158 astman_send_error(s, m, "No number specified"); 16159 return 0; 16160 } 16161 p = find_channel_from_str(channel); 16162 if (!p) { 16163 astman_send_error(s, m, "No such channel"); 16164 return 0; 16165 } 16166 if (!p->owner) { 16167 astman_send_error(s, m, "Channel does not have it's owner"); 16168 return 0; 16169 } 16170 for (i = 0; i < strlen(number); i++) { 16171 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] }; 16172 dahdi_queue_frame(p, &f); 16173 } 16174 astman_send_ack(s, m, "DAHDIDialOffhook"); 16175 return 0; 16176 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16081 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_dnd(), and find_channel_from_str().
Referenced by load_module().
16082 { 16083 struct dahdi_pvt *p; 16084 const char *channel = astman_get_header(m, "DAHDIChannel"); 16085 16086 if (ast_strlen_zero(channel)) { 16087 astman_send_error(s, m, "No channel specified"); 16088 return 0; 16089 } 16090 p = find_channel_from_str(channel); 16091 if (!p) { 16092 astman_send_error(s, m, "No such channel"); 16093 return 0; 16094 } 16095 dahdi_dnd(p, 0); 16096 astman_send_ack(s, m, "DND Disabled"); 16097 return 0; 16098 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16062 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_dnd(), and find_channel_from_str().
Referenced by load_module().
16063 { 16064 struct dahdi_pvt *p; 16065 const char *channel = astman_get_header(m, "DAHDIChannel"); 16066 16067 if (ast_strlen_zero(channel)) { 16068 astman_send_error(s, m, "No channel specified"); 16069 return 0; 16070 } 16071 p = find_channel_from_str(channel); 16072 if (!p) { 16073 astman_send_error(s, m, "No such channel"); 16074 return 0; 16075 } 16076 dahdi_dnd(p, 1); 16077 astman_send_ack(s, m, "DND Enabled"); 16078 return 0; 16079 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15351 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
15352 { 15353 if (dahdi_restart() != 0) { 15354 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 15355 return 1; 15356 } 15357 astman_send_ack(s, m, "DAHDIRestart: Success"); 15358 return 0; 15359 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16178 of file chan_dahdi.c.
References 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(), dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, and sig2str.
Referenced by load_module().
16179 { 16180 struct dahdi_pvt *tmp = NULL; 16181 const char *id = astman_get_header(m, "ActionID"); 16182 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 16183 char idText[256] = ""; 16184 int channels = 0; 16185 int dahdichanquery; 16186 16187 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) { 16188 /* Not numeric string. */ 16189 dahdichanquery = -1; 16190 } 16191 16192 astman_send_ack(s, m, "DAHDI channel status will follow"); 16193 if (!ast_strlen_zero(id)) 16194 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 16195 16196 ast_mutex_lock(&iflock); 16197 16198 for (tmp = iflist; tmp; tmp = tmp->next) { 16199 if (tmp->channel > 0) { 16200 int alm; 16201 16202 /* If a specific channel is queried for, only deliver status for that channel */ 16203 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 16204 continue; 16205 16206 alm = get_alarms(tmp); 16207 channels++; 16208 if (tmp->owner) { 16209 /* Add data if we have a current call */ 16210 astman_append(s, 16211 "Event: DAHDIShowChannels\r\n" 16212 "DAHDIChannel: %d\r\n" 16213 "Channel: %s\r\n" 16214 "Uniqueid: %s\r\n" 16215 "AccountCode: %s\r\n" 16216 "Signalling: %s\r\n" 16217 "SignallingCode: %d\r\n" 16218 "Context: %s\r\n" 16219 "DND: %s\r\n" 16220 "Alarm: %s\r\n" 16221 "%s" 16222 "\r\n", 16223 tmp->channel, 16224 tmp->owner->name, 16225 tmp->owner->uniqueid, 16226 tmp->owner->accountcode, 16227 sig2str(tmp->sig), 16228 tmp->sig, 16229 tmp->context, 16230 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16231 alarm2str(alm), idText); 16232 } else { 16233 astman_append(s, 16234 "Event: DAHDIShowChannels\r\n" 16235 "DAHDIChannel: %d\r\n" 16236 "Signalling: %s\r\n" 16237 "SignallingCode: %d\r\n" 16238 "Context: %s\r\n" 16239 "DND: %s\r\n" 16240 "Alarm: %s\r\n" 16241 "%s" 16242 "\r\n", 16243 tmp->channel, sig2str(tmp->sig), tmp->sig, 16244 tmp->context, 16245 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16246 alarm2str(alm), idText); 16247 } 16248 } 16249 } 16250 16251 ast_mutex_unlock(&iflock); 16252 16253 astman_append(s, 16254 "Event: DAHDIShowChannelsComplete\r\n" 16255 "%s" 16256 "Items: %d\r\n" 16257 "\r\n", 16258 idText, 16259 channels); 16260 return 0; 16261 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16100 of file chan_dahdi.c.
References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_fake_event(), find_channel_from_str(), dahdi_pvt::sig, and TRANSFER.
Referenced by load_module().
16101 { 16102 struct dahdi_pvt *p; 16103 const char *channel = astman_get_header(m, "DAHDIChannel"); 16104 16105 if (ast_strlen_zero(channel)) { 16106 astman_send_error(s, m, "No channel specified"); 16107 return 0; 16108 } 16109 p = find_channel_from_str(channel); 16110 if (!p) { 16111 astman_send_error(s, m, "No such channel"); 16112 return 0; 16113 } 16114 if (!analog_lib_handles(p->sig, 0, 0)) { 16115 astman_send_error(s, m, "Channel signaling is not analog"); 16116 return 0; 16117 } 16118 dahdi_fake_event(p,TRANSFER); 16119 astman_send_ack(s, m, "DAHDITransfer"); 16120 return 0; 16121 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 16123 of file chan_dahdi.c.
References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_fake_event(), find_channel_from_str(), HANGUP, and dahdi_pvt::sig.
Referenced by load_module().
16124 { 16125 struct dahdi_pvt *p; 16126 const char *channel = astman_get_header(m, "DAHDIChannel"); 16127 16128 if (ast_strlen_zero(channel)) { 16129 astman_send_error(s, m, "No channel specified"); 16130 return 0; 16131 } 16132 p = find_channel_from_str(channel); 16133 if (!p) { 16134 astman_send_error(s, m, "No such channel"); 16135 return 0; 16136 } 16137 if (!analog_lib_handles(p->sig, 0, 0)) { 16138 astman_send_error(s, m, "Channel signaling is not analog"); 16139 return 0; 16140 } 16141 dahdi_fake_event(p,HANGUP); 16142 astman_send_ack(s, m, "DAHDIHangup"); 16143 return 0; 16144 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 4629 of file chan_dahdi.c.
References alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
| static int alloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 4430 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(), dahdi_handle_event(), and my_allocate_sub().
04431 { 04432 struct dahdi_bufferinfo bi; 04433 int res; 04434 if (p->subs[x].dfd >= 0) { 04435 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 04436 return -1; 04437 } 04438 04439 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 04440 if (p->subs[x].dfd <= -1) { 04441 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 04442 return -1; 04443 } 04444 04445 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 04446 if (!res) { 04447 bi.txbufpolicy = p->buf_policy; 04448 bi.rxbufpolicy = p->buf_policy; 04449 bi.numbufs = p->buf_no; 04450 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 04451 if (res < 0) { 04452 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 04453 } 04454 } else 04455 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 04456 04457 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 04458 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 04459 dahdi_close_sub(p, x); 04460 p->subs[x].dfd = -1; 04461 return -1; 04462 } 04463 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 04464 return 0; 04465 }
| static int analog_lib_handles | ( | int | signalling, | |
| int | radio, | |||
| int | oprmode | |||
| ) | [static] |
Definition at line 1558 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 action_transfer(), action_transferhangup(), available(), dahdi_answer(), dahdi_call(), dahdi_dnd(), dahdi_exception(), dahdi_fixup(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), mkintf(), mwi_thread(), and my_get_sigpvt_bridged_channel().
01559 { 01560 switch (signalling) { 01561 case SIG_FXOLS: 01562 case SIG_FXOGS: 01563 case SIG_FXOKS: 01564 case SIG_FXSLS: 01565 case SIG_FXSGS: 01566 case SIG_FXSKS: 01567 case SIG_EMWINK: 01568 case SIG_EM: 01569 case SIG_EM_E1: 01570 case SIG_FEATD: 01571 case SIG_FEATDMF: 01572 case SIG_E911: 01573 case SIG_FGC_CAMA: 01574 case SIG_FGC_CAMAMF: 01575 case SIG_FEATB: 01576 case SIG_SFWINK: 01577 case SIG_SF: 01578 case SIG_SF_FEATD: 01579 case SIG_SF_FEATDMF: 01580 case SIG_FEATDMF_TA: 01581 case SIG_SF_FEATB: 01582 break; 01583 default: 01584 /* The rest of the function should cover the remainder of signalling types */ 01585 return 0; 01586 } 01587 01588 if (radio) { 01589 return 0; 01590 } 01591 01592 if (oprmode) { 01593 return 0; 01594 } 01595 01596 return 1; 01597 }
| static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 9945 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, 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_FLAG_END_DTMF_ONLY, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call_exten(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_ext_valid(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_remaining_ms(), ast_safe_sleep(), ast_set_callerid(), ast_set_flag, 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_tvnow(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, bump_gains(), dahdi_pvt::call_forward, ast_channel::caller, 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, canmatch_featurecode(), dahdi_pvt::canpark, dahdi_pvt::channel, dahdi_pvt::cid_name, 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, ast_party_caller::id, dahdi_pvt::immediate, dahdi_pvt::inalarm, ast_frame_subclass::integer, ISTRUNK, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, my_getsigstr(), my_handle_notify_message(), ast_party_id::name, name, NEED_MFDETECT, ast_party_id::number, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, 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, ast_party_number::str, 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, dahdi_pvt::usedistinctiveringdetection, and ast_party_number::valid.
Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and mwi_thread().
09946 { 09947 struct ast_channel *chan = data; 09948 struct dahdi_pvt *p = chan->tech_pvt; 09949 char exten[AST_MAX_EXTENSION] = ""; 09950 char exten2[AST_MAX_EXTENSION] = ""; 09951 unsigned char buf[256]; 09952 char dtmfcid[300]; 09953 char dtmfbuf[300]; 09954 struct callerid_state *cs = NULL; 09955 char *name = NULL, *number = NULL; 09956 int distMatches; 09957 int curRingData[3]; 09958 int receivedRingT; 09959 int counter1; 09960 int counter; 09961 int samples = 0; 09962 struct ast_smdi_md_message *smdi_msg = NULL; 09963 int flags = 0; 09964 int i; 09965 int timeout; 09966 int getforward = 0; 09967 char *s1, *s2; 09968 int len = 0; 09969 int res; 09970 int idx; 09971 09972 ast_mutex_lock(&ss_thread_lock); 09973 ss_thread_count++; 09974 ast_mutex_unlock(&ss_thread_lock); 09975 /* in the bizarre case where the channel has become a zombie before we 09976 even get started here, abort safely 09977 */ 09978 if (!p) { 09979 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 09980 ast_hangup(chan); 09981 goto quit; 09982 } 09983 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 09984 idx = dahdi_get_index(chan, p, 1); 09985 if (idx < 0) { 09986 ast_log(LOG_WARNING, "Huh?\n"); 09987 ast_hangup(chan); 09988 goto quit; 09989 } 09990 if (p->dsp) 09991 ast_dsp_digitreset(p->dsp); 09992 switch (p->sig) { 09993 case SIG_FEATD: 09994 case SIG_FEATDMF: 09995 case SIG_FEATDMF_TA: 09996 case SIG_E911: 09997 case SIG_FGC_CAMAMF: 09998 case SIG_FEATB: 09999 case SIG_EMWINK: 10000 case SIG_SF_FEATD: 10001 case SIG_SF_FEATDMF: 10002 case SIG_SF_FEATB: 10003 case SIG_SFWINK: 10004 if (dahdi_wink(p, idx)) 10005 goto quit; 10006 /* Fall through */ 10007 case SIG_EM: 10008 case SIG_EM_E1: 10009 case SIG_SF: 10010 case SIG_FGC_CAMA: 10011 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10012 if (p->dsp) 10013 ast_dsp_digitreset(p->dsp); 10014 /* set digit mode appropriately */ 10015 if (p->dsp) { 10016 if (NEED_MFDETECT(p)) 10017 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10018 else 10019 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10020 } 10021 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 10022 /* Wait for the first digit only if immediate=no */ 10023 if (!p->immediate) 10024 /* Wait for the first digit (up to 5 seconds). */ 10025 res = ast_waitfordigit(chan, 5000); 10026 else 10027 res = 0; 10028 if (res > 0) { 10029 /* save first char */ 10030 dtmfbuf[0] = res; 10031 switch (p->sig) { 10032 case SIG_FEATD: 10033 case SIG_SF_FEATD: 10034 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10035 if (res > 0) 10036 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10037 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10038 break; 10039 case SIG_FEATDMF_TA: 10040 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10041 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10042 if (dahdi_wink(p, idx)) goto quit; 10043 dtmfbuf[0] = 0; 10044 /* Wait for the first digit (up to 5 seconds). */ 10045 res = ast_waitfordigit(chan, 5000); 10046 if (res <= 0) break; 10047 dtmfbuf[0] = res; 10048 /* fall through intentionally */ 10049 case SIG_FEATDMF: 10050 case SIG_E911: 10051 case SIG_FGC_CAMAMF: 10052 case SIG_SF_FEATDMF: 10053 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10054 /* if international caca, do it again to get real ANO */ 10055 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 10056 { 10057 if (dahdi_wink(p, idx)) goto quit; 10058 dtmfbuf[0] = 0; 10059 /* Wait for the first digit (up to 5 seconds). */ 10060 res = ast_waitfordigit(chan, 5000); 10061 if (res <= 0) break; 10062 dtmfbuf[0] = res; 10063 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10064 } 10065 if (res > 0) { 10066 /* if E911, take off hook */ 10067 if (p->sig == SIG_E911) 10068 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10069 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 10070 } 10071 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10072 break; 10073 case SIG_FEATB: 10074 case SIG_SF_FEATB: 10075 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10076 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10077 break; 10078 case SIG_EMWINK: 10079 /* if we received a '*', we are actually receiving Feature Group D 10080 dial syntax, so use that mode; otherwise, fall through to normal 10081 mode 10082 */ 10083 if (res == '*') { 10084 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10085 if (res > 0) 10086 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10087 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10088 break; 10089 } 10090 default: 10091 /* If we got the first digit, get the rest */ 10092 len = 1; 10093 dtmfbuf[len] = '\0'; 10094 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10095 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10096 timeout = matchdigittimeout; 10097 } else { 10098 timeout = gendigittimeout; 10099 } 10100 res = ast_waitfordigit(chan, timeout); 10101 if (res < 0) { 10102 ast_debug(1, "waitfordigit returned < 0...\n"); 10103 ast_hangup(chan); 10104 goto quit; 10105 } else if (res) { 10106 dtmfbuf[len++] = res; 10107 dtmfbuf[len] = '\0'; 10108 } else { 10109 break; 10110 } 10111 } 10112 break; 10113 } 10114 } 10115 if (res == -1) { 10116 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 10117 ast_hangup(chan); 10118 goto quit; 10119 } else if (res < 0) { 10120 ast_debug(1, "Got hung up before digits finished\n"); 10121 ast_hangup(chan); 10122 goto quit; 10123 } 10124 10125 if (p->sig == SIG_FGC_CAMA) { 10126 char anibuf[100]; 10127 10128 if (ast_safe_sleep(chan,1000) == -1) { 10129 ast_hangup(chan); 10130 goto quit; 10131 } 10132 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10133 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10134 res = my_getsigstr(chan, anibuf, "#", 10000); 10135 if ((res > 0) && (strlen(anibuf) > 2)) { 10136 if (anibuf[strlen(anibuf) - 1] == '#') 10137 anibuf[strlen(anibuf) - 1] = 0; 10138 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 10139 } 10140 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10141 } 10142 10143 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 10144 if (ast_strlen_zero(exten)) 10145 ast_copy_string(exten, "s", sizeof(exten)); 10146 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 10147 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 10148 if (exten[0] == '*') { 10149 char *stringp=NULL; 10150 ast_copy_string(exten2, exten, sizeof(exten2)); 10151 /* Parse out extension and callerid */ 10152 stringp=exten2 +1; 10153 s1 = strsep(&stringp, "*"); 10154 s2 = strsep(&stringp, "*"); 10155 if (s2) { 10156 if (!ast_strlen_zero(p->cid_num)) 10157 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10158 else 10159 ast_set_callerid(chan, s1, NULL, s1); 10160 ast_copy_string(exten, s2, sizeof(exten)); 10161 } else 10162 ast_copy_string(exten, s1, sizeof(exten)); 10163 } else if (p->sig == SIG_FEATD) 10164 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10165 } 10166 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10167 if (exten[0] == '*') { 10168 char *stringp=NULL; 10169 ast_copy_string(exten2, exten, sizeof(exten2)); 10170 /* Parse out extension and callerid */ 10171 stringp=exten2 +1; 10172 s1 = strsep(&stringp, "#"); 10173 s2 = strsep(&stringp, "#"); 10174 if (s2) { 10175 if (!ast_strlen_zero(p->cid_num)) 10176 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10177 else 10178 if (*(s1 + 2)) 10179 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 10180 ast_copy_string(exten, s2 + 1, sizeof(exten)); 10181 } else 10182 ast_copy_string(exten, s1 + 2, sizeof(exten)); 10183 } else 10184 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10185 } 10186 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 10187 if (exten[0] == '*') { 10188 char *stringp=NULL; 10189 ast_copy_string(exten2, exten, sizeof(exten2)); 10190 /* Parse out extension and callerid */ 10191 stringp=exten2 +1; 10192 s1 = strsep(&stringp, "#"); 10193 s2 = strsep(&stringp, "#"); 10194 if (s2 && (*(s2 + 1) == '0')) { 10195 if (*(s2 + 2)) 10196 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 10197 } 10198 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 10199 else ast_copy_string(exten, "911", sizeof(exten)); 10200 } else 10201 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 10202 } 10203 if (p->sig == SIG_FEATB) { 10204 if (exten[0] == '*') { 10205 char *stringp=NULL; 10206 ast_copy_string(exten2, exten, sizeof(exten2)); 10207 /* Parse out extension and callerid */ 10208 stringp=exten2 +1; 10209 s1 = strsep(&stringp, "#"); 10210 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 10211 } else 10212 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 10213 } 10214 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10215 dahdi_wink(p, idx); 10216 /* some switches require a minimum guard time between 10217 the last FGD wink and something that answers 10218 immediately. This ensures it */ 10219 if (ast_safe_sleep(chan, 100)) { 10220 ast_hangup(chan); 10221 goto quit; 10222 } 10223 } 10224 dahdi_enable_ec(p); 10225 if (NEED_MFDETECT(p)) { 10226 if (p->dsp) { 10227 if (!p->hardwaredtmf) 10228 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10229 else { 10230 ast_dsp_free(p->dsp); 10231 p->dsp = NULL; 10232 } 10233 } 10234 } 10235 10236 if (ast_exists_extension(chan, chan->context, exten, 1, 10237 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 10238 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10239 if (p->dsp) ast_dsp_digitreset(p->dsp); 10240 res = ast_pbx_run(chan); 10241 if (res) { 10242 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10243 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10244 } 10245 goto quit; 10246 } else { 10247 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 10248 sleep(2); 10249 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 10250 if (res < 0) 10251 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 10252 else 10253 sleep(1); 10254 res = ast_streamfile(chan, "ss-noservice", chan->language); 10255 if (res >= 0) 10256 ast_waitstream(chan, ""); 10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10258 ast_hangup(chan); 10259 goto quit; 10260 } 10261 break; 10262 case SIG_FXOLS: 10263 case SIG_FXOGS: 10264 case SIG_FXOKS: 10265 /* Read the first digit */ 10266 timeout = firstdigittimeout; 10267 /* If starting a threeway call, never timeout on the first digit so someone 10268 can use flash-hook as a "hold" feature */ 10269 if (p->subs[SUB_THREEWAY].owner) 10270 timeout = 999999; 10271 while (len < AST_MAX_EXTENSION-1) { 10272 /* Read digit unless it's supposed to be immediate, in which case the 10273 only answer is 's' */ 10274 if (p->immediate) 10275 res = 's'; 10276 else 10277 res = ast_waitfordigit(chan, timeout); 10278 timeout = 0; 10279 if (res < 0) { 10280 ast_debug(1, "waitfordigit returned < 0...\n"); 10281 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10282 ast_hangup(chan); 10283 goto quit; 10284 } else if (res) { 10285 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 10286 exten[len++]=res; 10287 exten[len] = '\0'; 10288 } 10289 if (!ast_ignore_pattern(chan->context, exten)) 10290 tone_zone_play_tone(p->subs[idx].dfd, -1); 10291 else 10292 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10293 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) { 10294 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 10295 if (getforward) { 10296 /* Record this as the forwarding extension */ 10297 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 10298 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10300 if (res) 10301 break; 10302 usleep(500000); 10303 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10304 sleep(1); 10305 memset(exten, 0, sizeof(exten)); 10306 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10307 len = 0; 10308 getforward = 0; 10309 } else { 10310 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10311 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10312 if (!ast_strlen_zero(p->cid_num)) { 10313 if (!p->hidecallerid) 10314 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10315 else 10316 ast_set_callerid(chan, NULL, NULL, p->cid_num); 10317 } 10318 if (!ast_strlen_zero(p->cid_name)) { 10319 if (!p->hidecallerid) 10320 ast_set_callerid(chan, NULL, p->cid_name, NULL); 10321 } 10322 ast_setstate(chan, AST_STATE_RING); 10323 dahdi_enable_ec(p); 10324 res = ast_pbx_run(chan); 10325 if (res) { 10326 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10327 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10328 } 10329 goto quit; 10330 } 10331 } else { 10332 /* It's a match, but they just typed a digit, and there is an ambiguous match, 10333 so just set the timeout to matchdigittimeout and wait some more */ 10334 timeout = matchdigittimeout; 10335 } 10336 } else if (res == 0) { 10337 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 10338 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10339 dahdi_wait_event(p->subs[idx].dfd); 10340 ast_hangup(chan); 10341 goto quit; 10342 } else if (p->callwaiting && !strcmp(exten, "*70")) { 10343 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 10344 /* Disable call waiting if enabled */ 10345 p->callwaiting = 0; 10346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10347 if (res) { 10348 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10349 chan->name, strerror(errno)); 10350 } 10351 len = 0; 10352 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 10353 memset(exten, 0, sizeof(exten)); 10354 timeout = firstdigittimeout; 10355 10356 } else if (!strcmp(exten,ast_pickup_ext())) { 10357 /* Scan all channels and see if there are any 10358 * ringing channels that have call groups 10359 * that equal this channels pickup group 10360 */ 10361 if (idx == SUB_REAL) { 10362 /* Switch us from Third call to Call Wait */ 10363 if (p->subs[SUB_THREEWAY].owner) { 10364 /* If you make a threeway call and the *8# a call, it should actually 10365 look like a callwait */ 10366 alloc_sub(p, SUB_CALLWAIT); 10367 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 10368 unalloc_sub(p, SUB_THREEWAY); 10369 } 10370 dahdi_enable_ec(p); 10371 if (ast_pickup_call(chan)) { 10372 ast_debug(1, "No call pickup possible...\n"); 10373 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10374 dahdi_wait_event(p->subs[idx].dfd); 10375 } 10376 ast_hangup(chan); 10377 goto quit; 10378 } else { 10379 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 10380 ast_hangup(chan); 10381 goto quit; 10382 } 10383 10384 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 10385 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 10386 /* Disable Caller*ID if enabled */ 10387 p->hidecallerid = 1; 10388 ast_party_number_free(&chan->caller.id.number); 10389 ast_party_number_init(&chan->caller.id.number); 10390 ast_party_name_free(&chan->caller.id.name); 10391 ast_party_name_init(&chan->caller.id.name); 10392 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10393 if (res) { 10394 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10395 chan->name, strerror(errno)); 10396 } 10397 len = 0; 10398 memset(exten, 0, sizeof(exten)); 10399 timeout = firstdigittimeout; 10400 } else if (p->callreturn && !strcmp(exten, "*69")) { 10401 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10402 break; 10403 } else if (!strcmp(exten, "*78")) { 10404 dahdi_dnd(p, 1); 10405 /* Do not disturb */ 10406 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10407 getforward = 0; 10408 memset(exten, 0, sizeof(exten)); 10409 len = 0; 10410 } else if (!strcmp(exten, "*79")) { 10411 dahdi_dnd(p, 0); 10412 /* Do not disturb */ 10413 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10414 getforward = 0; 10415 memset(exten, 0, sizeof(exten)); 10416 len = 0; 10417 } else if (p->cancallforward && !strcmp(exten, "*72")) { 10418 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10419 getforward = 1; 10420 memset(exten, 0, sizeof(exten)); 10421 len = 0; 10422 } else if (p->cancallforward && !strcmp(exten, "*73")) { 10423 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 10424 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10425 memset(p->call_forward, 0, sizeof(p->call_forward)); 10426 getforward = 0; 10427 memset(exten, 0, sizeof(exten)); 10428 len = 0; 10429 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) && 10430 p->subs[SUB_THREEWAY].owner && 10431 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 10432 /* This is a three way call, the main call being a real channel, 10433 and we're parking the first call. */ 10434 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), 10435 chan, exten, chan->context, 0, NULL); 10436 ast_verb(3, "Parking call to '%s'\n", chan->name); 10437 break; 10438 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 10439 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 10440 /* Enable Caller*ID if enabled */ 10441 p->hidecallerid = 0; 10442 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 10443 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10444 if (res) { 10445 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10446 chan->name, strerror(errno)); 10447 } 10448 len = 0; 10449 memset(exten, 0, sizeof(exten)); 10450 timeout = firstdigittimeout; 10451 } else if (!strcmp(exten, "*0")) { 10452 struct ast_channel *nbridge = 10453 p->subs[SUB_THREEWAY].owner; 10454 struct dahdi_pvt *pbridge = NULL; 10455 /* set up the private struct of the bridged one, if any */ 10456 if (nbridge && ast_bridged_channel(nbridge)) 10457 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 10458 if (nbridge && pbridge && 10459 (nbridge->tech == &dahdi_tech) && 10460 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 10461 ISTRUNK(pbridge)) { 10462 int func = DAHDI_FLASH; 10463 /* Clear out the dial buffer */ 10464 p->dop.dialstr[0] = '\0'; 10465 /* flash hookswitch */ 10466 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 10467 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 10468 nbridge->name, strerror(errno)); 10469 } 10470 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10471 unalloc_sub(p, SUB_THREEWAY); 10472 p->owner = p->subs[SUB_REAL].owner; 10473 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 10474 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 10475 ast_hangup(chan); 10476 goto quit; 10477 } else { 10478 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10479 dahdi_wait_event(p->subs[idx].dfd); 10480 tone_zone_play_tone(p->subs[idx].dfd, -1); 10481 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10482 unalloc_sub(p, SUB_THREEWAY); 10483 p->owner = p->subs[SUB_REAL].owner; 10484 ast_hangup(chan); 10485 goto quit; 10486 } 10487 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, 10488 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 10489 && !canmatch_featurecode(exten)) { 10490 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, 10491 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 10492 chan->context); 10493 break; 10494 } 10495 if (!timeout) 10496 timeout = gendigittimeout; 10497 if (len && !ast_ignore_pattern(chan->context, exten)) 10498 tone_zone_play_tone(p->subs[idx].dfd, -1); 10499 } 10500 break; 10501 case SIG_FXSLS: 10502 case SIG_FXSGS: 10503 case SIG_FXSKS: 10504 /* check for SMDI messages */ 10505 if (p->use_smdi && p->smdi_iface) { 10506 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 10507 10508 if (smdi_msg != NULL) { 10509 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 10510 10511 if (smdi_msg->type == 'B') 10512 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 10513 else if (smdi_msg->type == 'N') 10514 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 10515 10516 ast_debug(1, "Received SMDI message on %s\n", chan->name); 10517 } else { 10518 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 10519 } 10520 } 10521 10522 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 10523 number = smdi_msg->calling_st; 10524 10525 /* If we want caller id, we're in a prering state due to a polarity reversal 10526 * and we're set to use a polarity reversal to trigger the start of caller id, 10527 * grab the caller id and wait for ringing to start... */ 10528 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 10529 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 10530 /* If set to use DTMF CID signalling, listen for DTMF */ 10531 if (p->cid_signalling == CID_SIG_DTMF) { 10532 int k = 0; 10533 int off_ms; 10534 struct timeval start = ast_tvnow(); 10535 int ms; 10536 cs = NULL; 10537 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 10538 dahdi_setlinear(p->subs[idx].dfd, 0); 10539 /* 10540 * We are the only party interested in the Rx stream since 10541 * we have not answered yet. We don't need or even want DTMF 10542 * emulation. The DTMF digits can come so fast that emulation 10543 * can drop some of them. 10544 */ 10545 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 10546 off_ms = 4000;/* This is a typical OFF time between rings. */ 10547 for (;;) { 10548 struct ast_frame *f; 10549 10550 ms = ast_remaining_ms(start, off_ms); 10551 res = ast_waitfor(chan, ms); 10552 if (res <= 0) { 10553 /* 10554 * We do not need to restore the dahdi_setlinear() 10555 * or AST_FLAG_END_DTMF_ONLY flag settings since we 10556 * are hanging up the channel. 10557 */ 10558 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10559 "Exiting simple switch\n"); 10560 ast_hangup(chan); 10561 goto quit; 10562 } 10563 f = ast_read(chan); 10564 if (!f) 10565 break; 10566 if (f->frametype == AST_FRAME_DTMF) { 10567 if (k < ARRAY_LEN(dtmfbuf) - 1) { 10568 dtmfbuf[k++] = f->subclass.integer; 10569 } 10570 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer); 10571 start = ast_tvnow(); 10572 } 10573 ast_frfree(f); 10574 if (chan->_state == AST_STATE_RING || 10575 chan->_state == AST_STATE_RINGING) 10576 break; /* Got ring */ 10577 } 10578 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 10579 dtmfbuf[k] = '\0'; 10580 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10581 /* Got cid and ring. */ 10582 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 10583 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10584 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 10585 /* If first byte is NULL, we have no cid */ 10586 if (!ast_strlen_zero(dtmfcid)) 10587 number = dtmfcid; 10588 else 10589 number = NULL; 10590 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10591 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 10592 cs = callerid_new(p->cid_signalling); 10593 if (cs) { 10594 int off_ms; 10595 struct timeval start; 10596 int ms; 10597 samples = 0; 10598 #if 1 10599 bump_gains(p); 10600 #endif 10601 /* Take out of linear mode for Caller*ID processing */ 10602 dahdi_setlinear(p->subs[idx].dfd, 0); 10603 10604 /* First we wait and listen for the Caller*ID */ 10605 for (;;) { 10606 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10607 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10608 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10609 callerid_free(cs); 10610 ast_hangup(chan); 10611 goto quit; 10612 } 10613 if (i & DAHDI_IOMUX_SIGEVENT) { 10614 res = dahdi_get_event(p->subs[idx].dfd); 10615 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10616 if (res == DAHDI_EVENT_NOALARM) { 10617 p->inalarm = 0; 10618 } 10619 10620 if (p->cid_signalling == CID_SIG_V23_JP) { 10621 if (res == DAHDI_EVENT_RINGBEGIN) { 10622 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10623 usleep(1); 10624 } 10625 } else { 10626 res = 0; 10627 break; 10628 } 10629 } else if (i & DAHDI_IOMUX_READ) { 10630 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10631 if (res < 0) { 10632 if (errno != ELAST) { 10633 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10634 callerid_free(cs); 10635 ast_hangup(chan); 10636 goto quit; 10637 } 10638 break; 10639 } 10640 samples += res; 10641 10642 if (p->cid_signalling == CID_SIG_V23_JP) { 10643 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 10644 } else { 10645 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10646 } 10647 if (res < 0) { 10648 /* 10649 * The previous diagnostic message output likely 10650 * explains why it failed. 10651 */ 10652 ast_log(LOG_WARNING, 10653 "Failed to decode CallerID on channel '%s'\n", 10654 chan->name); 10655 break; 10656 } else if (res) 10657 break; 10658 else if (samples > (8000 * 10)) 10659 break; 10660 } 10661 } 10662 if (res == 1) { 10663 callerid_get(cs, &name, &number, &flags); 10664 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10665 } 10666 10667 if (p->cid_signalling == CID_SIG_V23_JP) { 10668 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10669 usleep(1); 10670 } 10671 10672 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 10673 start = ast_tvnow(); 10674 off_ms = 4000;/* This is a typical OFF time between rings. */ 10675 for (;;) { 10676 struct ast_frame *f; 10677 10678 ms = ast_remaining_ms(start, off_ms); 10679 res = ast_waitfor(chan, ms); 10680 if (res <= 0) { 10681 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 10682 "Exiting simple switch\n"); 10683 ast_hangup(chan); 10684 goto quit; 10685 } 10686 if (!(f = ast_read(chan))) { 10687 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 10688 ast_hangup(chan); 10689 goto quit; 10690 } 10691 ast_frfree(f); 10692 if (chan->_state == AST_STATE_RING || 10693 chan->_state == AST_STATE_RINGING) 10694 break; /* Got ring */ 10695 } 10696 10697 /* We must have a ring by now, so, if configured, lets try to listen for 10698 * distinctive ringing */ 10699 if (p->usedistinctiveringdetection) { 10700 len = 0; 10701 distMatches = 0; 10702 /* Clear the current ring data array so we don't have old data in it. */ 10703 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10704 curRingData[receivedRingT] = 0; 10705 receivedRingT = 0; 10706 counter = 0; 10707 counter1 = 0; 10708 /* Check to see if context is what it should be, if not set to be. */ 10709 if (strcmp(p->context,p->defcontext) != 0) { 10710 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10711 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10712 } 10713 10714 for (;;) { 10715 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10716 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10717 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10718 callerid_free(cs); 10719 ast_hangup(chan); 10720 goto quit; 10721 } 10722 if (i & DAHDI_IOMUX_SIGEVENT) { 10723 res = dahdi_get_event(p->subs[idx].dfd); 10724 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10725 if (res == DAHDI_EVENT_NOALARM) { 10726 p->inalarm = 0; 10727 } 10728 res = 0; 10729 /* Let us detect distinctive ring */ 10730 10731 curRingData[receivedRingT] = p->ringt; 10732 10733 if (p->ringt < p->ringt_base/2) 10734 break; 10735 /* Increment the ringT counter so we can match it against 10736 values in chan_dahdi.conf for distinctive ring */ 10737 if (++receivedRingT == ARRAY_LEN(curRingData)) 10738 break; 10739 } else if (i & DAHDI_IOMUX_READ) { 10740 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10741 if (res < 0) { 10742 if (errno != ELAST) { 10743 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10744 callerid_free(cs); 10745 ast_hangup(chan); 10746 goto quit; 10747 } 10748 break; 10749 } 10750 if (p->ringt > 0) { 10751 if (!(--p->ringt)) { 10752 res = -1; 10753 break; 10754 } 10755 } 10756 } 10757 } 10758 /* this only shows up if you have n of the dring patterns filled in */ 10759 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10760 for (counter = 0; counter < 3; counter++) { 10761 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10762 channel */ 10763 distMatches = 0; 10764 for (counter1 = 0; counter1 < 3; counter1++) { 10765 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10766 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10767 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10768 curRingData[counter1]); 10769 distMatches++; 10770 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10771 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10772 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10773 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10774 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10775 distMatches++; 10776 } 10777 } 10778 10779 if (distMatches == 3) { 10780 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10781 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10782 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10783 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10784 break; 10785 } 10786 } 10787 } 10788 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10789 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10790 #if 1 10791 restore_gains(p); 10792 #endif 10793 } else 10794 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10795 } else { 10796 ast_log(LOG_WARNING, "Channel %s in prering " 10797 "state, but I have nothing to do. " 10798 "Terminating simple switch, should be " 10799 "restarted by the actual ring.\n", 10800 chan->name); 10801 ast_hangup(chan); 10802 goto quit; 10803 } 10804 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 10805 if (p->cid_signalling == CID_SIG_DTMF) { 10806 int k = 0; 10807 int off_ms; 10808 struct timeval start; 10809 int ms; 10810 cs = NULL; 10811 dahdi_setlinear(p->subs[idx].dfd, 0); 10812 off_ms = 2000; 10813 start = ast_tvnow(); 10814 for (;;) { 10815 struct ast_frame *f; 10816 10817 ms = ast_remaining_ms(start, off_ms); 10818 res = ast_waitfor(chan, ms); 10819 if (res <= 0) { 10820 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10821 "Exiting simple switch\n"); 10822 ast_hangup(chan); 10823 goto quit; 10824 } 10825 f = ast_read(chan); 10826 if (!f) { 10827 /* Hangup received waiting for DTMFCID. Exiting simple switch. */ 10828 ast_hangup(chan); 10829 goto quit; 10830 } 10831 if (f->frametype == AST_FRAME_DTMF) { 10832 dtmfbuf[k++] = f->subclass.integer; 10833 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer); 10834 start = ast_tvnow(); 10835 } 10836 ast_frfree(f); 10837 10838 if (p->ringt_base == p->ringt) 10839 break; 10840 } 10841 dtmfbuf[k] = '\0'; 10842 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10843 /* Got cid and ring. */ 10844 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10845 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 10846 dtmfcid, flags); 10847 /* If first byte is NULL, we have no cid */ 10848 if (!ast_strlen_zero(dtmfcid)) 10849 number = dtmfcid; 10850 else 10851 number = NULL; 10852 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10853 } else { 10854 /* FSK Bell202 callerID */ 10855 cs = callerid_new(p->cid_signalling); 10856 if (cs) { 10857 #if 1 10858 bump_gains(p); 10859 #endif 10860 samples = 0; 10861 len = 0; 10862 distMatches = 0; 10863 /* Clear the current ring data array so we don't have old data in it. */ 10864 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10865 curRingData[receivedRingT] = 0; 10866 receivedRingT = 0; 10867 counter = 0; 10868 counter1 = 0; 10869 /* Check to see if context is what it should be, if not set to be. */ 10870 if (strcmp(p->context,p->defcontext) != 0) { 10871 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10872 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10873 } 10874 10875 /* Take out of linear mode for Caller*ID processing */ 10876 dahdi_setlinear(p->subs[idx].dfd, 0); 10877 for (;;) { 10878 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10879 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10880 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10881 callerid_free(cs); 10882 ast_hangup(chan); 10883 goto quit; 10884 } 10885 if (i & DAHDI_IOMUX_SIGEVENT) { 10886 res = dahdi_get_event(p->subs[idx].dfd); 10887 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10888 if (res == DAHDI_EVENT_NOALARM) { 10889 p->inalarm = 0; 10890 } 10891 /* If we get a PR event, they hung up while processing calerid */ 10892 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 10893 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 10894 p->polarity = POLARITY_IDLE; 10895 callerid_free(cs); 10896 ast_hangup(chan); 10897 goto quit; 10898 } 10899 res = 0; 10900 /* Let us detect callerid when the telco uses distinctive ring */ 10901 10902 curRingData[receivedRingT] = p->ringt; 10903 10904 if (p->ringt < p->ringt_base/2) 10905 break; 10906 /* Increment the ringT counter so we can match it against 10907 values in chan_dahdi.conf for distinctive ring */ 10908 if (++receivedRingT == ARRAY_LEN(curRingData)) 10909 break; 10910 } else if (i & DAHDI_IOMUX_READ) { 10911 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10912 if (res < 0) { 10913 if (errno != ELAST) { 10914 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10915 callerid_free(cs); 10916 ast_hangup(chan); 10917 goto quit; 10918 } 10919 break; 10920 } 10921 if (p->ringt > 0) { 10922 if (!(--p->ringt)) { 10923 res = -1; 10924 break; 10925 } 10926 } 10927 samples += res; 10928 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10929 if (res < 0) { 10930 /* 10931 * The previous diagnostic message output likely 10932 * explains why it failed. 10933 */ 10934 ast_log(LOG_WARNING, 10935 "Failed to decode CallerID on channel '%s'\n", 10936 chan->name); 10937 break; 10938 } else if (res) 10939 break; 10940 else if (samples > (8000 * 10)) 10941 break; 10942 } 10943 } 10944 if (res == 1) { 10945 callerid_get(cs, &name, &number, &flags); 10946 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10947 } 10948 if (distinctiveringaftercid == 1) { 10949 /* Clear the current ring data array so we don't have old data in it. */ 10950 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 10951 curRingData[receivedRingT] = 0; 10952 } 10953 receivedRingT = 0; 10954 ast_verb(3, "Detecting post-CID distinctive ring\n"); 10955 for (;;) { 10956 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10957 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10958 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10959 callerid_free(cs); 10960 ast_hangup(chan); 10961 goto quit; 10962 } 10963 if (i & DAHDI_IOMUX_SIGEVENT) { 10964 res = dahdi_get_event(p->subs[idx].dfd); 10965 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10966 if (res == DAHDI_EVENT_NOALARM) { 10967 p->inalarm = 0; 10968 } 10969 res = 0; 10970 /* Let us detect callerid when the telco uses distinctive ring */ 10971 10972 curRingData[receivedRingT] = p->ringt; 10973 10974 if (p->ringt < p->ringt_base/2) 10975 break; 10976 /* Increment the ringT counter so we can match it against 10977 values in chan_dahdi.conf for distinctive ring */ 10978 if (++receivedRingT == ARRAY_LEN(curRingData)) 10979 break; 10980 } else if (i & DAHDI_IOMUX_READ) { 10981 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10982 if (res < 0) { 10983 if (errno != ELAST) { 10984 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10985 callerid_free(cs); 10986 ast_hangup(chan); 10987 goto quit; 10988 } 10989 break; 10990 } 10991 if (p->ringt > 0) { 10992 if (!(--p->ringt)) { 10993 res = -1; 10994 break; 10995 } 10996 } 10997 } 10998 } 10999 } 11000 if (p->usedistinctiveringdetection) { 11001 /* this only shows up if you have n of the dring patterns filled in */ 11002 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 11003 11004 for (counter = 0; counter < 3; counter++) { 11005 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 11006 channel */ 11007 /* this only shows up if you have n of the dring patterns filled in */ 11008 ast_verb(3, "Checking %d,%d,%d\n", 11009 p->drings.ringnum[counter].ring[0], 11010 p->drings.ringnum[counter].ring[1], 11011 p->drings.ringnum[counter].ring[2]); 11012 distMatches = 0; 11013 for (counter1 = 0; counter1 < 3; counter1++) { 11014 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 11015 if (p->drings.ringnum[counter].ring[counter1] == -1) { 11016 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 11017 curRingData[counter1]); 11018 distMatches++; 11019 } 11020 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 11021 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 11022 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 11023 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 11024 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 11025 distMatches++; 11026 } 11027 } 11028 if (distMatches == 3) { 11029 /* The ring matches, set the context to whatever is for distinctive ring.. */ 11030 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 11031 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 11032 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 11033 break; 11034 } 11035 } 11036 } 11037 /* Restore linear mode (if appropriate) for Caller*ID processing */ 11038 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 11039 #if 1 11040 restore_gains(p); 11041 #endif 11042 if (res < 0) { 11043 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 11044 } 11045 } else 11046 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 11047 } 11048 } else 11049 cs = NULL; 11050 11051 if (number) 11052 ast_shrink_phone_number(number); 11053 ast_set_callerid(chan, number, name, number); 11054 11055 if (smdi_msg) 11056 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 11057 11058 if (cs) 11059 callerid_free(cs); 11060 11061 my_handle_notify_message(chan, p, flags, -1); 11062 11063 ast_setstate(chan, AST_STATE_RING); 11064 chan->rings = 1; 11065 p->ringt = p->ringt_base; 11066 res = ast_pbx_run(chan); 11067 if (res) { 11068 ast_hangup(chan); 11069 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 11070 } 11071 goto quit; 11072 default: 11073 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 11074 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11075 if (res < 0) 11076 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11077 } 11078 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11079 if (res < 0) 11080 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11081 ast_hangup(chan); 11082 quit: 11083 ast_mutex_lock(&ss_thread_lock); 11084 ss_thread_count--; 11085 ast_cond_signal(&ss_thread_complete); 11086 ast_mutex_unlock(&ss_thread_lock); 11087 return NULL; 11088 }
| static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1650 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().
01651 { 01652 switch (tone) { 01653 case ANALOG_TONE_RINGTONE: 01654 return DAHDI_TONE_RINGTONE; 01655 case ANALOG_TONE_STUTTER: 01656 return DAHDI_TONE_STUTTER; 01657 case ANALOG_TONE_CONGESTION: 01658 return DAHDI_TONE_CONGESTION; 01659 case ANALOG_TONE_DIALTONE: 01660 return DAHDI_TONE_DIALTONE; 01661 case ANALOG_TONE_DIALRECALL: 01662 return DAHDI_TONE_DIALRECALL; 01663 case ANALOG_TONE_INFO: 01664 return DAHDI_TONE_INFO; 01665 default: 01666 return -1; 01667 } 01668 }
| static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1670 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_dtmf(), my_is_dialing(), my_new_analog_ast_channel(), my_play_tone(), my_set_inthreeway(), my_set_linear_mode(), my_swap_subchannels(), my_unallocate_sub(), and my_wink().
01671 { 01672 int index; 01673 01674 switch (analogsub) { 01675 case ANALOG_SUB_REAL: 01676 index = SUB_REAL; 01677 break; 01678 case ANALOG_SUB_CALLWAIT: 01679 index = SUB_CALLWAIT; 01680 break; 01681 case ANALOG_SUB_THREEWAY: 01682 index = SUB_THREEWAY; 01683 break; 01684 default: 01685 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01686 index = SUB_REAL; 01687 } 01688 01689 return index; 01690 }
| AST_DATA_STRUCTURE | ( | dahdi_pvt | , | |
| DATA_EXPORT_DAHDI_PVT | ||||
| ) |
| AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
| AST_MODFLAG_LOAD_ORDER | , | |||
| tdesc | , | |||
| . | load = load_module, |
|||
| . | unload = unload_module, |
|||
| . | reload = reload, |
|||
| . | load_pri = AST_MODPRI_CHANNEL_DRIVER, |
|||
| . | nonoptreq = "res_smdi" | |||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | restart_lock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | ss_thread_lock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | monlock | ) |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
| AST_MUTEX_DEFINE_STATIC | ( | iflock | ) |
Protect the interface list (of dahdi_pvt's).
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7665 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, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event().
07666 { 07667 /* In order to transfer, we need at least one of the channels to 07668 actually be in a call bridge. We can't conference two applications 07669 together (but then, why would we want to?) */ 07670 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07671 /* The three-way person we're about to transfer to could still be in MOH, so 07672 stop if now if appropriate */ 07673 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 07674 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 07675 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 07676 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 07677 } 07678 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 07679 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07680 } 07681 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 07682 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07683 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 07684 return -1; 07685 } 07686 /* Orphan the channel after releasing the lock */ 07687 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07688 unalloc_sub(p, SUB_THREEWAY); 07689 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07690 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07691 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 07692 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 07693 } 07694 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 07695 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07696 } 07697 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 07698 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07699 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 07700 return -1; 07701 } 07702 /* Three-way is now the REAL */ 07703 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07704 ast_channel_unlock(p->subs[SUB_REAL].owner); 07705 unalloc_sub(p, SUB_THREEWAY); 07706 /* Tell the caller not to hangup */ 07707 return 1; 07708 } else { 07709 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 07710 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 07711 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07712 return -1; 07713 } 07714 return 0; 07715 }
| static int available | ( | struct dahdi_pvt ** | pvt, | |
| int | is_specific_channel | |||
| ) | [static] |
Definition at line 13260 of file chan_dahdi.c.
References analog_available(), analog_lib_handles(), sig_pri_chan::chan_pvt, 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, dahdi_pvt::sig_pvt, SIG_SS7, and sig_ss7_available().
Referenced by __ast_string_field_ptr_build_va(), ast_logger_register_level(), and dahdi_request().
13261 { 13262 struct dahdi_pvt *p = *pvt; 13263 13264 if (p->inalarm) 13265 return 0; 13266 13267 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 13268 return analog_available(p->sig_pvt); 13269 13270 switch (p->sig) { 13271 #if defined(HAVE_PRI) 13272 case SIG_PRI_LIB_HANDLE_CASES: 13273 { 13274 struct sig_pri_chan *pvt_chan; 13275 int res; 13276 13277 pvt_chan = p->sig_pvt; 13278 res = sig_pri_available(&pvt_chan, is_specific_channel); 13279 *pvt = pvt_chan->chan_pvt; 13280 return res; 13281 } 13282 #endif /* defined(HAVE_PRI) */ 13283 #if defined(HAVE_SS7) 13284 case SIG_SS7: 13285 return sig_ss7_available(p->sig_pvt); 13286 #endif /* defined(HAVE_SS7) */ 13287 default: 13288 break; 13289 } 13290 13291 if (p->locallyblocked || p->remotelyblocked) { 13292 return 0; 13293 } 13294 13295 /* If no owner definitely available */ 13296 if (!p->owner) { 13297 #ifdef HAVE_OPENR2 13298 /* Trust MFC/R2 */ 13299 if (p->mfcr2) { 13300 if (p->mfcr2call) { 13301 return 0; 13302 } else { 13303 return 1; 13304 } 13305 } 13306 #endif 13307 return 1; 13308 } 13309 13310 return 0; 13311 }
| static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
| const char * | value, | |||
| int | reload, | |||
| int | lineno, | |||
| int * | found_pseudo | |||
| ) | [static] |
Definition at line 16966 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, device2chan(), dahdi_chan_conf::ignore_failed_channels, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), parse_spanchan(), dahdi_pvt::sig, and sig2str.
Referenced by process_dahdi().
16967 { 16968 char *c, *chan; 16969 char *subdir; 16970 int x, start, finish; 16971 struct dahdi_pvt *tmp; 16972 16973 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 16974 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 16975 return -1; 16976 } 16977 16978 c = ast_strdupa(value); 16979 c = parse_spanchan(c, &subdir); 16980 16981 while ((chan = strsep(&c, ","))) { 16982 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 16983 /* Range */ 16984 } else if (sscanf(chan, "%30d", &start)) { 16985 /* Just one */ 16986 finish = start; 16987 } else if (!strcasecmp(chan, "pseudo")) { 16988 finish = start = CHAN_PSEUDO; 16989 if (found_pseudo) 16990 *found_pseudo = 1; 16991 } else { 16992 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 16993 return -1; 16994 } 16995 if (finish < start) { 16996 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 16997 x = finish; 16998 finish = start; 16999 start = x; 17000 } 17001 17002 for (x = start; x <= finish; x++) { 17003 char fn[PATH_MAX]; 17004 int real_channel = x; 17005 17006 if (!ast_strlen_zero(subdir)) { 17007 real_channel = device2chan(subdir, x, fn, sizeof(fn)); 17008 if (real_channel < 0) { 17009 if (conf->ignore_failed_channels) { 17010 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n", 17011 subdir, x, real_channel); 17012 continue; 17013 } else { 17014 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n", 17015 subdir, x, real_channel); 17016 return -1; 17017 } 17018 } 17019 } 17020 tmp = mkintf(real_channel, conf, reload); 17021 17022 if (tmp) { 17023 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig)); 17024 } else { 17025 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 17026 (reload == 1) ? "reconfigure" : "register", value); 17027 return -1; 17028 } 17029 } 17030 } 17031 17032 return 0; 17033 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5144 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().
05145 { 05146 int res; 05147 05148 /* Bump receive gain by value stored in cid_rxgain */ 05149 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05150 if (res) { 05151 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 05152 return -1; 05153 } 05154 05155 return 0; 05156 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| format_t | law | |||
| ) | [static] |
Definition at line 11096 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
| static int canmatch_featurecode | ( | const char * | exten | ) | [static] |
Definition at line 9918 of file chan_dahdi.c.
References ast_pickup_ext(), and pickup_ext.
Referenced by analog_ss_thread().
09919 { 09920 int extlen = strlen(exten); 09921 const char *pickup_ext; 09922 if (!extlen) { 09923 return 1; 09924 } 09925 pickup_ext = ast_pickup_ext(); 09926 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) { 09927 return 1; 09928 } 09929 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */ 09930 if (exten[0] == '*' && extlen < 3) { 09931 if (extlen == 1) { 09932 return 1; 09933 } 09934 /* "*0" should be processed before it gets here */ 09935 switch (exten[1]) { 09936 case '6': 09937 case '7': 09938 case '8': 09939 return 1; 09940 } 09941 } 09942 return 0; 09943 }
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7717 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().
07718 { 07719 struct dahdi_confinfo ci; 07720 /* Fine if we already have a master, etc */ 07721 if (p->master || (p->confno > -1)) 07722 return 0; 07723 memset(&ci, 0, sizeof(ci)); 07724 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 07725 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 07726 return 0; 07727 } 07728 /* If we have no master and don't have a confno, then 07729 if we're in a conference, it's probably a MeetMe room or 07730 some such, so don't let us 3-way out! */ 07731 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 07732 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 07733 return 1; 07734 } 07735 return 0; 07736 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | index, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 4714 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().
04715 { 04716 /* If the conference already exists, and we're already in it 04717 don't bother doing anything */ 04718 struct dahdi_confinfo zi; 04719 04720 memset(&zi, 0, sizeof(zi)); 04721 zi.chan = 0; 04722 04723 if (slavechannel > 0) { 04724 /* If we have only one slave, do a digital mon */ 04725 zi.confmode = DAHDI_CONF_DIGITALMON; 04726 zi.confno = slavechannel; 04727 } else { 04728 if (!idx) { 04729 /* Real-side and pseudo-side both participate in conference */ 04730 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 04731 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 04732 } else 04733 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 04734 zi.confno = p->confno; 04735 } 04736 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 04737 return 0; 04738 if (c->dfd < 0) 04739 return 0; 04740 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04741 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 04742 return -1; 04743 } 04744 if (slavechannel < 1) { 04745 p->confno = zi.confno; 04746 } 04747 c->curconf = zi; 04748 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04749 return 0; 04750 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | index | |||
| ) | [static] |
Definition at line 4763 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().
04764 { 04765 struct dahdi_confinfo zi; 04766 if (/* Can't delete if there's no dfd */ 04767 (c->dfd < 0) || 04768 /* Don't delete from the conference if it's not our conference */ 04769 !isourconf(p, c) 04770 /* Don't delete if we don't think it's conferenced at all (implied) */ 04771 ) return 0; 04772 memset(&zi, 0, sizeof(zi)); 04773 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04774 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 04775 return -1; 04776 } 04777 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04778 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 04779 return 0; 04780 }
Definition at line 9583 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::lock, dahdi_subchannel::owner, dahdi_pvt::span, and dahdi_pvt::subs.
Referenced by dahdi_cc_callback(), and dahdi_new().
09585 { 09586 struct ast_str *chan_name; 09587 int x, y; 09588 09589 /* Create the new channel name tail. */ 09590 if (!(chan_name = ast_str_create(32))) { 09591 return NULL; 09592 } 09593 if (i->channel == CHAN_PSEUDO) { 09594 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 09595 #if defined(HAVE_PRI) 09596 } else if (i->pri) { 09597 ast_mutex_lock(&i->pri->lock); 09598 y = ++i->pri->new_chan_seq; 09599 if (is_outgoing) { 09600 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y); 09601 address[0] = '\0'; 09602 } else if (ast_strlen_zero(i->cid_subaddr)) { 09603 /* Put in caller-id number only since there is no subaddress. */ 09604 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y); 09605 } else { 09606 /* Put in caller-id number and subaddress. */ 09607 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num, 09608 i->cid_subaddr, (unsigned)y); 09609 } 09610 ast_mutex_unlock(&i->pri->lock); 09611 #endif /* defined(HAVE_PRI) */ 09612 } else { 09613 y = 1; 09614 do { 09615 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 09616 for (x = 0; x < 3; ++x) { 09617 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), 09618 i->subs[x].owner->name + 6)) { 09619 break; 09620 } 09621 } 09622 ++y; 09623 } while (x < 3); 09624 } 09625 return chan_name; 09626 }
| static void dahdi_ami_channel_event | ( | struct dahdi_pvt * | p, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 2166 of file chan_dahdi.c.
References ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, and dahdi_pvt::span.
Referenced by dahdi_new().
02167 { 02168 char ch_name[20]; 02169 02170 if (p->channel < CHAN_PSEUDO) { 02171 /* No B channel */ 02172 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel); 02173 } else if (p->channel == CHAN_PSEUDO) { 02174 /* Pseudo channel */ 02175 strcpy(ch_name, "pseudo"); 02176 } else { 02177 /* Real channel */ 02178 snprintf(ch_name, sizeof(ch_name), "%d", p->channel); 02179 } 02180 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel", 02181 "Channel: %s\r\n" 02182 "Uniqueid: %s\r\n" 02183 "DAHDISpan: %d\r\n" 02184 "DAHDIChannel: %s\r\n", 02185 chan->name, 02186 chan->uniqueid, 02187 p->span, 02188 ch_name); 02189 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6593 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, sig_ss7_answer(), SUB_REAL, and ast_channel::tech_pvt.
06594 { 06595 struct dahdi_pvt *p = ast->tech_pvt; 06596 int res = 0; 06597 int idx; 06598 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */ 06599 ast_mutex_lock(&p->lock); 06600 idx = dahdi_get_index(ast, p, 0); 06601 if (idx < 0) 06602 idx = SUB_REAL; 06603 /* nothing to do if a radio channel */ 06604 if ((p->radio || (p->oprmode < 0))) { 06605 ast_mutex_unlock(&p->lock); 06606 return 0; 06607 } 06608 06609 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06610 res = analog_answer(p->sig_pvt, ast); 06611 ast_mutex_unlock(&p->lock); 06612 return res; 06613 } 06614 06615 switch (p->sig) { 06616 #if defined(HAVE_PRI) 06617 case SIG_PRI_LIB_HANDLE_CASES: 06618 res = sig_pri_answer(p->sig_pvt, ast); 06619 break; 06620 #endif /* defined(HAVE_PRI) */ 06621 #if defined(HAVE_SS7) 06622 case SIG_SS7: 06623 res = sig_ss7_answer(p->sig_pvt, ast); 06624 break; 06625 #endif /* defined(HAVE_SS7) */ 06626 #ifdef HAVE_OPENR2 06627 case SIG_MFCR2: 06628 if (!p->mfcr2_call_accepted) { 06629 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 06630 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 06631 p->mfcr2_answer_pending = 1; 06632 if (p->mfcr2_charge_calls) { 06633 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 06634 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 06635 } else { 06636 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 06637 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 06638 } 06639 } else { 06640 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 06641 dahdi_r2_answer(p); 06642 } 06643 break; 06644 #endif 06645 case 0: 06646 ast_mutex_unlock(&p->lock); 06647 return 0; 06648 default: 06649 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 06650 res = -1; 06651 break; 06652 } 06653 ast_mutex_unlock(&p->lock); 06654 return res; 06655 }
| 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 7240 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_lock, ast_mutex_trylock, ast_mutex_unlock, ast_read(), ast_remaining_ms(), AST_STATE_RINGING, ast_tvnow(), ast_verb, ast_waitfor_n(), ast_write(), sig_pri_chan::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, 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, 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, t1, ast_channel::tech_pvt, dahdi_pvt::transfer, and update_conf().
07241 { 07242 struct ast_channel *who; 07243 struct dahdi_pvt *p0, *p1, *op0, *op1; 07244 struct dahdi_pvt *master = NULL, *slave = NULL; 07245 struct ast_frame *f; 07246 int inconf = 0; 07247 int nothingok = 1; 07248 int ofd0, ofd1; 07249 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 07250 int os0 = -1, os1 = -1; 07251 int priority = 0; 07252 struct ast_channel *oc0, *oc1; 07253 enum ast_bridge_result res; 07254 struct timeval start = ast_tvnow(); 07255 #ifdef PRI_2BCT 07256 int triedtopribridge = 0; 07257 q931_call *q931c0; 07258 q931_call *q931c1; 07259 #endif 07260 07261 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 07262 There is code below to handle it properly until DTMF is actually seen, 07263 but due to currently unresolved issues it's ignored... 07264 */ 07265 07266 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 07267 return AST_BRIDGE_FAILED_NOWARN; 07268 07269 ast_channel_lock(c0); 07270 while (ast_channel_trylock(c1)) { 07271 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07272 } 07273 07274 p0 = c0->tech_pvt; 07275 p1 = c1->tech_pvt; 07276 /* cant do pseudo-channels here */ 07277 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 07278 ast_channel_unlock(c0); 07279 ast_channel_unlock(c1); 07280 return AST_BRIDGE_FAILED_NOWARN; 07281 } 07282 07283 oi0 = dahdi_get_index(c0, p0, 0); 07284 oi1 = dahdi_get_index(c1, p1, 0); 07285 if ((oi0 < 0) || (oi1 < 0)) { 07286 ast_channel_unlock(c0); 07287 ast_channel_unlock(c1); 07288 return AST_BRIDGE_FAILED; 07289 } 07290 07291 op0 = p0 = c0->tech_pvt; 07292 op1 = p1 = c1->tech_pvt; 07293 ofd0 = c0->fds[0]; 07294 ofd1 = c1->fds[0]; 07295 oc0 = p0->owner; 07296 oc1 = p1->owner; 07297 07298 if (ast_mutex_trylock(&p0->lock)) { 07299 /* Don't block, due to potential for deadlock */ 07300 ast_channel_unlock(c0); 07301 ast_channel_unlock(c1); 07302 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07303 return AST_BRIDGE_RETRY; 07304 } 07305 if (ast_mutex_trylock(&p1->lock)) { 07306 /* Don't block, due to potential for deadlock */ 07307 ast_mutex_unlock(&p0->lock); 07308 ast_channel_unlock(c0); 07309 ast_channel_unlock(c1); 07310 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07311 return AST_BRIDGE_RETRY; 07312 } 07313 07314 if ((p0->callwaiting && p0->callwaitingcallerid) 07315 || (p1->callwaiting && p1->callwaitingcallerid)) { 07316 /* 07317 * Call Waiting Caller ID requires DTMF detection to know if it 07318 * can send the CID spill. 07319 * 07320 * For now, don't attempt to native bridge if either channel 07321 * needs DTMF detection. There is code below to handle it 07322 * properly until DTMF is actually seen, but due to currently 07323 * unresolved issues it's ignored... 07324 */ 07325 ast_mutex_unlock(&p0->lock); 07326 ast_mutex_unlock(&p1->lock); 07327 ast_channel_unlock(c0); 07328 ast_channel_unlock(c1); 07329 return AST_BRIDGE_FAILED_NOWARN; 07330 } 07331 07332 #if defined(HAVE_PRI) 07333 if ((dahdi_sig_pri_lib_handles(p0->sig) 07334 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 07335 || (dahdi_sig_pri_lib_handles(p1->sig) 07336 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 07337 /* 07338 * PRI nobch channels (hold and call waiting) are equivalent to 07339 * pseudo channels and cannot be done here. 07340 */ 07341 ast_mutex_unlock(&p0->lock); 07342 ast_mutex_unlock(&p1->lock); 07343 ast_channel_unlock(c0); 07344 ast_channel_unlock(c1); 07345 return AST_BRIDGE_FAILED_NOWARN; 07346 } 07347 #endif /* defined(HAVE_PRI) */ 07348 07349 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07350 if (p0->owner && p1->owner) { 07351 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 07352 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 07353 master = p0; 07354 slave = p1; 07355 inconf = 1; 07356 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 07357 master = p1; 07358 slave = p0; 07359 inconf = 1; 07360 } else { 07361 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 07362 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 07363 p0->channel, 07364 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07365 p0->subs[SUB_REAL].inthreeway, p0->channel, 07366 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07367 p1->subs[SUB_REAL].inthreeway); 07368 } 07369 nothingok = 0; 07370 } 07371 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 07372 if (p1->subs[SUB_THREEWAY].inthreeway) { 07373 master = p1; 07374 slave = p0; 07375 nothingok = 0; 07376 } 07377 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 07378 if (p0->subs[SUB_THREEWAY].inthreeway) { 07379 master = p0; 07380 slave = p1; 07381 nothingok = 0; 07382 } 07383 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 07384 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 07385 don't put us in anything */ 07386 if (p1->subs[SUB_CALLWAIT].inthreeway) { 07387 master = p1; 07388 slave = p0; 07389 nothingok = 0; 07390 } 07391 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 07392 /* Same as previous */ 07393 if (p0->subs[SUB_CALLWAIT].inthreeway) { 07394 master = p0; 07395 slave = p1; 07396 nothingok = 0; 07397 } 07398 } 07399 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 07400 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 07401 if (master && slave) { 07402 /* Stop any tones, or play ringtone as appropriate. If they're bridged 07403 in an active threeway call with a channel that is ringing, we should 07404 indicate ringing. */ 07405 if ((oi1 == SUB_THREEWAY) && 07406 p1->subs[SUB_THREEWAY].inthreeway && 07407 p1->subs[SUB_REAL].owner && 07408 p1->subs[SUB_REAL].inthreeway && 07409 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07410 ast_debug(1, 07411 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07412 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07413 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 07414 os1 = p1->subs[SUB_REAL].owner->_state; 07415 } else { 07416 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07417 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07418 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 07419 } 07420 if ((oi0 == SUB_THREEWAY) && 07421 p0->subs[SUB_THREEWAY].inthreeway && 07422 p0->subs[SUB_REAL].owner && 07423 p0->subs[SUB_REAL].inthreeway && 07424 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07425 ast_debug(1, 07426 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07427 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07428 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 07429 os0 = p0->subs[SUB_REAL].owner->_state; 07430 } else { 07431 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07432 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07433 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 07434 } 07435 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07436 if (!p0->echocanbridged || !p1->echocanbridged) { 07437 /* Disable echo cancellation if appropriate */ 07438 dahdi_disable_ec(p0); 07439 dahdi_disable_ec(p1); 07440 } 07441 } 07442 dahdi_link(slave, master); 07443 master->inconference = inconf; 07444 } else if (!nothingok) 07445 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 07446 07447 update_conf(p0); 07448 update_conf(p1); 07449 t0 = p0->subs[SUB_REAL].inthreeway; 07450 t1 = p1->subs[SUB_REAL].inthreeway; 07451 07452 ast_mutex_unlock(&p0->lock); 07453 ast_mutex_unlock(&p1->lock); 07454 07455 ast_channel_unlock(c0); 07456 ast_channel_unlock(c1); 07457 07458 /* Native bridge failed */ 07459 if ((!master || !slave) && !nothingok) { 07460 dahdi_enable_ec(p0); 07461 dahdi_enable_ec(p1); 07462 return AST_BRIDGE_FAILED; 07463 } 07464 07465 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 07466 07467 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07468 disable_dtmf_detect(op0); 07469 07470 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07471 disable_dtmf_detect(op1); 07472 07473 for (;;) { 07474 struct ast_channel *c0_priority[2] = {c0, c1}; 07475 struct ast_channel *c1_priority[2] = {c1, c0}; 07476 int ms; 07477 07478 /* Here's our main loop... Start by locking things, looking for private parts, 07479 and then balking if anything is wrong */ 07480 07481 ast_channel_lock(c0); 07482 while (ast_channel_trylock(c1)) { 07483 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07484 } 07485 07486 p0 = c0->tech_pvt; 07487 p1 = c1->tech_pvt; 07488 07489 if (op0 == p0) 07490 i0 = dahdi_get_index(c0, p0, 1); 07491 if (op1 == p1) 07492 i1 = dahdi_get_index(c1, p1, 1); 07493 07494 ast_channel_unlock(c0); 07495 ast_channel_unlock(c1); 07496 ms = ast_remaining_ms(start, timeoutms); 07497 if (!ms || 07498 (op0 != p0) || 07499 (op1 != p1) || 07500 (ofd0 != c0->fds[0]) || 07501 (ofd1 != c1->fds[0]) || 07502 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 07503 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 07504 (oc0 != p0->owner) || 07505 (oc1 != p1->owner) || 07506 (t0 != p0->subs[SUB_REAL].inthreeway) || 07507 (t1 != p1->subs[SUB_REAL].inthreeway) || 07508 (oi0 != i0) || 07509 (oi1 != i1)) { 07510 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 07511 op0->channel, oi0, op1->channel, oi1); 07512 res = AST_BRIDGE_RETRY; 07513 goto return_from_bridge; 07514 } 07515 07516 #ifdef PRI_2BCT 07517 if (!triedtopribridge) { 07518 triedtopribridge = 1; 07519 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) { 07520 ast_mutex_lock(&p0->pri->lock); 07521 switch (p0->sig) { 07522 case SIG_PRI_LIB_HANDLE_CASES: 07523 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 07524 break; 07525 default: 07526 q931c0 = NULL; 07527 break; 07528 } 07529 switch (p1->sig) { 07530 case SIG_PRI_LIB_HANDLE_CASES: 07531 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 07532 break; 07533 default: 07534 q931c1 = NULL; 07535 break; 07536 } 07537 if (q931c0 && q931c1) { 07538 pri_channel_bridge(q931c0, q931c1); 07539 } 07540 ast_mutex_unlock(&p0->pri->lock); 07541 } 07542 } 07543 #endif 07544 07545 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms); 07546 if (!who) { 07547 ast_debug(1, "Ooh, empty read...\n"); 07548 continue; 07549 } 07550 f = ast_read(who); 07551 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 07552 *fo = f; 07553 *rc = who; 07554 res = AST_BRIDGE_COMPLETE; 07555 goto return_from_bridge; 07556 } 07557 if (f->frametype == AST_FRAME_DTMF) { 07558 if ((who == c0) && p0->pulsedial) { 07559 ast_write(c1, f); 07560 } else if ((who == c1) && p1->pulsedial) { 07561 ast_write(c0, f); 07562 } else { 07563 *fo = f; 07564 *rc = who; 07565 res = AST_BRIDGE_COMPLETE; 07566 goto return_from_bridge; 07567 } 07568 } 07569 ast_frfree(f); 07570 07571 /* Swap who gets priority */ 07572 priority = !priority; 07573 } 07574 07575 return_from_bridge: 07576 if (op0 == p0) 07577 dahdi_enable_ec(p0); 07578 07579 if (op1 == p1) 07580 dahdi_enable_ec(p1); 07581 07582 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07583 enable_dtmf_detect(op0); 07584 07585 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07586 enable_dtmf_detect(op1); 07587 07588 dahdi_unlink(slave, master, 1); 07589 07590 return res; 07591 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 5378 of file chan_dahdi.c.
References ast_channel::_state, analog_call(), analog_lib_handles(), 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::connected, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, errno, dahdi_pvt::hidecallerid, ast_party_connected_line::id, IS_DIGITAL, dahdi_pvt::law, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_subchannel::needbusy, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, 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, sig_ss7_call(), ast_party_number::str, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_party_number::valid, and dahdi_pvt::waitingfordt.
05379 { 05380 struct dahdi_pvt *p = ast->tech_pvt; 05381 int x, res, mysig; 05382 char dest[256]; /* must be same length as p->dialdest */ 05383 05384 ast_mutex_lock(&p->lock); 05385 ast_copy_string(dest, rdest, sizeof(dest)); 05386 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 05387 if ((ast->_state == AST_STATE_BUSY)) { 05388 p->subs[SUB_REAL].needbusy = 1; 05389 ast_mutex_unlock(&p->lock); 05390 return 0; 05391 } 05392 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05393 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 05394 ast_mutex_unlock(&p->lock); 05395 return -1; 05396 } 05397 p->waitingfordt.tv_sec = 0; 05398 p->dialednone = 0; 05399 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 05400 { 05401 /* Special pseudo -- automatically up */ 05402 ast_setstate(ast, AST_STATE_UP); 05403 ast_mutex_unlock(&p->lock); 05404 return 0; 05405 } 05406 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 05407 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 05408 if (res) 05409 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 05410 p->outgoing = 1; 05411 05412 if (IS_DIGITAL(ast->transfercapability)){ 05413 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law); 05414 } else { 05415 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05416 } 05417 05418 #ifdef HAVE_PRI 05419 if (dahdi_sig_pri_lib_handles(p->sig)) { 05420 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, 05421 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW); 05422 ast_mutex_unlock(&p->lock); 05423 return res; 05424 } 05425 #endif 05426 05427 #if defined(HAVE_SS7) 05428 if (p->sig == SIG_SS7) { 05429 res = sig_ss7_call(p->sig_pvt, ast, rdest); 05430 ast_mutex_unlock(&p->lock); 05431 return res; 05432 } 05433 #endif /* defined(HAVE_SS7) */ 05434 05435 /* If this is analog signalling we can exit here */ 05436 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05437 p->callwaitrings = 0; 05438 res = analog_call(p->sig_pvt, ast, rdest, timeout); 05439 ast_mutex_unlock(&p->lock); 05440 return res; 05441 } 05442 05443 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 05444 switch (mysig) { 05445 case 0: 05446 /* Special pseudo -- automatically up*/ 05447 ast_setstate(ast, AST_STATE_UP); 05448 break; 05449 case SIG_MFCR2: 05450 break; 05451 default: 05452 ast_debug(1, "not yet implemented\n"); 05453 ast_mutex_unlock(&p->lock); 05454 return -1; 05455 } 05456 05457 #ifdef HAVE_OPENR2 05458 if (p->mfcr2) { 05459 openr2_calling_party_category_t chancat; 05460 int callres = 0; 05461 char *c, *l; 05462 05463 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 05464 p->dialdest[0] = '\0'; 05465 05466 c = strchr(dest, '/'); 05467 if (c) { 05468 c++; 05469 } else { 05470 c = ""; 05471 } 05472 if (!p->hidecallerid) { 05473 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL; 05474 } else { 05475 l = NULL; 05476 } 05477 if (strlen(c) < p->stripmsd) { 05478 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 05479 ast_mutex_unlock(&p->lock); 05480 return -1; 05481 } 05482 p->dialing = 1; 05483 chancat = dahdi_r2_get_channel_category(ast); 05484 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 05485 if (-1 == callres) { 05486 ast_mutex_unlock(&p->lock); 05487 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 05488 return -1; 05489 } 05490 p->mfcr2_call_accepted = 0; 05491 p->mfcr2_progress = 0; 05492 ast_setstate(ast, AST_STATE_DIALING); 05493 } 05494 #endif /* HAVE_OPENR2 */ 05495 ast_mutex_unlock(&p->lock); 05496 return 0; 05497 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5345 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().
05346 { 05347 struct dahdi_pvt *p = ast->tech_pvt; 05348 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 05349 if (p->cidspill) { 05350 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 05351 ast_free(p->cidspill); 05352 } 05353 05354 /* 05355 * SAS: Subscriber Alert Signal, 440Hz for 300ms 05356 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 05357 */ 05358 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 05359 return -1; 05360 save_conference(p); 05361 /* Silence */ 05362 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 05363 if (!p->callwaitrings && p->callwaitingcallerid) { 05364 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 05365 p->callwaitcas = 1; 05366 p->cidlen = 2400 + 680 + READ_SIZE * 4; 05367 } else { 05368 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 05369 p->callwaitcas = 0; 05370 p->cidlen = 2400 + READ_SIZE * 4; 05371 } 05372 p->cidpos = 0; 05373 send_callerid(p); 05374 05375 return 0; 05376 }
| static int dahdi_cc_callback | ( | struct ast_channel * | inbound, | |
| const char * | dest, | |||
| ast_cc_callback_fn | callback | |||
| ) | [static] |
Callback made when dial failed to get a channel out of dahdi_request().
| inbound | Incoming asterisk channel. | |
| dest | Same dial string passed to dahdi_request(). | |
| callback | Callback into CC core to announce a busy channel available for CC. |
This callback acts like a forked dial with all prongs of the fork busy. Essentially, for each channel that could have taken the call, indicate that it is busy.
| 0 | on success. | |
| -1 | on error. |
Definition at line 13925 of file chan_dahdi.c.
References AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, AST_CHANNEL_NAME, ast_free, ast_get_cc_monitor_policy(), ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), dahdi_starting_point::backwards, dahdi_pvt::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, HAVE_PRI, is_group_or_channel_match(), dahdi_pvt::next, dahdi_pvt::prev, dahdi_pvt::sig, dahdi_pvt::span, and dahdi_starting_point::span.
13926 { 13927 struct dahdi_pvt *p; 13928 struct dahdi_pvt *exitpvt; 13929 struct dahdi_starting_point start; 13930 int groupmatched = 0; 13931 int channelmatched = 0; 13932 13933 ast_mutex_lock(&iflock); 13934 p = determine_starting_point(dest, &start); 13935 if (!p) { 13936 ast_mutex_unlock(&iflock); 13937 return -1; 13938 } 13939 exitpvt = p; 13940 for (;;) { 13941 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) { 13942 /* We found a potential match. call the callback */ 13943 struct ast_str *device_name; 13944 char *dash; 13945 const char *monitor_type; 13946 char dialstring[AST_CHANNEL_NAME]; 13947 char full_device_name[AST_CHANNEL_NAME]; 13948 13949 switch (ast_get_cc_monitor_policy(p->cc_params)) { 13950 case AST_CC_MONITOR_NEVER: 13951 break; 13952 case AST_CC_MONITOR_NATIVE: 13953 case AST_CC_MONITOR_ALWAYS: 13954 case AST_CC_MONITOR_GENERIC: 13955 #if defined(HAVE_PRI) 13956 if (dahdi_sig_pri_lib_handles(p->sig)) { 13957 /* 13958 * ISDN is in a trunk busy condition so we need to monitor 13959 * the span congestion device state. 13960 */ 13961 snprintf(full_device_name, sizeof(full_device_name), 13962 "DAHDI/I%d/congestion", p->pri->span); 13963 } else 13964 #endif /* defined(HAVE_PRI) */ 13965 { 13966 #if defined(HAVE_PRI) 13967 device_name = create_channel_name(p, 1, ""); 13968 #else 13969 device_name = create_channel_name(p); 13970 #endif /* defined(HAVE_PRI) */ 13971 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", 13972 device_name ? ast_str_buffer(device_name) : ""); 13973 ast_free(device_name); 13974 /* 13975 * The portion after the '-' in the channel name is either a random 13976 * number, a sequence number, or a subchannel number. None are 13977 * necessary so strip them off. 13978 */ 13979 dash = strrchr(full_device_name, '-'); 13980 if (dash) { 13981 *dash = '\0'; 13982 } 13983 } 13984 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest); 13985 13986 /* 13987 * Analog can only do generic monitoring. 13988 * ISDN is in a trunk busy condition and any "device" is going 13989 * to be busy until a B channel becomes available. The generic 13990 * monitor can do this task. 13991 */ 13992 monitor_type = AST_CC_GENERIC_MONITOR_TYPE; 13993 callback(inbound, 13994 #if defined(HAVE_PRI) 13995 p->pri ? p->pri->cc_params : p->cc_params, 13996 #else 13997 p->cc_params, 13998 #endif /* defined(HAVE_PRI) */ 13999 monitor_type, full_device_name, dialstring, NULL); 14000 break; 14001 } 14002 } 14003 p = start.backwards ? p->prev : p->next; 14004 if (!p) { 14005 p = start.backwards ? ifend : iflist; 14006 } 14007 if (p == exitpvt) { 14008 break; 14009 } 14010 } 14011 ast_mutex_unlock(&iflock); 14012 return 0; 14013 }
| 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 1355 of file chan_dahdi.c.
References ast_cc_config_params_init, CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, and DEFAULT_CIDRINGS.
Referenced by process_dahdi(), and setup_dahdi().
01356 { 01357 /* recall that if a field is not included here it is initialized 01358 * to 0 or equivalent 01359 */ 01360 struct dahdi_chan_conf conf = { 01361 #ifdef HAVE_PRI 01362 .pri.pri = { 01363 .nsf = PRI_NSF_NONE, 01364 .switchtype = PRI_SWITCH_NI2, 01365 .dialplan = PRI_UNKNOWN + 1, 01366 .localdialplan = PRI_NATIONAL_ISDN + 1, 01367 .nodetype = PRI_CPE, 01368 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01369 .inband_on_setup_ack = 1, 01370 .inband_on_proceeding = 1, 01371 01372 #if defined(HAVE_PRI_CCSS) 01373 .cc_ptmp_recall_mode = 1,/* specificRecall */ 01374 .cc_qsig_signaling_link_req = 1,/* retain */ 01375 .cc_qsig_signaling_link_rsp = 1,/* retain */ 01376 #endif /* defined(HAVE_PRI_CCSS) */ 01377 01378 .minunused = 2, 01379 .idleext = "", 01380 .idledial = "", 01381 .internationalprefix = "", 01382 .nationalprefix = "", 01383 .localprefix = "", 01384 .privateprefix = "", 01385 .unknownprefix = "", 01386 .resetinterval = -1, 01387 }, 01388 #endif 01389 #if defined(HAVE_SS7) 01390 .ss7.ss7 = { 01391 .called_nai = SS7_NAI_NATIONAL, 01392 .calling_nai = SS7_NAI_NATIONAL, 01393 .internationalprefix = "", 01394 .nationalprefix = "", 01395 .subscriberprefix = "", 01396 .unknownprefix = "" 01397 }, 01398 #endif /* defined(HAVE_SS7) */ 01399 #ifdef HAVE_OPENR2 01400 .mfcr2 = { 01401 .variant = OR2_VAR_ITU, 01402 .mfback_timeout = -1, 01403 .metering_pulse_timeout = -1, 01404 .max_ani = 10, 01405 .max_dnis = 4, 01406 .get_ani_first = -1, 01407 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01408 .skip_category_request = -1, 01409 #endif 01410 .call_files = 0, 01411 .allow_collect_calls = 0, 01412 .charge_calls = 1, 01413 .accept_on_offer = 1, 01414 .forced_release = 0, 01415 .double_answer = 0, 01416 .immediate_accept = -1, 01417 .logdir = "", 01418 .r2proto_file = "", 01419 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01420 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01421 }, 01422 #endif 01423 .chan = { 01424 .context = "default", 01425 .cid_num = "", 01426 .cid_name = "", 01427 .cid_tag = "", 01428 .mohinterpret = "default", 01429 .mohsuggest = "", 01430 .parkinglot = "", 01431 .transfertobusy = 1, 01432 01433 .cid_signalling = CID_SIG_BELL, 01434 .cid_start = CID_START_RING, 01435 .dahditrcallerid = 0, 01436 .use_callerid = 1, 01437 .sig = -1, 01438 .outsigmod = -1, 01439 01440 .cid_rxgain = +5.0, 01441 01442 .tonezone = -1, 01443 01444 .echocancel.head.tap_length = 1, 01445 01446 .busycount = 3, 01447 01448 .accountcode = "", 01449 01450 .mailbox = "", 01451 01452 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01453 .mwisend_fsk = 1, 01454 #endif 01455 .polarityonanswerdelay = 600, 01456 01457 .sendcalleridafter = DEFAULT_CIDRINGS, 01458 01459 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01460 .buf_no = numbufs, 01461 .usefaxbuffers = 0, 01462 .cc_params = ast_cc_config_params_init(), 01463 }, 01464 .timing = { 01465 .prewinktime = -1, 01466 .preflashtime = -1, 01467 .winktime = -1, 01468 .flashtime = -1, 01469 .starttime = -1, 01470 .rxwinktime = -1, 01471 .rxflashtime = -1, 01472 .debouncetime = -1 01473 }, 01474 .is_sig_auto = 1, 01475 .smdi_port = "/dev/ttyS0", 01476 }; 01477 01478 return conf; 01479 }
| static int dahdi_channels_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 18619 of file chan_dahdi.c.
References ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), ast_mutex_lock, ast_mutex_unlock, and dahdi_pvt::next.
18621 { 18622 struct dahdi_pvt *tmp; 18623 struct ast_data *data_channel; 18624 18625 ast_mutex_lock(&iflock); 18626 for (tmp = iflist; tmp; tmp = tmp->next) { 18627 data_channel = ast_data_add_node(data_root, "channel"); 18628 if (!data_channel) { 18629 continue; 18630 } 18631 18632 ast_data_add_structure(dahdi_pvt, data_channel, tmp); 18633 18634 /* if this channel doesn't match remove it. */ 18635 if (!ast_data_search_match(search, data_channel)) { 18636 ast_data_remove_node(data_root, data_channel); 18637 } 18638 } 18639 ast_mutex_unlock(&iflock); 18640 18641 return 0; 18642 }
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 4396 of file chan_dahdi.c.
Referenced by dahdi_close_sub().
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 4402 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().
04403 { 04404 dahdi_close(chan_pvt->subs[sub_num].dfd); 04405 chan_pvt->subs[sub_num].dfd = -1; 04406 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 5188 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_dtmf(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_read(), my_confmute(), and my_handle_dtmf().
05189 { 05190 int x, res; 05191 05192 x = muted; 05193 #if defined(HAVE_PRI) || defined(HAVE_SS7) 05194 switch (p->sig) { 05195 #if defined(HAVE_PRI) 05196 case SIG_PRI_LIB_HANDLE_CASES: 05197 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 05198 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 05199 break; 05200 } 05201 /* Fall through */ 05202 #endif /* defined(HAVE_PRI) */ 05203 #if defined(HAVE_SS7) 05204 case SIG_SS7: 05205 #endif /* defined(HAVE_SS7) */ 05206 { 05207 int y = 1; 05208 05209 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 05210 if (res) 05211 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 05212 p->channel, strerror(errno)); 05213 } 05214 break; 05215 default: 05216 break; 05217 } 05218 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 05219 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 05220 if (res < 0) 05221 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 05222 return res; 05223 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15165 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.
15166 { 15167 int channel; 15168 int ret; 15169 switch (cmd) { 15170 case CLI_INIT: 15171 e->command = "dahdi destroy channel"; 15172 e->usage = 15173 "Usage: dahdi destroy channel <chan num>\n" 15174 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 15175 return NULL; 15176 case CLI_GENERATE: 15177 return NULL; 15178 } 15179 if (a->argc != 4) 15180 return CLI_SHOWUSAGE; 15181 15182 channel = atoi(a->argv[3]); 15183 ret = dahdi_destroy_channel_bynum(channel); 15184 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 15185 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 11446 of file chan_dahdi.c.
References ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::next, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and do_monitor().
11447 { 11448 struct dahdi_pvt *cur; 11449 11450 ast_mutex_lock(&iflock); 11451 for (cur = iflist; cur; cur = cur->next) { 11452 if (cur->channel == channel) { 11453 int x = DAHDI_FLASH; 11454 11455 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 11456 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11457 11458 destroy_channel(cur, 1); 11459 ast_mutex_unlock(&iflock); 11460 ast_module_unref(ast_module_info->self); 11461 return RESULT_SUCCESS; 11462 } 11463 } 11464 ast_mutex_unlock(&iflock); 11465 return RESULT_FAILURE; 11466 }
| static int dahdi_devicestate | ( | void * | data | ) | [static] |
Definition at line 13863 of file chan_dahdi.c.
References AST_DEVICE_UNKNOWN.
13864 { 13865 #if defined(HAVE_PRI) 13866 char *device; 13867 unsigned span; 13868 int res; 13869 13870 device = data; 13871 13872 if (*device != 'I') { 13873 /* The request is not for an ISDN span device. */ 13874 return AST_DEVICE_UNKNOWN; 13875 } 13876 res = sscanf(device, "I%30u", &span); 13877 if (res != 1 || !span || NUM_SPANS < span) { 13878 /* Bad format for ISDN span device name. */ 13879 return AST_DEVICE_UNKNOWN; 13880 } 13881 device = strchr(device, '/'); 13882 if (!device) { 13883 /* Bad format for ISDN span device name. */ 13884 return AST_DEVICE_UNKNOWN; 13885 } 13886 13887 /* 13888 * Since there are currently no other span devstate's defined, 13889 * it must be congestion. 13890 */ 13891 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13892 ++device; 13893 if (!strcmp(device, "congestion")) 13894 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13895 { 13896 return pris[span - 1].pri.congestion_devstate; 13897 } 13898 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13899 else if (!strcmp(device, "threshold")) { 13900 return pris[span - 1].pri.threshold_devstate; 13901 } 13902 return AST_DEVICE_UNKNOWN; 13903 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13904 #else 13905 return AST_DEVICE_UNKNOWN; 13906 #endif /* defined(HAVE_PRI) */ 13907 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 4500 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.
04501 { 04502 struct dahdi_pvt *pvt; 04503 int idx; 04504 int dtmf = -1; 04505 int res; 04506 04507 pvt = chan->tech_pvt; 04508 04509 ast_mutex_lock(&pvt->lock); 04510 04511 idx = dahdi_get_index(chan, pvt, 0); 04512 04513 if ((idx != SUB_REAL) || !pvt->owner) 04514 goto out; 04515 04516 #ifdef HAVE_PRI 04517 switch (pvt->sig) { 04518 case SIG_PRI_LIB_HANDLE_CASES: 04519 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 04520 if (!res) 04521 goto out; 04522 break; 04523 default: 04524 break; 04525 } 04526 #endif 04527 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 04528 goto out; 04529 04530 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 04531 struct dahdi_dialoperation zo = { 04532 .op = DAHDI_DIAL_OP_APPEND, 04533 }; 04534 04535 zo.dialstr[0] = 'T'; 04536 zo.dialstr[1] = digit; 04537 zo.dialstr[2] = '\0'; 04538 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 04539 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n", 04540 chan->name, digit, strerror(errno)); 04541 else 04542 pvt->dialing = 1; 04543 } else { 04544 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n", 04545 chan->name, digit); 04546 pvt->dialing = 1; 04547 pvt->begindigit = digit; 04548 } 04549 04550 out: 04551 ast_mutex_unlock(&pvt->lock); 04552 04553 return 0; 04554 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 4556 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.
04557 { 04558 struct dahdi_pvt *pvt; 04559 int res = 0; 04560 int idx; 04561 int x; 04562 04563 pvt = chan->tech_pvt; 04564 04565 ast_mutex_lock(&pvt->lock); 04566 04567 idx = dahdi_get_index(chan, pvt, 0); 04568 04569 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 04570 goto out; 04571 04572 #ifdef HAVE_PRI 04573 /* This means that the digit was already sent via PRI signalling */ 04574 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 04575 goto out; 04576 } 04577 #endif 04578 04579 if (pvt->begindigit) { 04580 x = -1; 04581 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n", 04582 chan->name, digit); 04583 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 04584 pvt->dialing = 0; 04585 pvt->begindigit = 0; 04586 } 04587 04588 out: 04589 ast_mutex_unlock(&pvt->lock); 04590 04591 return res; 04592 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4968 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().
04969 { 04970 int res; 04971 04972 if (p->echocanon) { 04973 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04974 04975 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04976 04977 if (res) 04978 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04979 else 04980 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 04981 } 04982 04983 p->echocanon = 0; 04984 }
| 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) | |
| flag | on 1 to enable, 0 to disable, -1 return dnd value |
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.
Definition at line 9895 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().
09896 { 09897 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 09898 return analog_dnd(dahdichan->sig_pvt, flag); 09899 } 09900 09901 if (flag == -1) { 09902 return dahdichan->dnd; 09903 } 09904 09905 /* Do not disturb */ 09906 dahdichan->dnd = flag; 09907 ast_verb(3, "%s DND on channel %d\n", 09908 flag? "Enabled" : "Disabled", 09909 dahdichan->channel); 09910 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 09911 "Channel: DAHDI/%d\r\n" 09912 "Status: %s\r\n", dahdichan->channel, 09913 flag? "enabled" : "disabled"); 09914 09915 return 0; 09916 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4896 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_setoption(), handle_init_event(), and my_set_echocanceller().
04897 { 04898 int res; 04899 if (!p) 04900 return; 04901 if (p->echocanon) { 04902 ast_debug(1, "Echo cancellation already on\n"); 04903 return; 04904 } 04905 if (p->digital) { 04906 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04907 return; 04908 } 04909 if (p->echocancel.head.tap_length) { 04910 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04911 switch (p->sig) { 04912 #if defined(HAVE_PRI) 04913 case SIG_PRI_LIB_HANDLE_CASES: 04914 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04915 /* 04916 * PRI nobch pseudo channel. Does not need ec anyway. 04917 * Does not handle ioctl(DAHDI_AUDIOMODE) 04918 */ 04919 return; 04920 } 04921 /* Fall through */ 04922 #endif /* defined(HAVE_PRI) */ 04923 #if defined(HAVE_SS7) 04924 case SIG_SS7: 04925 #endif /* defined(HAVE_SS7) */ 04926 { 04927 int x = 1; 04928 04929 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04930 if (res) 04931 ast_log(LOG_WARNING, 04932 "Unable to enable audio mode on channel %d (%s)\n", 04933 p->channel, strerror(errno)); 04934 } 04935 break; 04936 default: 04937 break; 04938 } 04939 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04940 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04941 if (res) { 04942 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04943 } else { 04944 p->echocanon = 1; 04945 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04946 } 04947 } else 04948 ast_debug(1, "No echo cancellation requested\n"); 04949 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8921 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.
08922 { 08923 struct dahdi_pvt *p = ast->tech_pvt; 08924 struct ast_frame *f; 08925 ast_mutex_lock(&p->lock); 08926 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08927 struct analog_pvt *analog_p = p->sig_pvt; 08928 f = analog_exception(analog_p, ast); 08929 } else { 08930 f = __dahdi_exception(ast); 08931 } 08932 ast_mutex_unlock(&p->lock); 08933 return f; 08934 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 16011 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, LOG_WARNING, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
16012 { 16013 if (p) { 16014 switch (mode) { 16015 case TRANSFER: 16016 p->fake_event = DAHDI_EVENT_WINKFLASH; 16017 break; 16018 case HANGUP: 16019 p->fake_event = DAHDI_EVENT_ONHOOK; 16020 break; 16021 default: 16022 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 16023 } 16024 } 16025 return 0; 16026 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 7593 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, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, sig_pri_fixup(), dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_fixup(), dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
07594 { 07595 struct dahdi_pvt *p = newchan->tech_pvt; 07596 int x; 07597 07598 ast_mutex_lock(&p->lock); 07599 07600 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 07601 if (p->owner == oldchan) { 07602 p->owner = newchan; 07603 } 07604 for (x = 0; x < 3; x++) { 07605 if (p->subs[x].owner == oldchan) { 07606 if (!x) { 07607 dahdi_unlink(NULL, p, 0); 07608 } 07609 p->subs[x].owner = newchan; 07610 } 07611 } 07612 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07613 analog_fixup(oldchan, newchan, p->sig_pvt); 07614 #if defined(HAVE_PRI) 07615 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 07616 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 07617 #endif /* defined(HAVE_PRI) */ 07618 #if defined(HAVE_SS7) 07619 } else if (p->sig == SIG_SS7) { 07620 sig_ss7_fixup(oldchan, newchan, p->sig_pvt); 07621 #endif /* defined(HAVE_SS7) */ 07622 } 07623 update_conf(p); 07624 07625 ast_mutex_unlock(&p->lock); 07626 07627 if (newchan->_state == AST_STATE_RINGING) { 07628 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 07629 } 07630 return 0; 07631 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 6948 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::lock, dahdi_pvt::rxgain, dahdi_pvt::sig, SIG_MFCR2, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, dahdi_pvt::span, ast_channel::tech_pvt, and dahdi_pvt::txgain.
06949 { 06950 struct dahdi_pvt *p = chan->tech_pvt; 06951 int res = 0; 06952 06953 if (!p) { 06954 /* No private structure! */ 06955 *buf = '\0'; 06956 return -1; 06957 } 06958 06959 if (!strcasecmp(data, "rxgain")) { 06960 ast_mutex_lock(&p->lock); 06961 snprintf(buf, len, "%f", p->rxgain); 06962 ast_mutex_unlock(&p->lock); 06963 } else if (!strcasecmp(data, "txgain")) { 06964 ast_mutex_lock(&p->lock); 06965 snprintf(buf, len, "%f", p->txgain); 06966 ast_mutex_unlock(&p->lock); 06967 } else if (!strcasecmp(data, "dahdi_channel")) { 06968 ast_mutex_lock(&p->lock); 06969 snprintf(buf, len, "%d", p->channel); 06970 ast_mutex_unlock(&p->lock); 06971 } else if (!strcasecmp(data, "dahdi_span")) { 06972 ast_mutex_lock(&p->lock); 06973 snprintf(buf, len, "%d", p->span); 06974 ast_mutex_unlock(&p->lock); 06975 } else if (!strcasecmp(data, "dahdi_type")) { 06976 ast_mutex_lock(&p->lock); 06977 switch (p->sig) { 06978 #if defined(HAVE_OPENR2) 06979 case SIG_MFCR2: 06980 ast_copy_string(buf, "mfc/r2", len); 06981 break; 06982 #endif /* defined(HAVE_OPENR2) */ 06983 #if defined(HAVE_PRI) 06984 case SIG_PRI_LIB_HANDLE_CASES: 06985 ast_copy_string(buf, "pri", len); 06986 break; 06987 #endif /* defined(HAVE_PRI) */ 06988 case 0: 06989 ast_copy_string(buf, "pseudo", len); 06990 break; 06991 #if defined(HAVE_SS7) 06992 case SIG_SS7: 06993 ast_copy_string(buf, "ss7", len); 06994 break; 06995 #endif /* defined(HAVE_SS7) */ 06996 default: 06997 /* The only thing left is analog ports. */ 06998 ast_copy_string(buf, "analog", len); 06999 break; 07000 } 07001 ast_mutex_unlock(&p->lock); 07002 #if defined(HAVE_PRI) 07003 #if defined(HAVE_PRI_REVERSE_CHARGE) 07004 } else if (!strcasecmp(data, "reversecharge")) { 07005 ast_mutex_lock(&p->lock); 07006 switch (p->sig) { 07007 case SIG_PRI_LIB_HANDLE_CASES: 07008 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 07009 break; 07010 default: 07011 *buf = '\0'; 07012 res = -1; 07013 break; 07014 } 07015 ast_mutex_unlock(&p->lock); 07016 #endif 07017 #if defined(HAVE_PRI_SETUP_KEYPAD) 07018 } else if (!strcasecmp(data, "keypad_digits")) { 07019 ast_mutex_lock(&p->lock); 07020 switch (p->sig) { 07021 case SIG_PRI_LIB_HANDLE_CASES: 07022 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 07023 len); 07024 break; 07025 default: 07026 *buf = '\0'; 07027 res = -1; 07028 break; 07029 } 07030 ast_mutex_unlock(&p->lock); 07031 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 07032 } else if (!strcasecmp(data, "no_media_path")) { 07033 ast_mutex_lock(&p->lock); 07034 switch (p->sig) { 07035 case SIG_PRI_LIB_HANDLE_CASES: 07036 /* 07037 * TRUE if the call is on hold or is call waiting because 07038 * there is no media path available. 07039 */ 07040 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel); 07041 break; 07042 default: 07043 *buf = '\0'; 07044 res = -1; 07045 break; 07046 } 07047 ast_mutex_unlock(&p->lock); 07048 #endif /* defined(HAVE_PRI) */ 07049 } else { 07050 *buf = '\0'; 07051 res = -1; 07052 } 07053 07054 return res; 07055 }
| static int dahdi_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 7087 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.
07088 { 07089 struct dahdi_pvt *p = chan->tech_pvt; 07090 int res = 0; 07091 07092 if (!p) { 07093 /* No private structure! */ 07094 return -1; 07095 } 07096 07097 if (!strcasecmp(data, "buffers")) { 07098 int num_bufs, policy; 07099 07100 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 07101 struct dahdi_bufferinfo bi = { 07102 .txbufpolicy = policy, 07103 .rxbufpolicy = policy, 07104 .bufsize = p->bufsize, 07105 .numbufs = num_bufs, 07106 }; 07107 int bpres; 07108 07109 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07110 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 07111 } else { 07112 p->bufferoverrideinuse = 1; 07113 } 07114 } else { 07115 res = -1; 07116 } 07117 } else if (!strcasecmp(data, "echocan_mode")) { 07118 if (!strcasecmp(value, "on")) { 07119 ast_mutex_lock(&p->lock); 07120 dahdi_enable_ec(p); 07121 ast_mutex_unlock(&p->lock); 07122 } else if (!strcasecmp(value, "off")) { 07123 ast_mutex_lock(&p->lock); 07124 dahdi_disable_ec(p); 07125 ast_mutex_unlock(&p->lock); 07126 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07127 } else if (!strcasecmp(value, "fax")) { 07128 int blah = 1; 07129 07130 ast_mutex_lock(&p->lock); 07131 if (!p->echocanon) { 07132 dahdi_enable_ec(p); 07133 } 07134 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07135 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 07136 } 07137 ast_mutex_unlock(&p->lock); 07138 } else if (!strcasecmp(value, "voice")) { 07139 int blah = 0; 07140 07141 ast_mutex_lock(&p->lock); 07142 if (!p->echocanon) { 07143 dahdi_enable_ec(p); 07144 } 07145 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07146 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 07147 } 07148 ast_mutex_unlock(&p->lock); 07149 #endif 07150 } else { 07151 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 07152 res = -1; 07153 } 07154 } else { 07155 res = -1; 07156 } 07157 07158 return res; 07159 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 495 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().
| static void dahdi_handle_dtmf | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 7770 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_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, 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, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, send_cwcidspill(), ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.
Referenced by dahdi_handle_event(), and dahdi_read().
07771 { 07772 struct dahdi_pvt *p = ast->tech_pvt; 07773 struct ast_frame *f = *dest; 07774 07775 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 07776 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 07777 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 07778 07779 if (p->confirmanswer) { 07780 if (f->frametype == AST_FRAME_DTMF_END) { 07781 ast_debug(1, "Confirm answer on %s!\n", ast->name); 07782 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 07783 of a DTMF digit */ 07784 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07785 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07786 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 07787 p->confirmanswer = 0; 07788 } else { 07789 p->subs[idx].f.frametype = AST_FRAME_NULL; 07790 p->subs[idx].f.subclass.integer = 0; 07791 } 07792 *dest = &p->subs[idx].f; 07793 } else if (p->callwaitcas) { 07794 if (f->frametype == AST_FRAME_DTMF_END) { 07795 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) { 07796 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 07797 ast_free(p->cidspill); 07798 p->cidspill = NULL; 07799 send_cwcidspill(p); 07800 } 07801 p->callwaitcas = 0; 07802 } 07803 p->subs[idx].f.frametype = AST_FRAME_NULL; 07804 p->subs[idx].f.subclass.integer = 0; 07805 *dest = &p->subs[idx].f; 07806 } else if (f->subclass.integer == 'f') { 07807 if (f->frametype == AST_FRAME_DTMF_END) { 07808 /* Fax tone -- Handle and return NULL */ 07809 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 07810 /* If faxbuffers are configured, use them for the fax transmission */ 07811 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 07812 struct dahdi_bufferinfo bi = { 07813 .txbufpolicy = p->faxbuf_policy, 07814 .bufsize = p->bufsize, 07815 .numbufs = p->faxbuf_no 07816 }; 07817 int res; 07818 07819 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07820 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 07821 } else { 07822 p->bufferoverrideinuse = 1; 07823 } 07824 } 07825 p->faxhandled = 1; 07826 if (p->dsp) { 07827 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 07828 ast_dsp_set_features(p->dsp, p->dsp_features); 07829 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 07830 } 07831 if (strcmp(ast->exten, "fax")) { 07832 const char *target_context = S_OR(ast->macrocontext, ast->context); 07833 07834 /* We need to unlock 'ast' here because ast_exists_extension has the 07835 * potential to start autoservice on the channel. Such action is prone 07836 * to deadlock. 07837 */ 07838 ast_mutex_unlock(&p->lock); 07839 ast_channel_unlock(ast); 07840 if (ast_exists_extension(ast, target_context, "fax", 1, 07841 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 07842 ast_channel_lock(ast); 07843 ast_mutex_lock(&p->lock); 07844 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 07845 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 07846 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 07847 if (ast_async_goto(ast, target_context, "fax", 1)) 07848 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 07849 } else { 07850 ast_channel_lock(ast); 07851 ast_mutex_lock(&p->lock); 07852 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 07853 } 07854 } else { 07855 ast_debug(1, "Already in a fax extension, not redirecting\n"); 07856 } 07857 } else { 07858 ast_debug(1, "Fax already handled\n"); 07859 } 07860 dahdi_confmute(p, 0); 07861 } 07862 p->subs[idx].f.frametype = AST_FRAME_NULL; 07863 p->subs[idx].f.subclass.integer = 0; 07864 *dest = &p->subs[idx].f; 07865 } 07866 }
| static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7896 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), analog_ss_thread(), ast_party_caller::ani, ast_party_caller::ani2, dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_lock, 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_mutex_lock, ast_mutex_unlock, ast_null_frame, 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(), ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, dahdi_pvt::cid_suppress_expire, 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_dtmf(), 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(), dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), ast_party_caller::id, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_party_id::number, 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_COR, 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_CALL_LEVEL_PROCEEDING, sig_pri_chan_alarm_notify(), sig_pri_dial_complete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_set_alarm(), ast_frame::src, ast_party_name::str, ast_party_number::str, 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(), ast_party_name::valid, ast_party_number::valid, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
07897 { 07898 int res, x; 07899 int idx, mysig; 07900 char *c; 07901 struct dahdi_pvt *p = ast->tech_pvt; 07902 pthread_t threadid; 07903 struct ast_channel *chan; 07904 struct ast_frame *f; 07905 07906 idx = dahdi_get_index(ast, p, 0); 07907 if (idx < 0) { 07908 return &ast_null_frame; 07909 } 07910 mysig = p->sig; 07911 if (p->outsigmod > -1) 07912 mysig = p->outsigmod; 07913 p->subs[idx].f.frametype = AST_FRAME_NULL; 07914 p->subs[idx].f.subclass.integer = 0; 07915 p->subs[idx].f.datalen = 0; 07916 p->subs[idx].f.samples = 0; 07917 p->subs[idx].f.mallocd = 0; 07918 p->subs[idx].f.offset = 0; 07919 p->subs[idx].f.src = "dahdi_handle_event"; 07920 p->subs[idx].f.data.ptr = NULL; 07921 f = &p->subs[idx].f; 07922 07923 if (p->fake_event) { 07924 res = p->fake_event; 07925 p->fake_event = 0; 07926 } else 07927 res = dahdi_get_event(p->subs[idx].dfd); 07928 07929 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 07930 07931 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 07932 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 07933 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 07934 #if defined(HAVE_PRI) 07935 if (dahdi_sig_pri_lib_handles(p->sig) 07936 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07937 && p->pri 07938 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07939 /* absorb event */ 07940 } else 07941 #endif /* defined(HAVE_PRI) */ 07942 { 07943 /* Unmute conference */ 07944 dahdi_confmute(p, 0); 07945 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 07946 p->subs[idx].f.subclass.integer = res & 0xff; 07947 dahdi_handle_dtmf(ast, idx, &f); 07948 } 07949 return f; 07950 } 07951 07952 if (res & DAHDI_EVENT_DTMFDOWN) { 07953 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07954 #if defined(HAVE_PRI) 07955 if (dahdi_sig_pri_lib_handles(p->sig) 07956 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07957 && p->pri 07958 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07959 /* absorb event */ 07960 } else 07961 #endif /* defined(HAVE_PRI) */ 07962 { 07963 /* Mute conference */ 07964 dahdi_confmute(p, 1); 07965 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07966 p->subs[idx].f.subclass.integer = res & 0xff; 07967 dahdi_handle_dtmf(ast, idx, &f); 07968 } 07969 return &p->subs[idx].f; 07970 } 07971 07972 switch (res) { 07973 case DAHDI_EVENT_EC_DISABLED: 07974 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07975 p->echocanon = 0; 07976 break; 07977 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07978 case DAHDI_EVENT_TX_CED_DETECTED: 07979 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 07980 break; 07981 case DAHDI_EVENT_RX_CED_DETECTED: 07982 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 07983 break; 07984 case DAHDI_EVENT_EC_NLP_DISABLED: 07985 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 07986 break; 07987 case DAHDI_EVENT_EC_NLP_ENABLED: 07988 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 07989 break; 07990 #endif 07991 case DAHDI_EVENT_BITSCHANGED: 07992 #ifdef HAVE_OPENR2 07993 if (p->sig != SIG_MFCR2) { 07994 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07995 } else { 07996 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 07997 openr2_chan_handle_cas(p->r2chan); 07998 } 07999 #else 08000 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 08001 #endif 08002 break; 08003 case DAHDI_EVENT_PULSE_START: 08004 /* Stop tone if there's a pulse start and the PBX isn't started */ 08005 if (!ast->pbx) 08006 tone_zone_play_tone(p->subs[idx].dfd, -1); 08007 break; 08008 case DAHDI_EVENT_DIALCOMPLETE: 08009 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */ 08010 #if defined(HAVE_PRI) 08011 if (dahdi_sig_pri_lib_handles(p->sig)) { 08012 if (p->inalarm) { 08013 break; 08014 } 08015 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) { 08016 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name, 08017 strerror(errno)); 08018 return NULL; 08019 } 08020 if (x) { 08021 /* Still dialing in DAHDI driver */ 08022 break; 08023 } 08024 /* 08025 * The ast channel is locked and the private may be locked more 08026 * than once. 08027 */ 08028 sig_pri_dial_complete(p->sig_pvt, ast); 08029 break; 08030 } 08031 #endif /* defined(HAVE_PRI) */ 08032 #ifdef HAVE_OPENR2 08033 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 08034 /* we don't need to do anything for this event for R2 signaling 08035 if the call is being setup */ 08036 break; 08037 } 08038 #endif 08039 if (p->inalarm) break; 08040 if ((p->radio || (p->oprmode < 0))) break; 08041 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 08042 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 08043 return NULL; 08044 } 08045 if (!x) { /* if not still dialing in driver */ 08046 dahdi_enable_ec(p); 08047 if (p->echobreak) { 08048 dahdi_train_ec(p); 08049 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 08050 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08051 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08052 p->echobreak = 0; 08053 } else { 08054 p->dialing = 0; 08055 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 08056 /* if thru with dialing after offhook */ 08057 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 08058 ast_setstate(ast, AST_STATE_UP); 08059 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08060 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08061 break; 08062 } else { /* if to state wait for offhook to dial rest */ 08063 /* we now wait for off hook */ 08064 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 08065 } 08066 } 08067 if (ast->_state == AST_STATE_DIALING) { 08068 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 08069 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 08070 } else if (p->confirmanswer || (!p->dialednone 08071 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 08072 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 08073 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 08074 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 08075 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 08076 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 08077 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 08078 || (mysig == SIG_SF_FEATB)))) { 08079 ast_setstate(ast, AST_STATE_RINGING); 08080 } else if (!p->answeronpolarityswitch) { 08081 ast_setstate(ast, AST_STATE_UP); 08082 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08083 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08084 /* If aops=0 and hops=1, this is necessary */ 08085 p->polarity = POLARITY_REV; 08086 } else { 08087 /* Start clean, so we can catch the change to REV polarity when party answers */ 08088 p->polarity = POLARITY_IDLE; 08089 } 08090 } 08091 } 08092 } 08093 break; 08094 case DAHDI_EVENT_ALARM: 08095 switch (p->sig) { 08096 #if defined(HAVE_PRI) 08097 case SIG_PRI_LIB_HANDLE_CASES: 08098 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 08099 break; 08100 #endif /* defined(HAVE_PRI) */ 08101 #if defined(HAVE_SS7) 08102 case SIG_SS7: 08103 sig_ss7_set_alarm(p->sig_pvt, 1); 08104 break; 08105 #endif /* defined(HAVE_SS7) */ 08106 default: 08107 p->inalarm = 1; 08108 break; 08109 } 08110 res = get_alarms(p); 08111 handle_alarms(p, res); 08112 #ifdef HAVE_PRI 08113 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 08114 /* fall through intentionally */ 08115 } else { 08116 break; 08117 } 08118 #endif 08119 #if defined(HAVE_SS7) 08120 if (p->sig == SIG_SS7) 08121 break; 08122 #endif /* defined(HAVE_SS7) */ 08123 #ifdef HAVE_OPENR2 08124 if (p->sig == SIG_MFCR2) 08125 break; 08126 #endif 08127 case DAHDI_EVENT_ONHOOK: 08128 if (p->radio) { 08129 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08130 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08131 break; 08132 } 08133 if (p->oprmode < 0) 08134 { 08135 if (p->oprmode != -1) break; 08136 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08137 { 08138 /* Make sure it starts ringing */ 08139 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08140 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 08141 save_conference(p->oprpeer); 08142 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08143 } 08144 break; 08145 } 08146 switch (p->sig) { 08147 case SIG_FXOLS: 08148 case SIG_FXOGS: 08149 case SIG_FXOKS: 08150 /* Check for some special conditions regarding call waiting */ 08151 if (idx == SUB_REAL) { 08152 /* The normal line was hung up */ 08153 if (p->subs[SUB_CALLWAIT].owner) { 08154 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 08155 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 08156 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 08157 unalloc_sub(p, SUB_CALLWAIT); 08158 #if 0 08159 p->subs[idx].needanswer = 0; 08160 p->subs[idx].needringing = 0; 08161 #endif 08162 p->callwaitingrepeat = 0; 08163 p->cidcwexpire = 0; 08164 p->cid_suppress_expire = 0; 08165 p->owner = NULL; 08166 /* Don't start streaming audio yet if the incoming call isn't up yet */ 08167 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 08168 p->dialing = 1; 08169 dahdi_ring_phone(p); 08170 } else if (p->subs[SUB_THREEWAY].owner) { 08171 unsigned int mssinceflash; 08172 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 08173 the private structure -- not especially easy or clean */ 08174 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 08175 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 08176 DLA_UNLOCK(&p->lock); 08177 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08178 /* We can grab ast and p in that order, without worry. We should make sure 08179 nothing seriously bad has happened though like some sort of bizarre double 08180 masquerade! */ 08181 DLA_LOCK(&p->lock); 08182 if (p->owner != ast) { 08183 ast_log(LOG_WARNING, "This isn't good...\n"); 08184 return NULL; 08185 } 08186 } 08187 if (!p->subs[SUB_THREEWAY].owner) { 08188 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 08189 return NULL; 08190 } 08191 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 08192 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash); 08193 if (mssinceflash < MIN_MS_SINCE_FLASH) { 08194 /* It hasn't been long enough since the last flashook. This is probably a bounce on 08195 hanging up. Hangup both channels now */ 08196 if (p->subs[SUB_THREEWAY].owner) 08197 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 08198 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08199 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 08200 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08201 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 08202 if (p->transfer) { 08203 /* In any case this isn't a threeway call anymore */ 08204 p->subs[SUB_REAL].inthreeway = 0; 08205 p->subs[SUB_THREEWAY].inthreeway = 0; 08206 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 08207 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 08208 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08209 /* Swap subs and dis-own channel */ 08210 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08211 p->owner = NULL; 08212 /* Ring the phone */ 08213 dahdi_ring_phone(p); 08214 } else { 08215 if ((res = attempt_transfer(p)) < 0) { 08216 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08217 if (p->subs[SUB_THREEWAY].owner) 08218 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08219 } else if (res) { 08220 /* Don't actually hang up at this point */ 08221 if (p->subs[SUB_THREEWAY].owner) 08222 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08223 break; 08224 } 08225 } 08226 } else { 08227 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08228 if (p->subs[SUB_THREEWAY].owner) 08229 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08230 } 08231 } else { 08232 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08233 /* Swap subs and dis-own channel */ 08234 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08235 p->owner = NULL; 08236 /* Ring the phone */ 08237 dahdi_ring_phone(p); 08238 } 08239 } 08240 } else { 08241 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 08242 } 08243 /* Fall through */ 08244 default: 08245 dahdi_disable_ec(p); 08246 return NULL; 08247 } 08248 break; 08249 case DAHDI_EVENT_RINGOFFHOOK: 08250 if (p->inalarm) break; 08251 if (p->oprmode < 0) 08252 { 08253 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08254 { 08255 /* Make sure it stops ringing */ 08256 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08257 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 08258 restore_conference(p->oprpeer); 08259 } 08260 break; 08261 } 08262 if (p->radio) 08263 { 08264 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08265 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08266 break; 08267 } 08268 /* for E911, its supposed to wait for offhook then dial 08269 the second half of the dial string */ 08270 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 08271 c = strchr(p->dialdest, '/'); 08272 if (c) 08273 c++; 08274 else 08275 c = p->dialdest; 08276 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 08277 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 08278 if (strlen(p->dop.dialstr) > 4) { 08279 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 08280 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 08281 p->echorest[sizeof(p->echorest) - 1] = '\0'; 08282 p->echobreak = 1; 08283 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 08284 } else 08285 p->echobreak = 0; 08286 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 08287 int saveerr = errno; 08288 08289 x = DAHDI_ONHOOK; 08290 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 08291 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 08292 return NULL; 08293 } 08294 p->dialing = 1; 08295 return &p->subs[idx].f; 08296 } 08297 switch (p->sig) { 08298 case SIG_FXOLS: 08299 case SIG_FXOGS: 08300 case SIG_FXOKS: 08301 switch (ast->_state) { 08302 case AST_STATE_RINGING: 08303 dahdi_enable_ec(p); 08304 dahdi_train_ec(p); 08305 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08306 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08307 /* Make sure it stops ringing */ 08308 p->subs[SUB_REAL].needringing = 0; 08309 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08310 ast_debug(1, "channel %d answered\n", p->channel); 08311 08312 /* Cancel any running CallerID spill */ 08313 ast_free(p->cidspill); 08314 p->cidspill = NULL; 08315 restore_conference(p); 08316 08317 p->dialing = 0; 08318 p->callwaitcas = 0; 08319 if (p->confirmanswer) { 08320 /* Ignore answer if "confirm answer" is enabled */ 08321 p->subs[idx].f.frametype = AST_FRAME_NULL; 08322 p->subs[idx].f.subclass.integer = 0; 08323 } else if (!ast_strlen_zero(p->dop.dialstr)) { 08324 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 08325 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08326 if (res < 0) { 08327 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08328 p->dop.dialstr[0] = '\0'; 08329 return NULL; 08330 } else { 08331 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 08332 p->subs[idx].f.frametype = AST_FRAME_NULL; 08333 p->subs[idx].f.subclass.integer = 0; 08334 p->dialing = 1; 08335 } 08336 p->dop.dialstr[0] = '\0'; 08337 ast_setstate(ast, AST_STATE_DIALING); 08338 } else 08339 ast_setstate(ast, AST_STATE_UP); 08340 return &p->subs[idx].f; 08341 case AST_STATE_DOWN: 08342 ast_setstate(ast, AST_STATE_RING); 08343 ast->rings = 1; 08344 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08345 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK; 08346 ast_debug(1, "channel %d picked up\n", p->channel); 08347 return &p->subs[idx].f; 08348 case AST_STATE_UP: 08349 /* Make sure it stops ringing */ 08350 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08351 /* Okay -- probably call waiting*/ 08352 if (ast_bridged_channel(p->owner)) 08353 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08354 p->subs[idx].needunhold = 1; 08355 break; 08356 case AST_STATE_RESERVED: 08357 /* Start up dialtone */ 08358 if (has_voicemail(p)) 08359 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08360 else 08361 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08362 break; 08363 default: 08364 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state); 08365 } 08366 break; 08367 case SIG_FXSLS: 08368 case SIG_FXSGS: 08369 case SIG_FXSKS: 08370 if (ast->_state == AST_STATE_RING) { 08371 p->ringt = p->ringt_base; 08372 } 08373 08374 /* If we get a ring then we cannot be in 08375 * reversed polarity. So we reset to idle */ 08376 ast_debug(1, "Setting IDLE polarity due " 08377 "to ring. Old polarity was %d\n", 08378 p->polarity); 08379 p->polarity = POLARITY_IDLE; 08380 08381 /* Fall through */ 08382 case SIG_EM: 08383 case SIG_EM_E1: 08384 case SIG_EMWINK: 08385 case SIG_FEATD: 08386 case SIG_FEATDMF: 08387 case SIG_FEATDMF_TA: 08388 case SIG_E911: 08389 case SIG_FGC_CAMA: 08390 case SIG_FGC_CAMAMF: 08391 case SIG_FEATB: 08392 case SIG_SF: 08393 case SIG_SFWINK: 08394 case SIG_SF_FEATD: 08395 case SIG_SF_FEATDMF: 08396 case SIG_SF_FEATB: 08397 if (ast->_state == AST_STATE_PRERING) 08398 ast_setstate(ast, AST_STATE_RING); 08399 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 08400 ast_debug(1, "Ring detected\n"); 08401 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08402 p->subs[idx].f.subclass.integer = AST_CONTROL_RING; 08403 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 08404 ast_debug(1, "Line answered\n"); 08405 if (p->confirmanswer) { 08406 p->subs[idx].f.frametype = AST_FRAME_NULL; 08407 p->subs[idx].f.subclass.integer = 0; 08408 } else { 08409 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08410 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08411 ast_setstate(ast, AST_STATE_UP); 08412 } 08413 } else if (ast->_state != AST_STATE_RING) 08414 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel); 08415 break; 08416 default: 08417 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08418 } 08419 break; 08420 case DAHDI_EVENT_RINGBEGIN: 08421 switch (p->sig) { 08422 case SIG_FXSLS: 08423 case SIG_FXSGS: 08424 case SIG_FXSKS: 08425 if (ast->_state == AST_STATE_RING) { 08426 p->ringt = p->ringt_base; 08427 } 08428 break; 08429 } 08430 break; 08431 case DAHDI_EVENT_RINGERON: 08432 break; 08433 case DAHDI_EVENT_NOALARM: 08434 switch (p->sig) { 08435 #if defined(HAVE_PRI) 08436 case SIG_PRI_LIB_HANDLE_CASES: 08437 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 08438 break; 08439 #endif /* defined(HAVE_PRI) */ 08440 #if defined(HAVE_SS7) 08441 case SIG_SS7: 08442 sig_ss7_set_alarm(p->sig_pvt, 0); 08443 break; 08444 #endif /* defined(HAVE_SS7) */ 08445 default: 08446 p->inalarm = 0; 08447 break; 08448 } 08449 handle_clear_alarms(p); 08450 break; 08451 case DAHDI_EVENT_WINKFLASH: 08452 if (p->inalarm) break; 08453 if (p->radio) break; 08454 if (p->oprmode < 0) break; 08455 if (p->oprmode > 1) 08456 { 08457 struct dahdi_params par; 08458 08459 memset(&par, 0, sizeof(par)); 08460 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 08461 { 08462 if (!par.rxisoffhook) 08463 { 08464 /* Make sure it stops ringing */ 08465 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08466 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 08467 save_conference(p); 08468 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08469 } 08470 } 08471 break; 08472 } 08473 /* Remember last time we got a flash-hook */ 08474 p->flashtime = ast_tvnow(); 08475 switch (mysig) { 08476 case SIG_FXOLS: 08477 case SIG_FXOGS: 08478 case SIG_FXOKS: 08479 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 08480 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 08481 08482 /* Cancel any running CallerID spill */ 08483 ast_free(p->cidspill); 08484 p->cidspill = NULL; 08485 restore_conference(p); 08486 p->callwaitcas = 0; 08487 08488 if (idx != SUB_REAL) { 08489 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 08490 goto winkflashdone; 08491 } 08492 08493 if (p->subs[SUB_CALLWAIT].owner) { 08494 /* Swap to call-wait */ 08495 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 08496 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 08497 p->owner = p->subs[SUB_REAL].owner; 08498 ast_debug(1, "Making %s the new owner\n", p->owner->name); 08499 if (p->owner->_state == AST_STATE_RINGING) { 08500 ast_setstate(p->owner, AST_STATE_UP); 08501 p->subs[SUB_REAL].needanswer = 1; 08502 } 08503 p->callwaitingrepeat = 0; 08504 p->cidcwexpire = 0; 08505 p->cid_suppress_expire = 0; 08506 /* Start music on hold if appropriate */ 08507 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 08508 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 08509 S_OR(p->mohsuggest, NULL), 08510 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08511 } 08512 p->subs[SUB_CALLWAIT].needhold = 1; 08513 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 08514 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 08515 S_OR(p->mohsuggest, NULL), 08516 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08517 } 08518 p->subs[SUB_REAL].needunhold = 1; 08519 } else if (!p->subs[SUB_THREEWAY].owner) { 08520 if (!p->threewaycalling) { 08521 /* Just send a flash if no 3-way calling */ 08522 p->subs[SUB_REAL].needflash = 1; 08523 goto winkflashdone; 08524 } else if (!check_for_conference(p)) { 08525 char cid_num[256]; 08526 char cid_name[256]; 08527 08528 cid_num[0] = 0; 08529 cid_name[0] = 0; 08530 if (p->dahditrcallerid && p->owner) { 08531 if (p->owner->caller.id.number.valid 08532 && p->owner->caller.id.number.str) { 08533 ast_copy_string(cid_num, p->owner->caller.id.number.str, 08534 sizeof(cid_num)); 08535 } 08536 if (p->owner->caller.id.name.valid 08537 && p->owner->caller.id.name.str) { 08538 ast_copy_string(cid_name, p->owner->caller.id.name.str, 08539 sizeof(cid_name)); 08540 } 08541 } 08542 /* XXX This section needs much more error checking!!! XXX */ 08543 /* Start a 3-way call if feasible */ 08544 if (!((ast->pbx) || 08545 (ast->_state == AST_STATE_UP) || 08546 (ast->_state == AST_STATE_RING))) { 08547 ast_debug(1, "Flash when call not up or ringing\n"); 08548 goto winkflashdone; 08549 } 08550 if (alloc_sub(p, SUB_THREEWAY)) { 08551 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 08552 goto winkflashdone; 08553 } 08554 08555 /* 08556 * Make new channel 08557 * 08558 * We cannot hold the p or ast locks while creating a new 08559 * channel. 08560 */ 08561 ast_mutex_unlock(&p->lock); 08562 ast_channel_unlock(ast); 08563 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL); 08564 ast_channel_lock(ast); 08565 ast_mutex_lock(&p->lock); 08566 if (p->dahditrcallerid) { 08567 if (!p->origcid_num) 08568 p->origcid_num = ast_strdup(p->cid_num); 08569 if (!p->origcid_name) 08570 p->origcid_name = ast_strdup(p->cid_name); 08571 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 08572 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 08573 } 08574 /* Swap things around between the three-way and real call */ 08575 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08576 /* Disable echo canceller for better dialing */ 08577 dahdi_disable_ec(p); 08578 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 08579 if (res) 08580 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 08581 p->owner = chan; 08582 if (!chan) { 08583 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 08584 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 08585 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 08586 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08587 dahdi_enable_ec(p); 08588 ast_hangup(chan); 08589 } else { 08590 ast_verb(3, "Started three way call on channel %d\n", p->channel); 08591 08592 /* Start music on hold if appropriate */ 08593 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08594 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 08595 S_OR(p->mohsuggest, NULL), 08596 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08597 } 08598 p->subs[SUB_THREEWAY].needhold = 1; 08599 } 08600 } 08601 } else { 08602 /* Already have a 3 way call */ 08603 if (p->subs[SUB_THREEWAY].inthreeway) { 08604 /* Call is already up, drop the last person */ 08605 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 08606 /* If the primary call isn't answered yet, use it */ 08607 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 08608 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 08609 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08610 p->owner = p->subs[SUB_REAL].owner; 08611 } 08612 /* Drop the last call and stop the conference */ 08613 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 08614 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08615 p->subs[SUB_REAL].inthreeway = 0; 08616 p->subs[SUB_THREEWAY].inthreeway = 0; 08617 } else { 08618 /* Lets see what we're up to */ 08619 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 08620 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 08621 int otherindex = SUB_THREEWAY; 08622 08623 ast_verb(3, "Building conference call with %s and %s\n", 08624 p->subs[SUB_THREEWAY].owner->name, 08625 p->subs[SUB_REAL].owner->name); 08626 /* Put them in the threeway, and flip */ 08627 p->subs[SUB_THREEWAY].inthreeway = 1; 08628 p->subs[SUB_REAL].inthreeway = 1; 08629 if (ast->_state == AST_STATE_UP) { 08630 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08631 otherindex = SUB_REAL; 08632 } 08633 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 08634 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 08635 p->subs[otherindex].needunhold = 1; 08636 p->owner = p->subs[SUB_REAL].owner; 08637 } else { 08638 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 08639 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08640 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08641 p->owner = p->subs[SUB_REAL].owner; 08642 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 08643 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08644 p->subs[SUB_REAL].needunhold = 1; 08645 dahdi_enable_ec(p); 08646 } 08647 } 08648 } 08649 winkflashdone: 08650 update_conf(p); 08651 break; 08652 case SIG_EM: 08653 case SIG_EM_E1: 08654 case SIG_FEATD: 08655 case SIG_SF: 08656 case SIG_SFWINK: 08657 case SIG_SF_FEATD: 08658 case SIG_FXSLS: 08659 case SIG_FXSGS: 08660 if (p->dialing) 08661 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 08662 else 08663 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel); 08664 break; 08665 case SIG_FEATDMF_TA: 08666 switch (p->whichwink) { 08667 case 0: 08668 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2, 08669 S_COR(p->owner->caller.ani.number.valid, 08670 p->owner->caller.ani.number.str, "")); 08671 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", 08672 p->owner->caller.ani2, 08673 S_COR(p->owner->caller.ani.number.valid, 08674 p->owner->caller.ani.number.str, "")); 08675 break; 08676 case 1: 08677 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 08678 break; 08679 case 2: 08680 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 08681 return NULL; 08682 } 08683 p->whichwink++; 08684 /* Fall through */ 08685 case SIG_FEATDMF: 08686 case SIG_E911: 08687 case SIG_FGC_CAMAMF: 08688 case SIG_FGC_CAMA: 08689 case SIG_FEATB: 08690 case SIG_SF_FEATDMF: 08691 case SIG_SF_FEATB: 08692 case SIG_EMWINK: 08693 /* FGD MF and EMWINK *Must* wait for wink */ 08694 if (!ast_strlen_zero(p->dop.dialstr)) { 08695 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08696 if (res < 0) { 08697 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08698 p->dop.dialstr[0] = '\0'; 08699 return NULL; 08700 } else 08701 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08702 } 08703 p->dop.dialstr[0] = '\0'; 08704 break; 08705 default: 08706 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08707 } 08708 break; 08709 case DAHDI_EVENT_HOOKCOMPLETE: 08710 if (p->inalarm) break; 08711 if ((p->radio || (p->oprmode < 0))) break; 08712 if (p->waitingfordt.tv_sec) break; 08713 switch (mysig) { 08714 case SIG_FXSLS: /* only interesting for FXS */ 08715 case SIG_FXSGS: 08716 case SIG_FXSKS: 08717 case SIG_EM: 08718 case SIG_EM_E1: 08719 case SIG_EMWINK: 08720 case SIG_FEATD: 08721 case SIG_SF: 08722 case SIG_SFWINK: 08723 case SIG_SF_FEATD: 08724 if (!ast_strlen_zero(p->dop.dialstr)) { 08725 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08726 if (res < 0) { 08727 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08728 p->dop.dialstr[0] = '\0'; 08729 return NULL; 08730 } else 08731 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08732 } 08733 p->dop.dialstr[0] = '\0'; 08734 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08735 break; 08736 case SIG_FEATDMF: 08737 case SIG_FEATDMF_TA: 08738 case SIG_E911: 08739 case SIG_FGC_CAMA: 08740 case SIG_FGC_CAMAMF: 08741 case SIG_FEATB: 08742 case SIG_SF_FEATDMF: 08743 case SIG_SF_FEATB: 08744 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 08745 break; 08746 default: 08747 break; 08748 } 08749 break; 08750 case DAHDI_EVENT_POLARITY: 08751 /* 08752 * If we get a Polarity Switch event, check to see 08753 * if we should change the polarity state and 08754 * mark the channel as UP or if this is an indication 08755 * of remote end disconnect. 08756 */ 08757 if (p->polarity == POLARITY_IDLE) { 08758 p->polarity = POLARITY_REV; 08759 if (p->answeronpolarityswitch && 08760 ((ast->_state == AST_STATE_DIALING) || 08761 (ast->_state == AST_STATE_RINGING))) { 08762 ast_debug(1, "Answering on polarity switch!\n"); 08763 ast_setstate(p->owner, AST_STATE_UP); 08764 if (p->hanguponpolarityswitch) { 08765 p->polaritydelaytv = ast_tvnow(); 08766 } 08767 } else 08768 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state); 08769 } 08770 /* Removed else statement from here as it was preventing hangups from ever happening*/ 08771 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 08772 if (p->hanguponpolarityswitch && 08773 (p->polarityonanswerdelay > 0) && 08774 (p->polarity == POLARITY_REV) && 08775 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 08776 /* Added log_debug information below to provide a better indication of what is going on */ 08777 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 08778 08779 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 08780 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 08781 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 08782 p->polarity = POLARITY_IDLE; 08783 } else 08784 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast->_state); 08785 08786 } else { 08787 p->polarity = POLARITY_IDLE; 08788 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state); 08789 } 08790 /* Added more log_debug information below to provide a better indication of what is going on */ 08791 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 08792 break; 08793 default: 08794 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 08795 } 08796 return &p->subs[idx].f; 08797 }
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6171 of file chan_dahdi.c.
References ast_channel::_state, analog_hangup(), analog_lib_handles(), ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_free, ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verb, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cid_tag, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, analog_pvt::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), revert_fax_buffers(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, sig_pri_hangup(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_hangup(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and dahdi_pvt::waitingfordt.
06172 { 06173 int res = 0; 06174 int idx,x; 06175 int law; 06176 /*static int restore_gains(struct dahdi_pvt *p);*/ 06177 struct dahdi_pvt *p = ast->tech_pvt; 06178 struct dahdi_params par; 06179 06180 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 06181 if (!ast->tech_pvt) { 06182 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 06183 return 0; 06184 } 06185 06186 ast_mutex_lock(&p->lock); 06187 p->exten[0] = '\0'; 06188 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06189 dahdi_confmute(p, 0); 06190 restore_gains(p); 06191 p->ignoredtmf = 0; 06192 p->waitingfordt.tv_sec = 0; 06193 06194 res = analog_hangup(p->sig_pvt, ast); 06195 revert_fax_buffers(p, ast); 06196 06197 goto hangup_out; 06198 } else { 06199 p->cid_num[0] = '\0'; 06200 p->cid_name[0] = '\0'; 06201 p->cid_subaddr[0] = '\0'; 06202 } 06203 06204 #if defined(HAVE_PRI) 06205 if (dahdi_sig_pri_lib_handles(p->sig)) { 06206 x = 1; 06207 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06208 06209 dahdi_confmute(p, 0); 06210 p->muting = 0; 06211 restore_gains(p); 06212 if (p->dsp) { 06213 ast_dsp_free(p->dsp); 06214 p->dsp = NULL; 06215 } 06216 p->ignoredtmf = 0; 06217 06218 /* Real channel, do some fixup */ 06219 p->subs[SUB_REAL].owner = NULL; 06220 p->subs[SUB_REAL].needbusy = 0; 06221 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06222 06223 p->owner = NULL; 06224 p->cid_tag[0] = '\0'; 06225 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06226 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06227 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06228 p->outgoing = 0; 06229 p->digital = 0; 06230 p->faxhandled = 0; 06231 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06232 06233 revert_fax_buffers(p, ast); 06234 06235 p->law = p->law_default; 06236 law = p->law_default; 06237 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06238 if (res < 0) { 06239 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06240 p->channel, strerror(errno)); 06241 } 06242 06243 sig_pri_hangup(p->sig_pvt, ast); 06244 06245 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06246 dahdi_disable_ec(p); 06247 06248 x = 0; 06249 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06250 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06251 06252 p->rdnis[0] = '\0'; 06253 update_conf(p); 06254 reset_conf(p); 06255 06256 /* Restore data mode */ 06257 x = 0; 06258 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06259 06260 if (num_restart_pending == 0) { 06261 restart_monitor(); 06262 } 06263 goto hangup_out; 06264 } 06265 #endif /* defined(HAVE_PRI) */ 06266 06267 #if defined(HAVE_SS7) 06268 if (p->sig == SIG_SS7) { 06269 x = 1; 06270 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06271 06272 dahdi_confmute(p, 0); 06273 p->muting = 0; 06274 restore_gains(p); 06275 if (p->dsp) { 06276 ast_dsp_free(p->dsp); 06277 p->dsp = NULL; 06278 } 06279 p->ignoredtmf = 0; 06280 06281 /* Real channel, do some fixup */ 06282 p->subs[SUB_REAL].owner = NULL; 06283 p->subs[SUB_REAL].needbusy = 0; 06284 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06285 06286 p->owner = NULL; 06287 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06288 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06289 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06290 p->outgoing = 0; 06291 p->digital = 0; 06292 p->faxhandled = 0; 06293 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06294 06295 revert_fax_buffers(p, ast); 06296 06297 p->law = p->law_default; 06298 law = p->law_default; 06299 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06300 if (res < 0) { 06301 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06302 p->channel, strerror(errno)); 06303 } 06304 06305 sig_ss7_hangup(p->sig_pvt, ast); 06306 06307 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06308 dahdi_disable_ec(p); 06309 06310 x = 0; 06311 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06312 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06313 06314 update_conf(p); 06315 reset_conf(p); 06316 06317 /* Restore data mode */ 06318 x = 0; 06319 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06320 06321 if (num_restart_pending == 0) { 06322 restart_monitor(); 06323 } 06324 goto hangup_out; 06325 } 06326 #endif /* defined(HAVE_SS7) */ 06327 06328 idx = dahdi_get_index(ast, p, 1); 06329 06330 dahdi_confmute(p, 0); 06331 p->muting = 0; 06332 restore_gains(p); 06333 if (p->origcid_num) { 06334 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 06335 ast_free(p->origcid_num); 06336 p->origcid_num = NULL; 06337 } 06338 if (p->origcid_name) { 06339 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 06340 ast_free(p->origcid_name); 06341 p->origcid_name = NULL; 06342 } 06343 if (p->dsp) 06344 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06345 06346 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 06347 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06348 p->ignoredtmf = 0; 06349 06350 if (idx > -1) { 06351 /* Real channel, do some fixup */ 06352 p->subs[idx].owner = NULL; 06353 p->subs[idx].needanswer = 0; 06354 p->subs[idx].needflash = 0; 06355 p->subs[idx].needringing = 0; 06356 p->subs[idx].needbusy = 0; 06357 p->subs[idx].needcongestion = 0; 06358 p->subs[idx].linear = 0; 06359 p->polarity = POLARITY_IDLE; 06360 dahdi_setlinear(p->subs[idx].dfd, 0); 06361 if (idx == SUB_REAL) { 06362 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 06363 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 06364 if (p->subs[SUB_CALLWAIT].inthreeway) { 06365 /* We had flipped over to answer a callwait and now it's gone */ 06366 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 06367 /* Move to the call-wait, but un-own us until they flip back. */ 06368 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06369 unalloc_sub(p, SUB_CALLWAIT); 06370 p->owner = NULL; 06371 } else { 06372 /* The three way hung up, but we still have a call wait */ 06373 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 06374 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06375 unalloc_sub(p, SUB_THREEWAY); 06376 if (p->subs[SUB_REAL].inthreeway) { 06377 /* This was part of a three way call. Immediately make way for 06378 another call */ 06379 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06380 p->owner = p->subs[SUB_REAL].owner; 06381 } else { 06382 /* This call hasn't been completed yet... Set owner to NULL */ 06383 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06384 p->owner = NULL; 06385 } 06386 p->subs[SUB_REAL].inthreeway = 0; 06387 } 06388 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 06389 /* Move to the call-wait and switch back to them. */ 06390 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06391 unalloc_sub(p, SUB_CALLWAIT); 06392 p->owner = p->subs[SUB_REAL].owner; 06393 if (p->owner->_state != AST_STATE_UP) 06394 p->subs[SUB_REAL].needanswer = 1; 06395 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06396 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06397 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 06398 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06399 unalloc_sub(p, SUB_THREEWAY); 06400 if (p->subs[SUB_REAL].inthreeway) { 06401 /* This was part of a three way call. Immediately make way for 06402 another call */ 06403 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06404 p->owner = p->subs[SUB_REAL].owner; 06405 } else { 06406 /* This call hasn't been completed yet... Set owner to NULL */ 06407 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06408 p->owner = NULL; 06409 } 06410 p->subs[SUB_REAL].inthreeway = 0; 06411 } 06412 } else if (idx == SUB_CALLWAIT) { 06413 /* Ditch the holding callwait call, and immediately make it availabe */ 06414 if (p->subs[SUB_CALLWAIT].inthreeway) { 06415 /* This is actually part of a three way, placed on hold. Place the third part 06416 on music on hold now */ 06417 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06418 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06419 S_OR(p->mohsuggest, NULL), 06420 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06421 } 06422 p->subs[SUB_THREEWAY].inthreeway = 0; 06423 /* Make it the call wait now */ 06424 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06425 unalloc_sub(p, SUB_THREEWAY); 06426 } else 06427 unalloc_sub(p, SUB_CALLWAIT); 06428 } else if (idx == SUB_THREEWAY) { 06429 if (p->subs[SUB_CALLWAIT].inthreeway) { 06430 /* The other party of the three way call is currently in a call-wait state. 06431 Start music on hold for them, and take the main guy out of the third call */ 06432 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06433 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06434 S_OR(p->mohsuggest, NULL), 06435 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06436 } 06437 p->subs[SUB_CALLWAIT].inthreeway = 0; 06438 } 06439 p->subs[SUB_REAL].inthreeway = 0; 06440 /* If this was part of a three way call index, let us make 06441 another three way call */ 06442 unalloc_sub(p, SUB_THREEWAY); 06443 } else { 06444 /* This wasn't any sort of call, but how are we an index? */ 06445 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 06446 } 06447 } 06448 06449 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 06450 p->owner = NULL; 06451 p->ringt = 0; 06452 p->distinctivering = 0; 06453 p->confirmanswer = 0; 06454 p->outgoing = 0; 06455 p->digital = 0; 06456 p->faxhandled = 0; 06457 p->pulsedial = 0; 06458 if (p->dsp) { 06459 ast_dsp_free(p->dsp); 06460 p->dsp = NULL; 06461 } 06462 06463 revert_fax_buffers(p, ast); 06464 06465 p->law = p->law_default; 06466 law = p->law_default; 06467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06468 if (res < 0) 06469 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06470 /* Perform low level hangup if no owner left */ 06471 #ifdef HAVE_OPENR2 06472 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 06473 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 06474 /* If it's an incoming call, check the mfcr2_forced_release setting */ 06475 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 06476 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 06477 } else { 06478 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 06479 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 06480 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 06481 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 06482 dahdi_r2_disconnect_call(p, r2cause); 06483 } 06484 } else if (p->mfcr2call) { 06485 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 06486 /* since ast_request() was called but not ast_call() we have not yet dialed 06487 and the openr2 stack will not call on_call_end callback, we need to unset 06488 the mfcr2call flag and bump the monitor count so the monitor thread can take 06489 care of this channel events from now on */ 06490 p->mfcr2call = 0; 06491 } 06492 #endif 06493 switch (p->sig) { 06494 case SIG_SS7: 06495 case SIG_MFCR2: 06496 case SIG_PRI_LIB_HANDLE_CASES: 06497 case 0: 06498 break; 06499 default: 06500 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06501 break; 06502 } 06503 if (res < 0) { 06504 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 06505 } 06506 switch (p->sig) { 06507 case SIG_FXOGS: 06508 case SIG_FXOLS: 06509 case SIG_FXOKS: 06510 memset(&par, 0, sizeof(par)); 06511 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 06512 if (!res) { 06513 struct analog_pvt *analog_p = p->sig_pvt; 06514 #if 0 06515 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 06516 #endif 06517 /* If they're off hook, try playing congestion */ 06518 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 06519 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06520 else 06521 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06522 analog_p->fxsoffhookstate = par.rxisoffhook; 06523 } 06524 break; 06525 case SIG_FXSGS: 06526 case SIG_FXSLS: 06527 case SIG_FXSKS: 06528 /* Make sure we're not made available for at least two seconds assuming 06529 we were actually used for an inbound or outbound call. */ 06530 if (ast->_state != AST_STATE_RESERVED) { 06531 time(&p->guardtime); 06532 p->guardtime += 2; 06533 } 06534 break; 06535 default: 06536 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06537 break; 06538 } 06539 if (p->sig) 06540 dahdi_disable_ec(p); 06541 x = 0; 06542 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06543 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06544 p->didtdd = 0; 06545 p->callwaitcas = 0; 06546 p->callwaiting = p->permcallwaiting; 06547 p->hidecallerid = p->permhidecallerid; 06548 p->waitingfordt.tv_sec = 0; 06549 p->dialing = 0; 06550 p->rdnis[0] = '\0'; 06551 update_conf(p); 06552 reset_conf(p); 06553 /* Restore data mode */ 06554 switch (p->sig) { 06555 case SIG_PRI_LIB_HANDLE_CASES: 06556 case SIG_SS7: 06557 x = 0; 06558 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06559 break; 06560 default: 06561 break; 06562 } 06563 if (num_restart_pending == 0) 06564 restart_monitor(); 06565 } 06566 06567 p->callwaitingrepeat = 0; 06568 p->cidcwexpire = 0; 06569 p->cid_suppress_expire = 0; 06570 p->oprmode = 0; 06571 hangup_out: 06572 ast->tech_pvt = NULL; 06573 ast_free(p->cidspill); 06574 p->cidspill = NULL; 06575 06576 ast_mutex_unlock(&p->lock); 06577 ast_verb(3, "Hungup '%s'\n", ast->name); 06578 06579 ast_mutex_lock(&iflock); 06580 if (p->restartpending) { 06581 num_restart_pending--; 06582 } 06583 06584 if (p->destroy) { 06585 destroy_channel(p, 0); 06586 } 06587 ast_mutex_unlock(&iflock); 06588 06589 ast_module_unref(ast_module_info->self); 06590 return 0; 06591 }
| static void dahdi_iflist_extract | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5564 of file chan_dahdi.c.
References DAHDI_IFLIST_NONE, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.
Referenced by destroy_dahdi_pvt().
05565 { 05566 /* Extract from the forward chain. */ 05567 if (pvt->prev) { 05568 pvt->prev->next = pvt->next; 05569 } else if (iflist == pvt) { 05570 /* Node is at the head of the list. */ 05571 iflist = pvt->next; 05572 } 05573 05574 /* Extract from the reverse chain. */ 05575 if (pvt->next) { 05576 pvt->next->prev = pvt->prev; 05577 } else if (ifend == pvt) { 05578 /* Node is at the end of the list. */ 05579 ifend = pvt->prev; 05580 } 05581 05582 /* Node is no longer in the list. */ 05583 pvt->which_iflist = DAHDI_IFLIST_NONE; 05584 pvt->prev = NULL; 05585 pvt->next = NULL; 05586 }
| static void dahdi_iflist_insert | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5514 of file chan_dahdi.c.
References dahdi_pvt::channel, DAHDI_IFLIST_MAIN, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.
Referenced by duplicate_pseudo(), and mkintf().
05515 { 05516 struct dahdi_pvt *cur; 05517 05518 pvt->which_iflist = DAHDI_IFLIST_MAIN; 05519 05520 /* Find place in middle of list for the new interface. */ 05521 for (cur = iflist; cur; cur = cur->next) { 05522 if (pvt->channel < cur->channel) { 05523 /* New interface goes before the current interface. */ 05524 pvt->prev = cur->prev; 05525 pvt->next = cur; 05526 if (cur->prev) { 05527 /* Insert into the middle of the list. */ 05528 cur->prev->next = pvt; 05529 } else { 05530 /* Insert at head of list. */ 05531 iflist = pvt; 05532 } 05533 cur->prev = pvt; 05534 return; 05535 } 05536 } 05537 05538 /* New interface goes onto the end of the list */ 05539 pvt->prev = ifend; 05540 pvt->next = NULL; 05541 if (ifend) { 05542 ifend->next = pvt; 05543 } 05544 ifend = pvt; 05545 if (!iflist) { 05546 /* List was empty */ 05547 iflist = pvt; 05548 } 05549 }
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 9459 of file chan_dahdi.c.
References ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohinterpret, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, sig_pri_indicate(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_indicate(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
Referenced by dahdi_fixup().
09460 { 09461 struct dahdi_pvt *p = chan->tech_pvt; 09462 int res=-1; 09463 int idx; 09464 int func = DAHDI_FLASH; 09465 09466 ast_mutex_lock(&p->lock); 09467 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 09468 switch (p->sig) { 09469 #if defined(HAVE_PRI) 09470 case SIG_PRI_LIB_HANDLE_CASES: 09471 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen); 09472 ast_mutex_unlock(&p->lock); 09473 return res; 09474 #endif /* defined(HAVE_PRI) */ 09475 #if defined(HAVE_SS7) 09476 case SIG_SS7: 09477 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen); 09478 ast_mutex_unlock(&p->lock); 09479 return res; 09480 #endif /* defined(HAVE_SS7) */ 09481 default: 09482 break; 09483 } 09484 #ifdef HAVE_OPENR2 09485 if (p->mfcr2 && !p->mfcr2_call_accepted) { 09486 ast_mutex_unlock(&p->lock); 09487 /* if this is an R2 call and the call is not yet accepted, we don't want the 09488 tone indications to mess up with the MF tones */ 09489 return 0; 09490 } 09491 #endif 09492 idx = dahdi_get_index(chan, p, 0); 09493 if (idx == SUB_REAL) { 09494 switch (condition) { 09495 case AST_CONTROL_BUSY: 09496 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 09497 break; 09498 case AST_CONTROL_RINGING: 09499 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 09500 09501 if (chan->_state != AST_STATE_UP) { 09502 if ((chan->_state != AST_STATE_RING) || 09503 ((p->sig != SIG_FXSKS) && 09504 (p->sig != SIG_FXSLS) && 09505 (p->sig != SIG_FXSGS))) 09506 ast_setstate(chan, AST_STATE_RINGING); 09507 } 09508 break; 09509 case AST_CONTROL_INCOMPLETE: 09510 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name); 09511 /* act as a progress or proceeding, allowing the caller to enter additional numbers */ 09512 res = 0; 09513 break; 09514 case AST_CONTROL_PROCEEDING: 09515 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name); 09516 /* don't continue in ast_indicate */ 09517 res = 0; 09518 break; 09519 case AST_CONTROL_PROGRESS: 09520 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name); 09521 /* don't continue in ast_indicate */ 09522 res = 0; 09523 break; 09524 case AST_CONTROL_CONGESTION: 09525 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 09526 switch (chan->hangupcause) { 09527 case AST_CAUSE_USER_BUSY: 09528 case AST_CAUSE_NORMAL_CLEARING: 09529 case 0:/* Cause has not been set. */ 09530 /* Supply a more appropriate cause. */ 09531 chan->hangupcause = AST_CAUSE_CONGESTION; 09532 break; 09533 default: 09534 break; 09535 } 09536 break; 09537 case AST_CONTROL_HOLD: 09538 ast_moh_start(chan, data, p->mohinterpret); 09539 break; 09540 case AST_CONTROL_UNHOLD: 09541 ast_moh_stop(chan); 09542 break; 09543 case AST_CONTROL_RADIO_KEY: 09544 if (p->radio) 09545 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 09546 res = 0; 09547 break; 09548 case AST_CONTROL_RADIO_UNKEY: 09549 if (p->radio) 09550 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 09551 res = 0; 09552 break; 09553 case AST_CONTROL_FLASH: 09554 /* flash hookswitch */ 09555 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 09556 /* Clear out the dial buffer */ 09557 p->dop.dialstr[0] = '\0'; 09558 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09559 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09560 chan->name, strerror(errno)); 09561 } else 09562 res = 0; 09563 } else 09564 res = 0; 09565 break; 09566 case AST_CONTROL_SRCUPDATE: 09567 res = 0; 09568 break; 09569 case -1: 09570 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09571 break; 09572 } 09573 } else { 09574 res = 0; 09575 } 09576 ast_mutex_unlock(&p->lock); 09577 return res; 09578 }
Definition at line 7217 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_pvt::master, MAX_SLAVES, and dahdi_pvt::slaves.
Referenced by dahdi_bridge().
07217 { 07218 int x; 07219 if (!slave || !master) { 07220 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 07221 return; 07222 } 07223 for (x = 0; x < MAX_SLAVES; x++) { 07224 if (!master->slaves[x]) { 07225 master->slaves[x] = slave; 07226 break; 07227 } 07228 } 07229 if (x >= MAX_SLAVES) { 07230 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 07231 master->slaves[MAX_SLAVES - 1] = slave; 07232 } 07233 if (slave->master) 07234 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 07235 slave->master = master; 07236 07237 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 07238 }
| static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
| int | sub_idx | |||
| ) | [static] |
Definition at line 3812 of file chan_dahdi.c.
References ast_channel_trylock, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by wakeup_sub().
03813 { 03814 for (;;) { 03815 if (!pvt->subs[sub_idx].owner) { 03816 /* No subchannel owner pointer */ 03817 break; 03818 } 03819 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) { 03820 /* Got subchannel owner lock */ 03821 break; 03822 } 03823 /* We must unlock the private to avoid the possibility of a deadlock */ 03824 DEADLOCK_AVOIDANCE(&pvt->lock); 03825 } 03826 }
| static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
| int | state, | |||
| int | startpbx, | |||
| int | idx, | |||
| int | law, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Definition at line 9628 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, dahdi_pvt::amaflags, analog_lib_handles(), ast_party_caller::ani, ast_party_caller::ani2, AST_ADSI_UNAVAILABLE, ast_cc_copy_config_params(), ast_channel_alloc, ast_channel_cc_params_init(), AST_CHANNEL_NAME, ast_channel_set_fd(), ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FLAG_DISABLE_DEVSTATE_CACHE, AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_free, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_RING, ast_str_buffer(), ast_strdup, ast_string_field_set, ast_strlen_zero(), dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call_forward, ast_channel::caller, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_channel::context, dahdi_pvt::context, create_channel_name(), dahdi_ami_channel_event(), dahdi_confmute(), dahdi_setlinear(), dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, ast_channel::dialed, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::flags, ast_party_redirecting::from, global_jbconf, dahdi_pvt::hardwaredtmf, ast_party_caller::id, language, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::muting, ast_variable::name, ast_party_id::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, ast_party_dialed::number, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, parkinglot, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, dahdi_pvt::radio, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::redirecting, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_PRI_LIB_HANDLE_CASES, SIG_SS7, ast_party_dialed::str, ast_party_number::str, SUB_REAL, dahdi_pvt::subs, ast_party_id::tag, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), do_monitor(), handle_init_event(), mwi_thread(), and my_new_analog_ast_channel().
09629 { 09630 struct ast_channel *tmp; 09631 format_t deflaw; 09632 int x; 09633 int features; 09634 struct ast_str *chan_name; 09635 struct ast_variable *v; 09636 char *dashptr; 09637 char device_name[AST_CHANNEL_NAME]; 09638 09639 if (i->subs[idx].owner) { 09640 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 09641 return NULL; 09642 } 09643 09644 #if defined(HAVE_PRI) 09645 /* 09646 * The dnid has been stuffed with the called-number[:subaddress] 09647 * by dahdi_request() for outgoing calls. 09648 */ 09649 chan_name = create_channel_name(i, i->outgoing, i->dnid); 09650 #else 09651 chan_name = create_channel_name(i); 09652 #endif /* defined(HAVE_PRI) */ 09653 if (!chan_name) { 09654 return NULL; 09655 } 09656 09657 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name)); 09658 ast_free(chan_name); 09659 if (!tmp) 09660 return NULL; 09661 tmp->tech = &dahdi_tech; 09662 #if defined(HAVE_PRI) 09663 if (i->pri) { 09664 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params); 09665 } 09666 #endif /* defined(HAVE_PRI) */ 09667 ast_channel_cc_params_init(tmp, i->cc_params); 09668 if (law) { 09669 i->law = law; 09670 if (law == DAHDI_LAW_ALAW) { 09671 deflaw = AST_FORMAT_ALAW; 09672 } else { 09673 deflaw = AST_FORMAT_ULAW; 09674 } 09675 } else { 09676 switch (i->sig) { 09677 case SIG_PRI_LIB_HANDLE_CASES: 09678 /* Make sure companding law is known. */ 09679 i->law = (i->law_default == DAHDI_LAW_ALAW) 09680 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW; 09681 break; 09682 default: 09683 i->law = i->law_default; 09684 break; 09685 } 09686 if (i->law_default == DAHDI_LAW_ALAW) { 09687 deflaw = AST_FORMAT_ALAW; 09688 } else { 09689 deflaw = AST_FORMAT_ULAW; 09690 } 09691 } 09692 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 09693 tmp->nativeformats = deflaw; 09694 /* Start out assuming ulaw since it's smaller :) */ 09695 tmp->rawreadformat = deflaw; 09696 tmp->readformat = deflaw; 09697 tmp->rawwriteformat = deflaw; 09698 tmp->writeformat = deflaw; 09699 i->subs[idx].linear = 0; 09700 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 09701 features = 0; 09702 if (idx == SUB_REAL) { 09703 if (i->busydetect && CANBUSYDETECT(i)) 09704 features |= DSP_FEATURE_BUSY_DETECT; 09705 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 09706 features |= DSP_FEATURE_CALL_PROGRESS; 09707 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 09708 features |= DSP_FEATURE_WAITDIALTONE; 09709 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 09710 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 09711 features |= DSP_FEATURE_FAX_DETECT; 09712 } 09713 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 09714 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 09715 i->hardwaredtmf = 0; 09716 features |= DSP_FEATURE_DIGIT_DETECT; 09717 } else if (NEED_MFDETECT(i)) { 09718 i->hardwaredtmf = 1; 09719 features |= DSP_FEATURE_DIGIT_DETECT; 09720 } 09721 } 09722 if (features) { 09723 if (i->dsp) { 09724 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 09725 } else { 09726 if (i->channel != CHAN_PSEUDO) 09727 i->dsp = ast_dsp_new(); 09728 else 09729 i->dsp = NULL; 09730 if (i->dsp) { 09731 i->dsp_features = features; 09732 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09733 /* We cannot do progress detection until receive PROGRESS message */ 09734 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) { 09735 /* Remember requested DSP features, don't treat 09736 talking as ANSWER */ 09737 i->dsp_features = features & ~DSP_PROGRESS_TALK; 09738 features = 0; 09739 } 09740 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09741 ast_dsp_set_features(i->dsp, features); 09742 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 09743 if (!ast_strlen_zero(progzone)) 09744 ast_dsp_set_call_progress_zone(i->dsp, progzone); 09745 if (i->busydetect && CANBUSYDETECT(i)) { 09746 ast_dsp_set_busy_count(i->dsp, i->busycount); 09747 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength); 09748 } 09749 } 09750 } 09751 } 09752 09753 if (state == AST_STATE_RING) 09754 tmp->rings = 1; 09755 tmp->tech_pvt = i; 09756 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 09757 /* Only FXO signalled stuff can be picked up */ 09758 tmp->callgroup = i->callgroup; 09759 tmp->pickupgroup = i->pickupgroup; 09760 } 09761 if (!ast_strlen_zero(i->parkinglot)) 09762 ast_string_field_set(tmp, parkinglot, i->parkinglot); 09763 if (!ast_strlen_zero(i->language)) 09764 ast_string_field_set(tmp, language, i->language); 09765 if (!i->owner) 09766 i->owner = tmp; 09767 if (!ast_strlen_zero(i->accountcode)) 09768 ast_string_field_set(tmp, accountcode, i->accountcode); 09769 if (i->amaflags) 09770 tmp->amaflags = i->amaflags; 09771 i->subs[idx].owner = tmp; 09772 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 09773 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) { 09774 ast_string_field_set(tmp, call_forward, i->call_forward); 09775 } 09776 /* If we've been told "no ADSI" then enforce it */ 09777 if (!i->adsi) 09778 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 09779 if (!ast_strlen_zero(i->exten)) 09780 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 09781 if (!ast_strlen_zero(i->rdnis)) { 09782 tmp->redirecting.from.number.valid = 1; 09783 tmp->redirecting.from.number.str = ast_strdup(i->rdnis); 09784 } 09785 if (!ast_strlen_zero(i->dnid)) { 09786 tmp->dialed.number.str = ast_strdup(i->dnid); 09787 } 09788 09789 /* Don't use ast_set_callerid() here because it will 09790 * generate a needless NewCallerID event */ 09791 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09792 if (!ast_strlen_zero(i->cid_ani)) { 09793 tmp->caller.ani.number.valid = 1; 09794 tmp->caller.ani.number.str = ast_strdup(i->cid_ani); 09795 } else if (!ast_strlen_zero(i->cid_num)) { 09796 tmp->caller.ani.number.valid = 1; 09797 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09798 } 09799 #else 09800 if (!ast_strlen_zero(i->cid_num)) { 09801 tmp->caller.ani.number.valid = 1; 09802 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09803 } 09804 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09805 tmp->caller.id.name.presentation = i->callingpres; 09806 tmp->caller.id.number.presentation = i->callingpres; 09807 tmp->caller.id.number.plan = i->cid_ton; 09808 tmp->caller.ani2 = i->cid_ani2; 09809 tmp->caller.id.tag = ast_strdup(i->cid_tag); 09810 /* clear the fake event in case we posted one before we had ast_channel */ 09811 i->fake_event = 0; 09812 /* Assure there is no confmute on this channel */ 09813 dahdi_confmute(i, 0); 09814 i->muting = 0; 09815 /* Configure the new channel jb */ 09816 ast_jb_configure(tmp, &global_jbconf); 09817 09818 /* Set initial device state */ 09819 ast_copy_string(device_name, tmp->name, sizeof(device_name)); 09820 dashptr = strrchr(device_name, '-'); 09821 if (dashptr) { 09822 *dashptr = '\0'; 09823 } 09824 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; 09825 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name); 09826 09827 for (v = i->vars ; v ; v = v->next) 09828 pbx_builtin_setvar_helper(tmp, v->name, v->value); 09829 09830 ast_module_ref(ast_module_info->self); 09831 09832 dahdi_ami_channel_event(i, tmp); 09833 if (startpbx) { 09834 #ifdef HAVE_OPENR2 09835 if (i->mfcr2call) { 09836 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 09837 } 09838 #endif 09839 if (ast_pbx_start(tmp)) { 09840 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 09841 ast_hangup(tmp); 09842 return NULL; 09843 } 09844 } 09845 return tmp; 09846 }
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 4349 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), duplicate_pseudo(), and mkintf().
04350 { 04351 int fd; 04352 int isnum; 04353 int chan = 0; 04354 int bs; 04355 int x; 04356 isnum = 1; 04357 for (x = 0; x < strlen(fn); x++) { 04358 if (!isdigit(fn[x])) { 04359 isnum = 0; 04360 break; 04361 } 04362 } 04363 if (isnum) { 04364 chan = atoi(fn); 04365 if (chan < 1) { 04366 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 04367 return -1; 04368 } 04369 fn = "/dev/dahdi/channel"; 04370 } 04371 fd = open(fn, O_RDWR | O_NONBLOCK); 04372 if (fd < 0) { 04373 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 04374 return -1; 04375 } 04376 if (chan) { 04377 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 04378 x = errno; 04379 close(fd); 04380 errno = x; 04381 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 04382 return -1; 04383 } 04384 } 04385 bs = READ_SIZE; 04386 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 04387 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 04388 x = errno; 04389 close(fd); 04390 errno = x; 04391 return -1; 04392 } 04393 return fd; 04394 }
| static int dahdi_queryoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int * | datalen | |||
| ) | [static] |
Definition at line 6688 of file chan_dahdi.c.
References ast_copy_string(), ast_debug, AST_OPTION_CC_AGENT_TYPE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, dahdi_pvt::sig, and ast_channel::tech_pvt.
06689 { 06690 char *cp; 06691 struct dahdi_pvt *p = chan->tech_pvt; 06692 06693 /* all supported options require data */ 06694 if (!p || !data || (*datalen < 1)) { 06695 errno = EINVAL; 06696 return -1; 06697 } 06698 06699 switch (option) { 06700 case AST_OPTION_DIGIT_DETECT: 06701 cp = (char *) data; 06702 *cp = p->ignoredtmf ? 0 : 1; 06703 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06704 break; 06705 case AST_OPTION_FAX_DETECT: 06706 cp = (char *) data; 06707 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1; 06708 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06709 break; 06710 case AST_OPTION_CC_AGENT_TYPE: 06711 #if defined(HAVE_PRI) 06712 #if defined(HAVE_PRI_CCSS) 06713 if (dahdi_sig_pri_lib_handles(p->sig)) { 06714 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen); 06715 break; 06716 } 06717 #endif /* defined(HAVE_PRI_CCSS) */ 06718 #endif /* defined(HAVE_PRI) */ 06719 return -1; 06720 default: 06721 return -1; 06722 } 06723 06724 errno = 0; 06725 06726 return 0; 06727 }
Definition at line 3837 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, and dahdi_pvt::owner.
Referenced by action_dahdidialoffhook().
03838 { 03839 for (;;) { 03840 if (p->owner) { 03841 if (ast_channel_trylock(p->owner)) { 03842 DEADLOCK_AVOIDANCE(&p->lock); 03843 } else { 03844 ast_queue_frame(p->owner, f); 03845 ast_channel_unlock(p->owner); 03846 break; 03847 } 03848 } else 03849 break; 03850 } 03851 }
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8936 of file chan_dahdi.c.
References __dahdi_exception(), ast_channel::_state, analog_exception(), analog_handle_dtmf(), analog_lib_handles(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_dsp_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), ast_dsp_was_muted(), AST_FLAG_BLOCKING, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_callwait(), dahdi_confmute(), dahdi_get_index, dahdi_handle_dtmf(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), dahdi_sig_pri_lib_handles(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::dsp, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, mute, dahdi_pvt::muting, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), dahdi_pvt::ringt, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI_CALL_LEVEL_PROCEEDING, dahdi_pvt::sig_pvt, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.
08937 { 08938 struct dahdi_pvt *p; 08939 int res; 08940 int idx; 08941 void *readbuf; 08942 struct ast_frame *f; 08943 08944 /* 08945 * For analog channels, we must do deadlock avoidance because 08946 * analog ports can have more than one Asterisk channel using 08947 * the same private structure. 08948 */ 08949 p = ast->tech_pvt; 08950 while (ast_mutex_trylock(&p->lock)) { 08951 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08952 08953 /* 08954 * Check to see if the channel is still associated with the same 08955 * private structure. While the Asterisk channel was unlocked 08956 * the following events may have occured: 08957 * 08958 * 1) A masquerade may have associated the channel with another 08959 * technology or private structure. 08960 * 08961 * 2) For PRI calls, call signaling could change the channel 08962 * association to another B channel (private structure). 08963 */ 08964 if (ast->tech_pvt != p) { 08965 /* The channel is no longer associated. Quit gracefully. */ 08966 return &ast_null_frame; 08967 } 08968 } 08969 08970 idx = dahdi_get_index(ast, p, 0); 08971 08972 /* Hang up if we don't really exist */ 08973 if (idx < 0) { 08974 ast_log(LOG_WARNING, "We don't exist?\n"); 08975 ast_mutex_unlock(&p->lock); 08976 return NULL; 08977 } 08978 08979 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 08980 ast_mutex_unlock(&p->lock); 08981 return NULL; 08982 } 08983 08984 p->subs[idx].f.frametype = AST_FRAME_NULL; 08985 p->subs[idx].f.datalen = 0; 08986 p->subs[idx].f.samples = 0; 08987 p->subs[idx].f.mallocd = 0; 08988 p->subs[idx].f.offset = 0; 08989 p->subs[idx].f.subclass.integer = 0; 08990 p->subs[idx].f.delivery = ast_tv(0,0); 08991 p->subs[idx].f.src = "dahdi_read"; 08992 p->subs[idx].f.data.ptr = NULL; 08993 08994 /* make sure it sends initial key state as first frame */ 08995 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 08996 { 08997 struct dahdi_params ps; 08998 08999 memset(&ps, 0, sizeof(ps)); 09000 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 09001 ast_mutex_unlock(&p->lock); 09002 return NULL; 09003 } 09004 p->firstradio = 1; 09005 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09006 if (ps.rxisoffhook) 09007 { 09008 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 09009 } 09010 else 09011 { 09012 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 09013 } 09014 ast_mutex_unlock(&p->lock); 09015 return &p->subs[idx].f; 09016 } 09017 if (p->ringt > 0) { 09018 if (!(--p->ringt)) { 09019 ast_mutex_unlock(&p->lock); 09020 return NULL; 09021 } 09022 } 09023 09024 #ifdef HAVE_OPENR2 09025 if (p->mfcr2) { 09026 openr2_chan_process_event(p->r2chan); 09027 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) { 09028 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, }; 09029 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING 09030 * now enqueue a progress frame to bridge the media up */ 09031 if (p->mfcr2_call_accepted && 09032 !p->mfcr2_progress && 09033 ast->_state == AST_STATE_RINGING) { 09034 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel); 09035 ast_queue_frame(p->owner, &f); 09036 p->mfcr2_progress = 1; 09037 } 09038 } 09039 } 09040 #endif 09041 09042 if (p->subs[idx].needringing) { 09043 /* Send ringing frame if requested */ 09044 p->subs[idx].needringing = 0; 09045 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09046 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING; 09047 ast_setstate(ast, AST_STATE_RINGING); 09048 ast_mutex_unlock(&p->lock); 09049 return &p->subs[idx].f; 09050 } 09051 09052 if (p->subs[idx].needbusy) { 09053 /* Send busy frame if requested */ 09054 p->subs[idx].needbusy = 0; 09055 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09056 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY; 09057 ast_mutex_unlock(&p->lock); 09058 return &p->subs[idx].f; 09059 } 09060 09061 if (p->subs[idx].needcongestion) { 09062 /* Send congestion frame if requested */ 09063 p->subs[idx].needcongestion = 0; 09064 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09065 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION; 09066 ast_mutex_unlock(&p->lock); 09067 return &p->subs[idx].f; 09068 } 09069 09070 if (p->subs[idx].needanswer) { 09071 /* Send answer frame if requested */ 09072 p->subs[idx].needanswer = 0; 09073 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09074 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 09075 ast_mutex_unlock(&p->lock); 09076 return &p->subs[idx].f; 09077 } 09078 #ifdef HAVE_OPENR2 09079 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 09080 /* openr2 took care of reading and handling any event 09081 (needanswer, needbusy etc), if we continue we will read() 09082 twice, lets just return a null frame. This should only 09083 happen when openr2 is dialing out */ 09084 ast_mutex_unlock(&p->lock); 09085 return &ast_null_frame; 09086 } 09087 #endif 09088 09089 if (p->subs[idx].needflash) { 09090 /* Send answer frame if requested */ 09091 p->subs[idx].needflash = 0; 09092 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09093 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH; 09094 ast_mutex_unlock(&p->lock); 09095 return &p->subs[idx].f; 09096 } 09097 09098 if (p->subs[idx].needhold) { 09099 /* Send answer frame if requested */ 09100 p->subs[idx].needhold = 0; 09101 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09102 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD; 09103 ast_mutex_unlock(&p->lock); 09104 ast_debug(1, "Sending hold on '%s'\n", ast->name); 09105 return &p->subs[idx].f; 09106 } 09107 09108 if (p->subs[idx].needunhold) { 09109 /* Send answer frame if requested */ 09110 p->subs[idx].needunhold = 0; 09111 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09112 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD; 09113 ast_mutex_unlock(&p->lock); 09114 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 09115 return &p->subs[idx].f; 09116 } 09117 09118 /* 09119 * If we have a fake_event, fake an exception to handle it only 09120 * if this channel owns the private. 09121 */ 09122 if (p->fake_event && p->owner == ast) { 09123 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09124 struct analog_pvt *analog_p = p->sig_pvt; 09125 09126 f = analog_exception(analog_p, ast); 09127 } else { 09128 f = __dahdi_exception(ast); 09129 } 09130 ast_mutex_unlock(&p->lock); 09131 return f; 09132 } 09133 09134 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 09135 if (!p->subs[idx].linear) { 09136 p->subs[idx].linear = 1; 09137 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09138 if (res) 09139 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 09140 } 09141 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 09142 (ast->rawreadformat == AST_FORMAT_ALAW)) { 09143 if (p->subs[idx].linear) { 09144 p->subs[idx].linear = 0; 09145 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09146 if (res) 09147 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 09148 } 09149 } else { 09150 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 09151 ast_mutex_unlock(&p->lock); 09152 return NULL; 09153 } 09154 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 09155 CHECK_BLOCKING(ast); 09156 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09157 ast_clear_flag(ast, AST_FLAG_BLOCKING); 09158 /* Check for hangup */ 09159 if (res < 0) { 09160 f = NULL; 09161 if (res == -1) { 09162 if (errno == EAGAIN) { 09163 /* Return "NULL" frame if there is nobody there */ 09164 ast_mutex_unlock(&p->lock); 09165 return &p->subs[idx].f; 09166 } else if (errno == ELAST) { 09167 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09168 struct analog_pvt *analog_p = p->sig_pvt; 09169 f = analog_exception(analog_p, ast); 09170 } else { 09171 f = __dahdi_exception(ast); 09172 } 09173 } else 09174 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 09175 } 09176 ast_mutex_unlock(&p->lock); 09177 return f; 09178 } 09179 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 09180 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09181 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09182 struct analog_pvt *analog_p = p->sig_pvt; 09183 f = analog_exception(analog_p, ast); 09184 } else { 09185 f = __dahdi_exception(ast); 09186 } 09187 ast_mutex_unlock(&p->lock); 09188 return f; 09189 } 09190 if (p->tdd) { /* if in TDD mode, see if we receive that */ 09191 int c; 09192 09193 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 09194 if (c < 0) { 09195 ast_debug(1,"tdd_feed failed\n"); 09196 ast_mutex_unlock(&p->lock); 09197 return NULL; 09198 } 09199 if (c) { /* if a char to return */ 09200 p->subs[idx].f.subclass.integer = 0; 09201 p->subs[idx].f.frametype = AST_FRAME_TEXT; 09202 p->subs[idx].f.mallocd = 0; 09203 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09204 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 09205 p->subs[idx].f.datalen = 1; 09206 *((char *) p->subs[idx].f.data.ptr) = c; 09207 ast_mutex_unlock(&p->lock); 09208 return &p->subs[idx].f; 09209 } 09210 } 09211 if (idx == SUB_REAL) { 09212 /* Ensure the CW timers decrement only on a single subchannel */ 09213 if (p->cidcwexpire) { 09214 if (!--p->cidcwexpire) { 09215 /* Expired CID/CW */ 09216 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 09217 restore_conference(p); 09218 } 09219 } 09220 if (p->cid_suppress_expire) { 09221 --p->cid_suppress_expire; 09222 } 09223 if (p->callwaitingrepeat) { 09224 if (!--p->callwaitingrepeat) { 09225 /* Expired, Repeat callwaiting tone */ 09226 ++p->callwaitrings; 09227 dahdi_callwait(ast); 09228 } 09229 } 09230 } 09231 if (p->subs[idx].linear) { 09232 p->subs[idx].f.datalen = READ_SIZE * 2; 09233 } else 09234 p->subs[idx].f.datalen = READ_SIZE; 09235 09236 /* Handle CallerID Transmission */ 09237 if ((p->owner == ast) && p->cidspill) { 09238 send_callerid(p); 09239 } 09240 09241 p->subs[idx].f.frametype = AST_FRAME_VOICE; 09242 p->subs[idx].f.subclass.codec = ast->rawreadformat; 09243 p->subs[idx].f.samples = READ_SIZE; 09244 p->subs[idx].f.mallocd = 0; 09245 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09246 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 09247 #if 0 09248 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 09249 #endif 09250 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */ 09251 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 09252 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 09253 ) { 09254 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 09255 don't send anything */ 09256 p->subs[idx].f.frametype = AST_FRAME_NULL; 09257 p->subs[idx].f.subclass.integer = 0; 09258 p->subs[idx].f.samples = 0; 09259 p->subs[idx].f.mallocd = 0; 09260 p->subs[idx].f.offset = 0; 09261 p->subs[idx].f.data.ptr = NULL; 09262 p->subs[idx].f.datalen= 0; 09263 } 09264 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 09265 /* Perform busy detection etc on the dahdi line */ 09266 int mute; 09267 09268 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 09269 09270 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 09271 mute = ast_dsp_was_muted(p->dsp); 09272 if (p->muting != mute) { 09273 p->muting = mute; 09274 dahdi_confmute(p, mute); 09275 } 09276 09277 if (f) { 09278 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { 09279 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 09280 /* Treat this as a "hangup" instead of a "busy" on the assumption that 09281 a busy */ 09282 ast_frfree(f); 09283 f = NULL; 09284 } 09285 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 09286 || f->frametype == AST_FRAME_DTMF_END) { 09287 #ifdef HAVE_PRI 09288 if (dahdi_sig_pri_lib_handles(p->sig) 09289 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 09290 && p->pri 09291 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 09292 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 09293 /* Don't accept in-band DTMF when in overlap dial mode */ 09294 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 09295 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 09296 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 09297 09298 f->frametype = AST_FRAME_NULL; 09299 f->subclass.integer = 0; 09300 } 09301 #endif 09302 /* DSP clears us of being pulse */ 09303 p->pulsedial = 0; 09304 } else if (p->waitingfordt.tv_sec) { 09305 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 09306 p->waitingfordt.tv_sec = 0; 09307 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 09308 ast_frfree(f); 09309 f = NULL; 09310 } else if (f->frametype == AST_FRAME_VOICE) { 09311 f->frametype = AST_FRAME_NULL; 09312 f->subclass.integer = 0; 09313 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) { 09314 p->waitingfordt.tv_sec = 0; 09315 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 09316 ast_dsp_set_features(p->dsp, p->dsp_features); 09317 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 09318 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 09319 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 09320 if (res < 0) { 09321 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 09322 p->dop.dialstr[0] = '\0'; 09323 ast_mutex_unlock(&p->lock); 09324 ast_frfree(f); 09325 return NULL; 09326 } else { 09327 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 09328 p->dialing = 1; 09329 p->dop.dialstr[0] = '\0'; 09330 p->dop.op = DAHDI_DIAL_OP_REPLACE; 09331 ast_setstate(ast, AST_STATE_DIALING); 09332 } 09333 } 09334 } 09335 } 09336 } 09337 } 09338 } else 09339 f = &p->subs[idx].f; 09340 09341 if (f) { 09342 switch (f->frametype) { 09343 case AST_FRAME_DTMF_BEGIN: 09344 case AST_FRAME_DTMF_END: 09345 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09346 analog_handle_dtmf(p->sig_pvt, ast, idx, &f); 09347 } else { 09348 dahdi_handle_dtmf(ast, idx, &f); 09349 } 09350 break; 09351 case AST_FRAME_VOICE: 09352 if (p->cidspill || p->cid_suppress_expire) { 09353 /* We are/were sending a caller id spill. Suppress any echo. */ 09354 p->subs[idx].f.frametype = AST_FRAME_NULL; 09355 p->subs[idx].f.subclass.integer = 0; 09356 p->subs[idx].f.samples = 0; 09357 p->subs[idx].f.mallocd = 0; 09358 p->subs[idx].f.offset = 0; 09359 p->subs[idx].f.data.ptr = NULL; 09360 p->subs[idx].f.datalen= 0; 09361 } 09362 break; 09363 default: 09364 break; 09365 } 09366 } 09367 09368 ast_mutex_unlock(&p->lock); 09369 return f; 09370 }
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| format_t | format, | |||
| const struct ast_channel * | requestor, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 13693 of file chan_dahdi.c.
References analog_lib_handles(), analog_request(), ast_atomic_fetchadd_int(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, AST_TRANS_CAP_DIGITAL, available(), dahdi_starting_point::backwards, dahdi_starting_point::cadance, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_starting_point::channelmatch, dahdi_pvt::confirmanswer, dahdi_new(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_pvt::dialstring, dahdi_pvt::distinctivering, dahdi_pvt::dnid, duplicate_pseudo(), dahdi_starting_point::groupmatch, is_group_or_channel_match(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::radio, restart_monitor(), dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, dahdi_pvt::sig, SIG_PRI_DEFLAW, sig_pri_extract_called_num_subaddr(), SIG_PRI_LIB_HANDLE_CASES, sig_pri_request(), dahdi_pvt::sig_pvt, SIG_SS7, SIG_SS7_DEFLAW, sig_ss7_request(), dahdi_starting_point::span, SUB_CALLWAIT, and SUB_REAL.
13694 { 13695 int callwait = 0; 13696 struct dahdi_pvt *p; 13697 struct ast_channel *tmp = NULL; 13698 struct dahdi_pvt *exitpvt; 13699 int channelmatched = 0; 13700 int groupmatched = 0; 13701 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13702 int transcapdigital = 0; 13703 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13704 struct dahdi_starting_point start; 13705 13706 ast_mutex_lock(&iflock); 13707 p = determine_starting_point(data, &start); 13708 if (!p) { 13709 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */ 13710 ast_mutex_unlock(&iflock); 13711 return NULL; 13712 } 13713 13714 /* Search for an unowned channel */ 13715 exitpvt = p; 13716 while (p && !tmp) { 13717 if (start.roundrobin) 13718 round_robin[start.rr_starting_point] = p; 13719 13720 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched) 13721 && available(&p, channelmatched)) { 13722 ast_debug(1, "Using channel %d\n", p->channel); 13723 13724 callwait = (p->owner != NULL); 13725 #ifdef HAVE_OPENR2 13726 if (p->mfcr2) { 13727 ast_mutex_lock(&p->lock); 13728 if (p->mfcr2call) { 13729 ast_mutex_unlock(&p->lock); 13730 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 13731 goto next; 13732 } 13733 p->mfcr2call = 1; 13734 ast_mutex_unlock(&p->lock); 13735 } 13736 #endif 13737 if (p->channel == CHAN_PSEUDO) { 13738 p = duplicate_pseudo(p); 13739 if (!p) { 13740 break; 13741 } 13742 } 13743 13744 p->distinctivering = 0; 13745 /* Make special notes */ 13746 switch (start.opt) { 13747 case '\0': 13748 /* No option present. */ 13749 break; 13750 case 'c': 13751 /* Confirm answer */ 13752 p->confirmanswer = 1; 13753 break; 13754 case 'r': 13755 /* Distinctive ring */ 13756 p->distinctivering = start.cadance; 13757 break; 13758 case 'd': 13759 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13760 /* If this is an ISDN call, make it digital */ 13761 transcapdigital = AST_TRANS_CAP_DIGITAL; 13762 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13763 break; 13764 default: 13765 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data); 13766 break; 13767 } 13768 13769 p->outgoing = 1; 13770 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 13771 tmp = analog_request(p->sig_pvt, &callwait, requestor); 13772 #ifdef HAVE_PRI 13773 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 13774 /* 13775 * We already have the B channel reserved for this call. We 13776 * just need to make sure that dahdi_hangup() has completed 13777 * cleaning up before continuing. 13778 */ 13779 ast_mutex_lock(&p->lock); 13780 ast_mutex_unlock(&p->lock); 13781 13782 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid, 13783 sizeof(p->dnid)); 13784 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital); 13785 #endif 13786 #if defined(HAVE_SS7) 13787 } else if (p->sig == SIG_SS7) { 13788 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital); 13789 #endif /* defined(HAVE_SS7) */ 13790 } else { 13791 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : ""); 13792 } 13793 if (!tmp) { 13794 p->outgoing = 0; 13795 #if defined(HAVE_PRI) 13796 switch (p->sig) { 13797 case SIG_PRI_LIB_HANDLE_CASES: 13798 #if defined(HAVE_PRI_CALL_WAITING) 13799 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) { 13800 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0; 13801 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); 13802 } 13803 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 13804 /* 13805 * This should be the last thing to clear when we are done with 13806 * the channel. 13807 */ 13808 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0; 13809 break; 13810 default: 13811 break; 13812 } 13813 #endif /* defined(HAVE_PRI) */ 13814 } else { 13815 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data); 13816 } 13817 break; 13818 } 13819 #ifdef HAVE_OPENR2 13820 next: 13821 #endif 13822 if (start.backwards) { 13823 p = p->prev; 13824 if (!p) 13825 p = ifend; 13826 } else { 13827 p = p->next; 13828 if (!p) 13829 p = iflist; 13830 } 13831 /* stop when you roll to the one that we started from */ 13832 if (p == exitpvt) 13833 break; 13834 } 13835 ast_mutex_unlock(&iflock); 13836 restart_monitor(); 13837 if (cause && !tmp) { 13838 if (callwait || channelmatched) { 13839 *cause = AST_CAUSE_BUSY; 13840 } else if (groupmatched) { 13841 *cause = AST_CAUSE_CONGESTION; 13842 } else { 13843 /* 13844 * We did not match any channel requested. 13845 * Dialplan error requesting non-existant channel? 13846 */ 13847 } 13848 } 13849 13850 return tmp; 13851 }
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 15216 of file chan_dahdi.c.
References ast_active_channels(), ast_cond_wait, ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verb, dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, LOG_WARNING, sig_pri_span::master, dahdi_pvt::next, dahdi_pvt::owner, setup_dahdi(), sig_pri_init_pri(), sig_ss7_init_linkset(), SIG_SS7_NUM_DCHANS, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdirestart(), and dahdi_restart_cmd().
15217 { 15218 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15219 int i, j; 15220 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 15221 int cancel_code; 15222 struct dahdi_pvt *p; 15223 15224 ast_mutex_lock(&restart_lock); 15225 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 15226 dahdi_softhangup_all(); 15227 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 15228 #ifdef HAVE_OPENR2 15229 dahdi_r2_destroy_links(); 15230 #endif 15231 15232 #if defined(HAVE_PRI) 15233 for (i = 0; i < NUM_SPANS; i++) { 15234 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 15235 cancel_code = pthread_cancel(pris[i].pri.master); 15236 pthread_kill(pris[i].pri.master, SIGURG); 15237 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code); 15238 pthread_join(pris[i].pri.master, NULL); 15239 ast_debug(4, "Joined thread of span %d\n", i); 15240 } 15241 } 15242 #endif 15243 15244 #if defined(HAVE_SS7) 15245 for (i = 0; i < NUM_SPANS; i++) { 15246 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 15247 cancel_code = pthread_cancel(linksets[i].ss7.master); 15248 pthread_kill(linksets[i].ss7.master, SIGURG); 15249 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code); 15250 pthread_join(linksets[i].ss7.master, NULL); 15251 ast_debug(4, "Joined thread of span %d\n", i); 15252 } 15253 } 15254 #endif /* defined(HAVE_SS7) */ 15255 15256 ast_mutex_lock(&monlock); 15257 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 15258 cancel_code = pthread_cancel(monitor_thread); 15259 pthread_kill(monitor_thread, SIGURG); 15260 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 15261 pthread_join(monitor_thread, NULL); 15262 ast_debug(4, "Joined monitor thread\n"); 15263 } 15264 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 15265 15266 ast_mutex_lock(&ss_thread_lock); 15267 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 15268 int x = DAHDI_FLASH; 15269 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count); 15270 15271 ast_mutex_lock(&iflock); 15272 for (p = iflist; p; p = p->next) { 15273 if (p->owner) { 15274 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 15275 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 15276 } 15277 } 15278 ast_mutex_unlock(&iflock); 15279 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 15280 } 15281 15282 /* ensure any created channels before monitor threads were stopped are hungup */ 15283 dahdi_softhangup_all(); 15284 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 15285 destroy_all_channels(); 15286 memset(round_robin, 0, sizeof(round_robin)); 15287 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 15288 15289 ast_mutex_unlock(&monlock); 15290 15291 #ifdef HAVE_PRI 15292 for (i = 0; i < NUM_SPANS; i++) { 15293 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) 15294 dahdi_close_pri_fd(&(pris[i]), j); 15295 } 15296 15297 memset(pris, 0, sizeof(pris)); 15298 for (i = 0; i < NUM_SPANS; i++) { 15299 sig_pri_init_pri(&pris[i].pri); 15300 } 15301 pri_set_error(dahdi_pri_error); 15302 pri_set_message(dahdi_pri_message); 15303 #endif 15304 #if defined(HAVE_SS7) 15305 for (i = 0; i < NUM_SPANS; i++) { 15306 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) 15307 dahdi_close_ss7_fd(&(linksets[i]), j); 15308 } 15309 15310 memset(linksets, 0, sizeof(linksets)); 15311 for (i = 0; i < NUM_SPANS; i++) { 15312 sig_ss7_init_linkset(&linksets[i].ss7); 15313 } 15314 ss7_set_error(dahdi_ss7_error); 15315 ss7_set_message(dahdi_ss7_message); 15316 #endif /* defined(HAVE_SS7) */ 15317 15318 if (setup_dahdi(2) != 0) { 15319 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 15320 ast_mutex_unlock(&ss_thread_lock); 15321 return 1; 15322 } 15323 ast_mutex_unlock(&ss_thread_lock); 15324 ast_mutex_unlock(&restart_lock); 15325 return 0; 15326 }
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15328 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.
15329 { 15330 switch (cmd) { 15331 case CLI_INIT: 15332 e->command = "dahdi restart"; 15333 e->usage = 15334 "Usage: dahdi restart\n" 15335 " Restarts the DAHDI channels: destroys them all and then\n" 15336 " re-reads them from chan_dahdi.conf.\n" 15337 " Note that this will STOP any running CALL on DAHDI channels.\n" 15338 ""; 15339 return NULL; 15340 case CLI_GENERATE: 15341 return NULL; 15342 } 15343 if (a->argc != 2) 15344 return CLI_SHOWUSAGE; 15345 15346 if (dahdi_restart() != 0) 15347 return CLI_FAILURE; 15348 return CLI_SUCCESS; 15349 }
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7633 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_handle_event(), and my_ring().
07634 { 07635 int x; 07636 int res; 07637 /* Make sure our transmit state is on hook */ 07638 x = 0; 07639 x = DAHDI_ONHOOK; 07640 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07641 do { 07642 x = DAHDI_RING; 07643 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07644 if (res) { 07645 switch (errno) { 07646 case EBUSY: 07647 case EINTR: 07648 /* Wait just in case */ 07649 usleep(10000); 07650 continue; 07651 case EINPROGRESS: 07652 res = 0; 07653 break; 07654 default: 07655 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 07656 res = 0; 07657 } 07658 } 07659 } while (res); 07660 return res; 07661 }
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 18779 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index, dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, LOG_WARNING, dahdi_pvt::mate, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
18780 { 18781 #define END_SILENCE_LEN 400 18782 #define HEADER_MS 50 18783 #define TRAILER_MS 5 18784 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 18785 #define ASCII_BYTES_PER_CHAR 80 18786 18787 unsigned char *buf,*mybuf; 18788 struct dahdi_pvt *p = c->tech_pvt; 18789 struct pollfd fds[1]; 18790 int size,res,fd,len,x; 18791 int bytes=0; 18792 /* Initial carrier (imaginary) */ 18793 float cr = 1.0; 18794 float ci = 0.0; 18795 float scont = 0.0; 18796 int idx; 18797 18798 idx = dahdi_get_index(c, p, 0); 18799 if (idx < 0) { 18800 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 18801 return -1; 18802 } 18803 if (!text[0]) return(0); /* if nothing to send, don't */ 18804 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 18805 if (p->mate) 18806 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 18807 else 18808 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 18809 if (!buf) 18810 return -1; 18811 mybuf = buf; 18812 if (p->mate) { 18813 int codec = AST_LAW(p); 18814 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 18815 PUT_CLID_MARKMS; 18816 } 18817 /* Put actual message */ 18818 for (x = 0; text[x]; x++) { 18819 PUT_CLID(text[x]); 18820 } 18821 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 18822 PUT_CLID_MARKMS; 18823 } 18824 len = bytes; 18825 buf = mybuf; 18826 } else { 18827 len = tdd_generate(p->tdd, buf, text); 18828 if (len < 1) { 18829 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 18830 ast_free(mybuf); 18831 return -1; 18832 } 18833 } 18834 memset(buf + len, 0x7f, END_SILENCE_LEN); 18835 len += END_SILENCE_LEN; 18836 fd = p->subs[idx].dfd; 18837 while (len) { 18838 if (ast_check_hangup(c)) { 18839 ast_free(mybuf); 18840 return -1; 18841 } 18842 size = len; 18843 if (size > READ_SIZE) 18844 size = READ_SIZE; 18845 fds[0].fd = fd; 18846 fds[0].events = POLLOUT | POLLPRI; 18847 fds[0].revents = 0; 18848 res = poll(fds, 1, -1); 18849 if (!res) { 18850 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 18851 continue; 18852 } 18853 /* if got exception */ 18854 if (fds[0].revents & POLLPRI) { 18855 ast_free(mybuf); 18856 return -1; 18857 } 18858 if (!(fds[0].revents & POLLOUT)) { 18859 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 18860 continue; 18861 } 18862 res = write(fd, buf, size); 18863 if (res != size) { 18864 if (res == -1) { 18865 ast_free(mybuf); 18866 return -1; 18867 } 18868 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 18869 break; 18870 } 18871 len -= size; 18872 buf += size; 18873 } 18874 ast_free(mybuf); 18875 return(0); 18876 }
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15938 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_false(), ast_mutex_lock, ast_mutex_unlock, ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, dahdi_pvt::next, and ast_cli_entry::usage.
15939 { 15940 int channel; 15941 int on; 15942 struct dahdi_pvt *dahdi_chan = NULL; 15943 15944 switch (cmd) { 15945 case CLI_INIT: 15946 e->command = "dahdi set dnd"; 15947 e->usage = 15948 "Usage: dahdi set dnd <chan#> <on|off>\n" 15949 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15950 " Changes take effect immediately.\n" 15951 " <chan num> is the channel number\n" 15952 " <on|off> Enable or disable DND mode?\n" 15953 ; 15954 return NULL; 15955 case CLI_GENERATE: 15956 return NULL; 15957 } 15958 15959 if (a->argc != 5) 15960 return CLI_SHOWUSAGE; 15961 15962 if ((channel = atoi(a->argv[3])) <= 0) { 15963 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 15964 return CLI_SHOWUSAGE; 15965 } 15966 15967 if (ast_true(a->argv[4])) 15968 on = 1; 15969 else if (ast_false(a->argv[4])) 15970 on = 0; 15971 else { 15972 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 15973 return CLI_SHOWUSAGE; 15974 } 15975 15976 ast_mutex_lock(&iflock); 15977 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 15978 if (dahdi_chan->channel != channel) 15979 continue; 15980 15981 /* Found the channel. Actually set it */ 15982 dahdi_dnd(dahdi_chan, on); 15983 break; 15984 } 15985 ast_mutex_unlock(&iflock); 15986 15987 if (!dahdi_chan) { 15988 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15989 return CLI_FAILURE; 15990 } 15991 15992 return CLI_SUCCESS; 15993 }
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 5171 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().
05172 { 05173 int x, res; 05174 05175 x = hs; 05176 res = ioctl(fd, DAHDI_HOOK, &x); 05177 05178 if (res < 0) { 05179 if (errno == EINPROGRESS) 05180 return 0; 05181 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 05182 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 05183 } 05184 05185 return res; 05186 }
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15786 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, errno, ast_cli_args::fd, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
15787 { 15788 int channel; 15789 int gain; 15790 int tx; 15791 struct dahdi_hwgain hwgain; 15792 struct dahdi_pvt *tmp = NULL; 15793 15794 switch (cmd) { 15795 case CLI_INIT: 15796 e->command = "dahdi set hwgain {rx|tx}"; 15797 e->usage = 15798 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 15799 " Sets the hardware gain on a given channel. Changes take effect\n" 15800 " immediately whether the channel is in use or not.\n" 15801 "\n" 15802 " <rx|tx> which direction do you want to change (relative to our module)\n" 15803 " <chan num> is the channel number relative to the device\n" 15804 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n" 15805 "\n" 15806 " Please note:\n" 15807 " * This is currently the only way to set hwgain by the channel driver.\n" 15808 " * hwgain is only supportable by hardware with analog ports because\n" 15809 " hwgain works on the analog side of an analog-digital conversion.\n"; 15810 return NULL; 15811 case CLI_GENERATE: 15812 return NULL; 15813 } 15814 15815 if (a->argc != 6) 15816 return CLI_SHOWUSAGE; 15817 15818 if (!strcasecmp("rx", a->argv[3])) 15819 tx = 0; /* rx */ 15820 else if (!strcasecmp("tx", a->argv[3])) 15821 tx = 1; /* tx */ 15822 else 15823 return CLI_SHOWUSAGE; 15824 15825 channel = atoi(a->argv[4]); 15826 gain = atof(a->argv[5])*10.0; 15827 15828 ast_mutex_lock(&iflock); 15829 15830 for (tmp = iflist; tmp; tmp = tmp->next) { 15831 15832 if (tmp->channel != channel) 15833 continue; 15834 15835 if (tmp->subs[SUB_REAL].dfd == -1) 15836 break; 15837 15838 hwgain.newgain = gain; 15839 hwgain.tx = tx; 15840 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15841 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15842 ast_mutex_unlock(&iflock); 15843 return CLI_FAILURE; 15844 } 15845 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15846 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15847 break; 15848 } 15849 15850 ast_mutex_unlock(&iflock); 15851 15852 if (tmp) 15853 return CLI_SUCCESS; 15854 15855 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15856 return CLI_FAILURE; 15857 15858 }
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15860 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, ast_cli_args::fd, dahdi_pvt::law, dahdi_pvt::next, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_cli_entry::usage.
15861 { 15862 int channel; 15863 float gain; 15864 int tx; 15865 int res; 15866 struct dahdi_pvt *tmp = NULL; 15867 15868 switch (cmd) { 15869 case CLI_INIT: 15870 e->command = "dahdi set swgain {rx|tx}"; 15871 e->usage = 15872 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15873 " Sets the software gain on a given channel and overrides the\n" 15874 " value provided at module loadtime. Changes take effect\n" 15875 " immediately whether the channel is in use or not.\n" 15876 "\n" 15877 " <rx|tx> which direction do you want to change (relative to our module)\n" 15878 " <chan num> is the channel number relative to the device\n" 15879 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15880 return NULL; 15881 case CLI_GENERATE: 15882 return NULL; 15883 } 15884 15885 if (a->argc != 6) 15886 return CLI_SHOWUSAGE; 15887 15888 if (!strcasecmp("rx", a->argv[3])) 15889 tx = 0; /* rx */ 15890 else if (!strcasecmp("tx", a->argv[3])) 15891 tx = 1; /* tx */ 15892 else 15893 return CLI_SHOWUSAGE; 15894 15895 channel = atoi(a->argv[4]); 15896 gain = atof(a->argv[5]); 15897 15898 ast_mutex_lock(&iflock); 15899 for (tmp = iflist; tmp; tmp = tmp->next) { 15900 15901 if (tmp->channel != channel) 15902 continue; 15903 15904 if (tmp->subs[SUB_REAL].dfd == -1) 15905 break; 15906 15907 if (tx) 15908 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law); 15909 else 15910 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law); 15911 15912 if (res) { 15913 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15914 ast_mutex_unlock(&iflock); 15915 return CLI_FAILURE; 15916 } 15917 15918 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15919 tx ? "tx" : "rx", gain, channel); 15920 15921 if (tx) { 15922 tmp->txgain = gain; 15923 } else { 15924 tmp->rxgain = gain; 15925 } 15926 break; 15927 } 15928 ast_mutex_unlock(&iflock); 15929 15930 if (tmp) 15931 return CLI_SUCCESS; 15932 15933 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15934 return CLI_FAILURE; 15935 15936 }
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 4424 of file chan_dahdi.c.
Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), my_all_subchannels_hungup(), my_distinctive_ring(), my_set_linear_mode(), my_start_cid_detect(), my_stop_cid_detect(), and send_callerid().
| static int dahdi_setoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 6729 of file chan_dahdi.c.
References ast_check_hangup(), ast_debug, ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_DIGIT_DETECT, AST_OPTION_ECHOCAN, AST_OPTION_FAX_DETECT, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, disable_dtmf_detect(), dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::dtmfrelax, enable_dtmf_detect(), errno, dahdi_pvt::law, len(), LOG_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, READ_SIZE, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txdrc, dahdi_pvt::txgain, and ast_channel_tech::type.
06730 { 06731 char *cp; 06732 signed char *scp; 06733 int x; 06734 int idx; 06735 struct dahdi_pvt *p = chan->tech_pvt, *pp; 06736 struct oprmode *oprmode; 06737 06738 06739 /* all supported options require data */ 06740 if (!p || !data || (datalen < 1)) { 06741 errno = EINVAL; 06742 return -1; 06743 } 06744 06745 switch (option) { 06746 case AST_OPTION_TXGAIN: 06747 scp = (signed char *) data; 06748 idx = dahdi_get_index(chan, p, 0); 06749 if (idx < 0) { 06750 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 06751 return -1; 06752 } 06753 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 06754 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law); 06755 case AST_OPTION_RXGAIN: 06756 scp = (signed char *) data; 06757 idx = dahdi_get_index(chan, p, 0); 06758 if (idx < 0) { 06759 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 06760 return -1; 06761 } 06762 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 06763 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law); 06764 case AST_OPTION_TONE_VERIFY: 06765 if (!p->dsp) 06766 break; 06767 cp = (char *) data; 06768 switch (*cp) { 06769 case 1: 06770 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 06771 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 06772 break; 06773 case 2: 06774 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 06775 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 06776 break; 06777 default: 06778 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 06779 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 06780 break; 06781 } 06782 break; 06783 case AST_OPTION_TDD: 06784 /* turn on or off TDD */ 06785 cp = (char *) data; 06786 p->mate = 0; 06787 if (!*cp) { /* turn it off */ 06788 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 06789 if (p->tdd) 06790 tdd_free(p->tdd); 06791 p->tdd = 0; 06792 break; 06793 } 06794 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 06795 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 06796 dahdi_disable_ec(p); 06797 /* otherwise, turn it on */ 06798 if (!p->didtdd) { /* if havent done it yet */ 06799 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 06800 unsigned char *buf; 06801 int size, res, fd, len; 06802 struct pollfd fds[1]; 06803 06804 buf = mybuf; 06805 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 06806 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 06807 len = 40000; 06808 idx = dahdi_get_index(chan, p, 0); 06809 if (idx < 0) { 06810 ast_log(LOG_WARNING, "No index in TDD?\n"); 06811 return -1; 06812 } 06813 fd = p->subs[idx].dfd; 06814 while (len) { 06815 if (ast_check_hangup(chan)) 06816 return -1; 06817 size = len; 06818 if (size > READ_SIZE) 06819 size = READ_SIZE; 06820 fds[0].fd = fd; 06821 fds[0].events = POLLPRI | POLLOUT; 06822 fds[0].revents = 0; 06823 res = poll(fds, 1, -1); 06824 if (!res) { 06825 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 06826 continue; 06827 } 06828 /* if got exception */ 06829 if (fds[0].revents & POLLPRI) 06830 return -1; 06831 if (!(fds[0].revents & POLLOUT)) { 06832 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 06833 continue; 06834 } 06835 res = write(fd, buf, size); 06836 if (res != size) { 06837 if (res == -1) return -1; 06838 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06839 break; 06840 } 06841 len -= size; 06842 buf += size; 06843 } 06844 p->didtdd = 1; /* set to have done it now */ 06845 } 06846 if (*cp == 2) { /* Mate mode */ 06847 if (p->tdd) 06848 tdd_free(p->tdd); 06849 p->tdd = 0; 06850 p->mate = 1; 06851 break; 06852 } 06853 if (!p->tdd) { /* if we don't have one yet */ 06854 p->tdd = tdd_new(); /* allocate one */ 06855 } 06856 break; 06857 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 06858 if (!p->dsp) 06859 break; 06860 cp = (char *) data; 06861 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 06862 *cp ? "ON" : "OFF", (int) *cp, chan->name); 06863 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 06864 break; 06865 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 06866 #if defined(HAVE_PRI) 06867 if (dahdi_sig_pri_lib_handles(p->sig) 06868 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 06869 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 06870 break; 06871 } 06872 #endif /* defined(HAVE_PRI) */ 06873 06874 cp = (char *) data; 06875 if (!*cp) { 06876 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 06877 x = 0; 06878 dahdi_disable_ec(p); 06879 } else { 06880 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 06881 x = 1; 06882 } 06883 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 06884 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 06885 break; 06886 case AST_OPTION_OPRMODE: /* Operator services mode */ 06887 oprmode = (struct oprmode *) data; 06888 /* We don't support operator mode across technologies */ 06889 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 06890 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 06891 chan->tech->type, oprmode->peer->tech->type); 06892 errno = EINVAL; 06893 return -1; 06894 } 06895 pp = oprmode->peer->tech_pvt; 06896 p->oprmode = pp->oprmode = 0; 06897 /* setup peers */ 06898 p->oprpeer = pp; 06899 pp->oprpeer = p; 06900 /* setup modes, if any */ 06901 if (oprmode->mode) 06902 { 06903 pp->oprmode = oprmode->mode; 06904 p->oprmode = -oprmode->mode; 06905 } 06906 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 06907 oprmode->mode, chan->name,oprmode->peer->name); 06908 break; 06909 case AST_OPTION_ECHOCAN: 06910 cp = (char *) data; 06911 if (*cp) { 06912 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name); 06913 dahdi_enable_ec(p); 06914 } else { 06915 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name); 06916 dahdi_disable_ec(p); 06917 } 06918 break; 06919 case AST_OPTION_DIGIT_DETECT: 06920 cp = (char *) data; 06921 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); 06922 if (*cp) { 06923 enable_dtmf_detect(p); 06924 } else { 06925 disable_dtmf_detect(p); 06926 } 06927 break; 06928 case AST_OPTION_FAX_DETECT: 06929 cp = (char *) data; 06930 if (p->dsp) { 06931 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name); 06932 if (*cp) { 06933 p->dsp_features |= DSP_FEATURE_FAX_DETECT; 06934 } else { 06935 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06936 } 06937 ast_dsp_set_features(p->dsp, p->dsp_features); 06938 } 06939 break; 06940 default: 06941 return -1; 06942 } 06943 errno = 0; 06944 06945 return 0; 06946 }
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15448 of file chan_dahdi.c.
References sig_pri_chan::allocated, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, sig_pri_chan::call, dahdi_pvt::callwaitcas, dahdi_pvt::channel, sig_ss7_chan::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, dahdi_pvt::head, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::master, MAX_SLAVES, ast_variable::name, ast_variable::next, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, sig_pri_chan::resetting, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, SIG_PRI_RESET_IDLE, dahdi_pvt::sig_pvt, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, dahdi_pvt::txdrc, dahdi_pvt::txgain, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
15449 { 15450 int channel; 15451 struct dahdi_pvt *tmp = NULL; 15452 struct dahdi_confinfo ci; 15453 struct dahdi_params ps; 15454 int x; 15455 15456 switch (cmd) { 15457 case CLI_INIT: 15458 e->command = "dahdi show channel"; 15459 e->usage = 15460 "Usage: dahdi show channel <chan num>\n" 15461 " Detailed information about a given channel\n"; 15462 return NULL; 15463 case CLI_GENERATE: 15464 return NULL; 15465 } 15466 15467 if (a->argc != 4) 15468 return CLI_SHOWUSAGE; 15469 15470 channel = atoi(a->argv[3]); 15471 15472 ast_mutex_lock(&iflock); 15473 for (tmp = iflist; tmp; tmp = tmp->next) { 15474 if (tmp->channel == channel) { 15475 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 15476 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 15477 ast_cli(a->fd, "Span: %d\n", tmp->span); 15478 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 15479 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 15480 ast_cli(a->fd, "Context: %s\n", tmp->context); 15481 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 15482 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 15483 #if defined(HAVE_PRI) 15484 #if defined(HAVE_PRI_SUBADDR) 15485 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr); 15486 #endif /* defined(HAVE_PRI_SUBADDR) */ 15487 #endif /* defined(HAVE_PRI) */ 15488 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 15489 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 15490 if (tmp->vars) { 15491 struct ast_variable *v; 15492 ast_cli(a->fd, "Variables:\n"); 15493 for (v = tmp->vars ; v ; v = v->next) 15494 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 15495 } 15496 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 15497 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 15498 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 15499 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 15500 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 15501 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : ""); 15502 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : ""); 15503 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : ""); 15504 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 15505 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 15506 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 15507 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 15508 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 15509 if (tmp->busydetect) { 15510 #if defined(BUSYDETECT_TONEONLY) 15511 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 15512 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 15513 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 15514 #endif 15515 #ifdef BUSYDETECT_DEBUG 15516 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 15517 #endif 15518 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 15519 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); 15520 } 15521 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 15522 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 15523 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 15524 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 15525 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 15526 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 15527 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain); 15528 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc); 15529 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no"); 15530 ast_cli(a->fd, "Echo Cancellation:\n"); 15531 15532 if (tmp->echocancel.head.tap_length) { 15533 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length); 15534 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 15535 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 15536 } 15537 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 15538 } else { 15539 ast_cli(a->fd, "\tnone\n"); 15540 } 15541 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 15542 if (tmp->master) 15543 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 15544 for (x = 0; x < MAX_SLAVES; x++) { 15545 if (tmp->slaves[x]) 15546 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 15547 } 15548 #ifdef HAVE_OPENR2 15549 if (tmp->mfcr2) { 15550 char calldir[OR2_MAX_PATH]; 15551 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 15552 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 15553 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 15554 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 15555 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 15556 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 15557 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 15558 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 15559 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 15560 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 15561 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 15562 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 15563 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 15564 #endif 15565 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 15566 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 15567 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 15568 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 15569 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 15570 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 15571 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 15572 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 15573 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 15574 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 15575 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 15576 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 15577 } 15578 #endif 15579 #if defined(HAVE_SS7) 15580 if (tmp->ss7) { 15581 struct sig_ss7_chan *chan = tmp->sig_pvt; 15582 15583 ast_cli(a->fd, "CIC: %d\n", chan->cic); 15584 } 15585 #endif /* defined(HAVE_SS7) */ 15586 #ifdef HAVE_PRI 15587 if (tmp->pri) { 15588 struct sig_pri_chan *chan = tmp->sig_pvt; 15589 15590 ast_cli(a->fd, "PRI Flags: "); 15591 if (chan->resetting != SIG_PRI_RESET_IDLE) { 15592 ast_cli(a->fd, "Resetting=%u ", chan->resetting); 15593 } 15594 if (chan->call) 15595 ast_cli(a->fd, "Call "); 15596 if (chan->allocated) { 15597 ast_cli(a->fd, "Allocated "); 15598 } 15599 ast_cli(a->fd, "\n"); 15600 if (tmp->logicalspan) 15601 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 15602 else 15603 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 15604 } 15605 #endif 15606 memset(&ci, 0, sizeof(ci)); 15607 ps.channo = tmp->channel; 15608 if (tmp->subs[SUB_REAL].dfd > -1) { 15609 memset(&ci, 0, sizeof(ci)); 15610 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 15611 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode); 15612 } 15613 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 15614 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 15615 } 15616 memset(&ps, 0, sizeof(ps)); 15617 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 15618 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 15619 } else { 15620 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 15621 } 15622 } 15623 ast_mutex_unlock(&iflock); 15624 return CLI_SUCCESS; 15625 } 15626 } 15627 ast_mutex_unlock(&iflock); 15628 15629 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15630 return CLI_FAILURE; 15631 }
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15361 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pvt::mohinterpret, dahdi_pvt::next, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.
15362 { 15363 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15364 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15365 ast_group_t targetnum = 0; 15366 int filtertype = 0; 15367 struct dahdi_pvt *tmp = NULL; 15368 char tmps[20] = ""; 15369 char statestr[20] = ""; 15370 char blockstr[20] = ""; 15371 15372 switch (cmd) { 15373 case CLI_INIT: 15374 e->command = "dahdi show channels [group|context]"; 15375 e->usage = 15376 "Usage: dahdi show channels [ group <group> | context <context> ]\n" 15377 " Shows a list of available channels with optional filtering\n" 15378 " <group> must be a number between 0 and 63\n"; 15379 return NULL; 15380 case CLI_GENERATE: 15381 return NULL; 15382 } 15383 15384 /* syntax: dahdi show channels [ group <group> | context <context> ] */ 15385 15386 if (!((a->argc == 3) || (a->argc == 5))) 15387 return CLI_SHOWUSAGE; 15388 15389 if (a->argc == 5) { 15390 if (!strcasecmp(a->argv[3], "group")) { 15391 targetnum = atoi(a->argv[4]); 15392 if (63 < targetnum) { 15393 return CLI_SHOWUSAGE; 15394 } 15395 targetnum = ((ast_group_t) 1) << targetnum; 15396 filtertype = 1; 15397 } else if (!strcasecmp(a->argv[3], "context")) { 15398 filtertype = 2; 15399 } 15400 } 15401 15402 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 15403 ast_mutex_lock(&iflock); 15404 for (tmp = iflist; tmp; tmp = tmp->next) { 15405 if (filtertype) { 15406 switch(filtertype) { 15407 case 1: /* dahdi show channels group <group> */ 15408 if (!(tmp->group & targetnum)) { 15409 continue; 15410 } 15411 break; 15412 case 2: /* dahdi show channels context <context> */ 15413 if (strcasecmp(tmp->context, a->argv[4])) { 15414 continue; 15415 } 15416 break; 15417 default: 15418 break; 15419 } 15420 } 15421 if (tmp->channel > 0) { 15422 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 15423 } else 15424 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 15425 15426 if (tmp->locallyblocked) 15427 blockstr[0] = 'L'; 15428 else 15429 blockstr[0] = ' '; 15430 15431 if (tmp->remotelyblocked) 15432 blockstr[1] = 'R'; 15433 else 15434 blockstr[1] = ' '; 15435 15436 blockstr[2] = '\0'; 15437 15438 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 15439 15440 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 15441 } 15442 ast_mutex_unlock(&iflock); 15443 return CLI_SUCCESS; 15444 #undef FORMAT 15445 #undef FORMAT2 15446 }
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15670 of file chan_dahdi.c.
References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.
15671 { 15672 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 15673 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 15674 int span; 15675 int res; 15676 char alarmstr[50]; 15677 15678 int ctl; 15679 struct dahdi_spaninfo s; 15680 15681 switch (cmd) { 15682 case CLI_INIT: 15683 e->command = "dahdi show status"; 15684 e->usage = 15685 "Usage: dahdi show status\n" 15686 " Shows a list of DAHDI cards with status\n"; 15687 return NULL; 15688 case CLI_GENERATE: 15689 return NULL; 15690 } 15691 ctl = open("/dev/dahdi/ctl", O_RDWR); 15692 if (ctl < 0) { 15693 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 15694 return CLI_FAILURE; 15695 } 15696 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO"); 15697 15698 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 15699 s.spanno = span; 15700 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 15701 if (res) { 15702 continue; 15703 } 15704 alarmstr[0] = '\0'; 15705 if (s.alarms > 0) { 15706 if (s.alarms & DAHDI_ALARM_BLUE) 15707 strcat(alarmstr, "BLU/"); 15708 if (s.alarms & DAHDI_ALARM_YELLOW) 15709 strcat(alarmstr, "YEL/"); 15710 if (s.alarms & DAHDI_ALARM_RED) 15711 strcat(alarmstr, "RED/"); 15712 if (s.alarms & DAHDI_ALARM_LOOPBACK) 15713 strcat(alarmstr, "LB/"); 15714 if (s.alarms & DAHDI_ALARM_RECOVER) 15715 strcat(alarmstr, "REC/"); 15716 if (s.alarms & DAHDI_ALARM_NOTOPEN) 15717 strcat(alarmstr, "NOP/"); 15718 if (!strlen(alarmstr)) 15719 strcat(alarmstr, "UUU/"); 15720 if (strlen(alarmstr)) { 15721 /* Strip trailing / */ 15722 alarmstr[strlen(alarmstr) - 1] = '\0'; 15723 } 15724 } else { 15725 if (s.numchans) 15726 strcpy(alarmstr, "OK"); 15727 else 15728 strcpy(alarmstr, "UNCONFIGURED"); 15729 } 15730 15731 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 15732 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 15733 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 15734 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 15735 "CAS", 15736 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 15737 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 15738 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 15739 "Unk", 15740 s.lineconfig & DAHDI_CONFIG_CRC4 ? 15741 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 15742 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "", 15743 lbostr[s.lbo] 15744 ); 15745 } 15746 close(ctl); 15747 15748 return CLI_SUCCESS; 15749 #undef FORMAT 15750 #undef FORMAT2 15751 }
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15753 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.
15754 { 15755 int pseudo_fd = -1; 15756 struct dahdi_versioninfo vi; 15757 15758 switch (cmd) { 15759 case CLI_INIT: 15760 e->command = "dahdi show version"; 15761 e->usage = 15762 "Usage: dahdi show version\n" 15763 " Shows the DAHDI version in use\n"; 15764 return NULL; 15765 case CLI_GENERATE: 15766 return NULL; 15767 } 15768 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 15769 ast_cli(a->fd, "Failed to open control file to get version.\n"); 15770 return CLI_SUCCESS; 15771 } 15772 15773 strcpy(vi.version, "Unknown"); 15774 strcpy(vi.echo_canceller, "Unknown"); 15775 15776 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 15777 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 15778 else 15779 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 15780 15781 close(pseudo_fd); 15782 15783 return CLI_SUCCESS; 15784 }
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 4648 of file chan_dahdi.c.
References SIG_BRI, SIG_BRI_PTMP, 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, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
Referenced by mkintf().
04649 { 04650 static char buf[256]; 04651 switch (sig) { 04652 case SIG_EM: 04653 return "E & M Immediate"; 04654 case SIG_EMWINK: 04655 return "E & M Wink"; 04656 case SIG_EM_E1: 04657 return "E & M E1"; 04658 case SIG_FEATD: 04659 return "Feature Group D (DTMF)"; 04660 case SIG_FEATDMF: 04661 return "Feature Group D (MF)"; 04662 case SIG_FEATDMF_TA: 04663 return "Feature Groud D (MF) Tandem Access"; 04664 case SIG_FEATB: 04665 return "Feature Group B (MF)"; 04666 case SIG_E911: 04667 return "E911 (MF)"; 04668 case SIG_FGC_CAMA: 04669 return "FGC/CAMA (Dialpulse)"; 04670 case SIG_FGC_CAMAMF: 04671 return "FGC/CAMA (MF)"; 04672 case SIG_FXSLS: 04673 return "FXS Loopstart"; 04674 case SIG_FXSGS: 04675 return "FXS Groundstart"; 04676 case SIG_FXSKS: 04677 return "FXS Kewlstart"; 04678 case SIG_FXOLS: 04679 return "FXO Loopstart"; 04680 case SIG_FXOGS: 04681 return "FXO Groundstart"; 04682 case SIG_FXOKS: 04683 return "FXO Kewlstart"; 04684 case SIG_PRI: 04685 return "ISDN PRI"; 04686 case SIG_BRI: 04687 return "ISDN BRI Point to Point"; 04688 case SIG_BRI_PTMP: 04689 return "ISDN BRI Point to MultiPoint"; 04690 case SIG_SS7: 04691 return "SS7"; 04692 case SIG_MFCR2: 04693 return "MFC/R2"; 04694 case SIG_SF: 04695 return "SF (Tone) Immediate"; 04696 case SIG_SFWINK: 04697 return "SF (Tone) Wink"; 04698 case SIG_SF_FEATD: 04699 return "SF (Tone) with Feature Group D (DTMF)"; 04700 case SIG_SF_FEATDMF: 04701 return "SF (Tone) with Feature Group D (MF)"; 04702 case SIG_SF_FEATB: 04703 return "SF (Tone) with Feature Group B (MF)"; 04704 case 0: 04705 return "Pseudo"; 04706 default: 04707 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 04708 return buf; 04709 } 04710 }
| static int dahdi_sig_pri_lib_handles | ( | int | signaling | ) | [inline, static] |
Definition at line 1542 of file chan_dahdi.c.
References SIG_PRI_LIB_HANDLE_CASES.
Referenced by dahdi_bridge(), dahdi_call(), dahdi_cc_callback(), dahdi_digit_end(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_queryoption(), dahdi_read(), dahdi_request(), dahdi_setoption(), handle_alarms(), handle_clear_alarms(), and mkintf().
01543 { 01544 int handles; 01545 01546 switch (signaling) { 01547 case SIG_PRI_LIB_HANDLE_CASES: 01548 handles = 1; 01549 break; 01550 default: 01551 handles = 0; 01552 break; 01553 } 01554 01555 return handles; 01556 }
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 15187 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose, dahdi_pvt::lock, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
15188 { 15189 struct dahdi_pvt *p; 15190 retry: 15191 ast_mutex_lock(&iflock); 15192 for (p = iflist; p; p = p->next) { 15193 ast_mutex_lock(&p->lock); 15194 if (p->owner && !p->restartpending) { 15195 if (ast_channel_trylock(p->owner)) { 15196 if (option_debug > 2) 15197 ast_verbose("Avoiding deadlock\n"); 15198 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 15199 ast_mutex_unlock(&p->lock); 15200 ast_mutex_unlock(&iflock); 15201 goto retry; 15202 } 15203 if (option_debug > 2) 15204 ast_verbose("Softhanging up on %s\n", p->owner->name); 15205 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 15206 p->restartpending = 1; 15207 num_restart_pending++; 15208 ast_channel_unlock(p->owner); 15209 } 15210 ast_mutex_unlock(&p->lock); 15211 } 15212 ast_mutex_unlock(&iflock); 15213 }
| static int dahdi_status_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 18548 of file chan_dahdi.c.
References ast_data_add_bool(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_log(), errno, and LOG_ERROR.
18550 { 18551 int ctl, res, span; 18552 struct ast_data *data_span, *data_alarms; 18553 struct dahdi_spaninfo s; 18554 18555 ctl = open("/dev/dahdi/ctl", O_RDWR); 18556 if (ctl < 0) { 18557 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 18558 return -1; 18559 } 18560 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 18561 s.spanno = span; 18562 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 18563 if (res) { 18564 continue; 18565 } 18566 18567 data_span = ast_data_add_node(data_root, "span"); 18568 if (!data_span) { 18569 continue; 18570 } 18571 ast_data_add_str(data_span, "description", s.desc); 18572 18573 /* insert the alarms status */ 18574 data_alarms = ast_data_add_node(data_span, "alarms"); 18575 if (!data_alarms) { 18576 continue; 18577 } 18578 18579 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE); 18580 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW); 18581 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED); 18582 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK); 18583 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER); 18584 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN); 18585 18586 ast_data_add_int(data_span, "irqmisses", s.irqmisses); 18587 ast_data_add_int(data_span, "bpviol", s.bpvcount); 18588 ast_data_add_int(data_span, "crc4", s.crc4count); 18589 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 18590 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 18591 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 18592 "CAS"); 18593 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 18594 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 18595 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 18596 "Unknown"); 18597 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ? 18598 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 18599 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : ""); 18600 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]); 18601 18602 /* if this span doesn't match remove it. */ 18603 if (!ast_data_search_match(search, data_span)) { 18604 ast_data_remove_node(data_root, data_span); 18605 } 18606 } 18607 close(ctl); 18608 18609 return 0; 18610 }
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4951 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), and my_train_echocanceller().
04952 { 04953 int x; 04954 int res; 04955 04956 if (p && p->echocanon && p->echotraining) { 04957 x = p->echotraining; 04958 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 04959 if (res) 04960 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 04961 else 04962 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 04963 } else { 04964 ast_debug(1, "No echo training requested\n"); 04965 } 04966 }
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 7161 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, dahdi_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::inconference, dahdi_pvt::lock, dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, dahdi_pvt::subs, and update_conf().
Referenced by dahdi_bridge(), and dahdi_fixup().
07162 { 07163 /* Unlink a specific slave or all slaves/masters from a given master */ 07164 int x; 07165 int hasslaves; 07166 if (!master) 07167 return; 07168 if (needlock) { 07169 ast_mutex_lock(&master->lock); 07170 if (slave) { 07171 while (ast_mutex_trylock(&slave->lock)) { 07172 DEADLOCK_AVOIDANCE(&master->lock); 07173 } 07174 } 07175 } 07176 hasslaves = 0; 07177 for (x = 0; x < MAX_SLAVES; x++) { 07178 if (master->slaves[x]) { 07179 if (!slave || (master->slaves[x] == slave)) { 07180 /* Take slave out of the conference */ 07181 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 07182 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 07183 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 07184 master->slaves[x]->master = NULL; 07185 master->slaves[x] = NULL; 07186 } else 07187 hasslaves = 1; 07188 } 07189 if (!hasslaves) 07190 master->inconference = 0; 07191 } 07192 if (!slave) { 07193 if (master->master) { 07194 /* Take master out of the conference */ 07195 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 07196 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 07197 hasslaves = 0; 07198 for (x = 0; x < MAX_SLAVES; x++) { 07199 if (master->master->slaves[x] == master) 07200 master->master->slaves[x] = NULL; 07201 else if (master->master->slaves[x]) 07202 hasslaves = 1; 07203 } 07204 if (!hasslaves) 07205 master->master->inconference = 0; 07206 } 07207 master->master = NULL; 07208 } 07209 update_conf(master); 07210 if (needlock) { 07211 if (slave) 07212 ast_mutex_unlock(&slave->lock); 07213 ast_mutex_unlock(&master->lock); 07214 } 07215 }
| static int dahdi_version_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 18651 of file chan_dahdi.c.
References ast_data_add_str(), ast_log(), errno, and LOG_ERROR.
18653 { 18654 int pseudo_fd = -1; 18655 struct dahdi_versioninfo vi = { 18656 .version = "Unknown", 18657 .echo_canceller = "Unknown" 18658 }; 18659 18660 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 18661 ast_log(LOG_ERROR, "Failed to open control file to get version.\n"); 18662 return -1; 18663 } 18664 18665 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) { 18666 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno)); 18667 } 18668 18669 close(pseudo_fd); 18670 18671 ast_data_add_str(data_root, "value", vi.version); 18672 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller); 18673 18674 return 0; 18675 }
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Referenced by analog_ss_thread(), and my_wait_event().
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | index | |||
| ) | [static] |
Definition at line 9868 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), and my_wink().
09869 { 09870 int j; 09871 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 09872 for (;;) 09873 { 09874 /* set bits of interest */ 09875 j = DAHDI_IOMUX_SIGEVENT; 09876 /* wait for some happening */ 09877 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 09878 /* exit loop if we have it */ 09879 if (j & DAHDI_IOMUX_SIGEVENT) break; 09880 } 09881 /* get the event info */ 09882 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 09883 return 0; 09884 }
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 9394 of file chan_dahdi.c.
References ast_debug, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), dahdi_pvt::channel, dahdi_pvt::cidspill, ast_frame_subclass::codec, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame::frametype, dahdi_subchannel::linear, LOG_WARNING, my_dahdi_write(), dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
09395 { 09396 struct dahdi_pvt *p = ast->tech_pvt; 09397 int res; 09398 int idx; 09399 idx = dahdi_get_index(ast, p, 0); 09400 if (idx < 0) { 09401 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 09402 return -1; 09403 } 09404 09405 /* Write a frame of (presumably voice) data */ 09406 if (frame->frametype != AST_FRAME_VOICE) { 09407 if (frame->frametype != AST_FRAME_IMAGE) 09408 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype); 09409 return 0; 09410 } 09411 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && 09412 (frame->subclass.codec != AST_FORMAT_ULAW) && 09413 (frame->subclass.codec != AST_FORMAT_ALAW)) { 09414 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 09415 return -1; 09416 } 09417 if (p->dialing) { 09418 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 09419 return 0; 09420 } 09421 if (!p->owner) { 09422 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 09423 return 0; 09424 } 09425 if (p->cidspill) { 09426 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n", 09427 ast->name); 09428 return 0; 09429 } 09430 /* Return if it's not valid data */ 09431 if (!frame->data.ptr || !frame->datalen) 09432 return 0; 09433 09434 if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 09435 if (!p->subs[idx].linear) { 09436 p->subs[idx].linear = 1; 09437 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09438 if (res) 09439 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 09440 } 09441 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 09442 } else { 09443 /* x-law already */ 09444 if (p->subs[idx].linear) { 09445 p->subs[idx].linear = 0; 09446 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09447 if (res) 09448 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 09449 } 09450 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 09451 } 09452 if (res < 0) { 09453 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 09454 return -1; 09455 } 09456 return 0; 09457 }
| static enum analog_event dahdievent_to_analogevent | ( | int | event | ) | [static] |
Definition at line 2776 of file chan_dahdi.c.
References ANALOG_EVENT_ALARM, ANALOG_EVENT_DIALCOMPLETE, ANALOG_EVENT_DTMFDOWN, ANALOG_EVENT_DTMFUP, ANALOG_EVENT_EC_DISABLED, ANALOG_EVENT_EC_NLP_DISABLED, ANALOG_EVENT_EC_NLP_ENABLED, ANALOG_EVENT_ERROR, ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_NOALARM, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_POLARITY, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_PULSEDIGIT, ANALOG_EVENT_REMOVED, ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_RINGERON, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_RX_CED_DETECTED, ANALOG_EVENT_TX_CED_DETECTED, and ANALOG_EVENT_WINKFLASH.
Referenced by do_monitor(), my_get_callerid(), and my_get_event().
02777 { 02778 enum analog_event res; 02779 02780 switch (event) { 02781 case DAHDI_EVENT_ONHOOK: 02782 res = ANALOG_EVENT_ONHOOK; 02783 break; 02784 case DAHDI_EVENT_RINGOFFHOOK: 02785 res = ANALOG_EVENT_RINGOFFHOOK; 02786 break; 02787 case DAHDI_EVENT_WINKFLASH: 02788 res = ANALOG_EVENT_WINKFLASH; 02789 break; 02790 case DAHDI_EVENT_ALARM: 02791 res = ANALOG_EVENT_ALARM; 02792 break; 02793 case DAHDI_EVENT_NOALARM: 02794 res = ANALOG_EVENT_NOALARM; 02795 break; 02796 case DAHDI_EVENT_DIALCOMPLETE: 02797 res = ANALOG_EVENT_DIALCOMPLETE; 02798 break; 02799 case DAHDI_EVENT_RINGERON: 02800 res = ANALOG_EVENT_RINGERON; 02801 break; 02802 case DAHDI_EVENT_RINGEROFF: 02803 res = ANALOG_EVENT_RINGEROFF; 02804 break; 02805 case DAHDI_EVENT_HOOKCOMPLETE: 02806 res = ANALOG_EVENT_HOOKCOMPLETE; 02807 break; 02808 case DAHDI_EVENT_PULSE_START: 02809 res = ANALOG_EVENT_PULSE_START; 02810 break; 02811 case DAHDI_EVENT_POLARITY: 02812 res = ANALOG_EVENT_POLARITY; 02813 break; 02814 case DAHDI_EVENT_RINGBEGIN: 02815 res = ANALOG_EVENT_RINGBEGIN; 02816 break; 02817 case DAHDI_EVENT_EC_DISABLED: 02818 res = ANALOG_EVENT_EC_DISABLED; 02819 break; 02820 case DAHDI_EVENT_REMOVED: 02821 res = ANALOG_EVENT_REMOVED; 02822 break; 02823 case DAHDI_EVENT_NEONMWI_ACTIVE: 02824 res = ANALOG_EVENT_NEONMWI_ACTIVE; 02825 break; 02826 case DAHDI_EVENT_NEONMWI_INACTIVE: 02827 res = ANALOG_EVENT_NEONMWI_INACTIVE; 02828 break; 02829 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 02830 case DAHDI_EVENT_TX_CED_DETECTED: 02831 res = ANALOG_EVENT_TX_CED_DETECTED; 02832 break; 02833 case DAHDI_EVENT_RX_CED_DETECTED: 02834 res = ANALOG_EVENT_RX_CED_DETECTED; 02835 break; 02836 case DAHDI_EVENT_EC_NLP_DISABLED: 02837 res = ANALOG_EVENT_EC_NLP_DISABLED; 02838 break; 02839 case DAHDI_EVENT_EC_NLP_ENABLED: 02840 res = ANALOG_EVENT_EC_NLP_ENABLED; 02841 break; 02842 #endif 02843 case DAHDI_EVENT_PULSEDIGIT: 02844 res = ANALOG_EVENT_PULSEDIGIT; 02845 break; 02846 case DAHDI_EVENT_DTMFDOWN: 02847 res = ANALOG_EVENT_DTMFDOWN; 02848 break; 02849 case DAHDI_EVENT_DTMFUP: 02850 res = ANALOG_EVENT_DTMFUP; 02851 break; 02852 default: 02853 switch(event & 0xFFFF0000) { 02854 case DAHDI_EVENT_PULSEDIGIT: 02855 case DAHDI_EVENT_DTMFDOWN: 02856 case DAHDI_EVENT_DTMFUP: 02857 /* The event includes a digit number in the low word. 02858 * Converting it to a 'enum analog_event' would remove 02859 * that information. Thus it is returned as-is. 02860 */ 02861 return event; 02862 } 02863 02864 res = ANALOG_EVENT_ERROR; 02865 break; 02866 } 02867 02868 return res; 02869 }
| static enum analog_sigtype dahdisig_to_analogsig | ( | int | sig | ) | [static] |
Definition at line 1599 of file chan_dahdi.c.
References ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, 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 mkintf().
01600 { 01601 switch (sig) { 01602 case SIG_FXOLS: 01603 return ANALOG_SIG_FXOLS; 01604 case SIG_FXOGS: 01605 return ANALOG_SIG_FXOGS; 01606 case SIG_FXOKS: 01607 return ANALOG_SIG_FXOKS; 01608 case SIG_FXSLS: 01609 return ANALOG_SIG_FXSLS; 01610 case SIG_FXSGS: 01611 return ANALOG_SIG_FXSGS; 01612 case SIG_FXSKS: 01613 return ANALOG_SIG_FXSKS; 01614 case SIG_EMWINK: 01615 return ANALOG_SIG_EMWINK; 01616 case SIG_EM: 01617 return ANALOG_SIG_EM; 01618 case SIG_EM_E1: 01619 return ANALOG_SIG_EM_E1; 01620 case SIG_FEATD: 01621 return ANALOG_SIG_FEATD; 01622 case SIG_FEATDMF: 01623 return ANALOG_SIG_FEATDMF; 01624 case SIG_E911: 01625 return SIG_E911; 01626 case SIG_FGC_CAMA: 01627 return ANALOG_SIG_FGC_CAMA; 01628 case SIG_FGC_CAMAMF: 01629 return ANALOG_SIG_FGC_CAMAMF; 01630 case SIG_FEATB: 01631 return ANALOG_SIG_FEATB; 01632 case SIG_SFWINK: 01633 return ANALOG_SIG_SFWINK; 01634 case SIG_SF: 01635 return ANALOG_SIG_SF; 01636 case SIG_SF_FEATD: 01637 return ANALOG_SIG_SF_FEATD; 01638 case SIG_SF_FEATDMF: 01639 return ANALOG_SIG_SF_FEATDMF; 01640 case SIG_FEATDMF_TA: 01641 return ANALOG_SIG_FEATDMF_TA; 01642 case SIG_SF_FEATB: 01643 return ANALOG_SIG_FEATB; 01644 default: 01645 return -1; 01646 } 01647 }
| static void deep_copy_dahdi_chan_conf | ( | struct dahdi_chan_conf * | dest, | |
| const struct dahdi_chan_conf * | src | |||
| ) | [static] |
Definition at line 18213 of file chan_dahdi.c.
References ast_cc_copy_config_params(), dahdi_pvt::cc_params, and dahdi_chan_conf::chan.
Referenced by setup_dahdi_int().
18214 { 18215 struct ast_cc_config_params *cc_params; 18216 18217 cc_params = dest->chan.cc_params; 18218 *dest = *src; 18219 dest->chan.cc_params = cc_params; 18220 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params); 18221 }
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 5846 of file chan_dahdi.c.
References ast_db_del(), ast_db_get(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::channel, destroy_dahdi_pvt(), sig_pri_span::lock, sig_pri_span::no_b_chan_iflist, NUM_SPANS, sig_pri_span::pri, and dahdi_pvt::span.
Referenced by __unload_module(), and dahdi_restart().
05847 { 05848 int chan; 05849 #if defined(HAVE_PRI) 05850 unsigned span; 05851 struct sig_pri_span *pri; 05852 #endif /* defined(HAVE_PRI) */ 05853 struct dahdi_pvt *p; 05854 05855 while (num_restart_pending) { 05856 usleep(1); 05857 } 05858 05859 ast_mutex_lock(&iflock); 05860 /* Destroy all the interfaces and free their memory */ 05861 while (iflist) { 05862 p = iflist; 05863 05864 chan = p->channel; 05865 #if defined(HAVE_PRI_SERVICE_MESSAGES) 05866 { 05867 char db_chan_name[20]; 05868 char db_answer[5]; 05869 char state; 05870 int why = -1; 05871 05872 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan); 05873 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 05874 sscanf(db_answer, "%1c:%30d", &state, &why); 05875 } 05876 if (!why) { 05877 /* SRVST persistence is not required */ 05878 ast_db_del(db_chan_name, SRVST_DBKEY); 05879 } 05880 } 05881 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 05882 /* Free associated memory */ 05883 destroy_dahdi_pvt(p); 05884 ast_verb(3, "Unregistered channel %d\n", chan); 05885 } 05886 ifcount = 0; 05887 ast_mutex_unlock(&iflock); 05888 05889 #if defined(HAVE_PRI) 05890 /* Destroy all of the no B channel interface lists */ 05891 for (span = 0; span < NUM_SPANS; ++span) { 05892 if (!pris[span].dchannels[0]) { 05893 break; 05894 } 05895 pri = &pris[span].pri; 05896 ast_mutex_lock(&pri->lock); 05897 while (pri->no_b_chan_iflist) { 05898 p = pri->no_b_chan_iflist; 05899 05900 /* Free associated memory */ 05901 destroy_dahdi_pvt(p); 05902 } 05903 ast_mutex_unlock(&pri->lock); 05904 } 05905 #endif /* defined(HAVE_PRI) */ 05906 }
| static void destroy_channel | ( | struct dahdi_pvt * | cur, | |
| int | now | |||
| ) | [static] |
Definition at line 5828 of file chan_dahdi.c.
References destroy_dahdi_pvt(), dahdi_subchannel::owner, dahdi_pvt::owner, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().
05829 { 05830 int i; 05831 05832 if (!now) { 05833 /* Do not destroy the channel now if it is owned by someone. */ 05834 if (cur->owner) { 05835 return; 05836 } 05837 for (i = 0; i < 3; i++) { 05838 if (cur->subs[i].owner) { 05839 return; 05840 } 05841 } 05842 } 05843 destroy_dahdi_pvt(cur); 05844 }
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5758 of file chan_dahdi.c.
References analog_delete(), analog_lib_handles(), ast_cc_config_params_destroy(), ast_event_unsubscribe(), ast_free, ast_mutex_destroy, ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_pvt::cc_params, dahdi_pvt::cidspill, dahdi_close_sub(), dahdi_iflist_extract(), DAHDI_IFLIST_MAIN, DAHDI_IFLIST_NONE, find_next_iface_in_span(), dahdi_pvt::lock, dahdi_pvt::manages_span_alarms, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig_pri_chan_delete(), SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SIG_SS7, sig_ss7_chan_delete(), dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, dahdi_pvt::vars, and dahdi_pvt::which_iflist.
Referenced by destroy_all_channels(), destroy_channel(), duplicate_pseudo(), and mkintf().
05759 { 05760 struct dahdi_pvt *p = pvt; 05761 05762 if (p->manages_span_alarms) { 05763 struct dahdi_pvt *next = find_next_iface_in_span(p); 05764 if (next) { 05765 next->manages_span_alarms = 1; 05766 } 05767 } 05768 05769 /* Remove channel from the list */ 05770 #if defined(HAVE_PRI) 05771 dahdi_unlink_pri_pvt(p); 05772 #endif /* defined(HAVE_PRI) */ 05773 #if defined(HAVE_SS7) 05774 dahdi_unlink_ss7_pvt(p); 05775 #endif /* defined(HAVE_SS7) */ 05776 switch (pvt->which_iflist) { 05777 case DAHDI_IFLIST_NONE: 05778 break; 05779 case DAHDI_IFLIST_MAIN: 05780 dahdi_iflist_extract(p); 05781 break; 05782 #if defined(HAVE_PRI) 05783 case DAHDI_IFLIST_NO_B_CHAN: 05784 if (p->pri) { 05785 dahdi_nobch_extract(p->pri, p); 05786 } 05787 break; 05788 #endif /* defined(HAVE_PRI) */ 05789 } 05790 05791 if (p->sig_pvt) { 05792 if (analog_lib_handles(p->sig, 0, 0)) { 05793 analog_delete(p->sig_pvt); 05794 } 05795 switch (p->sig) { 05796 #if defined(HAVE_PRI) 05797 case SIG_PRI_LIB_HANDLE_CASES: 05798 sig_pri_chan_delete(p->sig_pvt); 05799 break; 05800 #endif /* defined(HAVE_PRI) */ 05801 #if defined(HAVE_SS7) 05802 case SIG_SS7: 05803 sig_ss7_chan_delete(p->sig_pvt); 05804 break; 05805 #endif /* defined(HAVE_SS7) */ 05806 default: 05807 break; 05808 } 05809 } 05810 ast_free(p->cidspill); 05811 if (p->use_smdi) 05812 ast_smdi_interface_unref(p->smdi_iface); 05813 if (p->mwi_event_sub) 05814 ast_event_unsubscribe(p->mwi_event_sub); 05815 if (p->vars) { 05816 ast_variables_destroy(p->vars); 05817 } 05818 if (p->cc_params) { 05819 ast_cc_config_params_destroy(p->cc_params); 05820 } 05821 ast_mutex_destroy(&p->lock); 05822 dahdi_close_sub(p, SUB_REAL); 05823 if (p->owner) 05824 p->owner->tech_pvt = NULL; 05825 ast_free(p); 05826 }
| static struct dahdi_pvt* determine_starting_point | ( | const char * | data, | |
| struct dahdi_starting_point * | param | |||
| ) | [static, read] |
Definition at line 13532 of file chan_dahdi.c.
References args, ARRAY_LEN, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_starting_point::backwards, dahdi_starting_point::cadance, CHAN_PSEUDO, dahdi_starting_point::channelmatch, errno, dahdi_starting_point::groupmatch, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_starting_point::opt, dahdi_pvt::prev, dahdi_starting_point::roundrobin, dahdi_starting_point::rr_starting_point, and dahdi_starting_point::span.
Referenced by dahdi_cc_callback(), and dahdi_request().
13533 { 13534 char *dest; 13535 char *s; 13536 int x; 13537 int res = 0; 13538 struct dahdi_pvt *p; 13539 char *subdir = NULL; 13540 AST_DECLARE_APP_ARGS(args, 13541 AST_APP_ARG(group); /* channel/group token */ 13542 //AST_APP_ARG(ext); /* extension token */ 13543 //AST_APP_ARG(opts); /* options token */ 13544 AST_APP_ARG(other); /* Any remining unused arguments */ 13545 ); 13546 13547 /* 13548 * data is ---v 13549 * Dial(DAHDI/pseudo[/extension[/options]]) 13550 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]]) 13551 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]]) 13552 * Dial(DAHDI/i<span>[/extension[/options]]) 13553 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]) 13554 * 13555 * i - ISDN span channel restriction. 13556 * Used by CC to ensure that the CC recall goes out the same span. 13557 * Also to make ISDN channel names dialable when the sequence number 13558 * is stripped off. (Used by DTMF attended transfer feature.) 13559 * 13560 * g - channel group allocation search forward 13561 * G - channel group allocation search backward 13562 * r - channel group allocation round robin search forward 13563 * R - channel group allocation round robin search backward 13564 * 13565 * c - Wait for DTMF digit to confirm answer 13566 * r<cadance#> - Set distintive ring cadance number 13567 * d - Force bearer capability for ISDN/SS7 call to digital. 13568 */ 13569 13570 if (data) { 13571 dest = ast_strdupa(data); 13572 } else { 13573 ast_log(LOG_WARNING, "Channel requested with no data\n"); 13574 return NULL; 13575 } 13576 AST_NONSTANDARD_APP_ARGS(args, dest, '/'); 13577 if (!args.argc || ast_strlen_zero(args.group)) { 13578 ast_log(LOG_WARNING, "No channel/group specified\n"); 13579 return NULL; 13580 } 13581 13582 /* Initialize the output parameters */ 13583 memset(param, 0, sizeof(*param)); 13584 param->channelmatch = -1; 13585 13586 if (strchr(args.group, '!') != NULL) { 13587 char *prev = args.group; 13588 while ((s = strchr(prev, '!')) != NULL) { 13589 *s++ = '/'; 13590 prev = s; 13591 } 13592 *(prev - 1) = '\0'; 13593 subdir = args.group; 13594 args.group = prev; 13595 } else if (args.group[0] == 'i') { 13596 /* Extract the ISDN span channel restriction specifier. */ 13597 res = sscanf(args.group + 1, "%30d", &x); 13598 if (res < 1) { 13599 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data); 13600 return NULL; 13601 } 13602 param->span = x; 13603 13604 /* Remove the ISDN span channel restriction specifier. */ 13605 s = strchr(args.group, '-'); 13606 if (!s) { 13607 /* Search all groups since we are ISDN span restricted. */ 13608 return iflist; 13609 } 13610 args.group = s + 1; 13611 res = 0; 13612 } 13613 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { 13614 /* Retrieve the group number */ 13615 s = args.group + 1; 13616 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13617 if (res < 1) { 13618 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data); 13619 return NULL; 13620 } 13621 param->groupmatch = ((ast_group_t) 1 << x); 13622 13623 if (toupper(args.group[0]) == 'G') { 13624 if (args.group[0] == 'G') { 13625 param->backwards = 1; 13626 p = ifend; 13627 } else 13628 p = iflist; 13629 } else { 13630 if (ARRAY_LEN(round_robin) <= x) { 13631 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n", 13632 x, data); 13633 return NULL; 13634 } 13635 if (args.group[0] == 'R') { 13636 param->backwards = 1; 13637 p = round_robin[x] ? round_robin[x]->prev : ifend; 13638 if (!p) 13639 p = ifend; 13640 } else { 13641 p = round_robin[x] ? round_robin[x]->next : iflist; 13642 if (!p) 13643 p = iflist; 13644 } 13645 param->roundrobin = 1; 13646 param->rr_starting_point = x; 13647 } 13648 } else { 13649 s = args.group; 13650 if (!strcasecmp(s, "pseudo")) { 13651 /* Special case for pseudo */ 13652 x = CHAN_PSEUDO; 13653 param->channelmatch = x; 13654 } else { 13655 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13656 if (res < 1) { 13657 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data); 13658 return NULL; 13659 } else { 13660 param->channelmatch = x; 13661 } 13662 } 13663 if (subdir) { 13664 char path[PATH_MAX]; 13665 struct stat stbuf; 13666 13667 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d", 13668 subdir, param->channelmatch); 13669 if (stat(path, &stbuf) < 0) { 13670 ast_log(LOG_WARNING, "stat(%s) failed: %s\n", 13671 path, strerror(errno)); 13672 return NULL; 13673 } 13674 if (!S_ISCHR(stbuf.st_mode)) { 13675 ast_log(LOG_ERROR, "%s: Not a character device file\n", 13676 path); 13677 return NULL; 13678 } 13679 param->channelmatch = minor(stbuf.st_rdev); 13680 } 13681 13682 p = iflist; 13683 } 13684 13685 if (param->opt == 'r' && res < 3) { 13686 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data); 13687 param->opt = '\0'; 13688 } 13689 13690 return p; 13691 }
| static int device2chan | ( | const char * | subdir, | |
| int | channel, | |||
| char * | path, | |||
| int | pathlen | |||
| ) | [static] |
Definition at line 12305 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.
Referenced by build_channels().
12306 { 12307 struct stat stbuf; 12308 int num; 12309 12310 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel); 12311 if (stat(path, &stbuf) < 0) { 12312 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno)); 12313 return -errno; 12314 } 12315 if (!S_ISCHR(stbuf.st_mode)) { 12316 ast_log(LOG_ERROR, "%s: Not a character device file\n", path); 12317 return -EINVAL; 12318 } 12319 num = minor(stbuf.st_rdev); 12320 ast_log(LOG_DEBUG, "%s -> %d\n", path, num); 12321 return num; 12322 12323 }
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 4484 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
04485 { 04486 if (isdigit(digit)) 04487 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 04488 else if (digit >= 'A' && digit <= 'D') 04489 return DAHDI_TONE_DTMF_A + (digit - 'A'); 04490 else if (digit >= 'a' && digit <= 'd') 04491 return DAHDI_TONE_DTMF_A + (digit - 'a'); 04492 else if (digit == '*') 04493 return DAHDI_TONE_DTMF_s; 04494 else if (digit == '#') 04495 return DAHDI_TONE_DTMF_p; 04496 else 04497 return -1; 04498 }
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6657 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge(), and dahdi_setoption().
06658 { 06659 int val = 0; 06660 06661 p->ignoredtmf = 1; 06662 06663 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06664 06665 if (!p->hardwaredtmf && p->dsp) { 06666 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 06667 ast_dsp_set_features(p->dsp, p->dsp_features); 06668 } 06669 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 11720 of file chan_dahdi.c.
References ANALOG_EVENT_DTMFCID, analog_handle_init_event(), analog_lib_handles(), analog_ss_thread(), ast_calloc, ast_debug, ast_fdisset(), ast_free, ast_hangup(), AST_LAW, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, ast_pthread_create_detached, AST_STATE_PRERING, ast_strlen_zero(), mwi_thread_data::buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_new(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, dahdi_pvt::dtmfcid_delay, dahdi_pvt::dtmfcid_holdoff_state, errno, event2str(), analog_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), last, mwi_thread_data::len, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::mailbox, monitor_pfds_clean(), analog_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, analog_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, analog_subchannel::owner, analog_pvt::owner, mwi_thread_data::pvt, dahdi_pvt::radio, RESULT_SUCCESS, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, analog_pvt::subs, and dahdi_pvt::subs.
Referenced by restart_monitor().
11721 { 11722 int count, res, res2, spoint, pollres=0; 11723 struct dahdi_pvt *i; 11724 struct dahdi_pvt *last = NULL; 11725 struct dahdi_pvt *doomed; 11726 time_t thispass = 0, lastpass = 0; 11727 int found; 11728 char buf[1024]; 11729 struct pollfd *pfds=NULL; 11730 int lastalloc = -1; 11731 /* This thread monitors all the frame relay interfaces which are not yet in use 11732 (and thus do not have a separate thread) indefinitely */ 11733 /* From here on out, we die whenever asked */ 11734 #if 0 11735 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 11736 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 11737 return NULL; 11738 } 11739 ast_debug(1, "Monitor starting...\n"); 11740 #endif 11741 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11742 11743 pthread_cleanup_push(monitor_pfds_clean, &pfds); 11744 for (;;) { 11745 /* Lock the interface list */ 11746 ast_mutex_lock(&iflock); 11747 if (!pfds || (lastalloc != ifcount)) { 11748 if (pfds) { 11749 ast_free(pfds); 11750 pfds = NULL; 11751 } 11752 if (ifcount) { 11753 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 11754 ast_mutex_unlock(&iflock); 11755 return NULL; 11756 } 11757 } 11758 lastalloc = ifcount; 11759 } 11760 /* Build the stuff we're going to poll on, that is the socket of every 11761 dahdi_pvt that does not have an associated owner channel */ 11762 count = 0; 11763 for (i = iflist; i; i = i->next) { 11764 ast_mutex_lock(&i->lock); 11765 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 11766 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11767 struct analog_pvt *p = i->sig_pvt; 11768 11769 if (!p) { 11770 ast_log(LOG_ERROR, "No sig_pvt?\n"); 11771 } else if (!p->owner && !p->subs[SUB_REAL].owner) { 11772 /* This needs to be watched, as it lacks an owner */ 11773 pfds[count].fd = i->subs[SUB_REAL].dfd; 11774 pfds[count].events = POLLPRI; 11775 pfds[count].revents = 0; 11776 /* Message waiting or r2 channels also get watched for reading */ 11777 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11778 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11779 pfds[count].events |= POLLIN; 11780 } 11781 count++; 11782 } 11783 } else { 11784 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 11785 /* This needs to be watched, as it lacks an owner */ 11786 pfds[count].fd = i->subs[SUB_REAL].dfd; 11787 pfds[count].events = POLLPRI; 11788 pfds[count].revents = 0; 11789 /* If we are monitoring for VMWI or sending CID, we need to 11790 read from the channel as well */ 11791 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11792 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11793 pfds[count].events |= POLLIN; 11794 } 11795 count++; 11796 } 11797 } 11798 } 11799 ast_mutex_unlock(&i->lock); 11800 } 11801 /* Okay, now that we know what to do, release the interface lock */ 11802 ast_mutex_unlock(&iflock); 11803 11804 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11805 pthread_testcancel(); 11806 /* Wait at least a second for something to happen */ 11807 res = poll(pfds, count, 1000); 11808 pthread_testcancel(); 11809 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11810 11811 /* Okay, poll has finished. Let's see what happened. */ 11812 if (res < 0) { 11813 if ((errno != EAGAIN) && (errno != EINTR)) 11814 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 11815 continue; 11816 } 11817 /* Alright, lock the interface list again, and let's look and see what has 11818 happened */ 11819 ast_mutex_lock(&iflock); 11820 found = 0; 11821 spoint = 0; 11822 lastpass = thispass; 11823 thispass = time(NULL); 11824 doomed = NULL; 11825 for (i = iflist;; i = i->next) { 11826 if (doomed) { 11827 int res; 11828 res = dahdi_destroy_channel_bynum(doomed->channel); 11829 if (res != RESULT_SUCCESS) { 11830 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 11831 } 11832 doomed = NULL; 11833 } 11834 if (!i) { 11835 break; 11836 } 11837 11838 if (thispass != lastpass) { 11839 if (!found && ((i == last) || ((i == iflist) && !last))) { 11840 last = i; 11841 if (last) { 11842 struct analog_pvt *analog_p = last->sig_pvt; 11843 /* Only allow MWI to be initiated on a quiescent fxs port */ 11844 if (analog_p 11845 && !last->mwisendactive 11846 && (last->sig & __DAHDI_SIG_FXO) 11847 && !analog_p->fxsoffhookstate 11848 && !last->owner 11849 && !ast_strlen_zero(last->mailbox) 11850 && (thispass - analog_p->onhooktime > 3)) { 11851 res = has_voicemail(last); 11852 if (analog_p->msgstate != res) { 11853 /* Set driver resources for signalling VMWI */ 11854 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 11855 if (res2) { 11856 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 11857 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 11858 } 11859 /* If enabled for FSK spill then initiate it */ 11860 if (mwi_send_init(last)) { 11861 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 11862 } 11863 analog_p->msgstate = res; 11864 found ++; 11865 } 11866 } 11867 last = last->next; 11868 } 11869 } 11870 } 11871 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 11872 if (i->radio && !i->owner) 11873 { 11874 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11875 if (res) 11876 { 11877 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 11878 /* Don't hold iflock while handling init events */ 11879 ast_mutex_unlock(&iflock); 11880 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11881 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11882 else 11883 doomed = handle_init_event(i, res); 11884 ast_mutex_lock(&iflock); 11885 } 11886 continue; 11887 } 11888 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 11889 if (pollres & POLLIN) { 11890 if (i->owner || i->subs[SUB_REAL].owner) { 11891 #ifdef HAVE_PRI 11892 if (!i->pri) 11893 #endif 11894 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 11895 continue; 11896 } 11897 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { 11898 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 11899 continue; 11900 } 11901 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 11902 if (res > 0) { 11903 if (i->mwimonitor_fsk) { 11904 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 11905 pthread_attr_t attr; 11906 pthread_t threadid; 11907 struct mwi_thread_data *mtd; 11908 11909 pthread_attr_init(&attr); 11910 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11911 11912 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 11913 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 11914 mtd->pvt = i; 11915 memcpy(mtd->buf, buf, res); 11916 mtd->len = res; 11917 i->mwimonitoractive = 1; 11918 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 11919 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 11920 i->mwimonitoractive = 0; 11921 ast_free(mtd); 11922 } 11923 } 11924 } 11925 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 11926 } else if (i->cid_start == CID_START_DTMF_NOALERT) { 11927 int energy; 11928 struct timeval now; 11929 /* State machine dtmfcid_holdoff_state allows for the line to settle 11930 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 11931 */ 11932 if (1 == i->dtmfcid_holdoff_state) { 11933 gettimeofday(&i->dtmfcid_delay, NULL); 11934 i->dtmfcid_holdoff_state = 2; 11935 } else if (2 == i->dtmfcid_holdoff_state) { 11936 gettimeofday(&now, NULL); 11937 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 11938 i->dtmfcid_holdoff_state = 0; 11939 } 11940 } else { 11941 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 11942 if (!i->mwisendactive && energy > dtmfcid_level) { 11943 pthread_t threadid; 11944 struct ast_channel *chan; 11945 ast_mutex_unlock(&iflock); 11946 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11947 /* just in case this event changes or somehow destroys a channel, set doomed here too */ 11948 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); 11949 i->dtmfcid_holdoff_state = 1; 11950 } else { 11951 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11952 if (!chan) { 11953 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11954 } else { 11955 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11956 if (res) { 11957 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11958 ast_hangup(chan); 11959 } else { 11960 i->dtmfcid_holdoff_state = 1; 11961 } 11962 } 11963 } 11964 ast_mutex_lock(&iflock); 11965 } 11966 } 11967 } 11968 if (i->mwisendactive) { 11969 mwi_send_process_buffer(i, res); 11970 } 11971 } else { 11972 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 11973 } 11974 } 11975 if (pollres & POLLPRI) { 11976 if (i->owner || i->subs[SUB_REAL].owner) { 11977 #ifdef HAVE_PRI 11978 if (!i->pri) 11979 #endif 11980 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 11981 continue; 11982 } 11983 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11984 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 11985 /* Don't hold iflock while handling init events */ 11986 ast_mutex_unlock(&iflock); 11987 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 11988 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11989 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11990 else 11991 doomed = handle_init_event(i, res); 11992 } 11993 ast_mutex_lock(&iflock); 11994 } 11995 } 11996 } 11997 ast_mutex_unlock(&iflock); 11998 } 11999 /* Never reached */ 12000 pthread_cleanup_pop(1); 12001 return NULL; 12002 12003 }
| static int drc_sample | ( | int | sample, | |
| float | drc | |||
| ) | [static] |
Definition at line 4987 of file chan_dahdi.c.
Referenced by fill_rxgain(), and fill_txgain().
04988 { 04989 float neg; 04990 float shallow, steep; 04991 float max = SHRT_MAX; 04992 04993 neg = (sample < 0 ? -1 : 1); 04994 steep = drc*sample; 04995 shallow = neg*(max-max/drc)+(float)sample/drc; 04996 if (abs(steep) < abs(shallow)) { 04997 sample = steep; 04998 } 04999 else { 05000 sample = shallow; 05001 } 05002 05003 return sample; 05004 }
Definition at line 13468 of file chan_dahdi.c.
References ast_cc_config_params_init, ast_cc_copy_config_params(), ast_free, ast_log(), ast_malloc, ast_mutex_init, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::cc_params, dahdi_iflist_insert(), DAHDI_IFLIST_NONE, dahdi_open(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::which_iflist.
Referenced by dahdi_request().
13469 { 13470 struct dahdi_pvt *p; 13471 struct dahdi_bufferinfo bi; 13472 int res; 13473 13474 p = ast_malloc(sizeof(*p)); 13475 if (!p) { 13476 return NULL; 13477 } 13478 *p = *src; 13479 13480 /* Must deep copy the cc_params. */ 13481 p->cc_params = ast_cc_config_params_init(); 13482 if (!p->cc_params) { 13483 ast_free(p); 13484 return NULL; 13485 } 13486 ast_cc_copy_config_params(p->cc_params, src->cc_params); 13487 13488 p->which_iflist = DAHDI_IFLIST_NONE; 13489 p->next = NULL; 13490 p->prev = NULL; 13491 ast_mutex_init(&p->lock); 13492 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13493 if (p->subs[SUB_REAL].dfd < 0) { 13494 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 13495 destroy_dahdi_pvt(p); 13496 return NULL; 13497 } 13498 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13499 if (!res) { 13500 bi.txbufpolicy = src->buf_policy; 13501 bi.rxbufpolicy = src->buf_policy; 13502 bi.numbufs = src->buf_no; 13503 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13504 if (res < 0) { 13505 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 13506 } 13507 } else 13508 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 13509 p->destroy = 1; 13510 dahdi_iflist_insert(p); 13511 return p; 13512 }
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6671 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge(), and dahdi_setoption().
06672 { 06673 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06674 06675 if (p->channel == CHAN_PSEUDO) 06676 return; 06677 06678 p->ignoredtmf = 0; 06679 06680 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06681 06682 if (!p->hardwaredtmf && p->dsp) { 06683 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 06684 ast_dsp_set_features(p->dsp, p->dsp_features); 06685 } 06686 }
| static const char * event2str | ( | int | event | ) | [static] |
Definition at line 4639 of file chan_dahdi.c.
References ARRAY_LEN.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), do_monitor(), mwi_thread(), and my_distinctive_ring().
| static void fill_rxgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| float | drc, | |||
| int | law | |||
| ) | [static] |
Definition at line 5057 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_rxgain().
05058 { 05059 int j; 05060 int k; 05061 float linear_gain = pow(10.0, gain / 20.0); 05062 05063 switch (law) { 05064 case DAHDI_LAW_ALAW: 05065 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05066 if (gain || drc) { 05067 k = AST_ALAW(j); 05068 if (drc) { 05069 k = drc_sample(k, drc); 05070 } 05071 k = (float)k * linear_gain; 05072 if (k > 32767) { 05073 k = 32767; 05074 } else if (k < -32768) { 05075 k = -32768; 05076 } 05077 g->rxgain[j] = AST_LIN2A(k); 05078 } else { 05079 g->rxgain[j] = j; 05080 } 05081 } 05082 break; 05083 case DAHDI_LAW_MULAW: 05084 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05085 if (gain || drc) { 05086 k = AST_MULAW(j); 05087 if (drc) { 05088 k = drc_sample(k, drc); 05089 } 05090 k = (float)k * linear_gain; 05091 if (k > 32767) { 05092 k = 32767; 05093 } else if (k < -32768) { 05094 k = -32768; 05095 } 05096 g->rxgain[j] = AST_LIN2MU(k); 05097 } else { 05098 g->rxgain[j] = j; 05099 } 05100 } 05101 break; 05102 } 05103 }
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| float | drc, | |||
| int | law | |||
| ) | [static] |
Definition at line 5007 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_txgain().
05008 { 05009 int j; 05010 int k; 05011 05012 float linear_gain = pow(10.0, gain / 20.0); 05013 05014 switch (law) { 05015 case DAHDI_LAW_ALAW: 05016 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05017 if (gain || drc) { 05018 k = AST_ALAW(j); 05019 if (drc) { 05020 k = drc_sample(k, drc); 05021 } 05022 k = (float)k * linear_gain; 05023 if (k > 32767) { 05024 k = 32767; 05025 } else if (k < -32768) { 05026 k = -32768; 05027 } 05028 g->txgain[j] = AST_LIN2A(k); 05029 } else { 05030 g->txgain[j] = j; 05031 } 05032 } 05033 break; 05034 case DAHDI_LAW_MULAW: 05035 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05036 if (gain || drc) { 05037 k = AST_MULAW(j); 05038 if (drc) { 05039 k = drc_sample(k, drc); 05040 } 05041 k = (float)k * linear_gain; 05042 if (k > 32767) { 05043 k = 32767; 05044 } else if (k < -32768) { 05045 k = -32768; 05046 } 05047 g->txgain[j] = AST_LIN2MU(k); 05048 05049 } else { 05050 g->txgain[j] = j; 05051 } 05052 } 05053 break; 05054 } 05055 }
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 16027 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, and dahdi_pvt::next.
Referenced by find_channel_from_str().
16028 { 16029 struct dahdi_pvt *p; 16030 16031 ast_mutex_lock(&iflock); 16032 for (p = iflist; p; p = p->next) { 16033 if (p->channel == channel) { 16034 break; 16035 } 16036 } 16037 ast_mutex_unlock(&iflock); 16038 return p; 16039 }
| static struct dahdi_pvt* find_channel_from_str | ( | const char * | channel | ) | [static, read] |
Definition at line 16050 of file chan_dahdi.c.
References find_channel().
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
16051 { 16052 int chan_num; 16053 16054 if (sscanf(channel, "%30d", &chan_num) != 1) { 16055 /* Not numeric string. */ 16056 return NULL; 16057 } 16058 16059 return find_channel(chan_num); 16060 }
Definition at line 5747 of file chan_dahdi.c.
References dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::span.
Referenced by destroy_dahdi_pvt().
| static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
| p | a channel to check for alarms. |
Definition at line 7743 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdishowchannels(), dahdi_handle_event(), handle_init_event(), mkintf(), mwi_thread(), and my_get_and_handle_alarms().
07744 { 07745 int res; 07746 struct dahdi_spaninfo zi; 07747 struct dahdi_params params; 07748 07749 memset(&zi, 0, sizeof(zi)); 07750 zi.spanno = p->span; 07751 07752 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 07753 if (zi.alarms != DAHDI_ALARM_NONE) 07754 return zi.alarms; 07755 } else { 07756 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 07757 return 0; 07758 } 07759 07760 /* No alarms on the span. Check for channel alarms. */ 07761 memset(¶ms, 0, sizeof(params)); 07762 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 07763 return params.chan_alarms; 07764 07765 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 07766 07767 return DAHDI_ALARM_NONE; 07768 }
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 7868 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), EVENT_FLAG_SYSTEM, LOG_WARNING, manager_event, dahdi_pvt::manages_span_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), and dahdi_pvt::span.
Referenced by dahdi_handle_event(), handle_init_event(), mkintf(), mwi_thread(), and my_get_and_handle_alarms().
07869 { 07870 const char *alarm_str; 07871 07872 #if defined(HAVE_PRI) 07873 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 07874 return; 07875 } 07876 #endif /* defined(HAVE_PRI) */ 07877 07878 alarm_str = alarm2str(alms); 07879 if (report_alarms & REPORT_CHANNEL_ALARMS) { 07880 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 07881 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 07882 "Alarm: %s\r\n" 07883 "Channel: %d\r\n", 07884 alarm_str, p->channel); 07885 } 07886 07887 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 07888 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); 07889 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", 07890 "Alarm: %s\r\n" 07891 "Span: %d\r\n", 07892 alarm_str, p->span); 07893 } 07894 }
| static void handle_clear_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3853 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_sig_pri_lib_handles(), EVENT_FLAG_SYSTEM, LOG_NOTICE, manager_event, dahdi_pvt::manages_span_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::sig, sig_pri_is_alarm_ignored(), and dahdi_pvt::span.
Referenced by dahdi_handle_event(), handle_init_event(), and mwi_thread().
03854 { 03855 #if defined(HAVE_PRI) 03856 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 03857 return; 03858 } 03859 #endif /* defined(HAVE_PRI) */ 03860 03861 if (report_alarms & REPORT_CHANNEL_ALARMS) { 03862 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 03863 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 03864 } 03865 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 03866 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); 03867 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); 03868 } 03869 }
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15633 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, term_color(), and ast_cli_entry::usage.
15634 { 15635 int i, j; 15636 switch (cmd) { 15637 case CLI_INIT: 15638 e->command = "dahdi show cadences"; 15639 e->usage = 15640 "Usage: dahdi show cadences\n" 15641 " Shows all cadences currently defined\n"; 15642 return NULL; 15643 case CLI_GENERATE: 15644 return NULL; 15645 } 15646 for (i = 0; i < num_cadence; i++) { 15647 char output[1024]; 15648 char tmp[16], tmp2[64]; 15649 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 15650 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 15651 15652 for (j = 0; j < 16; j++) { 15653 if (cadences[i].ringcadence[j] == 0) 15654 break; 15655 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 15656 if (cidrings[i] * 2 - 1 == j) 15657 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 15658 else 15659 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 15660 if (j != 0) 15661 strncat(output, ",", sizeof(output) - strlen(output) - 1); 15662 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 15663 } 15664 ast_cli(a->fd,"%s\n",output); 15665 } 15666 return CLI_SUCCESS; 15667 }
Definition at line 11468 of file chan_dahdi.c.
References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, restore_conference(), 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_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, sig_ss7_set_alarm(), SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
11469 { 11470 int res; 11471 pthread_t threadid; 11472 struct ast_channel *chan; 11473 11474 /* Handle an event on a given channel for the monitor thread. */ 11475 11476 switch (event) { 11477 case DAHDI_EVENT_NONE: 11478 case DAHDI_EVENT_BITSCHANGED: 11479 break; 11480 case DAHDI_EVENT_WINKFLASH: 11481 case DAHDI_EVENT_RINGOFFHOOK: 11482 if (i->inalarm) break; 11483 if (i->radio) break; 11484 /* Got a ring/answer. What kind of channel are we? */ 11485 switch (i->sig) { 11486 case SIG_FXOLS: 11487 case SIG_FXOGS: 11488 case SIG_FXOKS: 11489 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11490 if (res && (errno == EBUSY)) 11491 break; 11492 11493 /* Cancel VMWI spill */ 11494 ast_free(i->cidspill); 11495 i->cidspill = NULL; 11496 restore_conference(i); 11497 11498 if (i->immediate) { 11499 dahdi_enable_ec(i); 11500 /* The channel is immediately up. Start right away */ 11501 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 11502 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL); 11503 if (!chan) { 11504 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 11505 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11506 if (res < 0) 11507 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11508 } 11509 } else { 11510 /* Check for callerid, digits, etc */ 11511 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL); 11512 if (chan) { 11513 if (has_voicemail(i)) 11514 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 11515 else 11516 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 11517 if (res < 0) 11518 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 11519 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11520 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11521 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11522 if (res < 0) 11523 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11524 ast_hangup(chan); 11525 } 11526 } else 11527 ast_log(LOG_WARNING, "Unable to create channel\n"); 11528 } 11529 break; 11530 case SIG_FXSLS: 11531 case SIG_FXSGS: 11532 case SIG_FXSKS: 11533 i->ringt = i->ringt_base; 11534 /* Fall through */ 11535 case SIG_EMWINK: 11536 case SIG_FEATD: 11537 case SIG_FEATDMF: 11538 case SIG_FEATDMF_TA: 11539 case SIG_E911: 11540 case SIG_FGC_CAMA: 11541 case SIG_FGC_CAMAMF: 11542 case SIG_FEATB: 11543 case SIG_EM: 11544 case SIG_EM_E1: 11545 case SIG_SFWINK: 11546 case SIG_SF_FEATD: 11547 case SIG_SF_FEATDMF: 11548 case SIG_SF_FEATB: 11549 case SIG_SF: 11550 /* Check for callerid, digits, etc */ 11551 if (i->cid_start == CID_START_POLARITY_IN) { 11552 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11553 } else { 11554 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL); 11555 } 11556 11557 if (!chan) { 11558 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11559 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11560 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11562 if (res < 0) { 11563 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11564 } 11565 ast_hangup(chan); 11566 } 11567 break; 11568 default: 11569 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11570 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11571 if (res < 0) 11572 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11573 return NULL; 11574 } 11575 break; 11576 case DAHDI_EVENT_NOALARM: 11577 switch (i->sig) { 11578 #if defined(HAVE_PRI) 11579 case SIG_PRI_LIB_HANDLE_CASES: 11580 ast_mutex_lock(&i->lock); 11581 sig_pri_chan_alarm_notify(i->sig_pvt, 1); 11582 ast_mutex_unlock(&i->lock); 11583 break; 11584 #endif /* defined(HAVE_PRI) */ 11585 #if defined(HAVE_SS7) 11586 case SIG_SS7: 11587 sig_ss7_set_alarm(i->sig_pvt, 0); 11588 break; 11589 #endif /* defined(HAVE_SS7) */ 11590 default: 11591 i->inalarm = 0; 11592 break; 11593 } 11594 handle_clear_alarms(i); 11595 break; 11596 case DAHDI_EVENT_ALARM: 11597 switch (i->sig) { 11598 #if defined(HAVE_PRI) 11599 case SIG_PRI_LIB_HANDLE_CASES: 11600 ast_mutex_lock(&i->lock); 11601 sig_pri_chan_alarm_notify(i->sig_pvt, 0); 11602 ast_mutex_unlock(&i->lock); 11603 break; 11604 #endif /* defined(HAVE_PRI) */ 11605 #if defined(HAVE_SS7) 11606 case SIG_SS7: 11607 sig_ss7_set_alarm(i->sig_pvt, 1); 11608 break; 11609 #endif /* defined(HAVE_SS7) */ 11610 default: 11611 i->inalarm = 1; 11612 break; 11613 } 11614 res = get_alarms(i); 11615 handle_alarms(i, res); 11616 /* fall thru intentionally */ 11617 case DAHDI_EVENT_ONHOOK: 11618 if (i->radio) 11619 break; 11620 /* Back on hook. Hang up. */ 11621 switch (i->sig) { 11622 case SIG_FXOLS: 11623 case SIG_FXOGS: 11624 case SIG_FEATD: 11625 case SIG_FEATDMF: 11626 case SIG_FEATDMF_TA: 11627 case SIG_E911: 11628 case SIG_FGC_CAMA: 11629 case SIG_FGC_CAMAMF: 11630 case SIG_FEATB: 11631 case SIG_EM: 11632 case SIG_EM_E1: 11633 case SIG_EMWINK: 11634 case SIG_SF_FEATD: 11635 case SIG_SF_FEATDMF: 11636 case SIG_SF_FEATB: 11637 case SIG_SF: 11638 case SIG_SFWINK: 11639 case SIG_FXSLS: 11640 case SIG_FXSGS: 11641 case SIG_FXSKS: 11642 case SIG_FXOKS: 11643 dahdi_disable_ec(i); 11644 /* Diddle the battery for the zhone */ 11645 #ifdef ZHONE_HACK 11646 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11647 usleep(1); 11648 #endif 11649 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11650 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 11651 break; 11652 case SIG_SS7: 11653 case SIG_PRI_LIB_HANDLE_CASES: 11654 dahdi_disable_ec(i); 11655 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11656 break; 11657 default: 11658 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11659 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11660 return NULL; 11661 } 11662 break; 11663 case DAHDI_EVENT_POLARITY: 11664 switch (i->sig) { 11665 case SIG_FXSLS: 11666 case SIG_FXSKS: 11667 case SIG_FXSGS: 11668 /* We have already got a PR before the channel was 11669 created, but it wasn't handled. We need polarity 11670 to be REV for remote hangup detection to work. 11671 At least in Spain */ 11672 if (i->hanguponpolarityswitch) 11673 i->polarity = POLARITY_REV; 11674 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 11675 i->polarity = POLARITY_REV; 11676 ast_verb(2, "Starting post polarity " 11677 "CID detection on channel %d\n", 11678 i->channel); 11679 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11680 if (!chan) { 11681 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11682 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11683 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11684 ast_hangup(chan); 11685 } 11686 } 11687 break; 11688 default: 11689 ast_log(LOG_WARNING, "handle_init_event detected " 11690 "polarity reversal on non-FXO (SIG_FXS) " 11691 "interface %d\n", i->channel); 11692 } 11693 break; 11694 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 11695 ast_log(LOG_NOTICE, 11696 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 11697 i->channel); 11698 return i; 11699 case DAHDI_EVENT_NEONMWI_ACTIVE: 11700 if (i->mwimonitor_neon) { 11701 notify_message(i->mailbox, 1); 11702 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 11703 } 11704 break; 11705 case DAHDI_EVENT_NEONMWI_INACTIVE: 11706 if (i->mwimonitor_neon) { 11707 notify_message(i->mailbox, 0); 11708 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 11709 } 11710 break; 11711 } 11712 return NULL; 11713 }
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5282 of file chan_dahdi.c.
References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, dahdi_pvt::mailbox, and mailbox.
Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), mwi_send_init(), and my_has_voicemail().
05283 { 05284 int new_msgs; 05285 struct ast_event *event; 05286 char *mailbox, *context; 05287 05288 mailbox = context = ast_strdupa(p->mailbox); 05289 strsep(&context, "@"); 05290 if (ast_strlen_zero(context)) 05291 context = "default"; 05292 05293 event = ast_event_get_cached(AST_EVENT_MWI, 05294 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 05295 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 05296 AST_EVENT_IE_END); 05297 05298 if (event) { 05299 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 05300 ast_event_destroy(event); 05301 } else 05302 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 05303 05304 return new_msgs; 05305 }
| static int is_group_or_channel_match | ( | struct dahdi_pvt * | p, | |
| int | span, | |||
| ast_group_t | groupmatch, | |||
| int * | groupmatched, | |||
| int | channelmatch, | |||
| int * | channelmatched | |||
| ) | [static] |
Definition at line 13227 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::group, and dahdi_pvt::span.
Referenced by dahdi_cc_callback(), and dahdi_request().
13228 { 13229 #if defined(HAVE_PRI) 13230 if (0 < span) { 13231 /* The channel must be on the specified PRI span. */ 13232 if (!p->pri || p->pri->span != span) { 13233 return 0; 13234 } 13235 if (!groupmatch && channelmatch == -1) { 13236 /* Match any group since it only needs to be on the PRI span. */ 13237 *groupmatched = 1; 13238 return 1; 13239 } 13240 } 13241 #endif /* defined(HAVE_PRI) */ 13242 /* check group matching */ 13243 if (groupmatch) { 13244 if ((p->group & groupmatch) != groupmatch) 13245 /* Doesn't match the specified group, try the next one */ 13246 return 0; 13247 *groupmatched = 1; 13248 } 13249 /* Check to see if we have a channel match */ 13250 if (channelmatch != -1) { 13251 if (p->channel != channelmatch) 13252 /* Doesn't match the specified channel, try the next one */ 13253 return 0; 13254 *channelmatched = 1; 13255 } 13256 13257 return 1; 13258 }
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 4752 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
04753 { 04754 /* If they're listening to our channel, they're ours */ 04755 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 04756 return 1; 04757 /* If they're a talker on our (allocated) conference, they're ours */ 04758 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 04759 return 1; 04760 return 0; 04761 }
Definition at line 4782 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by my_complete_conference_update(), and update_conf().
04783 { 04784 int x; 04785 int useslavenative; 04786 struct dahdi_pvt *slave = NULL; 04787 /* Start out optimistic */ 04788 useslavenative = 1; 04789 /* Update conference state in a stateless fashion */ 04790 for (x = 0; x < 3; x++) { 04791 /* Any three-way calling makes slave native mode *definitely* out 04792 of the question */ 04793 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 04794 useslavenative = 0; 04795 } 04796 /* If we don't have any 3-way calls, check to see if we have 04797 precisely one slave */ 04798 if (useslavenative) { 04799 for (x = 0; x < MAX_SLAVES; x++) { 04800 if (p->slaves[x]) { 04801 if (slave) { 04802 /* Whoops already have a slave! No 04803 slave native and stop right away */ 04804 slave = NULL; 04805 useslavenative = 0; 04806 break; 04807 } else { 04808 /* We have one slave so far */ 04809 slave = p->slaves[x]; 04810 } 04811 } 04812 } 04813 } 04814 /* If no slave, slave native definitely out */ 04815 if (!slave) 04816 useslavenative = 0; 04817 else if (slave->law != p->law) { 04818 useslavenative = 0; 04819 slave = NULL; 04820 } 04821 if (out) 04822 *out = slave; 04823 return useslavenative; 04824 }
| static int load_module | ( | void | ) | [static] |
Definition at line 18698 of file chan_dahdi.c.
References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_transfer(), action_transferhangup(), ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init, ast_data_register_multiple, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_register_application_xml, HAVE_PRI_CCSS, LOG_ERROR, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), and sig_ss7_init_linkset().
18699 { 18700 int res; 18701 #if defined(HAVE_PRI) || defined(HAVE_SS7) 18702 int y; 18703 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 18704 18705 #ifdef HAVE_PRI 18706 memset(pris, 0, sizeof(pris)); 18707 for (y = 0; y < NUM_SPANS; y++) { 18708 sig_pri_init_pri(&pris[y].pri); 18709 } 18710 pri_set_error(dahdi_pri_error); 18711 pri_set_message(dahdi_pri_message); 18712 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 18713 #ifdef HAVE_PRI_PROG_W_CAUSE 18714 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 18715 #endif 18716 #if defined(HAVE_PRI_CCSS) 18717 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks) 18718 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) { 18719 __unload_module(); 18720 return AST_MODULE_LOAD_FAILURE; 18721 } 18722 #endif /* defined(HAVE_PRI_CCSS) */ 18723 if (sig_pri_load( 18724 #if defined(HAVE_PRI_CCSS) 18725 dahdi_pri_cc_type 18726 #else 18727 NULL 18728 #endif /* defined(HAVE_PRI_CCSS) */ 18729 )) { 18730 __unload_module(); 18731 return AST_MODULE_LOAD_FAILURE; 18732 } 18733 #endif 18734 #if defined(HAVE_SS7) 18735 memset(linksets, 0, sizeof(linksets)); 18736 for (y = 0; y < NUM_SPANS; y++) { 18737 sig_ss7_init_linkset(&linksets[y].ss7); 18738 } 18739 ss7_set_error(dahdi_ss7_error); 18740 ss7_set_message(dahdi_ss7_message); 18741 #endif /* defined(HAVE_SS7) */ 18742 res = setup_dahdi(0); 18743 /* Make sure we can register our DAHDI channel type */ 18744 if (res) 18745 return AST_MODULE_LOAD_DECLINE; 18746 if (ast_channel_register(&dahdi_tech)) { 18747 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 18748 __unload_module(); 18749 return AST_MODULE_LOAD_FAILURE; 18750 } 18751 #ifdef HAVE_PRI 18752 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 18753 #endif 18754 #if defined(HAVE_SS7) 18755 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 18756 #endif /* defined(HAVE_SS7) */ 18757 #ifdef HAVE_OPENR2 18758 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 18759 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 18760 #endif 18761 18762 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 18763 /* register all the data providers */ 18764 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers)); 18765 memset(round_robin, 0, sizeof(round_robin)); 18766 ast_manager_register_xml("DAHDITransfer", 0, action_transfer); 18767 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup); 18768 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook); 18769 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon); 18770 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff); 18771 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels); 18772 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart); 18773 18774 ast_cond_init(&ss_thread_complete, NULL); 18775 18776 return res; 18777 }
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| int | reloading | |||
| ) | [static, read] |
< Current channel structure initializing
< TRUE if the channel interface already exists.
Definition at line 12339 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, analog_config_complete(), analog_lib_handles(), analog_new(), ANALOG_SIG_NONE, analog_pvt::answeronpolarityswitch, dahdi_pvt::answeronpolarityswitch, ARRAY_LEN, ast_calloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_copy_string(), ast_db_del(), ast_db_get(), ast_debug, ast_dsp_set_digitmode(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_log(), ast_mutex_init, ast_smdi_interface_find(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::callgroup, dahdi_pvt::callprogress, analog_pvt::callreturn, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, analog_pvt::callwaitingcallerid, dahdi_pvt::callwaitingcallerid, analog_pvt::cancallforward, dahdi_pvt::cancallforward, analog_pvt::canpark, dahdi_pvt::canpark, dahdi_pvt::cc_params, dahdi_chan_conf::chan, CHAN_PSEUDO, analog_pvt::channel, sig_pri_chan::channel, sig_ss7_chan::channel, dahdi_pvt::channel, sig_ss7_chan::cic, analog_pvt::cid_name, dahdi_pvt::cid_name, analog_pvt::cid_num, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, analog_pvt::cid_signalling, dahdi_pvt::cid_signalling, analog_pvt::cid_start, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, dahdi_pvt::confno, sig_ss7_chan::context, sig_pri_chan::context, context, dahdi_pvt::context, dahdi_iflist_insert(), dahdi_open(), dahdi_set_hook(), dahdi_sig2str(), dahdi_sig_pri_lib_handles(), dahdisig_to_analogsig(), analog_pvt::dahditrcallerid, dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, sig_pri_span::dialplan, sig_ss7_chan::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, analog_pvt::echotraining, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, ast_variable::file, dahdi_pvt::firstradio, analog_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), analog_pvt::hanguponpolarityswitch, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, sig_ss7_chan::hidecallerid, sig_pri_chan::hidecallerid, dahdi_pvt::hidecallerid, sig_pri_chan::hidecalleridname, dahdi_pvt::hidecalleridname, sig_pri_span::idledial, sig_pri_span::idleext, analog_pvt::immediate, sig_ss7_chan::immediate, sig_pri_chan::immediate, dahdi_pvt::immediate, sig_ss7_chan::inalarm, sig_pri_chan::inalarm, dahdi_pvt::inalarm, analog_pvt::inalarm, dahdi_pvt::inservice, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::law, dahdi_pvt::law_default, sig_ss7_chan::locallyblocked, dahdi_pvt::locallyblocked, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mailbox, dahdi_pvt::mailbox, sig_pri_span::minidle, sig_pri_span::minunused, sig_ss7_chan::mohinterpret, sig_pri_chan::mohinterpret, dahdi_pvt::mohinterpret, analog_pvt::mohsuggest, dahdi_pvt::mohsuggest, analog_pvt::msgstate, mwi_event_cb(), dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, ast_variable::next, dahdi_pvt::next, sig_pri_span::nodetype, sig_pri_span::numchans, analog_pvt::onhooktime, dahdi_pvt::oprmode, analog_pvt::outsigmod, dahdi_pvt::outsigmod, dahdi_pvt::parkinglot, analog_pvt::permcallwaiting, dahdi_pvt::permcallwaiting, analog_pvt::permhidecallerid, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, analog_pvt::polarityonanswerdelay, dahdi_pvt::polarityonanswerdelay, sig_pri_chan::priexclusive, dahdi_pvt::priexclusive, sig_pri_chan::priindication_oob, dahdi_pvt::priindication_oob, dahdi_pvt::propconfno, analog_pvt::pulse, dahdi_pvt::pulse, sig_pri_span::pvts, dahdi_pvt::radio, distRingData::range, sig_ss7_chan::remotelyblocked, dahdi_pvt::remotelyblocked, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, dahdi_pvt::ringt, analog_pvt::ringt, analog_pvt::ringt_base, dahdi_pvt::ringt_base, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, sig2str, SIG_BRI_PTMP, 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_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, sig_pri_chan_new(), SIG_PRI_LIB_HANDLE_CASES, sig_pri_set_alarm(), dahdi_pvt::sig_pvt, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sig_ss7_chan_new(), sig_ss7_set_alarm(), sigtype_to_signalling(), analog_pvt::smdi_iface, dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, analog_pvt::stripmsd, sig_ss7_chan::stripmsd, sig_pri_chan::stripmsd, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, sig_pri_span::switchtype, analog_pvt::threewaycalling, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, analog_pvt::transfer, dahdi_pvt::transfer, analog_pvt::transfertobusy, dahdi_pvt::transfertobusy, sig_pri_span::trunkgroup, dahdi_pvt::txdrc, dahdi_pvt::txgain, update_conf(), analog_pvt::use_callerid, sig_ss7_chan::use_callerid, sig_pri_chan::use_callerid, dahdi_pvt::use_callerid, sig_ss7_chan::use_callingpres, sig_pri_chan::use_callingpres, dahdi_pvt::use_callingpres, analog_pvt::use_smdi, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by build_channels(), and process_dahdi().
12340 { 12341 /* Make a dahdi_pvt structure for this interface */ 12342 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */ 12343 char fn[80]; 12344 struct dahdi_bufferinfo bi; 12345 12346 int res; 12347 #if defined(HAVE_PRI) 12348 int span = 0; 12349 #endif /* defined(HAVE_PRI) */ 12350 int here = 0;/*!< TRUE if the channel interface already exists. */ 12351 int x; 12352 struct analog_pvt *analog_p = NULL; 12353 struct dahdi_params p; 12354 #if defined(HAVE_PRI) 12355 struct dahdi_spaninfo si; 12356 struct sig_pri_chan *pri_chan = NULL; 12357 #endif /* defined(HAVE_PRI) */ 12358 #if defined(HAVE_SS7) 12359 struct sig_ss7_chan *ss7_chan = NULL; 12360 #endif /* defined(HAVE_SS7) */ 12361 12362 /* Search channel interface list to see if it already exists. */ 12363 for (tmp = iflist; tmp; tmp = tmp->next) { 12364 if (!tmp->destroy) { 12365 if (tmp->channel == channel) { 12366 /* The channel interface already exists. */ 12367 here = 1; 12368 break; 12369 } 12370 if (tmp->channel > channel) { 12371 /* No way it can be in the sorted list. */ 12372 tmp = NULL; 12373 break; 12374 } 12375 } 12376 } 12377 12378 if (!here && reloading != 1) { 12379 tmp = ast_calloc(1, sizeof(*tmp)); 12380 if (!tmp) { 12381 return NULL; 12382 } 12383 tmp->cc_params = ast_cc_config_params_init(); 12384 if (!tmp->cc_params) { 12385 ast_free(tmp); 12386 return NULL; 12387 } 12388 ast_mutex_init(&tmp->lock); 12389 ifcount++; 12390 for (x = 0; x < 3; x++) 12391 tmp->subs[x].dfd = -1; 12392 tmp->channel = channel; 12393 tmp->priindication_oob = conf->chan.priindication_oob; 12394 } 12395 12396 if (tmp) { 12397 int chan_sig = conf->chan.sig; 12398 12399 /* If there are variables in tmp before it is updated to match the new config, clear them */ 12400 if (reloading && tmp->vars) { 12401 ast_variables_destroy(tmp->vars); 12402 tmp->vars = NULL; 12403 } 12404 12405 12406 if (!here) { 12407 /* Can only get here if this is a new channel interface being created. */ 12408 if ((channel != CHAN_PSEUDO)) { 12409 int count = 0; 12410 12411 snprintf(fn, sizeof(fn), "%d", channel); 12412 /* Open non-blocking */ 12413 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12414 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */ 12415 usleep(1); 12416 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12417 count++; 12418 } 12419 /* Allocate a DAHDI structure */ 12420 if (tmp->subs[SUB_REAL].dfd < 0) { 12421 ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel); 12422 destroy_dahdi_pvt(tmp); 12423 return NULL; 12424 } 12425 memset(&p, 0, sizeof(p)); 12426 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12427 if (res < 0) { 12428 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 12429 destroy_dahdi_pvt(tmp); 12430 return NULL; 12431 } 12432 if (conf->is_sig_auto) 12433 chan_sig = sigtype_to_signalling(p.sigtype); 12434 if (p.sigtype != (chan_sig & 0x3ffff)) { 12435 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype)); 12436 destroy_dahdi_pvt(tmp); 12437 return NULL; 12438 } 12439 tmp->law_default = p.curlaw; 12440 tmp->law = p.curlaw; 12441 tmp->span = p.spanno; 12442 #if defined(HAVE_PRI) 12443 span = p.spanno - 1; 12444 #endif /* defined(HAVE_PRI) */ 12445 } else { 12446 chan_sig = 0; 12447 } 12448 tmp->sig = chan_sig; 12449 tmp->outsigmod = conf->chan.outsigmod; 12450 12451 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) { 12452 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp); 12453 if (!analog_p) { 12454 destroy_dahdi_pvt(tmp); 12455 return NULL; 12456 } 12457 tmp->sig_pvt = analog_p; 12458 } 12459 #if defined(HAVE_SS7) 12460 if (chan_sig == SIG_SS7) { 12461 struct dahdi_ss7 *ss7; 12462 int clear = 0; 12463 12464 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 12465 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12466 destroy_dahdi_pvt(tmp); 12467 return NULL; 12468 } 12469 12470 ss7 = ss7_resolve_linkset(cur_linkset); 12471 if (!ss7) { 12472 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 12473 destroy_dahdi_pvt(tmp); 12474 return NULL; 12475 } 12476 ss7->ss7.span = cur_linkset; 12477 if (cur_cicbeginswith < 0) { 12478 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 12479 destroy_dahdi_pvt(tmp); 12480 return NULL; 12481 } 12482 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7); 12483 if (!ss7_chan) { 12484 destroy_dahdi_pvt(tmp); 12485 return NULL; 12486 } 12487 tmp->sig_pvt = ss7_chan; 12488 tmp->ss7 = &ss7->ss7; 12489 12490 ss7_chan->channel = tmp->channel; 12491 ss7_chan->cic = cur_cicbeginswith++; 12492 12493 /* DB: Add CIC's DPC information */ 12494 ss7_chan->dpc = cur_defaultdpc; 12495 12496 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan; 12497 12498 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix)); 12499 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix)); 12500 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix)); 12501 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix)); 12502 12503 ss7->ss7.called_nai = conf->ss7.ss7.called_nai; 12504 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai; 12505 } 12506 #endif /* defined(HAVE_SS7) */ 12507 #ifdef HAVE_OPENR2 12508 if (chan_sig == SIG_MFCR2) { 12509 struct dahdi_mfcr2 *r2_link; 12510 r2_link = dahdi_r2_get_link(conf); 12511 if (!r2_link) { 12512 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 12513 destroy_dahdi_pvt(tmp); 12514 return NULL; 12515 } 12516 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 12517 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 12518 destroy_dahdi_pvt(tmp); 12519 return NULL; 12520 } 12521 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) { 12522 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 12523 destroy_dahdi_pvt(tmp); 12524 return NULL; 12525 } 12526 r2_link->pvts[r2_link->numchans++] = tmp; 12527 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 12528 tmp->subs[SUB_REAL].dfd, 12529 NULL, NULL); 12530 if (!tmp->r2chan) { 12531 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 12532 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 12533 destroy_dahdi_pvt(tmp); 12534 return NULL; 12535 } 12536 tmp->mfcr2 = r2_link; 12537 if (conf->mfcr2.call_files) { 12538 openr2_chan_enable_call_files(tmp->r2chan); 12539 } 12540 openr2_chan_set_client_data(tmp->r2chan, tmp); 12541 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 12542 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 12543 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 12544 tmp->mfcr2_category = conf->mfcr2.category; 12545 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 12546 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 12547 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 12548 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 12549 tmp->mfcr2call = 0; 12550 tmp->mfcr2_dnis_index = 0; 12551 tmp->mfcr2_ani_index = 0; 12552 } 12553 #endif 12554 #ifdef HAVE_PRI 12555 if (dahdi_sig_pri_lib_handles(chan_sig)) { 12556 int offset; 12557 int matchesdchan; 12558 int x,y; 12559 int myswitchtype = 0; 12560 12561 offset = 0; 12562 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 12563 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12564 destroy_dahdi_pvt(tmp); 12565 return NULL; 12566 } 12567 if (span >= NUM_SPANS) { 12568 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 12569 destroy_dahdi_pvt(tmp); 12570 return NULL; 12571 } else { 12572 si.spanno = 0; 12573 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12574 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12575 destroy_dahdi_pvt(tmp); 12576 return NULL; 12577 } 12578 /* Store the logical span first based upon the real span */ 12579 tmp->logicalspan = pris[span].prilogicalspan; 12580 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 12581 if (span < 0) { 12582 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 12583 destroy_dahdi_pvt(tmp); 12584 return NULL; 12585 } 12586 myswitchtype = conf->pri.pri.switchtype; 12587 /* Make sure this isn't a d-channel */ 12588 matchesdchan=0; 12589 for (x = 0; x < NUM_SPANS; x++) { 12590 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 12591 if (pris[x].dchannels[y] == tmp->channel) { 12592 matchesdchan = 1; 12593 break; 12594 } 12595 } 12596 } 12597 if (!matchesdchan) { 12598 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) { 12599 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype)); 12600 destroy_dahdi_pvt(tmp); 12601 return NULL; 12602 } 12603 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) { 12604 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype)); 12605 destroy_dahdi_pvt(tmp); 12606 return NULL; 12607 } 12608 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) { 12609 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan)); 12610 destroy_dahdi_pvt(tmp); 12611 return NULL; 12612 } 12613 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) { 12614 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial); 12615 destroy_dahdi_pvt(tmp); 12616 return NULL; 12617 } 12618 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) { 12619 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext); 12620 destroy_dahdi_pvt(tmp); 12621 return NULL; 12622 } 12623 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) { 12624 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused); 12625 destroy_dahdi_pvt(tmp); 12626 return NULL; 12627 } 12628 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) { 12629 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle); 12630 destroy_dahdi_pvt(tmp); 12631 return NULL; 12632 } 12633 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) { 12634 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 12635 pris[span].pri.trunkgroup); 12636 destroy_dahdi_pvt(tmp); 12637 return NULL; 12638 } 12639 12640 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel); 12641 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup); 12642 if (!pri_chan) { 12643 destroy_dahdi_pvt(tmp); 12644 return NULL; 12645 } 12646 tmp->sig_pvt = pri_chan; 12647 tmp->pri = &pris[span].pri; 12648 12649 tmp->priexclusive = conf->chan.priexclusive; 12650 12651 if (!tmp->pri->cc_params) { 12652 tmp->pri->cc_params = ast_cc_config_params_init(); 12653 if (!tmp->pri->cc_params) { 12654 destroy_dahdi_pvt(tmp); 12655 return NULL; 12656 } 12657 } 12658 ast_cc_copy_config_params(tmp->pri->cc_params, 12659 conf->chan.cc_params); 12660 12661 pris[span].pri.sig = chan_sig; 12662 pris[span].pri.nodetype = conf->pri.pri.nodetype; 12663 pris[span].pri.switchtype = myswitchtype; 12664 pris[span].pri.nsf = conf->pri.pri.nsf; 12665 pris[span].pri.dialplan = conf->pri.pri.dialplan; 12666 pris[span].pri.localdialplan = conf->pri.pri.localdialplan; 12667 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt; 12668 pris[span].pri.minunused = conf->pri.pri.minunused; 12669 pris[span].pri.minidle = conf->pri.pri.minidle; 12670 pris[span].pri.overlapdial = conf->pri.pri.overlapdial; 12671 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping; 12672 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval; 12673 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12674 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support; 12675 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12676 #ifdef HAVE_PRI_INBANDDISCONNECT 12677 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect; 12678 #endif 12679 #if defined(HAVE_PRI_CALL_HOLD) 12680 pris[span].pri.hold_disconnect_transfer = 12681 conf->pri.pri.hold_disconnect_transfer; 12682 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 12683 #if defined(HAVE_PRI_CCSS) 12684 pris[span].pri.cc_ptmp_recall_mode = 12685 conf->pri.pri.cc_ptmp_recall_mode; 12686 pris[span].pri.cc_qsig_signaling_link_req = 12687 conf->pri.pri.cc_qsig_signaling_link_req; 12688 pris[span].pri.cc_qsig_signaling_link_rsp = 12689 conf->pri.pri.cc_qsig_signaling_link_rsp; 12690 #endif /* defined(HAVE_PRI_CCSS) */ 12691 #if defined(HAVE_PRI_CALL_WAITING) 12692 pris[span].pri.max_call_waiting_calls = 12693 conf->pri.pri.max_call_waiting_calls; 12694 pris[span].pri.allow_call_waiting_calls = 12695 conf->pri.pri.allow_call_waiting_calls; 12696 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12697 pris[span].pri.transfer = conf->chan.transfer; 12698 pris[span].pri.facilityenable = conf->pri.pri.facilityenable; 12699 #if defined(HAVE_PRI_L2_PERSISTENCE) 12700 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence; 12701 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 12702 #if defined(HAVE_PRI_AOC_EVENTS) 12703 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag; 12704 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup; 12705 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 12706 if (chan_sig == SIG_BRI_PTMP) { 12707 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored; 12708 } else { 12709 /* Option does not apply to this line type. */ 12710 pris[span].pri.layer1_ignored = 0; 12711 } 12712 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag; 12713 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack; 12714 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding; 12715 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag)); 12716 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list)); 12717 #if defined(HAVE_PRI_MWI) 12718 ast_copy_string(pris[span].pri.mwi_mailboxes, 12719 conf->pri.pri.mwi_mailboxes, 12720 sizeof(pris[span].pri.mwi_mailboxes)); 12721 #endif /* defined(HAVE_PRI_MWI) */ 12722 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial)); 12723 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext)); 12724 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix)); 12725 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix)); 12726 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix)); 12727 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix)); 12728 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix)); 12729 pris[span].pri.resetinterval = conf->pri.pri.resetinterval; 12730 12731 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12732 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x]; 12733 } 12734 12735 #if defined(HAVE_PRI_CALL_WAITING) 12736 /* Channel initial config parameters. */ 12737 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd; 12738 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid; 12739 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname; 12740 pris[span].pri.ch_cfg.immediate = conf->chan.immediate; 12741 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive; 12742 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob; 12743 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid; 12744 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres; 12745 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context)); 12746 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret)); 12747 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12748 } else { 12749 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos); 12750 destroy_dahdi_pvt(tmp); 12751 return NULL; 12752 } 12753 } 12754 } 12755 #endif 12756 } else { 12757 /* already exists in interface list */ 12758 ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig)); 12759 chan_sig = tmp->sig; 12760 if (tmp->subs[SUB_REAL].dfd > -1) { 12761 memset(&p, 0, sizeof(p)); 12762 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12763 } 12764 } 12765 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 12766 switch (chan_sig) { 12767 case SIG_FXSKS: 12768 case SIG_FXSLS: 12769 case SIG_EM: 12770 case SIG_EM_E1: 12771 case SIG_EMWINK: 12772 case SIG_FEATD: 12773 case SIG_FEATDMF: 12774 case SIG_FEATDMF_TA: 12775 case SIG_FEATB: 12776 case SIG_E911: 12777 case SIG_SF: 12778 case SIG_SFWINK: 12779 case SIG_FGC_CAMA: 12780 case SIG_FGC_CAMAMF: 12781 case SIG_SF_FEATD: 12782 case SIG_SF_FEATDMF: 12783 case SIG_SF_FEATB: 12784 p.starttime = 250; 12785 break; 12786 } 12787 12788 if (tmp->radio) { 12789 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 12790 p.channo = channel; 12791 p.rxwinktime = 1; 12792 p.rxflashtime = 1; 12793 p.starttime = 1; 12794 p.debouncetime = 5; 12795 } else { 12796 p.channo = channel; 12797 /* Override timing settings based on config file */ 12798 if (conf->timing.prewinktime >= 0) 12799 p.prewinktime = conf->timing.prewinktime; 12800 if (conf->timing.preflashtime >= 0) 12801 p.preflashtime = conf->timing.preflashtime; 12802 if (conf->timing.winktime >= 0) 12803 p.winktime = conf->timing.winktime; 12804 if (conf->timing.flashtime >= 0) 12805 p.flashtime = conf->timing.flashtime; 12806 if (conf->timing.starttime >= 0) 12807 p.starttime = conf->timing.starttime; 12808 if (conf->timing.rxwinktime >= 0) 12809 p.rxwinktime = conf->timing.rxwinktime; 12810 if (conf->timing.rxflashtime >= 0) 12811 p.rxflashtime = conf->timing.rxflashtime; 12812 if (conf->timing.debouncetime >= 0) 12813 p.debouncetime = conf->timing.debouncetime; 12814 } 12815 12816 /* don't set parms on a pseudo-channel */ 12817 if (tmp->subs[SUB_REAL].dfd >= 0) 12818 { 12819 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 12820 if (res < 0) { 12821 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 12822 destroy_dahdi_pvt(tmp); 12823 return NULL; 12824 } 12825 } 12826 #if 1 12827 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 12828 memset(&bi, 0, sizeof(bi)); 12829 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 12830 if (!res) { 12831 bi.txbufpolicy = conf->chan.buf_policy; 12832 bi.rxbufpolicy = conf->chan.buf_policy; 12833 bi.numbufs = conf->chan.buf_no; 12834 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 12835 if (res < 0) { 12836 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 12837 } 12838 } else { 12839 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 12840 } 12841 tmp->buf_policy = conf->chan.buf_policy; 12842 tmp->buf_no = conf->chan.buf_no; 12843 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 12844 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 12845 tmp->faxbuf_no = conf->chan.faxbuf_no; 12846 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 12847 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 12848 * The reason the ioctl call above failed should to be determined before worrying about the 12849 * faxbuffer-related ioctl calls */ 12850 tmp->bufsize = bi.bufsize; 12851 } 12852 #endif 12853 tmp->immediate = conf->chan.immediate; 12854 tmp->transfertobusy = conf->chan.transfertobusy; 12855 if (chan_sig & __DAHDI_SIG_FXS) { 12856 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 12857 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 12858 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 12859 } 12860 tmp->ringt_base = ringt_base; 12861 tmp->firstradio = 0; 12862 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 12863 tmp->permcallwaiting = conf->chan.callwaiting; 12864 else 12865 tmp->permcallwaiting = 0; 12866 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 12867 tmp->destroy = 0; 12868 tmp->drings = conf->chan.drings; 12869 12870 /* 10 is a nice default. */ 12871 if (tmp->drings.ringnum[0].range == 0) 12872 tmp->drings.ringnum[0].range = 10; 12873 if (tmp->drings.ringnum[1].range == 0) 12874 tmp->drings.ringnum[1].range = 10; 12875 if (tmp->drings.ringnum[2].range == 0) 12876 tmp->drings.ringnum[2].range = 10; 12877 12878 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 12879 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 12880 tmp->threewaycalling = conf->chan.threewaycalling; 12881 tmp->adsi = conf->chan.adsi; 12882 tmp->use_smdi = conf->chan.use_smdi; 12883 tmp->permhidecallerid = conf->chan.hidecallerid; 12884 tmp->hidecalleridname = conf->chan.hidecalleridname; 12885 tmp->callreturn = conf->chan.callreturn; 12886 tmp->echocancel = conf->chan.echocancel; 12887 tmp->echotraining = conf->chan.echotraining; 12888 tmp->pulse = conf->chan.pulse; 12889 if (tmp->echocancel.head.tap_length) { 12890 tmp->echocanbridged = conf->chan.echocanbridged; 12891 } else { 12892 if (conf->chan.echocanbridged) 12893 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 12894 tmp->echocanbridged = 0; 12895 } 12896 tmp->busydetect = conf->chan.busydetect; 12897 tmp->busycount = conf->chan.busycount; 12898 tmp->busy_tonelength = conf->chan.busy_tonelength; 12899 tmp->busy_quietlength = conf->chan.busy_quietlength; 12900 tmp->callprogress = conf->chan.callprogress; 12901 tmp->waitfordialtone = conf->chan.waitfordialtone; 12902 tmp->cancallforward = conf->chan.cancallforward; 12903 tmp->dtmfrelax = conf->chan.dtmfrelax; 12904 tmp->callwaiting = tmp->permcallwaiting; 12905 tmp->hidecallerid = tmp->permhidecallerid; 12906 tmp->channel = channel; 12907 tmp->stripmsd = conf->chan.stripmsd; 12908 tmp->use_callerid = conf->chan.use_callerid; 12909 tmp->cid_signalling = conf->chan.cid_signalling; 12910 tmp->cid_start = conf->chan.cid_start; 12911 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 12912 tmp->restrictcid = conf->chan.restrictcid; 12913 tmp->use_callingpres = conf->chan.use_callingpres; 12914 if (tmp->usedistinctiveringdetection) { 12915 if (!tmp->use_callerid) { 12916 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 12917 tmp->use_callerid = 1; 12918 } 12919 } 12920 12921 if (tmp->cid_signalling == CID_SIG_SMDI) { 12922 if (!tmp->use_smdi) { 12923 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 12924 tmp->use_smdi = 1; 12925 } 12926 } 12927 if (tmp->use_smdi) { 12928 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 12929 if (!(tmp->smdi_iface)) { 12930 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 12931 tmp->use_smdi = 0; 12932 } 12933 } 12934 12935 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 12936 tmp->amaflags = conf->chan.amaflags; 12937 if (!here) { 12938 tmp->confno = -1; 12939 tmp->propconfno = -1; 12940 } 12941 tmp->canpark = conf->chan.canpark; 12942 tmp->transfer = conf->chan.transfer; 12943 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 12944 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 12945 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 12946 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 12947 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 12948 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 12949 tmp->cid_ton = 0; 12950 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) { 12951 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 12952 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 12953 } else { 12954 tmp->cid_num[0] = '\0'; 12955 tmp->cid_name[0] = '\0'; 12956 } 12957 #if defined(HAVE_PRI) 12958 if (dahdi_sig_pri_lib_handles(tmp->sig)) { 12959 tmp->cid_tag[0] = '\0'; 12960 } else 12961 #endif /* defined(HAVE_PRI) */ 12962 { 12963 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); 12964 } 12965 tmp->cid_subaddr[0] = '\0'; 12966 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 12967 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 12968 char *mailbox, *context; 12969 mailbox = context = ast_strdupa(tmp->mailbox); 12970 strsep(&context, "@"); 12971 if (ast_strlen_zero(context)) 12972 context = "default"; 12973 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL, 12974 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 12975 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 12976 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 12977 AST_EVENT_IE_END); 12978 } 12979 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 12980 tmp->mwisend_setting = conf->chan.mwisend_setting; 12981 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 12982 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 12983 #endif 12984 12985 tmp->group = conf->chan.group; 12986 tmp->callgroup = conf->chan.callgroup; 12987 tmp->pickupgroup= conf->chan.pickupgroup; 12988 if (conf->chan.vars) { 12989 struct ast_variable *v, *tmpvar; 12990 for (v = conf->chan.vars ; v ; v = v->next) { 12991 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 12992 tmpvar->next = tmp->vars; 12993 tmp->vars = tmpvar; 12994 } 12995 } 12996 } 12997 tmp->cid_rxgain = conf->chan.cid_rxgain; 12998 tmp->rxgain = conf->chan.rxgain; 12999 tmp->txgain = conf->chan.txgain; 13000 tmp->txdrc = conf->chan.txdrc; 13001 tmp->rxdrc = conf->chan.rxdrc; 13002 tmp->tonezone = conf->chan.tonezone; 13003 if (tmp->subs[SUB_REAL].dfd > -1) { 13004 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law); 13005 if (tmp->dsp) 13006 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 13007 update_conf(tmp); 13008 if (!here) { 13009 switch (chan_sig) { 13010 case SIG_PRI_LIB_HANDLE_CASES: 13011 case SIG_SS7: 13012 case SIG_MFCR2: 13013 break; 13014 default: 13015 /* Hang it up to be sure it's good */ 13016 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 13017 break; 13018 } 13019 } 13020 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 13021 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 13022 /* the dchannel is down so put the channel in alarm */ 13023 switch (tmp->sig) { 13024 #ifdef HAVE_PRI 13025 case SIG_PRI_LIB_HANDLE_CASES: 13026 sig_pri_set_alarm(tmp->sig_pvt, 1); 13027 break; 13028 #endif 13029 #if defined(HAVE_SS7) 13030 case SIG_SS7: 13031 sig_ss7_set_alarm(tmp->sig_pvt, 1); 13032 break; 13033 #endif /* defined(HAVE_SS7) */ 13034 default: 13035 /* The only sig submodule left should be sig_analog. */ 13036 analog_p = tmp->sig_pvt; 13037 if (analog_p) { 13038 analog_p->inalarm = 1; 13039 } 13040 tmp->inalarm = 1; 13041 break; 13042 } 13043 handle_alarms(tmp, res); 13044 } 13045 } 13046 13047 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13048 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13049 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13050 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 13051 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); 13052 13053 if (!here) { 13054 tmp->locallyblocked = 0; 13055 tmp->remotelyblocked = 0; 13056 switch (tmp->sig) { 13057 #if defined(HAVE_PRI) 13058 case SIG_PRI_LIB_HANDLE_CASES: 13059 tmp->inservice = 1;/* Inservice until actually implemented. */ 13060 #if defined(HAVE_PRI_SERVICE_MESSAGES) 13061 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0; 13062 if (chan_sig == SIG_PRI) { 13063 char db_chan_name[20]; 13064 char db_answer[5]; 13065 13066 /* 13067 * Initialize the active out-of-service status 13068 * and delete any record if the feature is not enabled. 13069 */ 13070 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); 13071 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 13072 unsigned *why; 13073 13074 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 13075 if (tmp->pri->enable_service_message_support) { 13076 char state; 13077 13078 sscanf(db_answer, "%1c:%30u", &state, why); 13079 13080 /* Ensure that only the implemented bits could be set.*/ 13081 *why &= (SRVST_NEAREND | SRVST_FAREND); 13082 } 13083 if (!*why) { 13084 ast_db_del(db_chan_name, SRVST_DBKEY); 13085 } 13086 } 13087 } 13088 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 13089 break; 13090 #endif /* defined(HAVE_PRI) */ 13091 #if defined(HAVE_SS7) 13092 case SIG_SS7: 13093 tmp->inservice = 0; 13094 break; 13095 #endif /* defined(HAVE_SS7) */ 13096 default: 13097 /* We default to in service on protocols that don't have a reset */ 13098 tmp->inservice = 1; 13099 break; 13100 } 13101 } 13102 13103 switch (tmp->sig) { 13104 #if defined(HAVE_PRI) 13105 case SIG_PRI_LIB_HANDLE_CASES: 13106 if (pri_chan) { 13107 pri_chan->channel = tmp->channel; 13108 pri_chan->hidecallerid = tmp->hidecallerid; 13109 pri_chan->hidecalleridname = tmp->hidecalleridname; 13110 pri_chan->immediate = tmp->immediate; 13111 pri_chan->inalarm = tmp->inalarm; 13112 pri_chan->priexclusive = tmp->priexclusive; 13113 pri_chan->priindication_oob = tmp->priindication_oob; 13114 pri_chan->use_callerid = tmp->use_callerid; 13115 pri_chan->use_callingpres = tmp->use_callingpres; 13116 ast_copy_string(pri_chan->context, tmp->context, 13117 sizeof(pri_chan->context)); 13118 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret, 13119 sizeof(pri_chan->mohinterpret)); 13120 pri_chan->stripmsd = tmp->stripmsd; 13121 } 13122 break; 13123 #endif /* defined(HAVE_PRI) */ 13124 #if defined(HAVE_SS7) 13125 case SIG_SS7: 13126 if (ss7_chan) { 13127 ss7_chan->inalarm = tmp->inalarm; 13128 13129 ss7_chan->stripmsd = tmp->stripmsd; 13130 ss7_chan->hidecallerid = tmp->hidecallerid; 13131 ss7_chan->use_callerid = tmp->use_callerid; 13132 ss7_chan->use_callingpres = tmp->use_callingpres; 13133 ss7_chan->immediate = tmp->immediate; 13134 ss7_chan->locallyblocked = tmp->locallyblocked; 13135 ss7_chan->remotelyblocked = tmp->remotelyblocked; 13136 ast_copy_string(ss7_chan->context, tmp->context, 13137 sizeof(ss7_chan->context)); 13138 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret, 13139 sizeof(ss7_chan->mohinterpret)); 13140 } 13141 break; 13142 #endif /* defined(HAVE_SS7) */ 13143 default: 13144 /* The only sig submodule left should be sig_analog. */ 13145 analog_p = tmp->sig_pvt; 13146 if (analog_p) { 13147 analog_p->channel = tmp->channel; 13148 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13149 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13150 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13151 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ 13152 analog_p->callreturn = conf->chan.callreturn; 13153 analog_p->cancallforward = conf->chan.cancallforward; 13154 analog_p->canpark = conf->chan.canpark; 13155 analog_p->dahditrcallerid = conf->chan.dahditrcallerid; 13156 analog_p->immediate = conf->chan.immediate; 13157 analog_p->permhidecallerid = conf->chan.permhidecallerid; 13158 analog_p->pulse = conf->chan.pulse; 13159 analog_p->threewaycalling = conf->chan.threewaycalling; 13160 analog_p->transfer = conf->chan.transfer; 13161 analog_p->transfertobusy = conf->chan.transfertobusy; 13162 analog_p->use_callerid = tmp->use_callerid; 13163 analog_p->use_smdi = tmp->use_smdi; 13164 analog_p->smdi_iface = tmp->smdi_iface; 13165 analog_p->outsigmod = ANALOG_SIG_NONE; 13166 analog_p->echotraining = conf->chan.echotraining; 13167 analog_p->cid_signalling = conf->chan.cid_signalling; 13168 analog_p->stripmsd = conf->chan.stripmsd; 13169 switch (conf->chan.cid_start) { 13170 case CID_START_POLARITY: 13171 analog_p->cid_start = ANALOG_CID_START_POLARITY; 13172 break; 13173 case CID_START_POLARITY_IN: 13174 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; 13175 break; 13176 case CID_START_DTMF_NOALERT: 13177 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; 13178 break; 13179 default: 13180 analog_p->cid_start = ANALOG_CID_START_RING; 13181 break; 13182 } 13183 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; 13184 analog_p->ringt = conf->chan.ringt; 13185 analog_p->ringt_base = ringt_base; 13186 analog_p->onhooktime = time(NULL); 13187 if (chan_sig & __DAHDI_SIG_FXO) { 13188 memset(&p, 0, sizeof(p)); 13189 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 13190 if (!res) { 13191 analog_p->fxsoffhookstate = p.rxisoffhook; 13192 } 13193 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 13194 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 13195 #endif 13196 } 13197 analog_p->msgstate = -1; 13198 13199 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); 13200 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); 13201 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); 13202 13203 analog_config_complete(analog_p); 13204 } 13205 break; 13206 } 13207 #if defined(HAVE_PRI) 13208 if (tmp->channel == CHAN_PSEUDO) { 13209 /* 13210 * Save off pseudo channel buffer policy values for dynamic creation of 13211 * no B channel interfaces. 13212 */ 13213 dahdi_pseudo_parms.buf_no = tmp->buf_no; 13214 dahdi_pseudo_parms.buf_policy = tmp->buf_policy; 13215 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no; 13216 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy; 13217 } 13218 #endif /* defined(HAVE_PRI) */ 13219 } 13220 if (tmp && !here) { 13221 /* Add the new channel interface to the sorted channel interface list. */ 13222 dahdi_iflist_insert(tmp); 13223 } 13224 return tmp; 13225 }
| static void monitor_pfds_clean | ( | void * | arg | ) | [static] |
Definition at line 11715 of file chan_dahdi.c.
References ast_free.
Referenced by do_monitor().
11715 { 11716 struct pollfd **pfds = arg; 11717 ast_free(*pfds); 11718 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 486 of file chan_dahdi.c.
Referenced by mkintf().
00487 { 00488 /* This module does not handle MWI in an event-based manner. However, it 00489 * subscribes to MWI for each mailbox that is configured so that the core 00490 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00491 * event cache instead of checking the mailbox directly. */ 00492 }
| static int mwi_send_init | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 11262 of file chan_dahdi.c.
References ast_callerid_vmwi_generate(), ast_calloc, ast_free, AST_LAW, ast_log(), CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
11263 { 11264 int x; 11265 11266 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11267 /* Determine how this spill is to be sent */ 11268 if (pvt->mwisend_rpas) { 11269 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11270 pvt->mwisendactive = 1; 11271 } else if (pvt->mwisend_fsk) { 11272 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11273 pvt->mwisendactive = 1; 11274 } else { 11275 pvt->mwisendactive = 0; 11276 return 0; 11277 } 11278 #else 11279 if (mwisend_rpas) { 11280 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11281 } else { 11282 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11283 } 11284 pvt->mwisendactive = 1; 11285 #endif 11286 11287 if (pvt->cidspill) { 11288 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 11289 ast_free(pvt->cidspill); 11290 pvt->cidspill = NULL; 11291 pvt->cidpos = 0; 11292 pvt->cidlen = 0; 11293 } 11294 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 11295 if (!pvt->cidspill) { 11296 pvt->mwisendactive = 0; 11297 return -1; 11298 } 11299 x = DAHDI_FLUSH_BOTH; 11300 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 11301 x = 3000; 11302 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11304 if (pvt->mwisend_fsk) { 11305 #endif 11306 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 11307 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 11308 pvt->cidpos = 0; 11309 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11310 } 11311 #endif 11312 return 0; 11313 }
| static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
| int | num_read | |||
| ) | [static] |
Definition at line 11315 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
11316 { 11317 struct timeval now; 11318 int res; 11319 11320 /* sanity check to catch if this had been interrupted previously 11321 * i.e. state says there is more to do but there is no spill allocated 11322 */ 11323 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 11324 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11325 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11326 /* Normal processing -- Perform mwi send action */ 11327 switch ( pvt->mwisend_data.mwisend_current) { 11328 case MWI_SEND_SA: 11329 /* Send the Ring Pulse Signal Alert */ 11330 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 11331 if (res) { 11332 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 11333 goto quit; 11334 } 11335 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 11336 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 11337 break; 11338 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 11339 break; 11340 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 11341 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11342 if (pvt->mwisend_fsk) { 11343 #endif 11344 gettimeofday(&now, NULL); 11345 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 11346 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11347 } 11348 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11349 } else { /* support for mwisendtype=nofsk */ 11350 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11351 } 11352 #endif 11353 break; 11354 case MWI_SEND_SPILL: 11355 /* We read some number of bytes. Write an equal amount of data */ 11356 if(0 < num_read) { 11357 if (num_read > pvt->cidlen - pvt->cidpos) 11358 num_read = pvt->cidlen - pvt->cidpos; 11359 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 11360 if (res > 0) { 11361 pvt->cidpos += res; 11362 if (pvt->cidpos >= pvt->cidlen) { 11363 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11364 } 11365 } else { 11366 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 11367 goto quit; 11368 } 11369 } 11370 break; 11371 case MWI_SEND_CLEANUP: 11372 /* For now, do nothing */ 11373 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11374 break; 11375 default: 11376 /* Should not get here, punt*/ 11377 goto quit; 11378 } 11379 } 11380 11381 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 11382 if (pvt->cidspill) { 11383 ast_free(pvt->cidspill); 11384 pvt->cidspill = NULL; 11385 pvt->cidpos = 0; 11386 pvt->cidlen = 0; 11387 } 11388 pvt->mwisendactive = 0; 11389 } 11390 return 0; 11391 quit: 11392 if (pvt->cidspill) { 11393 ast_free(pvt->cidspill); 11394 pvt->cidspill = NULL; 11395 pvt->cidpos = 0; 11396 pvt->cidlen = 0; 11397 } 11398 pvt->mwisendactive = 0; 11399 return -1; 11400 }
| static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
| int | event | |||
| ) | [static] |
Definition at line 11402 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA_WAIT, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
11403 { 11404 int handled = 0; 11405 11406 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11407 switch (event) { 11408 case DAHDI_EVENT_RINGEROFF: 11409 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 11410 handled = 1; 11411 11412 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 11413 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno)); 11414 ast_free(pvt->cidspill); 11415 pvt->cidspill = NULL; 11416 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11417 pvt->mwisendactive = 0; 11418 } else { 11419 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 11420 gettimeofday(&pvt->mwisend_data.pause, NULL); 11421 } 11422 } 11423 break; 11424 /* Going off hook, I need to punt this spill */ 11425 case DAHDI_EVENT_RINGOFFHOOK: 11426 if (pvt->cidspill) { 11427 ast_free(pvt->cidspill); 11428 pvt->cidspill = NULL; 11429 pvt->cidpos = 0; 11430 pvt->cidlen = 0; 11431 } 11432 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11433 pvt->mwisendactive = 0; 11434 break; 11435 case DAHDI_EVENT_RINGERON: 11436 case DAHDI_EVENT_HOOKCOMPLETE: 11437 break; 11438 default: 11439 break; 11440 } 11441 } 11442 return handled; 11443 }
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 11110 of file chan_dahdi.c.
References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), ast_free, ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_get(), callerid_new(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), callerid_state::flags, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitoractive, name, notify_message(), dahdi_pvt::oprmode, mwi_thread_data::pvt, dahdi_pvt::radio, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
11111 { 11112 struct mwi_thread_data *mtd = data; 11113 struct callerid_state *cs; 11114 pthread_t threadid; 11115 int samples = 0; 11116 char *name, *number; 11117 int flags; 11118 int i, res; 11119 unsigned int spill_done = 0; 11120 int spill_result = -1; 11121 11122 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 11123 goto quit_no_clean; 11124 } 11125 11126 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 11127 11128 bump_gains(mtd->pvt); 11129 11130 for (;;) { 11131 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 11132 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 11133 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 11134 goto quit; 11135 } 11136 11137 if (i & DAHDI_IOMUX_SIGEVENT) { 11138 struct ast_channel *chan; 11139 11140 /* If we get an event, screen out events that we do not act on. 11141 * Otherwise, cancel and go to the simple switch to let it deal with it. 11142 */ 11143 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 11144 11145 switch (res) { 11146 case DAHDI_EVENT_NEONMWI_ACTIVE: 11147 case DAHDI_EVENT_NEONMWI_INACTIVE: 11148 case DAHDI_EVENT_NONE: 11149 case DAHDI_EVENT_BITSCHANGED: 11150 break; 11151 case DAHDI_EVENT_NOALARM: 11152 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11153 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11154 11155 analog_p->inalarm = 0; 11156 } 11157 mtd->pvt->inalarm = 0; 11158 handle_clear_alarms(mtd->pvt); 11159 break; 11160 case DAHDI_EVENT_ALARM: 11161 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11162 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11163 11164 analog_p->inalarm = 1; 11165 } 11166 mtd->pvt->inalarm = 1; 11167 res = get_alarms(mtd->pvt); 11168 handle_alarms(mtd->pvt, res); 11169 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 11170 default: 11171 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res)); 11172 callerid_free(cs); 11173 11174 restore_gains(mtd->pvt); 11175 mtd->pvt->ringt = mtd->pvt->ringt_base; 11176 11177 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) { 11178 int result; 11179 11180 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11181 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan); 11182 } else { 11183 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11184 } 11185 if (result) { 11186 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 11187 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11188 if (res < 0) 11189 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 11190 ast_hangup(chan); 11191 } 11192 } else { 11193 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 11194 } 11195 goto quit_no_clean; 11196 } 11197 } else if (i & DAHDI_IOMUX_READ) { 11198 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 11199 if (errno != ELAST) { 11200 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 11201 goto quit; 11202 } 11203 break; 11204 } 11205 samples += res; 11206 if (!spill_done) { 11207 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 11208 /* 11209 * The previous diagnostic message output likely 11210 * explains why it failed. 11211 */ 11212 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 11213 break; 11214 } else if (spill_result) { 11215 spill_done = 1; 11216 } 11217 } else { 11218 /* keep reading data until the energy level drops below the threshold 11219 so we don't get another 'trigger' on the remaining carrier signal 11220 */ 11221 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 11222 break; 11223 } 11224 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 11225 break; 11226 } 11227 } 11228 11229 if (spill_result == 1) { 11230 callerid_get(cs, &name, &number, &flags); 11231 if (flags & CID_MSGWAITING) { 11232 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 11233 notify_message(mtd->pvt->mailbox, 1); 11234 } else if (flags & CID_NOMSGWAITING) { 11235 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 11236 notify_message(mtd->pvt->mailbox, 0); 11237 } else { 11238 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 11239 } 11240 } 11241 11242 11243 quit: 11244 callerid_free(cs); 11245 11246 restore_gains(mtd->pvt); 11247 11248 quit_no_clean: 11249 mtd->pvt->mwimonitoractive = 0; 11250 ast_free(mtd); 11251 11252 return NULL; 11253 }
| static void my_all_subchannels_hungup | ( | void * | pvt | ) | [static] |
Definition at line 2439 of file chan_dahdi.c.
References ast_dsp_free(), ast_log(), dahdi_pvt::channel, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, errno, dahdi_pvt::faxhandled, dahdi_pvt::law, dahdi_pvt::law_default, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.
02440 { 02441 struct dahdi_pvt *p = pvt; 02442 int res, law; 02443 02444 p->faxhandled = 0; 02445 p->didtdd = 0; 02446 02447 if (p->dsp) { 02448 ast_dsp_free(p->dsp); 02449 p->dsp = NULL; 02450 } 02451 02452 p->law = p->law_default; 02453 law = p->law_default; 02454 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02455 if (res < 0) 02456 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02457 02458 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02459 02460 #if 1 02461 { 02462 int i; 02463 p->owner = NULL; 02464 /* Cleanup owners here */ 02465 for (i = 0; i < 3; i++) { 02466 p->subs[i].owner = NULL; 02467 } 02468 } 02469 #endif 02470 02471 reset_conf(p); 02472 if (num_restart_pending == 0) { 02473 restart_monitor(); 02474 } 02475 }
| static int my_allocate_sub | ( | void * | pvt, | |
| enum analog_sub | analogsub | |||
| ) | [static] |
Definition at line 2750 of file chan_dahdi.c.
References alloc_sub(), and analogsub_to_dahdisub().
02751 { 02752 struct dahdi_pvt *p = pvt; 02753 02754 return alloc_sub(p, analogsub_to_dahdisub(analogsub)); 02755 }
| static void my_answer_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2988 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().
02989 { 02990 struct dahdi_pvt *p = pvt; 02991 02992 if (!p->answeronpolarityswitch) { 02993 return; 02994 } 02995 02996 my_set_polarity(pvt, 1); 02997 }
| static int my_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1931 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(), and send_callerid().
01932 { 01933 struct dahdi_pvt *p = pvt; 01934 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01935 if (p->cidspill) { 01936 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01937 ast_free(p->cidspill); 01938 } 01939 01940 /* 01941 * SAS: Subscriber Alert Signal, 440Hz for 300ms 01942 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 01943 */ 01944 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01945 return -1; 01946 save_conference(p); 01947 /* Silence */ 01948 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01949 if (!p->callwaitrings && p->callwaitingcallerid) { 01950 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01951 p->callwaitcas = 1; 01952 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01953 } else { 01954 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01955 p->callwaitcas = 0; 01956 p->cidlen = 2400 + READ_SIZE * 4; 01957 } 01958 p->cidpos = 0; 01959 send_callerid(p); 01960 01961 return 0; 01962 }
| static void my_cancel_cidspill | ( | void * | pvt | ) | [static] |
Definition at line 2389 of file chan_dahdi.c.
References ast_free, dahdi_pvt::cidspill, and restore_conference().
02390 { 02391 struct dahdi_pvt *p = pvt; 02392 02393 ast_free(p->cidspill); 02394 p->cidspill = NULL; 02395 restore_conference(p); 02396 }
| static int my_check_confirmanswer | ( | void * | pvt | ) | [static] |
Definition at line 2372 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02373 { 02374 struct dahdi_pvt *p = pvt; 02375 if (p->confirmanswer) { 02376 return 1; 02377 } 02378 02379 return 0; 02380 }
| static int my_check_for_conference | ( | void * | pvt | ) | [static] |
Definition at line 2549 of file chan_dahdi.c.
References check_for_conference().
02550 { 02551 struct dahdi_pvt *p = pvt; 02552 return check_for_conference(p); 02553 }
| static int my_check_waitingfordt | ( | void * | pvt | ) | [static] |
Definition at line 2355 of file chan_dahdi.c.
References dahdi_pvt::waitingfordt.
02356 { 02357 struct dahdi_pvt *p = pvt; 02358 02359 if (p->waitingfordt.tv_sec) { 02360 return 1; 02361 } 02362 02363 return 0; 02364 }
| static int my_complete_conference_update | ( | void * | pvt, | |
| int | needconference | |||
| ) | [static] |
Definition at line 2499 of file chan_dahdi.c.
References conf_add(), dahdi_pvt::confno, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
02500 { 02501 struct dahdi_pvt *p = pvt; 02502 int needconf = needconference; 02503 int x; 02504 int useslavenative; 02505 struct dahdi_pvt *slave = NULL; 02506 02507 useslavenative = isslavenative(p, &slave); 02508 02509 /* If we have a slave, add him to our conference now. or DAX 02510 if this is slave native */ 02511 for (x = 0; x < MAX_SLAVES; x++) { 02512 if (p->slaves[x]) { 02513 if (useslavenative) 02514 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02515 else { 02516 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02517 needconf++; 02518 } 02519 } 02520 } 02521 /* If we're supposed to be in there, do so now */ 02522 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02523 if (useslavenative) 02524 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02525 else { 02526 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02527 needconf++; 02528 } 02529 } 02530 /* If we have a master, add ourselves to his conference */ 02531 if (p->master) { 02532 if (isslavenative(p->master, NULL)) { 02533 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02534 } else { 02535 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02536 } 02537 } 02538 if (!needconf) { 02539 /* Nobody is left (or should be left) in our conference. 02540 Kill it. */ 02541 p->confno = -1; 02542 } 02543 02544 return 0; 02545 }
| static int my_conf_add | ( | void * | pvt, | |
| enum analog_sub | sub | |||
| ) | [static] |
Definition at line 2489 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.
02490 { 02491 struct dahdi_pvt *p = pvt; 02492 int x = analogsub_to_dahdisub(sub); 02493 02494 return conf_add(p, &p->subs[x], x, 0); 02495 }
| static int my_conf_del | ( | void * | pvt, | |
| enum analog_sub | sub | |||
| ) | [static] |
Definition at line 2479 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.
02480 { 02481 struct dahdi_pvt *p = pvt; 02482 int x = analogsub_to_dahdisub(sub); 02483 02484 return conf_del(p, &p->subs[x], x); 02485 }
| static int my_confmute | ( | void * | pvt, | |
| int | mute | |||
| ) | [static] |
Definition at line 2398 of file chan_dahdi.c.
References dahdi_confmute().
02399 { 02400 struct dahdi_pvt *p = pvt; 02401 return dahdi_confmute(p, mute); 02402 }
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 9372 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, READ_SIZE, and dahdi_pvt::subs.
Referenced by dahdi_write().
09373 { 09374 int sent=0; 09375 int size; 09376 int res; 09377 int fd; 09378 fd = p->subs[idx].dfd; 09379 while (len) { 09380 size = len; 09381 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 09382 size = (linear ? READ_SIZE * 2 : READ_SIZE); 09383 res = write(fd, buf, size); 09384 if (res != size) { 09385 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 09386 return sent; 09387 } 09388 len -= size; 09389 buf += size; 09390 } 09391 return sent; 09392 }
| static void my_deadlock_avoidance_private | ( | void * | pvt | ) | [static] |
Definition at line 2149 of file chan_dahdi.c.
References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.
02150 { 02151 struct dahdi_pvt *p = pvt; 02152 02153 DEADLOCK_AVOIDANCE(&p->lock); 02154 }
| static void my_decrease_ss_count | ( | void | ) | [static] |
Definition at line 2431 of file chan_dahdi.c.
References ast_cond_signal, ast_mutex_lock, and ast_mutex_unlock.
02432 { 02433 ast_mutex_lock(&ss_thread_lock); 02434 ss_thread_count--; 02435 ast_cond_signal(&ss_thread_complete); 02436 ast_mutex_unlock(&ss_thread_lock); 02437 }
| static int my_dial_digits | ( | void * | pvt, | |
| enum analog_sub | sub, | |||
| struct analog_dialoperation * | dop | |||
| ) | [static] |
Definition at line 3022 of file chan_dahdi.c.
References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, analogsub_to_dahdisub(), ast_copy_string(), ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, analog_dialoperation::dialstr, errno, LOG_ERROR, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.
03023 { 03024 int index = analogsub_to_dahdisub(sub); 03025 int res; 03026 struct dahdi_pvt *p = pvt; 03027 struct dahdi_dialoperation ddop; 03028 03029 if (dop->op != ANALOG_DIAL_OP_REPLACE) { 03030 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n"); 03031 return -1; 03032 } 03033 03034 if (sub != ANALOG_SUB_REAL) { 03035 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n", 03036 dop->dialstr, p->channel, sub); 03037 return -1; 03038 } 03039 03040 ddop.op = DAHDI_DIAL_OP_REPLACE; 03041 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr)); 03042 03043 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr); 03044 03045 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop); 03046 if (res == -1) { 03047 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno)); 03048 } 03049 03050 return res; 03051 }
| static int my_distinctive_ring | ( | struct ast_channel * | chan, | |
| void * | pvt, | |||
| int | idx, | |||
| int * | ringdata | |||
| ) | [static] |
Definition at line 1795 of file chan_dahdi.c.
References ast_copy_string(), ast_hangup(), ast_log(), ast_verb, ast_channel::context, dahdi_pvt::context, ringContextData::contextData, dahdi_get_event(), dahdi_setlinear(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::drings, errno, event2str(), analog_pvt::inalarm, dahdi_pvt::inalarm, dahdi_subchannel::linear, LOG_NOTICE, LOG_WARNING, distRingData::range, restore_gains(), distRingData::ring, RING_PATTERNS, dahdi_distRings::ringContext, dahdi_distRings::ringnum, analog_pvt::ringt, analog_pvt::ringt_base, S_OR, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.
01796 { 01797 unsigned char buf[256]; 01798 int distMatches; 01799 int curRingData[RING_PATTERNS]; 01800 int receivedRingT; 01801 int counter1; 01802 int counter; 01803 int i; 01804 int res; 01805 int checkaftercid = 0; 01806 01807 struct dahdi_pvt *p = pvt; 01808 struct analog_pvt *analog_p = p->sig_pvt; 01809 01810 if (ringdata == NULL) { 01811 ringdata = curRingData; 01812 } else { 01813 checkaftercid = 1; 01814 } 01815 01816 /* We must have a ring by now, so, if configured, lets try to listen for 01817 * distinctive ringing */ 01818 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { 01819 /* Clear the current ring data array so we don't have old data in it. */ 01820 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++) 01821 ringdata[receivedRingT] = 0; 01822 receivedRingT = 0; 01823 if (checkaftercid && distinctiveringaftercid) 01824 ast_verb(3, "Detecting post-CID distinctive ring\n"); 01825 /* Check to see if context is what it should be, if not set to be. */ 01826 else if (strcmp(p->context,p->defcontext) != 0) { 01827 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 01828 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 01829 } 01830 01831 for (;;) { 01832 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 01833 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 01834 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 01835 ast_hangup(chan); 01836 return 1; 01837 } 01838 if (i & DAHDI_IOMUX_SIGEVENT) { 01839 res = dahdi_get_event(p->subs[idx].dfd); 01840 if (res == DAHDI_EVENT_NOALARM) { 01841 p->inalarm = 0; 01842 analog_p->inalarm = 0; 01843 } 01844 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 01845 res = 0; 01846 /* Let us detect distinctive ring */ 01847 01848 ringdata[receivedRingT] = analog_p->ringt; 01849 01850 if (analog_p->ringt < analog_p->ringt_base/2) 01851 break; 01852 /* Increment the ringT counter so we can match it against 01853 values in chan_dahdi.conf for distinctive ring */ 01854 if (++receivedRingT == RING_PATTERNS) 01855 break; 01856 } else if (i & DAHDI_IOMUX_READ) { 01857 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 01858 if (res < 0) { 01859 if (errno != ELAST) { 01860 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01861 ast_hangup(chan); 01862 return 1; 01863 } 01864 break; 01865 } 01866 if (analog_p->ringt > 0) { 01867 if (!(--analog_p->ringt)) { 01868 res = -1; 01869 break; 01870 } 01871 } 01872 } 01873 } 01874 } 01875 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { 01876 /* this only shows up if you have n of the dring patterns filled in */ 01877 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); 01878 for (counter = 0; counter < 3; counter++) { 01879 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ 01880 distMatches = 0; 01881 /* this only shows up if you have n of the dring patterns filled in */ 01882 ast_verb(3, "Checking %d,%d,%d\n", 01883 p->drings.ringnum[counter].ring[0], 01884 p->drings.ringnum[counter].ring[1], 01885 p->drings.ringnum[counter].ring[2]); 01886 for (counter1 = 0; counter1 < 3; counter1++) { 01887 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 01888 if (p->drings.ringnum[counter].ring[counter1] == -1) { 01889 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 01890 ringdata[counter1]); 01891 distMatches++; 01892 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 01893 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 01894 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 01895 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 01896 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 01897 distMatches++; 01898 } 01899 } 01900 01901 if (distMatches == 3) { 01902 /* The ring matches, set the context to whatever is for distinctive ring.. */ 01903 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 01904 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 01905 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 01906 break; 01907 } 01908 } 01909 } 01910 /* Restore linear mode (if appropriate) for Caller*ID processing */ 01911 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 01912 restore_gains(p); 01913 01914 return 0; 01915 }
| static int my_dsp_reset_and_flush_digits | ( | void * | pvt | ) | [static] |
Definition at line 1999 of file chan_dahdi.c.
References ast_dsp_digitreset(), and dahdi_pvt::dsp.
02000 { 02001 struct dahdi_pvt *p = pvt; 02002 if (p->dsp) 02003 ast_dsp_digitreset(p->dsp); 02004 02005 return 0; 02006 }
| static int my_dsp_set_digitmode | ( | void * | pvt, | |
| enum analog_dsp_digitmode | mode | |||
| ) | [static] |
Definition at line 2008 of file chan_dahdi.c.
References ANALOG_DIGITMODE_DTMF, ANALOG_DIGITMODE_MF, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_log(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, dahdi_pvt::hardwaredtmf, and LOG_ERROR.
02009 { 02010 struct dahdi_pvt *p = pvt; 02011 02012 if (p->channel == CHAN_PSEUDO) 02013 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n"); 02014 02015 if (mode == ANALOG_DIGITMODE_DTMF) { 02016 /* If we do hardware dtmf, no need for a DSP */ 02017 if (p->hardwaredtmf) { 02018 if (p->dsp) { 02019 ast_dsp_free(p->dsp); 02020 p->dsp = NULL; 02021 } 02022 return 0; 02023 } 02024 02025 if (!p->dsp) { 02026 p->dsp = ast_dsp_new(); 02027 if (!p->dsp) { 02028 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02029 return -1; 02030 } 02031 } 02032 02033 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 02034 } else if (mode == ANALOG_DIGITMODE_MF) { 02035 if (!p->dsp) { 02036 p->dsp = ast_dsp_new(); 02037 if (!p->dsp) { 02038 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02039 return -1; 02040 } 02041 } 02042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 02043 } 02044 return 0; 02045 }
| static int my_flash | ( | void * | pvt | ) | [static] |
Definition at line 2947 of file chan_dahdi.c.
References dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
| static void my_get_and_handle_alarms | ( | void * | pvt | ) | [static] |
Definition at line 2235 of file chan_dahdi.c.
References get_alarms(), and handle_alarms().
02236 { 02237 int res; 02238 struct dahdi_pvt *p = pvt; 02239 02240 res = get_alarms(p); 02241 handle_alarms(p, res); 02242 }
| static int my_get_callerid | ( | void * | pvt, | |
| char * | namebuf, | |||
| char * | numbuf, | |||
| enum analog_event * | ev, | |||
| size_t | timeout | |||
| ) | [static] |
Definition at line 1721 of file chan_dahdi.c.
References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_copy_string(), ast_debug, AST_LAW, ast_log(), callerid_feed(), callerid_feed_jp(), callerid_get(), CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cs, dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, errno, LOG_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.
01722 { 01723 struct dahdi_pvt *p = pvt; 01724 struct analog_pvt *analog_p = p->sig_pvt; 01725 struct pollfd poller; 01726 char *name, *num; 01727 int index = SUB_REAL; 01728 int res; 01729 unsigned char buf[256]; 01730 int flags; 01731 01732 poller.fd = p->subs[SUB_REAL].dfd; 01733 poller.events = POLLPRI | POLLIN; 01734 poller.revents = 0; 01735 01736 res = poll(&poller, 1, timeout); 01737 01738 if (poller.revents & POLLPRI) { 01739 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd)); 01740 return 1; 01741 } 01742 01743 if (poller.revents & POLLIN) { 01744 /*** NOTES ***/ 01745 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function 01746 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until 01747 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be 01748 * a failure and die, and returning 2 means no event was received. */ 01749 res = read(p->subs[index].dfd, buf, sizeof(buf)); 01750 if (res < 0) { 01751 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01752 return -1; 01753 } 01754 01755 if (analog_p->ringt > 0) { 01756 if (!(--analog_p->ringt)) { 01757 /* only return if we timeout from a ring event */ 01758 return -1; 01759 } 01760 } 01761 01762 if (p->cid_signalling == CID_SIG_V23_JP) { 01763 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); 01764 } else { 01765 res = callerid_feed(p->cs, buf, res, AST_LAW(p)); 01766 } 01767 if (res < 0) { 01768 /* 01769 * The previous diagnostic message output likely 01770 * explains why it failed. 01771 */ 01772 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 01773 return -1; 01774 } 01775 01776 if (res == 1) { 01777 callerid_get(p->cs, &name, &num, &flags); 01778 if (name) 01779 ast_copy_string(namebuf, name, ANALOG_MAX_CID); 01780 if (num) 01781 ast_copy_string(numbuf, num, ANALOG_MAX_CID); 01782 01783 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags); 01784 return 0; 01785 } 01786 } 01787 01788 *ev = ANALOG_EVENT_NONE; 01789 return 2; 01790 }
| static int my_get_event | ( | void * | pvt | ) | [static] |
Definition at line 2880 of file chan_dahdi.c.
References dahdi_get_event(), dahdievent_to_analogevent(), dahdi_subchannel::dfd, dahdi_pvt::fake_event, SUB_REAL, and dahdi_pvt::subs.
02881 { 02882 struct dahdi_pvt *p = pvt; 02883 int res; 02884 02885 if (p->fake_event) { 02886 res = p->fake_event; 02887 p->fake_event = 0; 02888 } else 02889 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 02890 02891 return dahdievent_to_analogevent(res); 02892 }
| static const char* my_get_orig_dialstring | ( | void * | pvt | ) | [static] |
Definition at line 2417 of file chan_dahdi.c.
References dahdi_pvt::dialstring.
02418 { 02419 struct dahdi_pvt *p = pvt; 02420 02421 return p->dialstring; 02422 }
| static void* my_get_sigpvt_bridged_channel | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 2244 of file chan_dahdi.c.
References analog_lib_handles(), ast_bridged_channel(), dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, ast_channel::tech, and ast_channel::tech_pvt.
02245 { 02246 struct ast_channel *bridged = ast_bridged_channel(chan); 02247 02248 if (bridged && bridged->tech == &dahdi_tech) { 02249 struct dahdi_pvt *p = bridged->tech_pvt; 02250 02251 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 02252 return p->sig_pvt; 02253 } 02254 } 02255 return NULL; 02256 }
| static int my_get_sub_fd | ( | void * | pvt, | |
| enum analog_sub | sub | |||
| ) | [static] |
Definition at line 2258 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02259 { 02260 struct dahdi_pvt *p = pvt; 02261 int dahdi_sub = analogsub_to_dahdisub(sub); 02262 return p->subs[dahdi_sub].dfd; 02263 }
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 9849 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by analog_ss_thread().
09850 { 09851 char c; 09852 09853 *str = 0; /* start with empty output buffer */ 09854 for (;;) 09855 { 09856 /* Wait for the first digit (up to specified ms). */ 09857 c = ast_waitfordigit(chan, ms); 09858 /* if timeout, hangup or error, return as such */ 09859 if (c < 1) 09860 return c; 09861 *str++ = c; 09862 *str = 0; 09863 if (strchr(term, c)) 09864 return 1; 09865 } 09866 }
| static void my_handle_dtmf | ( | void * | pvt, | |
| struct ast_channel * | ast, | |||
| enum analog_sub | analog_index, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 2065 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, ast_channel::caller, dahdi_pvt::callprogress, CALLPROGRESS_FAX, 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, f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, ast_party_number::str, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::usefaxbuffers, and ast_party_number::valid.
02066 { 02067 struct ast_frame *f = *dest; 02068 struct dahdi_pvt *p = pvt; 02069 int idx = analogsub_to_dahdisub(analog_index); 02070 02071 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 02072 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 02073 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 02074 02075 if (f->subclass.integer == 'f') { 02076 if (f->frametype == AST_FRAME_DTMF_END) { 02077 /* Fax tone -- Handle and return NULL */ 02078 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 02079 /* If faxbuffers are configured, use them for the fax transmission */ 02080 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 02081 struct dahdi_bufferinfo bi = { 02082 .txbufpolicy = p->faxbuf_policy, 02083 .bufsize = p->bufsize, 02084 .numbufs = p->faxbuf_no 02085 }; 02086 int res; 02087 02088 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 02089 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 02090 } else { 02091 p->bufferoverrideinuse = 1; 02092 } 02093 } 02094 p->faxhandled = 1; 02095 if (p->dsp) { 02096 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 02097 ast_dsp_set_features(p->dsp, p->dsp_features); 02098 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 02099 } 02100 if (strcmp(ast->exten, "fax")) { 02101 const char *target_context = S_OR(ast->macrocontext, ast->context); 02102 02103 /* We need to unlock 'ast' here because ast_exists_extension has the 02104 * potential to start autoservice on the channel. Such action is prone 02105 * to deadlock. 02106 */ 02107 ast_mutex_unlock(&p->lock); 02108 ast_channel_unlock(ast); 02109 if (ast_exists_extension(ast, target_context, "fax", 1, 02110 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 02111 ast_channel_lock(ast); 02112 ast_mutex_lock(&p->lock); 02113 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 02114 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 02115 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 02116 if (ast_async_goto(ast, target_context, "fax", 1)) 02117 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 02118 } else { 02119 ast_channel_lock(ast); 02120 ast_mutex_lock(&p->lock); 02121 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 02122 } 02123 } else { 02124 ast_debug(1, "Already in a fax extension, not redirecting\n"); 02125 } 02126 } else { 02127 ast_debug(1, "Fax already handled\n"); 02128 } 02129 dahdi_confmute(p, 0); 02130 } 02131 p->subs[idx].f.frametype = AST_FRAME_NULL; 02132 p->subs[idx].f.subclass.integer = 0; 02133 *dest = &p->subs[idx].f; 02134 } 02135 }
| static void my_handle_notify_message | ( | struct ast_channel * | chan, | |
| void * | pvt, | |||
| int | cid_flags, | |||
| int | neon_mwievent | |||
| ) | [static] |
Definition at line 3669 of file chan_dahdi.c.
References ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ast_hangup(), ast_log(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, LOG_NOTICE, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, and notify_message().
Referenced by analog_ss_thread().
03670 { 03671 struct dahdi_pvt *p = pvt; 03672 03673 if (neon_mwievent > -1 && !p->mwimonitor_neon) 03674 return; 03675 03676 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) { 03677 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox); 03678 notify_message(p->mailbox, 1); 03679 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) { 03680 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox); 03681 notify_message(p->mailbox, 0); 03682 } 03683 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 03684 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 03685 if (neon_mwievent == -1 && p->mwimonitor_rpas) { 03686 ast_hangup(chan); 03687 return; 03688 } 03689 }
| static void my_hangup_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2999 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
03000 { 03001 struct dahdi_pvt *p = pvt; 03002 03003 if (!p->hanguponpolarityswitch) { 03004 return; 03005 } 03006 03007 if (p->answeronpolarityswitch) { 03008 my_set_polarity(pvt, 0); 03009 } else { 03010 my_set_polarity(pvt, 1); 03011 } 03012 }
| static int my_has_voicemail | ( | void * | pvt | ) | [static] |
Definition at line 2759 of file chan_dahdi.c.
References has_voicemail().
02760 { 02761 struct dahdi_pvt *p = pvt; 02762 02763 return has_voicemail(p); 02764 }
| static int my_have_progressdetect | ( | void * | pvt | ) | [static] |
Definition at line 3691 of file chan_dahdi.c.
References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.
03692 { 03693 struct dahdi_pvt *p = pvt; 03694 03695 if ((p->callprogress & CALLPROGRESS_PROGRESS) 03696 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03697 return 1; 03698 } else { 03699 /* Don't have progress detection. */ 03700 return 0; 03701 } 03702 }
| static void my_increase_ss_count | ( | void | ) | [static] |
Definition at line 2424 of file chan_dahdi.c.
References ast_mutex_lock, and ast_mutex_unlock.
02425 { 02426 ast_mutex_lock(&ss_thread_lock); 02427 ss_thread_count++; 02428 ast_mutex_unlock(&ss_thread_lock); 02429 }
| static int my_is_dialing | ( | void * | pvt, | |
| enum analog_sub | sub | |||
| ) | [static] |
Definition at line 3064 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_subchannel::dfd, LOG_DEBUG, and dahdi_pvt::subs.
| static int my_is_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2894 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SUB_REAL, and dahdi_pvt::subs.
02895 { 02896 struct dahdi_pvt *p = pvt; 02897 int res; 02898 struct dahdi_params par; 02899 02900 memset(&par, 0, sizeof(par)); 02901 02902 if (p->subs[SUB_REAL].dfd > -1) 02903 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02904 else { 02905 /* Assume not off hook on CVRS */ 02906 res = 0; 02907 par.rxisoffhook = 0; 02908 } 02909 if (res) { 02910 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 02911 } 02912 02913 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 02914 /* When "onhook" that means no battery on the line, and thus 02915 it is out of service..., if it's on a TDM card... If it's a channel 02916 bank, there is no telling... */ 02917 return (par.rxbits > -1) || par.rxisoffhook; 02918 } 02919 02920 return par.rxisoffhook; 02921 }
| static void my_lock_private | ( | void * | pvt | ) | [static] |
Definition at line 2137 of file chan_dahdi.c.
References ast_mutex_lock, and dahdi_pvt::lock.
02138 { 02139 struct dahdi_pvt *p = pvt; 02140 ast_mutex_lock(&p->lock); 02141 }
| 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, read] |
Definition at line 2589 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and dahdi_new().
02590 { 02591 struct dahdi_pvt *p = pvt; 02592 int dsub = analogsub_to_dahdisub(sub); 02593 02594 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : ""); 02595 }
| static int my_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2956 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
02957 { 02958 struct dahdi_pvt *p = pvt; 02959 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02960 }
| static int my_on_hook | ( | void * | pvt | ) | [static] |
Definition at line 3080 of file chan_dahdi.c.
References ANALOG_SUB_REAL, dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
03081 { 03082 struct dahdi_pvt *p = pvt; 03083 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK); 03084 }
| static int my_play_tone | ( | void * | pvt, | |
| enum analog_sub | sub, | |||
| enum analog_tone | tone | |||
| ) | [static] |
Definition at line 2766 of file chan_dahdi.c.
References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02767 { 02768 struct dahdi_pvt *p = pvt; 02769 int index; 02770 02771 index = analogsub_to_dahdisub(sub); 02772 02773 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone)); 02774 }
| static int my_ring | ( | void * | pvt | ) | [static] |
Definition at line 2940 of file chan_dahdi.c.
References dahdi_ring_phone().
02941 { 02942 struct dahdi_pvt *p = pvt; 02943 02944 return dahdi_ring_phone(p); 02945 }
| static int my_send_callerid | ( | void * | pvt, | |
| int | cwcid, | |||
| struct ast_party_caller * | caller | |||
| ) | [static] |
Definition at line 1964 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), ast_callerid_generate(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_verb, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, ast_party_caller::id, LOG_WARNING, MAX_CALLERID_SIZE, ast_party_id::name, ast_party_id::number, READ_SIZE, send_callerid(), ast_party_number::str, and ast_party_name::str.
01965 { 01966 struct dahdi_pvt *p = pvt; 01967 01968 ast_debug(2, "Starting cid spill\n"); 01969 01970 if (p->cidspill) { 01971 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01972 ast_free(p->cidspill); 01973 } 01974 01975 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01976 if (cwcid == 0) { 01977 p->cidlen = ast_callerid_generate(p->cidspill, 01978 caller->id.name.str, 01979 caller->id.number.str, 01980 AST_LAW(p)); 01981 } else { 01982 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", 01983 caller->id.name.str, caller->id.number.str); 01984 p->callwaitcas = 0; 01985 p->cidcwexpire = 0; 01986 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, 01987 caller->id.name.str, 01988 caller->id.number.str, 01989 AST_LAW(p)); 01990 p->cidlen += READ_SIZE * 4; 01991 } 01992 p->cidpos = 0; 01993 p->cid_suppress_expire = 0; 01994 send_callerid(p); 01995 } 01996 return 0; 01997 }
| static void my_set_alarm | ( | void * | pvt, | |
| int | in_alarm | |||
| ) | [static] |
Definition at line 2281 of file chan_dahdi.c.
References dahdi_pvt::inalarm.
| static void my_set_cadence | ( | void * | pvt, | |
| int * | cid_rings, | |||
| struct ast_channel * | ast | |||
| ) | [static] |
Definition at line 2265 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::dfd, dahdi_pvt::distinctivering, errno, LOG_WARNING, dahdi_pvt::sendcalleridafter, SUB_REAL, and dahdi_pvt::subs.
02266 { 02267 struct dahdi_pvt *p = pvt; 02268 02269 /* Choose proper cadence */ 02270 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02271 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02272 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02273 *cid_rings = cidrings[p->distinctivering - 1]; 02274 } else { 02275 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02276 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02277 *cid_rings = p->sendcalleridafter; 02278 } 02279 }
| static void my_set_callwaiting | ( | void * | pvt, | |
| int | callwaiting_enable | |||
| ) | [static] |
Definition at line 2382 of file chan_dahdi.c.
References dahdi_pvt::callwaiting.
02383 { 02384 struct dahdi_pvt *p = pvt; 02385 02386 p->callwaiting = callwaiting_enable; 02387 }
| static void my_set_confirmanswer | ( | void * | pvt, | |
| int | flag | |||
| ) | [static] |
Definition at line 2366 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02367 { 02368 struct dahdi_pvt *p = pvt; 02369 p->confirmanswer = flag; 02370 }
| static void my_set_dialing | ( | void * | pvt, | |
| int | is_dialing | |||
| ) | [static] |
Definition at line 2288 of file chan_dahdi.c.
References dahdi_pvt::dialing.
| static int my_set_echocanceller | ( | void * | pvt, | |
| int | enable | |||
| ) | [static] |
Definition at line 2926 of file chan_dahdi.c.
References dahdi_disable_ec(), and dahdi_enable_ec().
02927 { 02928 struct dahdi_pvt *p = pvt; 02929 02930 if (enable) 02931 dahdi_enable_ec(p); 02932 else 02933 dahdi_disable_ec(p); 02934 02935 return 0; 02936 }
| static void my_set_inthreeway | ( | void * | pvt, | |
| enum analog_sub | sub, | |||
| int | inthreeway | |||
| ) | [static] |
Definition at line 2225 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.
02226 { 02227 struct dahdi_pvt *p = pvt; 02228 int idx = analogsub_to_dahdisub(sub); 02229 02230 p->subs[idx].inthreeway = inthreeway; 02231 }
| static int my_set_linear_mode | ( | void * | pvt, | |
| enum analog_sub | sub, | |||
| int | linear_mode | |||
| ) | [static] |
Definition at line 2213 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.
02214 { 02215 struct dahdi_pvt *p = pvt; 02216 int oldval; 02217 int idx = analogsub_to_dahdisub(sub); 02218 02219 dahdi_setlinear(p->subs[idx].dfd, linear_mode); 02220 oldval = p->subs[idx].linear; 02221 p->subs[idx].linear = linear_mode ? 1 : 0; 02222 return oldval; 02223 }
| static void my_set_needringing | ( | void * | pvt, | |
| int | value | |||
| ) | [static] |
Definition at line 2962 of file chan_dahdi.c.
References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
02963 { 02964 struct dahdi_pvt *p = pvt; 02965 p->subs[SUB_REAL].needringing = value; 02966 }
| static void my_set_new_owner | ( | void * | pvt, | |
| struct ast_channel * | new_owner | |||
| ) | [static] |
Definition at line 2410 of file chan_dahdi.c.
References dahdi_pvt::owner.
| static void my_set_outgoing | ( | void * | pvt, | |
| int | is_outgoing | |||
| ) | [static] |
Definition at line 2295 of file chan_dahdi.c.
References dahdi_pvt::outgoing.
| static void my_set_polarity | ( | void * | pvt, | |
| int | value | |||
| ) | [static] |
Definition at line 2968 of file chan_dahdi.c.
References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::polarity, SUB_REAL, and dahdi_pvt::subs.
Referenced by my_answer_polarityswitch(), my_hangup_polarityswitch(), and my_start_polarityswitch().
| static void my_set_pulsedial | ( | void * | pvt, | |
| int | flag | |||
| ) | [static] |
Definition at line 2404 of file chan_dahdi.c.
References dahdi_pvt::pulsedial.
| static void my_set_ringtimeout | ( | void * | pvt, | |
| int | ringt | |||
| ) | [static] |
Definition at line 2338 of file chan_dahdi.c.
References dahdi_pvt::ringt.
| static void my_set_waitingfordt | ( | void * | pvt, | |
| struct ast_channel * | ast | |||
| ) | [static] |
Definition at line 2344 of file chan_dahdi.c.
References ast_log(), ast_setstate(), AST_STATE_OFFHOOK, CANPROGRESSDETECT, dahdi_pvt::dsp, LOG_DEBUG, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.
02345 { 02346 struct dahdi_pvt *p = pvt; 02347 02348 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) { 02349 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone); 02350 gettimeofday(&p->waitingfordt, NULL); 02351 ast_setstate(ast, AST_STATE_OFFHOOK); 02352 } 02353 }
| static int my_start | ( | void * | pvt | ) | [static] |
Definition at line 3014 of file chan_dahdi.c.
References dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
| static int my_start_cid_detect | ( | void * | pvt, | |
| int | cid_signalling | |||
| ) | [static] |
Definition at line 1696 of file chan_dahdi.c.
References ast_log(), bump_gains(), callerid_new(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, LOG_ERROR, SUB_REAL, and dahdi_pvt::subs.
01697 { 01698 struct dahdi_pvt *p = pvt; 01699 int index = SUB_REAL; 01700 p->cs = callerid_new(cid_signalling); 01701 if (!p->cs) { 01702 ast_log(LOG_ERROR, "Unable to alloc callerid\n"); 01703 return -1; 01704 } 01705 bump_gains(p); 01706 dahdi_setlinear(p->subs[index].dfd, 0); 01707 01708 return 0; 01709 }
| static void my_start_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2979 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
02980 { 02981 struct dahdi_pvt *p = pvt; 02982 02983 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02984 my_set_polarity(pvt, 0); 02985 } 02986 }
| static int my_stop_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1917 of file chan_dahdi.c.
References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.
01918 { 01919 struct dahdi_pvt *p = pvt; 01920 p->callwaitingrepeat = 0; 01921 p->cidcwexpire = 0; 01922 p->cid_suppress_expire = 0; 01923 01924 return 0; 01925 }
| static int my_stop_cid_detect | ( | void * | pvt | ) | [static] |
Definition at line 1711 of file chan_dahdi.c.
References callerid_free(), dahdi_pvt::cs, dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, SUB_REAL, and dahdi_pvt::subs.
01712 { 01713 struct dahdi_pvt *p = pvt; 01714 int index = SUB_REAL; 01715 if (p->cs) 01716 callerid_free(p->cs); 01717 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 01718 return 0; 01719 }
| 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] |
Definition at line 2555 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_channel_set_fd(), dahdi_subchannel::chan, db, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
02556 { 02557 struct dahdi_pvt *p = pvt; 02558 int da, db; 02559 int tchan; 02560 int tinthreeway; 02561 02562 da = analogsub_to_dahdisub(a); 02563 db = analogsub_to_dahdisub(b); 02564 02565 tchan = p->subs[da].chan; 02566 p->subs[da].chan = p->subs[db].chan; 02567 p->subs[db].chan = tchan; 02568 02569 tinthreeway = p->subs[da].inthreeway; 02570 p->subs[da].inthreeway = p->subs[db].inthreeway; 02571 p->subs[db].inthreeway = tinthreeway; 02572 02573 p->subs[da].owner = ast_a; 02574 p->subs[db].owner = ast_b; 02575 02576 if (ast_a) 02577 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); 02578 if (ast_b) 02579 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); 02580 02581 wakeup_sub(p, a); 02582 wakeup_sub(p, b); 02583 02584 return; 02585 }
| static int my_train_echocanceller | ( | void * | pvt | ) | [static] |
Definition at line 3055 of file chan_dahdi.c.
References dahdi_train_ec().
03056 { 03057 struct dahdi_pvt *p = pvt; 03058 03059 dahdi_train_ec(p); 03060 03061 return 0; 03062 }
| static int my_unallocate_sub | ( | void * | pvt, | |
| enum analog_sub | analogsub | |||
| ) | [static] |
Definition at line 2741 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and unalloc_sub().
02742 { 02743 struct dahdi_pvt *p = pvt; 02744 02745 return unalloc_sub(p, analogsub_to_dahdisub(analogsub)); 02746 }
| static void my_unlock_private | ( | void * | pvt | ) | [static] |
Definition at line 2143 of file chan_dahdi.c.
References ast_mutex_unlock, and dahdi_pvt::lock.
02144 { 02145 struct dahdi_pvt *p = pvt; 02146 ast_mutex_unlock(&p->lock); 02147 }
| static int my_wait_event | ( | void * | pvt | ) | [static] |
Definition at line 2873 of file chan_dahdi.c.
References dahdi_wait_event(), dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
02874 { 02875 struct dahdi_pvt *p = pvt; 02876 02877 return dahdi_wait_event(p->subs[SUB_REAL].dfd); 02878 }
| static int my_wink | ( | void * | pvt, | |
| enum analog_sub | sub | |||
| ) | [static] |
Definition at line 2049 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.
02050 { 02051 struct dahdi_pvt *p = pvt; 02052 int index = analogsub_to_dahdisub(sub); 02053 if (index != SUB_REAL) { 02054 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n"); 02055 } 02056 return dahdi_wink(p, index); 02057 }
| static void notify_message | ( | char * | mailbox_full, | |
| int | thereornot | |||
| ) | [static] |
Send MWI state change.
This function does two things:
1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.
2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.
Definition at line 3640 of file chan_dahdi.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, and mailbox.
Referenced by handle_init_event(), mwi_thread(), and my_handle_notify_message().
03641 { 03642 char s[sizeof(mwimonitornotify) + 80]; 03643 struct ast_event *event; 03644 char *mailbox, *context; 03645 03646 /* Strip off @default */ 03647 context = mailbox = ast_strdupa(mailbox_full); 03648 strsep(&context, "@"); 03649 if (ast_strlen_zero(context)) 03650 context = "default"; 03651 03652 if (!(event = ast_event_new(AST_EVENT_MWI, 03653 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03654 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03655 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03656 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03657 AST_EVENT_IE_END))) { 03658 return; 03659 } 03660 03661 ast_event_queue_and_cache(event); 03662 03663 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 03664 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 03665 ast_safe_system(s); 03666 } 03667 }
| static int parse_buffers_policy | ( | const char * | parse, | |
| int * | num_buffers, | |||
| int * | policy | |||
| ) | [static] |
Definition at line 7058 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write(), and process_dahdi().
07059 { 07060 int res; 07061 char policy_str[21] = ""; 07062 07063 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) { 07064 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 07065 return 1; 07066 } 07067 if (*num_buffers < 0) { 07068 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 07069 return -1; 07070 } 07071 if (!strcasecmp(policy_str, "full")) { 07072 *policy = DAHDI_POLICY_WHEN_FULL; 07073 } else if (!strcasecmp(policy_str, "immediate")) { 07074 *policy = DAHDI_POLICY_IMMEDIATE; 07075 #if defined(HAVE_DAHDI_HALF_FULL) 07076 } else if (!strcasecmp(policy_str, "half")) { 07077 *policy = DAHDI_POLICY_HALF_FULL; 07078 #endif 07079 } else { 07080 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 07081 return -1; 07082 } 07083 07084 return 0; 07085 }
| static char* parse_spanchan | ( | char * | chanstr, | |
| char ** | subdir | |||
| ) | [static] |
Definition at line 16952 of file chan_dahdi.c.
References string_replace().
Referenced by build_channels().
16953 { 16954 char *p; 16955 16956 if ((p = strrchr(chanstr, '!')) == NULL) { 16957 *subdir = NULL; 16958 return chanstr; 16959 } 16960 *p++ = '\0'; 16961 string_replace(chanstr, '!', '/'); 16962 *subdir = chanstr; 16963 return p; 16964 }
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 17095 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cc_config_params_destroy(), ast_cc_is_config_param(), ast_cc_set_param(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_new(), ast_variables_destroy(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::callgroup, dahdi_pvt::callprogress, CALLPROGRESS_FAX, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_pvt::cc_params, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_BELL, 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::cid_tag, dahdi_pvt::context, ringContextData::contextData, dahdi_chan_conf_default(), DAHDI_CHAN_MAPPING_LOGICAL, DAHDI_CHAN_MAPPING_PHYSICAL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pvt::destroy, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_chan_conf::ignore_failed_channels, dahdi_pvt::immediate, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, LINKSET_FLAG_EXPLICITACM, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::manages_span_alarms, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_CADENCE_MAX, dahdi_pvt::outsigmod, dahdi_pvt::parkinglot, parse_buffers_policy(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_echocancel(), dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, READ_SIZE, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, 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, SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, SIG_PRI_AOC_GRANT_S, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, dahdi_pvt::span, SS7_NAI_DYNAMIC, dahdi_pvt::stripmsd, dahdi_pvt::threewaycalling, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txdrc, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by setup_dahdi_int().
17096 { 17097 struct dahdi_pvt *tmp; 17098 int y; 17099 int found_pseudo = 0; 17100 struct ast_variable *dahdichan = NULL; 17101 17102 for (; v; v = v->next) { 17103 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 17104 continue; 17105 17106 /* Create the interface list */ 17107 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) { 17108 if (options & PROC_DAHDI_OPT_NOCHAN) { 17109 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 17110 continue; 17111 } 17112 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) { 17113 if (confp->ignore_failed_channels) { 17114 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value); 17115 continue; 17116 } else { 17117 return -1; 17118 } 17119 } 17120 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 17121 } else if (!strcasecmp(v->name, "ignore_failed_channels")) { 17122 confp->ignore_failed_channels = ast_true(v->value); 17123 } else if (!strcasecmp(v->name, "buffers")) { 17124 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 17125 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 17126 confp->chan.buf_no = numbufs; 17127 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 17128 } 17129 } else if (!strcasecmp(v->name, "faxbuffers")) { 17130 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) { 17131 confp->chan.usefaxbuffers = 1; 17132 } 17133 } else if (!strcasecmp(v->name, "dahdichan")) { 17134 /* Only process the last dahdichan value. */ 17135 dahdichan = v; 17136 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 17137 usedistinctiveringdetection = ast_true(v->value); 17138 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 17139 distinctiveringaftercid = ast_true(v->value); 17140 } else if (!strcasecmp(v->name, "dring1context")) { 17141 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 17142 } else if (!strcasecmp(v->name, "dring2context")) { 17143 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 17144 } else if (!strcasecmp(v->name, "dring3context")) { 17145 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 17146 } else if (!strcasecmp(v->name, "dring1range")) { 17147 confp->chan.drings.ringnum[0].range = atoi(v->value); 17148 } else if (!strcasecmp(v->name, "dring2range")) { 17149 confp->chan.drings.ringnum[1].range = atoi(v->value); 17150 } else if (!strcasecmp(v->name, "dring3range")) { 17151 confp->chan.drings.ringnum[2].range = atoi(v->value); 17152 } else if (!strcasecmp(v->name, "dring1")) { 17153 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]); 17154 } else if (!strcasecmp(v->name, "dring2")) { 17155 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]); 17156 } else if (!strcasecmp(v->name, "dring3")) { 17157 sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]); 17158 } else if (!strcasecmp(v->name, "usecallerid")) { 17159 confp->chan.use_callerid = ast_true(v->value); 17160 } else if (!strcasecmp(v->name, "cidsignalling")) { 17161 if (!strcasecmp(v->value, "bell")) 17162 confp->chan.cid_signalling = CID_SIG_BELL; 17163 else if (!strcasecmp(v->value, "v23")) 17164 confp->chan.cid_signalling = CID_SIG_V23; 17165 else if (!strcasecmp(v->value, "dtmf")) 17166 confp->chan.cid_signalling = CID_SIG_DTMF; 17167 else if (!strcasecmp(v->value, "smdi")) 17168 confp->chan.cid_signalling = CID_SIG_SMDI; 17169 else if (!strcasecmp(v->value, "v23_jp")) 17170 confp->chan.cid_signalling = CID_SIG_V23_JP; 17171 else if (ast_true(v->value)) 17172 confp->chan.cid_signalling = CID_SIG_BELL; 17173 } else if (!strcasecmp(v->name, "cidstart")) { 17174 if (!strcasecmp(v->value, "ring")) 17175 confp->chan.cid_start = CID_START_RING; 17176 else if (!strcasecmp(v->value, "polarity_in")) 17177 confp->chan.cid_start = CID_START_POLARITY_IN; 17178 else if (!strcasecmp(v->value, "polarity")) 17179 confp->chan.cid_start = CID_START_POLARITY; 17180 else if (!strcasecmp(v->value, "dtmf")) 17181 confp->chan.cid_start = CID_START_DTMF_NOALERT; 17182 else if (ast_true(v->value)) 17183 confp->chan.cid_start = CID_START_RING; 17184 } else if (!strcasecmp(v->name, "threewaycalling")) { 17185 confp->chan.threewaycalling = ast_true(v->value); 17186 } else if (!strcasecmp(v->name, "cancallforward")) { 17187 confp->chan.cancallforward = ast_true(v->value); 17188 } else if (!strcasecmp(v->name, "relaxdtmf")) { 17189 if (ast_true(v->value)) 17190 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 17191 else 17192 confp->chan.dtmfrelax = 0; 17193 } else if (!strcasecmp(v->name, "mailbox")) { 17194 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 17195 } else if (!strcasecmp(v->name, "hasvoicemail")) { 17196 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 17197 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 17198 } 17199 } else if (!strcasecmp(v->name, "adsi")) { 17200 confp->chan.adsi = ast_true(v->value); 17201 } else if (!strcasecmp(v->name, "usesmdi")) { 17202 confp->chan.use_smdi = ast_true(v->value); 17203 } else if (!strcasecmp(v->name, "smdiport")) { 17204 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 17205 } else if (!strcasecmp(v->name, "transfer")) { 17206 confp->chan.transfer = ast_true(v->value); 17207 } else if (!strcasecmp(v->name, "canpark")) { 17208 confp->chan.canpark = ast_true(v->value); 17209 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 17210 confp->chan.echocanbridged = ast_true(v->value); 17211 } else if (!strcasecmp(v->name, "busydetect")) { 17212 confp->chan.busydetect = ast_true(v->value); 17213 } else if (!strcasecmp(v->name, "busycount")) { 17214 confp->chan.busycount = atoi(v->value); 17215 } else if (!strcasecmp(v->name, "busypattern")) { 17216 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { 17217 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 17218 } 17219 } else if (!strcasecmp(v->name, "callprogress")) { 17220 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 17221 if (ast_true(v->value)) 17222 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 17223 } else if (!strcasecmp(v->name, "waitfordialtone")) { 17224 confp->chan.waitfordialtone = atoi(v->value); 17225 } else if (!strcasecmp(v->name, "faxdetect")) { 17226 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 17227 if (!strcasecmp(v->value, "incoming")) { 17228 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 17229 } else if (!strcasecmp(v->value, "outgoing")) { 17230 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 17231 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 17232 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 17233 } else if (!strcasecmp(v->name, "echocancel")) { 17234 process_echocancel(confp, v->value, v->lineno); 17235 } else if (!strcasecmp(v->name, "echotraining")) { 17236 if (sscanf(v->value, "%30d", &y) == 1) { 17237 if ((y < 10) || (y > 4000)) { 17238 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 17239 } else { 17240 confp->chan.echotraining = y; 17241 } 17242 } else if (ast_true(v->value)) { 17243 confp->chan.echotraining = 400; 17244 } else 17245 confp->chan.echotraining = 0; 17246 } else if (!strcasecmp(v->name, "hidecallerid")) { 17247 confp->chan.hidecallerid = ast_true(v->value); 17248 } else if (!strcasecmp(v->name, "hidecalleridname")) { 17249 confp->chan.hidecalleridname = ast_true(v->value); 17250 } else if (!strcasecmp(v->name, "pulsedial")) { 17251 confp->chan.pulse = ast_true(v->value); 17252 } else if (!strcasecmp(v->name, "callreturn")) { 17253 confp->chan.callreturn = ast_true(v->value); 17254 } else if (!strcasecmp(v->name, "callwaiting")) { 17255 confp->chan.callwaiting = ast_true(v->value); 17256 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 17257 confp->chan.callwaitingcallerid = ast_true(v->value); 17258 } else if (!strcasecmp(v->name, "context")) { 17259 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 17260 } else if (!strcasecmp(v->name, "language")) { 17261 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 17262 } else if (!strcasecmp(v->name, "progzone")) { 17263 ast_copy_string(progzone, v->value, sizeof(progzone)); 17264 } else if (!strcasecmp(v->name, "mohinterpret") 17265 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 17266 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 17267 } else if (!strcasecmp(v->name, "mohsuggest")) { 17268 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 17269 } else if (!strcasecmp(v->name, "parkinglot")) { 17270 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 17271 } else if (!strcasecmp(v->name, "stripmsd")) { 17272 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 17273 confp->chan.stripmsd = atoi(v->value); 17274 } else if (!strcasecmp(v->name, "jitterbuffers")) { 17275 numbufs = atoi(v->value); 17276 } else if (!strcasecmp(v->name, "group")) { 17277 confp->chan.group = ast_get_group(v->value); 17278 } else if (!strcasecmp(v->name, "callgroup")) { 17279 if (!strcasecmp(v->value, "none")) 17280 confp->chan.callgroup = 0; 17281 else 17282 confp->chan.callgroup = ast_get_group(v->value); 17283 } else if (!strcasecmp(v->name, "pickupgroup")) { 17284 if (!strcasecmp(v->value, "none")) 17285 confp->chan.pickupgroup = 0; 17286 else 17287 confp->chan.pickupgroup = ast_get_group(v->value); 17288 } else if (!strcasecmp(v->name, "setvar")) { 17289 char *varname = ast_strdupa(v->value), *varval = NULL; 17290 struct ast_variable *tmpvar; 17291 if (varname && (varval = strchr(varname, '='))) { 17292 *varval++ = '\0'; 17293 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 17294 tmpvar->next = confp->chan.vars; 17295 confp->chan.vars = tmpvar; 17296 } 17297 } 17298 } else if (!strcasecmp(v->name, "immediate")) { 17299 confp->chan.immediate = ast_true(v->value); 17300 } else if (!strcasecmp(v->name, "transfertobusy")) { 17301 confp->chan.transfertobusy = ast_true(v->value); 17302 } else if (!strcasecmp(v->name, "mwimonitor")) { 17303 confp->chan.mwimonitor_neon = 0; 17304 confp->chan.mwimonitor_fsk = 0; 17305 confp->chan.mwimonitor_rpas = 0; 17306 if (strcasestr(v->value, "fsk")) { 17307 confp->chan.mwimonitor_fsk = 1; 17308 } 17309 if (strcasestr(v->value, "rpas")) { 17310 confp->chan.mwimonitor_rpas = 1; 17311 } 17312 if (strcasestr(v->value, "neon")) { 17313 confp->chan.mwimonitor_neon = 1; 17314 } 17315 /* If set to true or yes, assume that simple fsk is desired */ 17316 if (ast_true(v->value)) { 17317 confp->chan.mwimonitor_fsk = 1; 17318 } 17319 } else if (!strcasecmp(v->name, "cid_rxgain")) { 17320 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 17321 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 17322 } 17323 } else if (!strcasecmp(v->name, "rxgain")) { 17324 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 17325 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 17326 } 17327 } else if (!strcasecmp(v->name, "txgain")) { 17328 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 17329 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 17330 } 17331 } else if (!strcasecmp(v->name, "txdrc")) { 17332 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) { 17333 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value); 17334 } 17335 } else if (!strcasecmp(v->name, "rxdrc")) { 17336 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) { 17337 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value); 17338 } 17339 } else if (!strcasecmp(v->name, "tonezone")) { 17340 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 17341 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 17342 } 17343 } else if (!strcasecmp(v->name, "callerid")) { 17344 if (!strcasecmp(v->value, "asreceived")) { 17345 confp->chan.cid_num[0] = '\0'; 17346 confp->chan.cid_name[0] = '\0'; 17347 } else { 17348 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 17349 } 17350 } else if (!strcasecmp(v->name, "fullname")) { 17351 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 17352 } else if (!strcasecmp(v->name, "cid_number")) { 17353 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 17354 } else if (!strcasecmp(v->name, "cid_tag")) { 17355 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); 17356 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 17357 confp->chan.dahditrcallerid = ast_true(v->value); 17358 } else if (!strcasecmp(v->name, "restrictcid")) { 17359 confp->chan.restrictcid = ast_true(v->value); 17360 } else if (!strcasecmp(v->name, "usecallingpres")) { 17361 confp->chan.use_callingpres = ast_true(v->value); 17362 } else if (!strcasecmp(v->name, "accountcode")) { 17363 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 17364 } else if (!strcasecmp(v->name, "amaflags")) { 17365 y = ast_cdr_amaflags2int(v->value); 17366 if (y < 0) 17367 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 17368 else 17369 confp->chan.amaflags = y; 17370 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 17371 confp->chan.polarityonanswerdelay = atoi(v->value); 17372 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 17373 confp->chan.answeronpolarityswitch = ast_true(v->value); 17374 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 17375 confp->chan.hanguponpolarityswitch = ast_true(v->value); 17376 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 17377 confp->chan.sendcalleridafter = atoi(v->value); 17378 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 17379 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 17380 } else if (ast_cc_is_config_param(v->name)) { 17381 ast_cc_set_param(confp->chan.cc_params, v->name, v->value); 17382 } else if (!strcasecmp(v->name, "mwisendtype")) { 17383 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 17384 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 17385 mwisend_rpas = 1; 17386 } else { 17387 mwisend_rpas = 0; 17388 } 17389 #else 17390 /* Default is fsk, to turn it off you must specify nofsk */ 17391 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 17392 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 17393 confp->chan.mwisend_fsk = 0; 17394 } else { /* Default FSK */ 17395 confp->chan.mwisend_fsk = 1; 17396 } 17397 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 17398 confp->chan.mwisend_rpas = 1; 17399 } else { 17400 confp->chan.mwisend_rpas = 0; 17401 } 17402 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 17403 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 17404 } 17405 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 17406 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 17407 } 17408 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 17409 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 17410 } 17411 #endif 17412 } else if (reload != 1) { 17413 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 17414 int orig_radio = confp->chan.radio; 17415 int orig_outsigmod = confp->chan.outsigmod; 17416 int orig_auto = confp->is_sig_auto; 17417 17418 confp->chan.radio = 0; 17419 confp->chan.outsigmod = -1; 17420 confp->is_sig_auto = 0; 17421 if (!strcasecmp(v->value, "em")) { 17422 confp->chan.sig = SIG_EM; 17423 } else if (!strcasecmp(v->value, "em_e1")) { 17424 confp->chan.sig = SIG_EM_E1; 17425 } else if (!strcasecmp(v->value, "em_w")) { 17426 confp->chan.sig = SIG_EMWINK; 17427 } else if (!strcasecmp(v->value, "fxs_ls")) { 17428 confp->chan.sig = SIG_FXSLS; 17429 } else if (!strcasecmp(v->value, "fxs_gs")) { 17430 confp->chan.sig = SIG_FXSGS; 17431 } else if (!strcasecmp(v->value, "fxs_ks")) { 17432 confp->chan.sig = SIG_FXSKS; 17433 } else if (!strcasecmp(v->value, "fxo_ls")) { 17434 confp->chan.sig = SIG_FXOLS; 17435 } else if (!strcasecmp(v->value, "fxo_gs")) { 17436 confp->chan.sig = SIG_FXOGS; 17437 } else if (!strcasecmp(v->value, "fxo_ks")) { 17438 confp->chan.sig = SIG_FXOKS; 17439 } else if (!strcasecmp(v->value, "fxs_rx")) { 17440 confp->chan.sig = SIG_FXSKS; 17441 confp->chan.radio = 1; 17442 } else if (!strcasecmp(v->value, "fxo_rx")) { 17443 confp->chan.sig = SIG_FXOLS; 17444 confp->chan.radio = 1; 17445 } else if (!strcasecmp(v->value, "fxs_tx")) { 17446 confp->chan.sig = SIG_FXSLS; 17447 confp->chan.radio = 1; 17448 } else if (!strcasecmp(v->value, "fxo_tx")) { 17449 confp->chan.sig = SIG_FXOGS; 17450 confp->chan.radio = 1; 17451 } else if (!strcasecmp(v->value, "em_rx")) { 17452 confp->chan.sig = SIG_EM; 17453 confp->chan.radio = 1; 17454 } else if (!strcasecmp(v->value, "em_tx")) { 17455 confp->chan.sig = SIG_EM; 17456 confp->chan.radio = 1; 17457 } else if (!strcasecmp(v->value, "em_rxtx")) { 17458 confp->chan.sig = SIG_EM; 17459 confp->chan.radio = 2; 17460 } else if (!strcasecmp(v->value, "em_txrx")) { 17461 confp->chan.sig = SIG_EM; 17462 confp->chan.radio = 2; 17463 } else if (!strcasecmp(v->value, "sf")) { 17464 confp->chan.sig = SIG_SF; 17465 } else if (!strcasecmp(v->value, "sf_w")) { 17466 confp->chan.sig = SIG_SFWINK; 17467 } else if (!strcasecmp(v->value, "sf_featd")) { 17468 confp->chan.sig = SIG_FEATD; 17469 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17470 confp->chan.sig = SIG_FEATDMF; 17471 } else if (!strcasecmp(v->value, "sf_featb")) { 17472 confp->chan.sig = SIG_SF_FEATB; 17473 } else if (!strcasecmp(v->value, "sf")) { 17474 confp->chan.sig = SIG_SF; 17475 } else if (!strcasecmp(v->value, "sf_rx")) { 17476 confp->chan.sig = SIG_SF; 17477 confp->chan.radio = 1; 17478 } else if (!strcasecmp(v->value, "sf_tx")) { 17479 confp->chan.sig = SIG_SF; 17480 confp->chan.radio = 1; 17481 } else if (!strcasecmp(v->value, "sf_rxtx")) { 17482 confp->chan.sig = SIG_SF; 17483 confp->chan.radio = 2; 17484 } else if (!strcasecmp(v->value, "sf_txrx")) { 17485 confp->chan.sig = SIG_SF; 17486 confp->chan.radio = 2; 17487 } else if (!strcasecmp(v->value, "featd")) { 17488 confp->chan.sig = SIG_FEATD; 17489 } else if (!strcasecmp(v->value, "featdmf")) { 17490 confp->chan.sig = SIG_FEATDMF; 17491 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17492 confp->chan.sig = SIG_FEATDMF_TA; 17493 } else if (!strcasecmp(v->value, "e911")) { 17494 confp->chan.sig = SIG_E911; 17495 } else if (!strcasecmp(v->value, "fgccama")) { 17496 confp->chan.sig = SIG_FGC_CAMA; 17497 } else if (!strcasecmp(v->value, "fgccamamf")) { 17498 confp->chan.sig = SIG_FGC_CAMAMF; 17499 } else if (!strcasecmp(v->value, "featb")) { 17500 confp->chan.sig = SIG_FEATB; 17501 #ifdef HAVE_PRI 17502 } else if (!strcasecmp(v->value, "pri_net")) { 17503 confp->chan.sig = SIG_PRI; 17504 confp->pri.pri.nodetype = PRI_NETWORK; 17505 } else if (!strcasecmp(v->value, "pri_cpe")) { 17506 confp->chan.sig = SIG_PRI; 17507 confp->pri.pri.nodetype = PRI_CPE; 17508 } else if (!strcasecmp(v->value, "bri_cpe")) { 17509 confp->chan.sig = SIG_BRI; 17510 confp->pri.pri.nodetype = PRI_CPE; 17511 } else if (!strcasecmp(v->value, "bri_net")) { 17512 confp->chan.sig = SIG_BRI; 17513 confp->pri.pri.nodetype = PRI_NETWORK; 17514 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 17515 confp->chan.sig = SIG_BRI_PTMP; 17516 confp->pri.pri.nodetype = PRI_CPE; 17517 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 17518 #if defined(HAVE_PRI_CALL_HOLD) 17519 confp->chan.sig = SIG_BRI_PTMP; 17520 confp->pri.pri.nodetype = PRI_NETWORK; 17521 #else 17522 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 17523 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 17524 #endif 17525 #if defined(HAVE_SS7) 17526 } else if (!strcasecmp(v->value, "ss7")) { 17527 confp->chan.sig = SIG_SS7; 17528 #endif /* defined(HAVE_SS7) */ 17529 #ifdef HAVE_OPENR2 17530 } else if (!strcasecmp(v->value, "mfcr2")) { 17531 confp->chan.sig = SIG_MFCR2; 17532 #endif 17533 } else if (!strcasecmp(v->value, "auto")) { 17534 confp->is_sig_auto = 1; 17535 } else { 17536 confp->chan.outsigmod = orig_outsigmod; 17537 confp->chan.radio = orig_radio; 17538 confp->is_sig_auto = orig_auto; 17539 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17540 } 17541 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 17542 if (!strcasecmp(v->value, "em")) { 17543 confp->chan.outsigmod = SIG_EM; 17544 } else if (!strcasecmp(v->value, "em_e1")) { 17545 confp->chan.outsigmod = SIG_EM_E1; 17546 } else if (!strcasecmp(v->value, "em_w")) { 17547 confp->chan.outsigmod = SIG_EMWINK; 17548 } else if (!strcasecmp(v->value, "sf")) { 17549 confp->chan.outsigmod = SIG_SF; 17550 } else if (!strcasecmp(v->value, "sf_w")) { 17551 confp->chan.outsigmod = SIG_SFWINK; 17552 } else if (!strcasecmp(v->value, "sf_featd")) { 17553 confp->chan.outsigmod = SIG_FEATD; 17554 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17555 confp->chan.outsigmod = SIG_FEATDMF; 17556 } else if (!strcasecmp(v->value, "sf_featb")) { 17557 confp->chan.outsigmod = SIG_SF_FEATB; 17558 } else if (!strcasecmp(v->value, "sf")) { 17559 confp->chan.outsigmod = SIG_SF; 17560 } else if (!strcasecmp(v->value, "featd")) { 17561 confp->chan.outsigmod = SIG_FEATD; 17562 } else if (!strcasecmp(v->value, "featdmf")) { 17563 confp->chan.outsigmod = SIG_FEATDMF; 17564 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17565 confp->chan.outsigmod = SIG_FEATDMF_TA; 17566 } else if (!strcasecmp(v->value, "e911")) { 17567 confp->chan.outsigmod = SIG_E911; 17568 } else if (!strcasecmp(v->value, "fgccama")) { 17569 confp->chan.outsigmod = SIG_FGC_CAMA; 17570 } else if (!strcasecmp(v->value, "fgccamamf")) { 17571 confp->chan.outsigmod = SIG_FGC_CAMAMF; 17572 } else if (!strcasecmp(v->value, "featb")) { 17573 confp->chan.outsigmod = SIG_FEATB; 17574 } else { 17575 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17576 } 17577 #ifdef HAVE_PRI 17578 } else if (!strcasecmp(v->name, "pridialplan")) { 17579 if (!strcasecmp(v->value, "national")) { 17580 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1; 17581 } else if (!strcasecmp(v->value, "unknown")) { 17582 confp->pri.pri.dialplan = PRI_UNKNOWN + 1; 17583 } else if (!strcasecmp(v->value, "private")) { 17584 confp->pri.pri.dialplan = PRI_PRIVATE + 1; 17585 } else if (!strcasecmp(v->value, "international")) { 17586 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 17587 } else if (!strcasecmp(v->value, "local")) { 17588 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1; 17589 } else if (!strcasecmp(v->value, "dynamic")) { 17590 confp->pri.pri.dialplan = -1; 17591 } else if (!strcasecmp(v->value, "redundant")) { 17592 confp->pri.pri.dialplan = -2; 17593 } else { 17594 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 17595 } 17596 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 17597 if (!strcasecmp(v->value, "national")) { 17598 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1; 17599 } else if (!strcasecmp(v->value, "unknown")) { 17600 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1; 17601 } else if (!strcasecmp(v->value, "private")) { 17602 confp->pri.pri.localdialplan = PRI_PRIVATE + 1; 17603 } else if (!strcasecmp(v->value, "international")) { 17604 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 17605 } else if (!strcasecmp(v->value, "local")) { 17606 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1; 17607 } else if (!strcasecmp(v->value, "dynamic")) { 17608 confp->pri.pri.localdialplan = -1; 17609 } else if (!strcasecmp(v->value, "redundant")) { 17610 confp->pri.pri.localdialplan = -2; 17611 } else { 17612 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 17613 } 17614 } else if (!strcasecmp(v->name, "switchtype")) { 17615 if (!strcasecmp(v->value, "national")) 17616 confp->pri.pri.switchtype = PRI_SWITCH_NI2; 17617 else if (!strcasecmp(v->value, "ni1")) 17618 confp->pri.pri.switchtype = PRI_SWITCH_NI1; 17619 else if (!strcasecmp(v->value, "dms100")) 17620 confp->pri.pri.switchtype = PRI_SWITCH_DMS100; 17621 else if (!strcasecmp(v->value, "4ess")) 17622 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS; 17623 else if (!strcasecmp(v->value, "5ess")) 17624 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E; 17625 else if (!strcasecmp(v->value, "euroisdn")) 17626 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1; 17627 else if (!strcasecmp(v->value, "qsig")) 17628 confp->pri.pri.switchtype = PRI_SWITCH_QSIG; 17629 else { 17630 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 17631 return -1; 17632 } 17633 } else if (!strcasecmp(v->name, "msn")) { 17634 ast_copy_string(confp->pri.pri.msn_list, v->value, 17635 sizeof(confp->pri.pri.msn_list)); 17636 } else if (!strcasecmp(v->name, "nsf")) { 17637 if (!strcasecmp(v->value, "sdn")) 17638 confp->pri.pri.nsf = PRI_NSF_SDN; 17639 else if (!strcasecmp(v->value, "megacom")) 17640 confp->pri.pri.nsf = PRI_NSF_MEGACOM; 17641 else if (!strcasecmp(v->value, "tollfreemegacom")) 17642 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 17643 else if (!strcasecmp(v->value, "accunet")) 17644 confp->pri.pri.nsf = PRI_NSF_ACCUNET; 17645 else if (!strcasecmp(v->value, "none")) 17646 confp->pri.pri.nsf = PRI_NSF_NONE; 17647 else { 17648 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 17649 confp->pri.pri.nsf = PRI_NSF_NONE; 17650 } 17651 } else if (!strcasecmp(v->name, "priindication")) { 17652 if (!strcasecmp(v->value, "outofband")) 17653 confp->chan.priindication_oob = 1; 17654 else if (!strcasecmp(v->value, "inband")) 17655 confp->chan.priindication_oob = 0; 17656 else 17657 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 17658 v->value, v->lineno); 17659 } else if (!strcasecmp(v->name, "priexclusive")) { 17660 confp->chan.priexclusive = ast_true(v->value); 17661 } else if (!strcasecmp(v->name, "internationalprefix")) { 17662 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix)); 17663 } else if (!strcasecmp(v->name, "nationalprefix")) { 17664 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix)); 17665 } else if (!strcasecmp(v->name, "localprefix")) { 17666 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix)); 17667 } else if (!strcasecmp(v->name, "privateprefix")) { 17668 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix)); 17669 } else if (!strcasecmp(v->name, "unknownprefix")) { 17670 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix)); 17671 } else if (!strcasecmp(v->name, "resetinterval")) { 17672 if (!strcasecmp(v->value, "never")) 17673 confp->pri.pri.resetinterval = -1; 17674 else if (atoi(v->value) >= 60) 17675 confp->pri.pri.resetinterval = atoi(v->value); 17676 else 17677 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 17678 v->value, v->lineno); 17679 } else if (!strcasecmp(v->name, "minunused")) { 17680 confp->pri.pri.minunused = atoi(v->value); 17681 } else if (!strcasecmp(v->name, "minidle")) { 17682 confp->pri.pri.minidle = atoi(v->value); 17683 } else if (!strcasecmp(v->name, "idleext")) { 17684 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext)); 17685 } else if (!strcasecmp(v->name, "idledial")) { 17686 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial)); 17687 } else if (!strcasecmp(v->name, "overlapdial")) { 17688 if (ast_true(v->value)) { 17689 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17690 } else if (!strcasecmp(v->value, "incoming")) { 17691 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 17692 } else if (!strcasecmp(v->value, "outgoing")) { 17693 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 17694 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 17695 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17696 } else { 17697 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 17698 } 17699 #ifdef HAVE_PRI_PROG_W_CAUSE 17700 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 17701 if (!strcasecmp(v->value, "logical")) { 17702 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 17703 } else if (!strcasecmp(v->value, "physical")) { 17704 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17705 } else { 17706 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17707 } 17708 #endif 17709 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 17710 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value); 17711 #if defined(HAVE_PRI_SERVICE_MESSAGES) 17712 } else if (!strcasecmp(v->name, "service_message_support")) { 17713 /* assuming switchtype for this channel group has been configured already */ 17714 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 17715 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E 17716 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) { 17717 confp->pri.pri.enable_service_message_support = 1; 17718 } else { 17719 confp->pri.pri.enable_service_message_support = 0; 17720 } 17721 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 17722 #ifdef HAVE_PRI_INBANDDISCONNECT 17723 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 17724 confp->pri.pri.inbanddisconnect = ast_true(v->value); 17725 #endif 17726 } else if (!strcasecmp(v->name, "pritimer")) { 17727 #ifdef PRI_GETSET_TIMERS 17728 char tmp[20]; 17729 char *timerc; 17730 char *c; 17731 int timer; 17732 int timeridx; 17733 17734 ast_copy_string(tmp, v->value, sizeof(tmp)); 17735 c = tmp; 17736 timerc = strsep(&c, ","); 17737 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 17738 timeridx = pri_timer2idx(timerc); 17739 timer = atoi(c); 17740 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 17741 ast_log(LOG_WARNING, 17742 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 17743 v->lineno); 17744 } else if (!timer) { 17745 ast_log(LOG_WARNING, 17746 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 17747 c, timerc, v->lineno); 17748 } else { 17749 confp->pri.pri.pritimers[timeridx] = timer; 17750 } 17751 } else { 17752 ast_log(LOG_WARNING, 17753 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 17754 v->value, v->lineno); 17755 } 17756 #endif /* PRI_GETSET_TIMERS */ 17757 } else if (!strcasecmp(v->name, "facilityenable")) { 17758 confp->pri.pri.facilityenable = ast_true(v->value); 17759 #if defined(HAVE_PRI_AOC_EVENTS) 17760 } else if (!strcasecmp(v->name, "aoc_enable")) { 17761 confp->pri.pri.aoc_passthrough_flag = 0; 17762 if (strchr(v->value, 's') || strchr(v->value, 'S')) { 17763 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S; 17764 } 17765 if (strchr(v->value, 'd') || strchr(v->value, 'D')) { 17766 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D; 17767 } 17768 if (strchr(v->value, 'e') || strchr(v->value, 'E')) { 17769 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E; 17770 } 17771 } else if (!strcasecmp(v->name, "aoce_delayhangup")) { 17772 confp->pri.pri.aoce_delayhangup = ast_true(v->value); 17773 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 17774 #if defined(HAVE_PRI_CALL_HOLD) 17775 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) { 17776 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value); 17777 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 17778 #if defined(HAVE_PRI_CCSS) 17779 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) { 17780 if (!strcasecmp(v->value, "global")) { 17781 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */ 17782 } else if (!strcasecmp(v->value, "specific")) { 17783 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17784 } else { 17785 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17786 } 17787 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) { 17788 if (!strcasecmp(v->value, "release")) { 17789 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */ 17790 } else if (!strcasecmp(v->value, "retain")) { 17791 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17792 } else if (!strcasecmp(v->value, "do_not_care")) { 17793 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */ 17794 } else { 17795 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17796 } 17797 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) { 17798 if (!strcasecmp(v->value, "release")) { 17799 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */ 17800 } else if (!strcasecmp(v->value, "retain")) { 17801 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17802 } else { 17803 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17804 } 17805 #endif /* defined(HAVE_PRI_CCSS) */ 17806 #if defined(HAVE_PRI_CALL_WAITING) 17807 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) { 17808 confp->pri.pri.max_call_waiting_calls = atoi(v->value); 17809 if (confp->pri.pri.max_call_waiting_calls < 0) { 17810 /* Negative values are not allowed. */ 17811 confp->pri.pri.max_call_waiting_calls = 0; 17812 } 17813 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) { 17814 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value); 17815 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 17816 #if defined(HAVE_PRI_MWI) 17817 } else if (!strcasecmp(v->name, "mwi_mailboxes")) { 17818 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value, 17819 sizeof(confp->pri.pri.mwi_mailboxes)); 17820 #endif /* defined(HAVE_PRI_MWI) */ 17821 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) { 17822 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value); 17823 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) { 17824 confp->pri.pri.inband_on_setup_ack = ast_true(v->value); 17825 } else if (!strcasecmp(v->name, "inband_on_proceeding")) { 17826 confp->pri.pri.inband_on_proceeding = ast_true(v->value); 17827 } else if (!strcasecmp(v->name, "layer1_presence")) { 17828 if (!strcasecmp(v->value, "required")) { 17829 confp->pri.pri.layer1_ignored = 0; 17830 } else if (!strcasecmp(v->value, "ignore")) { 17831 confp->pri.pri.layer1_ignored = 1; 17832 } else { 17833 /* Default */ 17834 confp->pri.pri.layer1_ignored = 0; 17835 } 17836 #if defined(HAVE_PRI_L2_PERSISTENCE) 17837 } else if (!strcasecmp(v->name, "layer2_persistence")) { 17838 if (!strcasecmp(v->value, "keep_up")) { 17839 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP; 17840 } else if (!strcasecmp(v->value, "leave_down")) { 17841 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN; 17842 } else { 17843 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT; 17844 } 17845 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 17846 #endif /* HAVE_PRI */ 17847 #if defined(HAVE_SS7) 17848 } else if (!strcasecmp(v->name, "ss7type")) { 17849 if (!strcasecmp(v->value, "itu")) { 17850 cur_ss7type = SS7_ITU; 17851 } else if (!strcasecmp(v->value, "ansi")) { 17852 cur_ss7type = SS7_ANSI; 17853 } else 17854 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 17855 } else if (!strcasecmp(v->name, "linkset")) { 17856 cur_linkset = atoi(v->value); 17857 } else if (!strcasecmp(v->name, "pointcode")) { 17858 cur_pointcode = parse_pointcode(v->value); 17859 } else if (!strcasecmp(v->name, "adjpointcode")) { 17860 cur_adjpointcode = parse_pointcode(v->value); 17861 } else if (!strcasecmp(v->name, "defaultdpc")) { 17862 cur_defaultdpc = parse_pointcode(v->value); 17863 } else if (!strcasecmp(v->name, "cicbeginswith")) { 17864 cur_cicbeginswith = atoi(v->value); 17865 } else if (!strcasecmp(v->name, "networkindicator")) { 17866 if (!strcasecmp(v->value, "national")) 17867 cur_networkindicator = SS7_NI_NAT; 17868 else if (!strcasecmp(v->value, "national_spare")) 17869 cur_networkindicator = SS7_NI_NAT_SPARE; 17870 else if (!strcasecmp(v->value, "international")) 17871 cur_networkindicator = SS7_NI_INT; 17872 else if (!strcasecmp(v->value, "international_spare")) 17873 cur_networkindicator = SS7_NI_INT_SPARE; 17874 else 17875 cur_networkindicator = -1; 17876 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 17877 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix)); 17878 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 17879 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix)); 17880 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 17881 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix)); 17882 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 17883 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix)); 17884 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 17885 if (!strcasecmp(v->value, "national")) { 17886 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL; 17887 } else if (!strcasecmp(v->value, "international")) { 17888 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL; 17889 } else if (!strcasecmp(v->value, "subscriber")) { 17890 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER; 17891 } else if (!strcasecmp(v->value, "unknown")) { 17892 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN; 17893 } else if (!strcasecmp(v->value, "dynamic")) { 17894 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC; 17895 } else { 17896 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 17897 } 17898 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 17899 if (!strcasecmp(v->value, "national")) { 17900 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL; 17901 } else if (!strcasecmp(v->value, "international")) { 17902 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL; 17903 } else if (!strcasecmp(v->value, "subscriber")) { 17904 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER; 17905 } else if (!strcasecmp(v->value, "unknown")) { 17906 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN; 17907 } else if (!strcasecmp(v->value, "dynamic")) { 17908 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC; 17909 } else { 17910 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 17911 } 17912 } else if (!strcasecmp(v->name, "sigchan")) { 17913 int sigchan, res; 17914 sigchan = atoi(v->value); 17915 res = linkset_addsigchan(sigchan); 17916 if (res < 0) 17917 return -1; 17918 17919 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 17920 struct dahdi_ss7 *link; 17921 link = ss7_resolve_linkset(cur_linkset); 17922 if (!link) { 17923 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 17924 return -1; 17925 } 17926 if (ast_true(v->value)) 17927 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM; 17928 #endif /* defined(HAVE_SS7) */ 17929 #ifdef HAVE_OPENR2 17930 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 17931 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 17932 ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file); 17933 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 17934 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 17935 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 17936 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 17937 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 17938 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 17939 confp->mfcr2.variant = OR2_VAR_ITU; 17940 } 17941 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 17942 confp->mfcr2.mfback_timeout = atoi(v->value); 17943 if (!confp->mfcr2.mfback_timeout) { 17944 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 17945 confp->mfcr2.mfback_timeout = -1; 17946 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 17947 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 17948 } 17949 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 17950 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 17951 if (confp->mfcr2.metering_pulse_timeout > 500) { 17952 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 17953 } 17954 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 17955 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 17956 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 17957 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 17958 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 17959 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 17960 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 17961 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 17962 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 17963 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 17964 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 17965 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 17966 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 17967 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 17968 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 17969 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 17970 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0; 17971 #endif 17972 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 17973 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 17974 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 17975 confp->mfcr2.max_ani = atoi(v->value); 17976 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 17977 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 17978 } 17979 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 17980 confp->mfcr2.max_dnis = atoi(v->value); 17981 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 17982 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 17983 } 17984 } else if (!strcasecmp(v->name, "mfcr2_category")) { 17985 confp->mfcr2.category = openr2_proto_get_category(v->value); 17986 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 17987 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 17988 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 17989 v->value, v->lineno); 17990 } 17991 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 17992 openr2_log_level_t tmplevel; 17993 char *clevel; 17994 char *logval = ast_strdupa(v->value); 17995 while (logval) { 17996 clevel = strsep(&logval,","); 17997 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 17998 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 17999 continue; 18000 } 18001 confp->mfcr2.loglevel |= tmplevel; 18002 } 18003 #endif /* HAVE_OPENR2 */ 18004 } else if (!strcasecmp(v->name, "cadence")) { 18005 /* setup to scan our argument */ 18006 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 18007 int i; 18008 struct dahdi_ring_cadence new_cadence; 18009 int cid_location = -1; 18010 int firstcadencepos = 0; 18011 char original_args[80]; 18012 int cadence_is_ok = 1; 18013 18014 ast_copy_string(original_args, v->value, sizeof(original_args)); 18015 /* 16 cadences allowed (8 pairs) */ 18016 element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]); 18017 18018 /* Cadence must be even (on/off) */ 18019 if (element_count % 2 == 1) { 18020 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 18021 cadence_is_ok = 0; 18022 } 18023 18024 /* Ring cadences cannot be negative */ 18025 for (i = 0; i < element_count; i++) { 18026 if (c[i] == 0) { 18027 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 18028 cadence_is_ok = 0; 18029 break; 18030 } else if (c[i] < 0) { 18031 if (i % 2 == 1) { 18032 /* Silence duration, negative possibly okay */ 18033 if (cid_location == -1) { 18034 cid_location = i; 18035 c[i] *= -1; 18036 } else { 18037 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 18038 cadence_is_ok = 0; 18039 break; 18040 } 18041 } else { 18042 if (firstcadencepos == 0) { 18043 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 18044 /* duration will be passed negative to the DAHDI driver */ 18045 } else { 18046 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 18047 cadence_is_ok = 0; 18048 break; 18049 } 18050 } 18051 } 18052 } 18053 18054 /* Substitute our scanned cadence */ 18055 for (i = 0; i < 16; i++) { 18056 new_cadence.ringcadence[i] = c[i]; 18057 } 18058 18059 if (cadence_is_ok) { 18060 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 18061 if (element_count < 2) { 18062 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 18063 } else { 18064 if (cid_location == -1) { 18065 /* user didn't say; default to first pause */ 18066 cid_location = 1; 18067 } else { 18068 /* convert element_index to cidrings value */ 18069 cid_location = (cid_location + 1) / 2; 18070 } 18071 /* ---we like their cadence; try to install it--- */ 18072 if (!user_has_defined_cadences++) 18073 /* this is the first user-defined cadence; clear the default user cadences */ 18074 num_cadence = 0; 18075 if ((num_cadence+1) >= NUM_CADENCE_MAX) 18076 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 18077 else { 18078 cadences[num_cadence] = new_cadence; 18079 cidrings[num_cadence++] = cid_location; 18080 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 18081 } 18082 } 18083 } 18084 } else if (!strcasecmp(v->name, "ringtimeout")) { 18085 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 18086 } else if (!strcasecmp(v->name, "prewink")) { 18087 confp->timing.prewinktime = atoi(v->value); 18088 } else if (!strcasecmp(v->name, "preflash")) { 18089 confp->timing.preflashtime = atoi(v->value); 18090 } else if (!strcasecmp(v->name, "wink")) { 18091 confp->timing.winktime = atoi(v->value); 18092 } else if (!strcasecmp(v->name, "flash")) { 18093 confp->timing.flashtime = atoi(v->value); 18094 } else if (!strcasecmp(v->name, "start")) { 18095 confp->timing.starttime = atoi(v->value); 18096 } else if (!strcasecmp(v->name, "rxwink")) { 18097 confp->timing.rxwinktime = atoi(v->value); 18098 } else if (!strcasecmp(v->name, "rxflash")) { 18099 confp->timing.rxflashtime = atoi(v->value); 18100 } else if (!strcasecmp(v->name, "debounce")) { 18101 confp->timing.debouncetime = atoi(v->value); 18102 } else if (!strcasecmp(v->name, "toneduration")) { 18103 int toneduration; 18104 int ctlfd; 18105 int res; 18106 struct dahdi_dialparams dps; 18107 18108 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 18109 if (ctlfd == -1) { 18110 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 18111 return -1; 18112 } 18113 18114 toneduration = atoi(v->value); 18115 if (toneduration > -1) { 18116 memset(&dps, 0, sizeof(dps)); 18117 18118 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 18119 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 18120 if (res < 0) { 18121 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 18122 close(ctlfd); 18123 return -1; 18124 } 18125 } 18126 close(ctlfd); 18127 } else if (!strcasecmp(v->name, "defaultcic")) { 18128 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 18129 } else if (!strcasecmp(v->name, "defaultozz")) { 18130 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 18131 } else if (!strcasecmp(v->name, "mwilevel")) { 18132 mwilevel = atoi(v->value); 18133 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 18134 dtmfcid_level = atoi(v->value); 18135 } else if (!strcasecmp(v->name, "reportalarms")) { 18136 if (!strcasecmp(v->value, "all")) 18137 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; 18138 if (!strcasecmp(v->value, "none")) 18139 report_alarms = 0; 18140 else if (!strcasecmp(v->value, "channels")) 18141 report_alarms = REPORT_CHANNEL_ALARMS; 18142 else if (!strcasecmp(v->value, "spans")) 18143 report_alarms = REPORT_SPAN_ALARMS; 18144 } 18145 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 18146 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 18147 } 18148 18149 /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */ 18150 if (confp->chan.vars) { 18151 ast_variables_destroy(confp->chan.vars); 18152 confp->chan.vars = NULL; 18153 } 18154 18155 if (dahdichan) { 18156 /* Process the deferred dahdichan value. */ 18157 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno, 18158 &found_pseudo)) { 18159 if (confp->ignore_failed_channels) { 18160 ast_log(LOG_WARNING, 18161 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n", 18162 dahdichan->value); 18163 } else { 18164 return -1; 18165 } 18166 } 18167 } 18168 18169 /* mark the first channels of each DAHDI span to watch for their span alarms */ 18170 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { 18171 if (!tmp->destroy && tmp->span != y) { 18172 tmp->manages_span_alarms = 1; 18173 y = tmp->span; 18174 } else { 18175 tmp->manages_span_alarms = 0; 18176 } 18177 } 18178 18179 /*< \todo why check for the pseudo in the per-channel section. 18180 * Any actual use for manual setup of the pseudo channel? */ 18181 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) { 18182 /* use the default configuration for a channel, so 18183 that any settings from real configured channels 18184 don't "leak" into the pseudo channel config 18185 */ 18186 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18187 18188 if (conf.chan.cc_params) { 18189 tmp = mkintf(CHAN_PSEUDO, &conf, reload); 18190 } else { 18191 tmp = NULL; 18192 } 18193 if (tmp) { 18194 ast_verb(3, "Automatically generated pseudo channel\n"); 18195 } else { 18196 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 18197 } 18198 ast_cc_config_params_destroy(conf.chan.cc_params); 18199 } 18200 return 0; 18201 }
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 17039 of file chan_dahdi.c.
References ARRAY_LEN, ast_app_separate_args, ast_log(), ast_strdupa, ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, LOG_WARNING, name, dahdi_pvt::params, and value.
Referenced by process_dahdi().
17040 { 17041 char *parse = ast_strdupa(data); 17042 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 17043 unsigned int param_count; 17044 unsigned int x; 17045 17046 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 17047 return; 17048 17049 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 17050 17051 /* first parameter is tap length, process it here */ 17052 17053 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 17054 17055 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 17056 confp->chan.echocancel.head.tap_length = x; 17057 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 17058 confp->chan.echocancel.head.tap_length = 128; 17059 17060 /* now process any remaining parameters */ 17061 17062 for (x = 1; x < param_count; x++) { 17063 struct { 17064 char *name; 17065 char *value; 17066 } param; 17067 17068 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 17069 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]); 17070 continue; 17071 } 17072 17073 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 17074 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name); 17075 continue; 17076 } 17077 17078 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 17079 17080 if (param.value) { 17081 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 17082 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value); 17083 continue; 17084 } 17085 } 17086 confp->chan.echocancel.head.param_count++; 17087 } 17088 }
| static int reload | ( | void | ) | [static] |
Definition at line 18879 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
18880 { 18881 int res = 0; 18882 18883 res = setup_dahdi(1); 18884 if (res) { 18885 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 18886 return -1; 18887 } 18888 return 0; 18889 }
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4826 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup(), and my_all_subchannels_hungup().
04827 { 04828 p->confno = -1; 04829 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 04830 if (p->subs[SUB_REAL].dfd > -1) { 04831 struct dahdi_confinfo zi; 04832 04833 memset(&zi, 0, sizeof(zi)); 04834 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 04835 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 04836 } 04837 return 0; 04838 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 12005 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING.
Referenced by dahdi_hangup(), dahdi_request(), my_all_subchannels_hungup(), and setup_dahdi_int().
12006 { 12007 /* If we're supposed to be stopped -- stay stopped */ 12008 if (monitor_thread == AST_PTHREADT_STOP) 12009 return 0; 12010 ast_mutex_lock(&monlock); 12011 if (monitor_thread == pthread_self()) { 12012 ast_mutex_unlock(&monlock); 12013 ast_log(LOG_WARNING, "Cannot kill myself\n"); 12014 return -1; 12015 } 12016 if (monitor_thread != AST_PTHREADT_NULL) { 12017 /* Wake up the thread */ 12018 pthread_kill(monitor_thread, SIGURG); 12019 } else { 12020 /* Start a new monitor */ 12021 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 12022 ast_mutex_unlock(&monlock); 12023 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 12024 return -1; 12025 } 12026 } 12027 ast_mutex_unlock(&monlock); 12028 return 0; 12029 }
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5251 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_read(), handle_init_event(), my_cancel_cidspill(), and send_callerid().
05252 { 05253 int res; 05254 if (p->saveconf.confmode) { 05255 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 05256 p->saveconf.confmode = 0; 05257 if (res) { 05258 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 05259 return -1; 05260 } 05261 ast_debug(1, "Restored conferencing\n"); 05262 } 05263 return 0; 05264 }
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5158 of file chan_dahdi.c.
References ast_log(), 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(), dahdi_hangup(), mwi_thread(), and my_distinctive_ring().
| static int revert_fax_buffers | ( | struct dahdi_pvt * | p, | |
| struct ast_channel * | ast | |||
| ) | [static] |
Definition at line 6149 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
06150 { 06151 if (p->bufferoverrideinuse) { 06152 /* faxbuffers are in use, revert them */ 06153 struct dahdi_bufferinfo bi = { 06154 .txbufpolicy = p->buf_policy, 06155 .rxbufpolicy = p->buf_policy, 06156 .bufsize = p->bufsize, 06157 .numbufs = p->buf_no 06158 }; 06159 int bpres; 06160 06161 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06162 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno)); 06163 } 06164 p->bufferoverrideinuse = 0; 06165 return bpres; 06166 } 06167 06168 return -1; 06169 }
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5225 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().
05226 { 05227 struct dahdi_confinfo c; 05228 int res; 05229 if (p->saveconf.confmode) { 05230 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 05231 return -1; 05232 } 05233 p->saveconf.chan = 0; 05234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 05235 if (res) { 05236 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 05237 p->saveconf.confmode = 0; 05238 return -1; 05239 } 05240 memset(&c, 0, sizeof(c)); 05241 c.confmode = DAHDI_CONF_NORMAL; 05242 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 05243 if (res) { 05244 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 05245 return -1; 05246 } 05247 ast_debug(1, "Disabled conferencing\n"); 05248 return 0; 05249 }
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5309 of file chan_dahdi.c.
References ast_debug, ast_free, ast_log(), dahdi_pvt::callwaitcas, CALLWAITING_SUPPRESS_SAMPLES, dahdi_pvt::cid_suppress_expire, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), dahdi_subchannel::dfd, errno, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), dahdi_read(), my_callwait(), my_send_callerid(), and send_cwcidspill().
05310 { 05311 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 05312 int res; 05313 /* Take out of linear mode if necessary */ 05314 if (p->subs[SUB_REAL].linear) { 05315 p->subs[SUB_REAL].linear = 0; 05316 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 05317 } 05318 while (p->cidpos < p->cidlen) { 05319 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 05320 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res); 05321 if (res < 0) { 05322 if (errno == EAGAIN) 05323 return 0; 05324 else { 05325 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05326 return -1; 05327 } 05328 } 05329 if (!res) 05330 return 0; 05331 p->cidpos += res; 05332 } 05333 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 05334 ast_free(p->cidspill); 05335 p->cidspill = NULL; 05336 if (p->callwaitcas) { 05337 /* Wait for CID/CW to expire */ 05338 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 05339 p->cid_suppress_expire = p->cidcwexpire; 05340 } else 05341 restore_conference(p); 05342 return 0; 05343 }
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5266 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, READ_SIZE, and send_callerid().
Referenced by dahdi_handle_dtmf().
05267 { 05268 p->callwaitcas = 0; 05269 p->cidcwexpire = 0; 05270 p->cid_suppress_expire = 0; 05271 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 05272 return -1; 05273 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 05274 /* Make sure we account for the end */ 05275 p->cidlen += READ_SIZE * 4; 05276 p->cidpos = 0; 05277 send_callerid(p); 05278 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 05279 return 0; 05280 }
| static int set_actual_gain | ( | int | fd, | |
| float | rxgain, | |||
| float | txgain, | |||
| float | rxdrc, | |||
| float | txdrc, | |||
| int | law | |||
| ) | [static] |
Definition at line 5139 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), and restore_gains().
05140 { 05141 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law); 05142 }
| static int set_actual_rxgain | ( | int | fd, | |
| float | gain, | |||
| float | drc, | |||
| int | law | |||
| ) | [static] |
Definition at line 5122 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05123 { 05124 struct dahdi_gains g; 05125 int res; 05126 05127 memset(&g, 0, sizeof(g)); 05128 res = ioctl(fd, DAHDI_GETGAINS, &g); 05129 if (res) { 05130 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05131 return res; 05132 } 05133 05134 fill_rxgain(&g, gain, drc, law); 05135 05136 return ioctl(fd, DAHDI_SETGAINS, &g); 05137 }
| static int set_actual_txgain | ( | int | fd, | |
| float | gain, | |||
| float | drc, | |||
| int | law | |||
| ) | [static] |
Definition at line 5105 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05106 { 05107 struct dahdi_gains g; 05108 int res; 05109 05110 memset(&g, 0, sizeof(g)); 05111 res = ioctl(fd, DAHDI_GETGAINS, &g); 05112 if (res) { 05113 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05114 return res; 05115 } 05116 05117 fill_txgain(&g, gain, drc, law); 05118 05119 return ioctl(fd, DAHDI_SETGAINS, &g); 05120 }
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 18522 of file chan_dahdi.c.
References ast_cc_config_params_destroy(), dahdi_pvt::cc_params, dahdi_chan_conf::chan, dahdi_chan_conf_default(), and setup_dahdi_int().
Referenced by dahdi_restart(), load_module(), and reload().
18523 { 18524 int res; 18525 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default(); 18526 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 18527 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18528 18529 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) { 18530 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf); 18531 } else { 18532 res = -1; 18533 } 18534 ast_cc_config_params_destroy(default_conf.chan.cc_params); 18535 ast_cc_config_params_destroy(base_conf.chan.cc_params); 18536 ast_cc_config_params_destroy(conf.chan.cc_params); 18537 18538 return res; 18539 }
| static int setup_dahdi_int | ( | int | reload, | |
| struct dahdi_chan_conf * | default_conf, | |||
| struct dahdi_chan_conf * | base_conf, | |||
| struct dahdi_chan_conf * | conf | |||
| ) | [static] |
Definition at line 18235 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_new(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), global_jbconf, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_ss7_linkset::master, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_span::pvts, restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.
Referenced by setup_dahdi().
18236 { 18237 struct ast_config *cfg; 18238 struct ast_config *ucfg; 18239 struct ast_variable *v; 18240 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 18241 const char *chans; 18242 const char *cat; 18243 int res; 18244 18245 #ifdef HAVE_PRI 18246 char *c; 18247 int spanno; 18248 int i; 18249 int logicalspan; 18250 int trunkgroup; 18251 int dchannels[SIG_PRI_NUM_DCHANS]; 18252 #endif 18253 int have_cfg_now; 18254 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */ 18255 18256 cfg = ast_config_load(config, config_flags); 18257 have_cfg_now = !!cfg; 18258 if (!cfg) { 18259 /* Error if we have no config file */ 18260 if (had_cfg_before) { 18261 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 18262 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18263 } 18264 cfg = ast_config_new();/* Dummy config */ 18265 if (!cfg) { 18266 return 0; 18267 } 18268 ucfg = ast_config_load("users.conf", config_flags); 18269 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18270 ast_config_destroy(cfg); 18271 return 0; 18272 } 18273 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18274 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18275 ast_config_destroy(cfg); 18276 return 0; 18277 } 18278 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 18279 ucfg = ast_config_load("users.conf", config_flags); 18280 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18281 return 0; 18282 } 18283 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18284 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18285 return 0; 18286 } 18287 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18288 cfg = ast_config_load(config, config_flags); 18289 have_cfg_now = !!cfg; 18290 if (!cfg) { 18291 if (had_cfg_before) { 18292 /* We should have been able to load the config. */ 18293 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config); 18294 ast_config_destroy(ucfg); 18295 return 0; 18296 } 18297 cfg = ast_config_new();/* Dummy config */ 18298 if (!cfg) { 18299 ast_config_destroy(ucfg); 18300 return 0; 18301 } 18302 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18303 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18304 ast_config_destroy(ucfg); 18305 return 0; 18306 } 18307 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18308 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18309 return 0; 18310 } else { 18311 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18312 ucfg = ast_config_load("users.conf", config_flags); 18313 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18314 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18315 ast_config_destroy(cfg); 18316 return 0; 18317 } 18318 } 18319 had_cfg_before = have_cfg_now; 18320 18321 /* It's a little silly to lock it, but we might as well just to be sure */ 18322 ast_mutex_lock(&iflock); 18323 #ifdef HAVE_PRI 18324 if (reload != 1) { 18325 /* Process trunkgroups first */ 18326 v = ast_variable_browse(cfg, "trunkgroups"); 18327 while (v) { 18328 if (!strcasecmp(v->name, "trunkgroup")) { 18329 trunkgroup = atoi(v->value); 18330 if (trunkgroup > 0) { 18331 if ((c = strchr(v->value, ','))) { 18332 i = 0; 18333 memset(dchannels, 0, sizeof(dchannels)); 18334 while (c && (i < SIG_PRI_NUM_DCHANS)) { 18335 dchannels[i] = atoi(c + 1); 18336 if (dchannels[i] < 0) { 18337 ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18338 } else 18339 i++; 18340 c = strchr(c + 1, ','); 18341 } 18342 if (i) { 18343 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 18344 ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno); 18345 } else 18346 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); 18347 } else 18348 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18349 } else 18350 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18351 } else 18352 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 18353 } else if (!strcasecmp(v->name, "spanmap")) { 18354 spanno = atoi(v->value); 18355 if (spanno > 0) { 18356 if ((c = strchr(v->value, ','))) { 18357 trunkgroup = atoi(c + 1); 18358 if (trunkgroup > 0) { 18359 if ((c = strchr(c + 1, ','))) 18360 logicalspan = atoi(c + 1); 18361 else 18362 logicalspan = 0; 18363 if (logicalspan >= 0) { 18364 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 18365 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18366 } else 18367 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18368 } else 18369 ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno); 18370 } else 18371 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 18372 } else 18373 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 18374 } else 18375 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 18376 } else { 18377 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 18378 } 18379 v = v->next; 18380 } 18381 } 18382 #endif 18383 18384 /* Copy the default jb config over global_jbconf */ 18385 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 18386 18387 mwimonitornotify[0] = '\0'; 18388 18389 v = ast_variable_browse(cfg, "channels"); 18390 if ((res = process_dahdi(base_conf, 18391 "" /* Must be empty for the channels category. Silly voicemail mailbox. */, 18392 v, reload, 0))) { 18393 ast_mutex_unlock(&iflock); 18394 ast_config_destroy(cfg); 18395 if (ucfg) { 18396 ast_config_destroy(ucfg); 18397 } 18398 return res; 18399 } 18400 18401 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 18402 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 18403 /* [channels] and [trunkgroups] are used. Let's also reserve 18404 * [globals] and [general] for future use 18405 */ 18406 if (!strcasecmp(cat, "general") || 18407 !strcasecmp(cat, "trunkgroups") || 18408 !strcasecmp(cat, "globals") || 18409 !strcasecmp(cat, "channels")) { 18410 continue; 18411 } 18412 18413 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 18414 if (ast_strlen_zero(chans)) { 18415 /* Section is useless without a dahdichan value present. */ 18416 continue; 18417 } 18418 18419 /* Copy base_conf to conf. */ 18420 deep_copy_dahdi_chan_conf(conf, base_conf); 18421 18422 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 18423 ast_mutex_unlock(&iflock); 18424 ast_config_destroy(cfg); 18425 if (ucfg) { 18426 ast_config_destroy(ucfg); 18427 } 18428 return res; 18429 } 18430 } 18431 18432 ast_config_destroy(cfg); 18433 18434 if (ucfg) { 18435 /* Reset base_conf, so things don't leak from chan_dahdi.conf */ 18436 deep_copy_dahdi_chan_conf(base_conf, default_conf); 18437 process_dahdi(base_conf, 18438 "" /* Must be empty for the general category. Silly voicemail mailbox. */, 18439 ast_variable_browse(ucfg, "general"), 1, 0); 18440 18441 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 18442 if (!strcasecmp(cat, "general")) { 18443 continue; 18444 } 18445 18446 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 18447 if (ast_strlen_zero(chans)) { 18448 /* Section is useless without a dahdichan value present. */ 18449 continue; 18450 } 18451 18452 /* Copy base_conf to conf. */ 18453 deep_copy_dahdi_chan_conf(conf, base_conf); 18454 18455 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 18456 ast_config_destroy(ucfg); 18457 ast_mutex_unlock(&iflock); 18458 return res; 18459 } 18460 } 18461 ast_config_destroy(ucfg); 18462 } 18463 ast_mutex_unlock(&iflock); 18464 18465 #ifdef HAVE_PRI 18466 if (reload != 1) { 18467 int x; 18468 for (x = 0; x < NUM_SPANS; x++) { 18469 if (pris[x].pri.pvts[0]) { 18470 prepare_pri(pris + x); 18471 if (sig_pri_start_pri(&pris[x].pri)) { 18472 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 18473 return -1; 18474 } else 18475 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 18476 } 18477 } 18478 } 18479 #endif 18480 #if defined(HAVE_SS7) 18481 if (reload != 1) { 18482 int x; 18483 for (x = 0; x < NUM_SPANS; x++) { 18484 if (linksets[x].ss7.ss7) { 18485 linksets[x].ss7.calls = &dahdi_ss7_callbacks; 18486 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) { 18487 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 18488 return -1; 18489 } else 18490 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 18491 } 18492 } 18493 } 18494 #endif /* defined(HAVE_SS7) */ 18495 #ifdef HAVE_OPENR2 18496 if (reload != 1) { 18497 int x; 18498 for (x = 0; x < r2links_count; x++) { 18499 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 18500 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 18501 return -1; 18502 } else { 18503 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 18504 } 18505 } 18506 } 18507 #endif 18508 /* And start the monitor for the first time */ 18509 restart_monitor(); 18510 return 0; 18511 }
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 12288 of file chan_dahdi.c.
Referenced by mkintf().
12289 { 12290 return sigtype; 12291 }
| static void string_replace | ( | char * | str, | |
| int | char1, | |||
| int | char2 | |||
| ) | [static] |
Definition at line 16943 of file chan_dahdi.c.
Referenced by parse_spanchan().
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 4321 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), and dahdi_hangup().
04322 { 04323 int tchan; 04324 int tinthreeway; 04325 struct ast_channel *towner; 04326 04327 ast_debug(1, "Swapping %d and %d\n", a, b); 04328 04329 tchan = p->subs[a].chan; 04330 towner = p->subs[a].owner; 04331 tinthreeway = p->subs[a].inthreeway; 04332 04333 p->subs[a].chan = p->subs[b].chan; 04334 p->subs[a].owner = p->subs[b].owner; 04335 p->subs[a].inthreeway = p->subs[b].inthreeway; 04336 04337 p->subs[b].chan = tchan; 04338 p->subs[b].owner = towner; 04339 p->subs[b].inthreeway = tinthreeway; 04340 04341 if (p->subs[a].owner) 04342 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 04343 if (p->subs[b].owner) 04344 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 04345 wakeup_sub(p, a); 04346 wakeup_sub(p, b); 04347 }
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 4467 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and my_unallocate_sub().
04468 { 04469 if (!x) { 04470 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 04471 return -1; 04472 } 04473 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 04474 dahdi_close_sub(p, x); 04475 p->subs[x].linear = 0; 04476 p->subs[x].chan = 0; 04477 p->subs[x].owner = NULL; 04478 p->subs[x].inthreeway = 0; 04479 p->polarity = POLARITY_IDLE; 04480 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 04481 return 0; 04482 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 16927 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, and sig_pri_span::lock.
16928 { 16929 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16930 int y; 16931 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16932 #ifdef HAVE_PRI 16933 for (y = 0; y < NUM_SPANS; y++) 16934 ast_mutex_destroy(&pris[y].pri.lock); 16935 #endif 16936 #if defined(HAVE_SS7) 16937 for (y = 0; y < NUM_SPANS; y++) 16938 ast_mutex_destroy(&linksets[y].ss7.lock); 16939 #endif /* defined(HAVE_SS7) */ 16940 return __unload_module(); 16941 }
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4840 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_unlink(), and mkintf().
04841 { 04842 int needconf = 0; 04843 int x; 04844 int useslavenative; 04845 struct dahdi_pvt *slave = NULL; 04846 04847 useslavenative = isslavenative(p, &slave); 04848 /* Start with the obvious, general stuff */ 04849 for (x = 0; x < 3; x++) { 04850 /* Look for three way calls */ 04851 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 04852 conf_add(p, &p->subs[x], x, 0); 04853 needconf++; 04854 } else { 04855 conf_del(p, &p->subs[x], x); 04856 } 04857 } 04858 /* If we have a slave, add him to our conference now. or DAX 04859 if this is slave native */ 04860 for (x = 0; x < MAX_SLAVES; x++) { 04861 if (p->slaves[x]) { 04862 if (useslavenative) 04863 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 04864 else { 04865 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 04866 needconf++; 04867 } 04868 } 04869 } 04870 /* If we're supposed to be in there, do so now */ 04871 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 04872 if (useslavenative) 04873 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 04874 else { 04875 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 04876 needconf++; 04877 } 04878 } 04879 /* If we have a master, add ourselves to his conference */ 04880 if (p->master) { 04881 if (isslavenative(p->master, NULL)) { 04882 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 04883 } else { 04884 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 04885 } 04886 } 04887 if (!needconf) { 04888 /* Nobody is left (or should be left) in our conference. 04889 Kill it. */ 04890 p->confno = -1; 04891 } 04892 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 04893 return 0; 04894 }
| static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
| int | a | |||
| ) | [static] |
Definition at line 3828 of file chan_dahdi.c.
References ast_channel_unlock, ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by my_swap_subchannels(), and swap_subs().
03829 { 03830 dahdi_lock_sub_owner(p, a); 03831 if (p->subs[a].owner) { 03832 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 03833 ast_channel_unlock(p->subs[a].owner); 03834 } 03835 }
| int alarm |
Definition at line 4617 of file chan_dahdi.c.
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 412 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 393 of file chan_dahdi.c.
int cidrings[NUM_CADENCE_MAX] [static] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
Definition at line 404 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 347 of file chan_dahdi.c.
struct analog_callback dahdi_analog_callbacks [static] |
Definition at line 3704 of file chan_dahdi.c.
struct ast_data_handler dahdi_channels_data_provider [static] |
{
.version = AST_DATA_HANDLER_VERSION,
.get = dahdi_channels_data_provider_get
}
Definition at line 18682 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 15995 of file chan_dahdi.c.
struct ast_data_entry dahdi_data_providers[] [static] |
{
AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
}
Definition at line 18692 of file chan_dahdi.c.
struct ast_data_handler dahdi_status_data_provider [static] |
{
.version = AST_DATA_HANDLER_VERSION,
.get = dahdi_status_data_provider_get
}
Definition at line 18677 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1501 of file chan_dahdi.c.
struct ast_data_handler dahdi_version_data_provider [static] |
{
.version = AST_DATA_HANDLER_VERSION,
.get = dahdi_version_data_provider_get
}
Definition at line 18687 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 296 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 420 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 421 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 432 of file chan_dahdi.c.
int dtmfcid_level = 256 [static] |
Definition at line 437 of file chan_dahdi.c.
const char* const events[] [static] |
Definition at line 4594 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 449 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 452 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 304 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi_int().
int ifcount = 0 [static] |
Definition at line 461 of file chan_dahdi.c.
Main interface list end
Definition at line 1308 of file chan_dahdi.c.
Main interface list start
Definition at line 1307 of file chan_dahdi.c.
const char* const lbostr[] [static] |
Definition at line 283 of file chan_dahdi.c.
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 455 of file chan_dahdi.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 473 of file chan_dahdi.c.
int mwilevel = 512 [static] |
Definition at line 436 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 424 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 426 of file chan_dahdi.c.
| char* name |
Definition at line 4618 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 390 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 478 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 434 of file chan_dahdi.c.
char progzone[10] = "" [static] |
Definition at line 429 of file chan_dahdi.c.
int report_alarms = REPORT_CHANNEL_ALARMS [static] |
Definition at line 441 of file chan_dahdi.c.
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 534 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] [static] |
Round robin search locations.
Definition at line 3775 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 474 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 477 of file chan_dahdi.c.
const char* const subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 635 of file chan_dahdi.c.
const char tdesc[] = "DAHDI Telephony Driver" [static] |
Definition at line 326 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 431 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 391 of file chan_dahdi.c.
1.6.1