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 3797 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 1251 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 1546 of file chan_dahdi.c.
Referenced by my_complete_conference_update(), and update_conf().
#define HANGUP 1 |
Definition at line 16056 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(), dahdi_indicate(), and dahdi_show_channel().
#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 17084 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 17138 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 17140 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 4732 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 1548 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 16055 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 8819 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().
08820 { 08821 int res; 08822 int idx; 08823 struct ast_frame *f; 08824 int usedindex = -1; 08825 struct dahdi_pvt *p = ast->tech_pvt; 08826 08827 if ((idx = dahdi_get_index(ast, p, 0)) < 0) { 08828 idx = SUB_REAL; 08829 } 08830 08831 p->subs[idx].f.frametype = AST_FRAME_NULL; 08832 p->subs[idx].f.datalen = 0; 08833 p->subs[idx].f.samples = 0; 08834 p->subs[idx].f.mallocd = 0; 08835 p->subs[idx].f.offset = 0; 08836 p->subs[idx].f.subclass.integer = 0; 08837 p->subs[idx].f.delivery = ast_tv(0,0); 08838 p->subs[idx].f.src = "dahdi_exception"; 08839 p->subs[idx].f.data.ptr = NULL; 08840 08841 08842 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 08843 /* If nobody owns us, absorb the event appropriately, otherwise 08844 we loop indefinitely. This occurs when, during call waiting, the 08845 other end hangs up our channel so that it no longer exists, but we 08846 have neither FLASH'd nor ONHOOK'd to signify our desire to 08847 change to the other channel. */ 08848 if (p->fake_event) { 08849 res = p->fake_event; 08850 p->fake_event = 0; 08851 } else 08852 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 08853 /* Switch to real if there is one and this isn't something really silly... */ 08854 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 08855 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 08856 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 08857 p->owner = p->subs[SUB_REAL].owner; 08858 if (p->owner && ast_bridged_channel(p->owner)) 08859 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08860 p->subs[SUB_REAL].needunhold = 1; 08861 } 08862 switch (res) { 08863 case DAHDI_EVENT_ONHOOK: 08864 dahdi_disable_ec(p); 08865 if (p->owner) { 08866 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 08867 dahdi_ring_phone(p); 08868 p->callwaitingrepeat = 0; 08869 p->cidcwexpire = 0; 08870 p->cid_suppress_expire = 0; 08871 } else 08872 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08873 update_conf(p); 08874 break; 08875 case DAHDI_EVENT_RINGOFFHOOK: 08876 dahdi_enable_ec(p); 08877 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08878 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 08879 p->subs[SUB_REAL].needanswer = 1; 08880 p->dialing = 0; 08881 } 08882 break; 08883 case DAHDI_EVENT_HOOKCOMPLETE: 08884 case DAHDI_EVENT_RINGERON: 08885 case DAHDI_EVENT_RINGEROFF: 08886 /* Do nothing */ 08887 break; 08888 case DAHDI_EVENT_WINKFLASH: 08889 p->flashtime = ast_tvnow(); 08890 if (p->owner) { 08891 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 08892 if (p->owner->_state != AST_STATE_UP) { 08893 /* Answer if necessary */ 08894 usedindex = dahdi_get_index(p->owner, p, 0); 08895 if (usedindex > -1) { 08896 p->subs[usedindex].needanswer = 1; 08897 } 08898 ast_setstate(p->owner, AST_STATE_UP); 08899 } 08900 p->callwaitingrepeat = 0; 08901 p->cidcwexpire = 0; 08902 p->cid_suppress_expire = 0; 08903 if (ast_bridged_channel(p->owner)) 08904 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08905 p->subs[SUB_REAL].needunhold = 1; 08906 } else 08907 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08908 update_conf(p); 08909 break; 08910 default: 08911 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 08912 } 08913 f = &p->subs[idx].f; 08914 return f; 08915 } 08916 if (!(p->radio || (p->oprmode < 0))) 08917 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 08918 /* If it's not us, return NULL immediately */ 08919 if (ast != p->owner) { 08920 if (p->owner) { 08921 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 08922 } 08923 f = &p->subs[idx].f; 08924 return f; 08925 } 08926 08927 f = dahdi_handle_event(ast); 08928 if (!f) { 08929 const char *name = ast_strdupa(ast->name); 08930 08931 /* Tell the CDR this DAHDI device hung up */ 08932 ast_mutex_unlock(&p->lock); 08933 ast_channel_unlock(ast); 08934 ast_set_hangupsource(ast, name, 0); 08935 ast_channel_lock(ast); 08936 ast_mutex_lock(&p->lock); 08937 } 08938 return f; 08939 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 16878 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().
16879 { 16880 struct dahdi_pvt *p; 16881 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16882 int i, j; 16883 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16884 16885 #ifdef HAVE_PRI 16886 for (i = 0; i < NUM_SPANS; i++) { 16887 if (pris[i].pri.master != AST_PTHREADT_NULL) { 16888 pthread_cancel(pris[i].pri.master); 16889 pthread_kill(pris[i].pri.master, SIGURG); 16890 } 16891 } 16892 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 16893 ast_unregister_application(dahdi_send_keypad_facility_app); 16894 #ifdef HAVE_PRI_PROG_W_CAUSE 16895 ast_unregister_application(dahdi_send_callrerouting_facility_app); 16896 #endif 16897 #endif 16898 #if defined(HAVE_SS7) 16899 for (i = 0; i < NUM_SPANS; i++) { 16900 if (linksets[i].ss7.master != AST_PTHREADT_NULL) { 16901 pthread_cancel(linksets[i].ss7.master); 16902 pthread_kill(linksets[i].ss7.master, SIGURG); 16903 } 16904 } 16905 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 16906 #endif /* defined(HAVE_SS7) */ 16907 #if defined(HAVE_OPENR2) 16908 dahdi_r2_destroy_links(); 16909 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 16910 ast_unregister_application(dahdi_accept_r2_call_app); 16911 #endif 16912 16913 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 16914 ast_manager_unregister("DAHDIDialOffhook"); 16915 ast_manager_unregister("DAHDIHangup"); 16916 ast_manager_unregister("DAHDITransfer"); 16917 ast_manager_unregister("DAHDIDNDoff"); 16918 ast_manager_unregister("DAHDIDNDon"); 16919 ast_manager_unregister("DAHDIShowChannels"); 16920 ast_manager_unregister("DAHDIRestart"); 16921 ast_data_unregister(NULL); 16922 ast_channel_unregister(&dahdi_tech); 16923 16924 /* Hangup all interfaces if they have an owner */ 16925 ast_mutex_lock(&iflock); 16926 for (p = iflist; p; p = p->next) { 16927 if (p->owner) 16928 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 16929 } 16930 ast_mutex_unlock(&iflock); 16931 16932 ast_mutex_lock(&monlock); 16933 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 16934 pthread_cancel(monitor_thread); 16935 pthread_kill(monitor_thread, SIGURG); 16936 pthread_join(monitor_thread, NULL); 16937 } 16938 monitor_thread = AST_PTHREADT_STOP; 16939 ast_mutex_unlock(&monlock); 16940 16941 destroy_all_channels(); 16942 16943 #if defined(HAVE_PRI) 16944 for (i = 0; i < NUM_SPANS; i++) { 16945 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 16946 pthread_join(pris[i].pri.master, NULL); 16947 } 16948 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) { 16949 dahdi_close_pri_fd(&(pris[i]), j); 16950 } 16951 sig_pri_stop_pri(&pris[i].pri); 16952 } 16953 #if defined(HAVE_PRI_CCSS) 16954 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks); 16955 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks); 16956 #endif /* defined(HAVE_PRI_CCSS) */ 16957 sig_pri_unload(); 16958 #endif 16959 16960 #if defined(HAVE_SS7) 16961 for (i = 0; i < NUM_SPANS; i++) { 16962 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 16963 pthread_join(linksets[i].ss7.master, NULL); 16964 } 16965 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) { 16966 dahdi_close_ss7_fd(&(linksets[i]), j); 16967 } 16968 } 16969 #endif /* defined(HAVE_SS7) */ 16970 ast_cond_destroy(&ss_thread_complete); 16971 return 0; 16972 }
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 3798 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.
03799 { 03800 int res; 03801 if (p->subs[SUB_REAL].owner == ast) 03802 res = 0; 03803 else if (p->subs[SUB_CALLWAIT].owner == ast) 03804 res = 1; 03805 else if (p->subs[SUB_THREEWAY].owner == ast) 03806 res = 2; 03807 else { 03808 res = -1; 03809 if (!nullok) 03810 ast_log(LOG_WARNING, 03811 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 03812 ast ? ast->name : "", p->channel, fname, line); 03813 } 03814 return res; 03815 }
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16193 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().
16194 { 16195 struct dahdi_pvt *p; 16196 const char *channel = astman_get_header(m, "DAHDIChannel"); 16197 const char *number = astman_get_header(m, "Number"); 16198 int i; 16199 16200 if (ast_strlen_zero(channel)) { 16201 astman_send_error(s, m, "No channel specified"); 16202 return 0; 16203 } 16204 if (ast_strlen_zero(number)) { 16205 astman_send_error(s, m, "No number specified"); 16206 return 0; 16207 } 16208 p = find_channel_from_str(channel); 16209 if (!p) { 16210 astman_send_error(s, m, "No such channel"); 16211 return 0; 16212 } 16213 if (!p->owner) { 16214 astman_send_error(s, m, "Channel does not have it's owner"); 16215 return 0; 16216 } 16217 for (i = 0; i < strlen(number); i++) { 16218 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] }; 16219 dahdi_queue_frame(p, &f); 16220 } 16221 astman_send_ack(s, m, "DAHDIDialOffhook"); 16222 return 0; 16223 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16128 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().
16129 { 16130 struct dahdi_pvt *p; 16131 const char *channel = astman_get_header(m, "DAHDIChannel"); 16132 16133 if (ast_strlen_zero(channel)) { 16134 astman_send_error(s, m, "No channel specified"); 16135 return 0; 16136 } 16137 p = find_channel_from_str(channel); 16138 if (!p) { 16139 astman_send_error(s, m, "No such channel"); 16140 return 0; 16141 } 16142 dahdi_dnd(p, 0); 16143 astman_send_ack(s, m, "DND Disabled"); 16144 return 0; 16145 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16109 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().
16110 { 16111 struct dahdi_pvt *p; 16112 const char *channel = astman_get_header(m, "DAHDIChannel"); 16113 16114 if (ast_strlen_zero(channel)) { 16115 astman_send_error(s, m, "No channel specified"); 16116 return 0; 16117 } 16118 p = find_channel_from_str(channel); 16119 if (!p) { 16120 astman_send_error(s, m, "No such channel"); 16121 return 0; 16122 } 16123 dahdi_dnd(p, 1); 16124 astman_send_ack(s, m, "DND Enabled"); 16125 return 0; 16126 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15379 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
15380 { 15381 if (dahdi_restart() != 0) { 15382 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 15383 return 1; 15384 } 15385 astman_send_ack(s, m, "DAHDIRestart: Success"); 15386 return 0; 15387 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16225 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().
16226 { 16227 struct dahdi_pvt *tmp = NULL; 16228 const char *id = astman_get_header(m, "ActionID"); 16229 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 16230 char idText[256] = ""; 16231 int channels = 0; 16232 int dahdichanquery; 16233 16234 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) { 16235 /* Not numeric string. */ 16236 dahdichanquery = -1; 16237 } 16238 16239 astman_send_ack(s, m, "DAHDI channel status will follow"); 16240 if (!ast_strlen_zero(id)) 16241 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 16242 16243 ast_mutex_lock(&iflock); 16244 16245 for (tmp = iflist; tmp; tmp = tmp->next) { 16246 if (tmp->channel > 0) { 16247 int alm; 16248 16249 /* If a specific channel is queried for, only deliver status for that channel */ 16250 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 16251 continue; 16252 16253 alm = get_alarms(tmp); 16254 channels++; 16255 if (tmp->owner) { 16256 /* Add data if we have a current call */ 16257 astman_append(s, 16258 "Event: DAHDIShowChannels\r\n" 16259 "DAHDIChannel: %d\r\n" 16260 "Channel: %s\r\n" 16261 "Uniqueid: %s\r\n" 16262 "AccountCode: %s\r\n" 16263 "Signalling: %s\r\n" 16264 "SignallingCode: %d\r\n" 16265 "Context: %s\r\n" 16266 "DND: %s\r\n" 16267 "Alarm: %s\r\n" 16268 "%s" 16269 "\r\n", 16270 tmp->channel, 16271 tmp->owner->name, 16272 tmp->owner->uniqueid, 16273 tmp->owner->accountcode, 16274 sig2str(tmp->sig), 16275 tmp->sig, 16276 tmp->context, 16277 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16278 alarm2str(alm), idText); 16279 } else { 16280 astman_append(s, 16281 "Event: DAHDIShowChannels\r\n" 16282 "DAHDIChannel: %d\r\n" 16283 "Signalling: %s\r\n" 16284 "SignallingCode: %d\r\n" 16285 "Context: %s\r\n" 16286 "DND: %s\r\n" 16287 "Alarm: %s\r\n" 16288 "%s" 16289 "\r\n", 16290 tmp->channel, sig2str(tmp->sig), tmp->sig, 16291 tmp->context, 16292 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16293 alarm2str(alm), idText); 16294 } 16295 } 16296 } 16297 16298 ast_mutex_unlock(&iflock); 16299 16300 astman_append(s, 16301 "Event: DAHDIShowChannelsComplete\r\n" 16302 "%s" 16303 "Items: %d\r\n" 16304 "\r\n", 16305 idText, 16306 channels); 16307 return 0; 16308 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16147 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().
16148 { 16149 struct dahdi_pvt *p; 16150 const char *channel = astman_get_header(m, "DAHDIChannel"); 16151 16152 if (ast_strlen_zero(channel)) { 16153 astman_send_error(s, m, "No channel specified"); 16154 return 0; 16155 } 16156 p = find_channel_from_str(channel); 16157 if (!p) { 16158 astman_send_error(s, m, "No such channel"); 16159 return 0; 16160 } 16161 if (!analog_lib_handles(p->sig, 0, 0)) { 16162 astman_send_error(s, m, "Channel signaling is not analog"); 16163 return 0; 16164 } 16165 dahdi_fake_event(p,TRANSFER); 16166 astman_send_ack(s, m, "DAHDITransfer"); 16167 return 0; 16168 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16170 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().
16171 { 16172 struct dahdi_pvt *p; 16173 const char *channel = astman_get_header(m, "DAHDIChannel"); 16174 16175 if (ast_strlen_zero(channel)) { 16176 astman_send_error(s, m, "No channel specified"); 16177 return 0; 16178 } 16179 p = find_channel_from_str(channel); 16180 if (!p) { 16181 astman_send_error(s, m, "No such channel"); 16182 return 0; 16183 } 16184 if (!analog_lib_handles(p->sig, 0, 0)) { 16185 astman_send_error(s, m, "Channel signaling is not analog"); 16186 return 0; 16187 } 16188 dahdi_fake_event(p,HANGUP); 16189 astman_send_ack(s, m, "DAHDIHangup"); 16190 return 0; 16191 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 4649 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 4450 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().
04451 { 04452 struct dahdi_bufferinfo bi; 04453 int res; 04454 if (p->subs[x].dfd >= 0) { 04455 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 04456 return -1; 04457 } 04458 04459 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 04460 if (p->subs[x].dfd <= -1) { 04461 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 04462 return -1; 04463 } 04464 04465 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 04466 if (!res) { 04467 bi.txbufpolicy = p->buf_policy; 04468 bi.rxbufpolicy = p->buf_policy; 04469 bi.numbufs = p->buf_no; 04470 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 04471 if (res < 0) { 04472 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 04473 } 04474 } else 04475 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 04476 04477 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 04478 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 04479 dahdi_close_sub(p, x); 04480 p->subs[x].dfd = -1; 04481 return -1; 04482 } 04483 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 04484 return 0; 04485 }
static int analog_lib_handles | ( | int | signalling, | |
int | radio, | |||
int | oprmode | |||
) | [static] |
Definition at line 1578 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().
01579 { 01580 switch (signalling) { 01581 case SIG_FXOLS: 01582 case SIG_FXOGS: 01583 case SIG_FXOKS: 01584 case SIG_FXSLS: 01585 case SIG_FXSGS: 01586 case SIG_FXSKS: 01587 case SIG_EMWINK: 01588 case SIG_EM: 01589 case SIG_EM_E1: 01590 case SIG_FEATD: 01591 case SIG_FEATDMF: 01592 case SIG_E911: 01593 case SIG_FGC_CAMA: 01594 case SIG_FGC_CAMAMF: 01595 case SIG_FEATB: 01596 case SIG_SFWINK: 01597 case SIG_SF: 01598 case SIG_SF_FEATD: 01599 case SIG_SF_FEATDMF: 01600 case SIG_FEATDMF_TA: 01601 case SIG_SF_FEATB: 01602 break; 01603 default: 01604 /* The rest of the function should cover the remainder of signalling types */ 01605 return 0; 01606 } 01607 01608 if (radio) { 01609 return 0; 01610 } 01611 01612 if (oprmode) { 01613 return 0; 01614 } 01615 01616 return 1; 01617 }
static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 9970 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().
09971 { 09972 struct ast_channel *chan = data; 09973 struct dahdi_pvt *p = chan->tech_pvt; 09974 char exten[AST_MAX_EXTENSION] = ""; 09975 char exten2[AST_MAX_EXTENSION] = ""; 09976 unsigned char buf[256]; 09977 char dtmfcid[300]; 09978 char dtmfbuf[300]; 09979 struct callerid_state *cs = NULL; 09980 char *name = NULL, *number = NULL; 09981 int distMatches; 09982 int curRingData[3]; 09983 int receivedRingT; 09984 int counter1; 09985 int counter; 09986 int samples = 0; 09987 struct ast_smdi_md_message *smdi_msg = NULL; 09988 int flags = 0; 09989 int i; 09990 int timeout; 09991 int getforward = 0; 09992 char *s1, *s2; 09993 int len = 0; 09994 int res; 09995 int idx; 09996 09997 ast_mutex_lock(&ss_thread_lock); 09998 ss_thread_count++; 09999 ast_mutex_unlock(&ss_thread_lock); 10000 /* in the bizarre case where the channel has become a zombie before we 10001 even get started here, abort safely 10002 */ 10003 if (!p) { 10004 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 10005 ast_hangup(chan); 10006 goto quit; 10007 } 10008 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 10009 idx = dahdi_get_index(chan, p, 1); 10010 if (idx < 0) { 10011 ast_log(LOG_WARNING, "Huh?\n"); 10012 ast_hangup(chan); 10013 goto quit; 10014 } 10015 if (p->dsp) 10016 ast_dsp_digitreset(p->dsp); 10017 switch (p->sig) { 10018 case SIG_FEATD: 10019 case SIG_FEATDMF: 10020 case SIG_FEATDMF_TA: 10021 case SIG_E911: 10022 case SIG_FGC_CAMAMF: 10023 case SIG_FEATB: 10024 case SIG_EMWINK: 10025 case SIG_SF_FEATD: 10026 case SIG_SF_FEATDMF: 10027 case SIG_SF_FEATB: 10028 case SIG_SFWINK: 10029 if (dahdi_wink(p, idx)) 10030 goto quit; 10031 /* Fall through */ 10032 case SIG_EM: 10033 case SIG_EM_E1: 10034 case SIG_SF: 10035 case SIG_FGC_CAMA: 10036 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10037 if (p->dsp) 10038 ast_dsp_digitreset(p->dsp); 10039 /* set digit mode appropriately */ 10040 if (p->dsp) { 10041 if (NEED_MFDETECT(p)) 10042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10043 else 10044 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10045 } 10046 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 10047 /* Wait for the first digit only if immediate=no */ 10048 if (!p->immediate) 10049 /* Wait for the first digit (up to 5 seconds). */ 10050 res = ast_waitfordigit(chan, 5000); 10051 else 10052 res = 0; 10053 if (res > 0) { 10054 /* save first char */ 10055 dtmfbuf[0] = res; 10056 switch (p->sig) { 10057 case SIG_FEATD: 10058 case SIG_SF_FEATD: 10059 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10060 if (res > 0) 10061 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10062 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10063 break; 10064 case SIG_FEATDMF_TA: 10065 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10066 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10067 if (dahdi_wink(p, idx)) goto quit; 10068 dtmfbuf[0] = 0; 10069 /* Wait for the first digit (up to 5 seconds). */ 10070 res = ast_waitfordigit(chan, 5000); 10071 if (res <= 0) break; 10072 dtmfbuf[0] = res; 10073 /* fall through intentionally */ 10074 case SIG_FEATDMF: 10075 case SIG_E911: 10076 case SIG_FGC_CAMAMF: 10077 case SIG_SF_FEATDMF: 10078 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10079 /* if international caca, do it again to get real ANO */ 10080 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 10081 { 10082 if (dahdi_wink(p, idx)) goto quit; 10083 dtmfbuf[0] = 0; 10084 /* Wait for the first digit (up to 5 seconds). */ 10085 res = ast_waitfordigit(chan, 5000); 10086 if (res <= 0) break; 10087 dtmfbuf[0] = res; 10088 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10089 } 10090 if (res > 0) { 10091 /* if E911, take off hook */ 10092 if (p->sig == SIG_E911) 10093 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10094 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 10095 } 10096 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10097 break; 10098 case SIG_FEATB: 10099 case SIG_SF_FEATB: 10100 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10101 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10102 break; 10103 case SIG_EMWINK: 10104 /* if we received a '*', we are actually receiving Feature Group D 10105 dial syntax, so use that mode; otherwise, fall through to normal 10106 mode 10107 */ 10108 if (res == '*') { 10109 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10110 if (res > 0) 10111 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10112 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10113 break; 10114 } 10115 default: 10116 /* If we got the first digit, get the rest */ 10117 len = 1; 10118 dtmfbuf[len] = '\0'; 10119 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10120 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10121 timeout = matchdigittimeout; 10122 } else { 10123 timeout = gendigittimeout; 10124 } 10125 res = ast_waitfordigit(chan, timeout); 10126 if (res < 0) { 10127 ast_debug(1, "waitfordigit returned < 0...\n"); 10128 ast_hangup(chan); 10129 goto quit; 10130 } else if (res) { 10131 dtmfbuf[len++] = res; 10132 dtmfbuf[len] = '\0'; 10133 } else { 10134 break; 10135 } 10136 } 10137 break; 10138 } 10139 } 10140 if (res == -1) { 10141 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 10142 ast_hangup(chan); 10143 goto quit; 10144 } else if (res < 0) { 10145 ast_debug(1, "Got hung up before digits finished\n"); 10146 ast_hangup(chan); 10147 goto quit; 10148 } 10149 10150 if (p->sig == SIG_FGC_CAMA) { 10151 char anibuf[100]; 10152 10153 if (ast_safe_sleep(chan,1000) == -1) { 10154 ast_hangup(chan); 10155 goto quit; 10156 } 10157 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10158 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10159 res = my_getsigstr(chan, anibuf, "#", 10000); 10160 if ((res > 0) && (strlen(anibuf) > 2)) { 10161 if (anibuf[strlen(anibuf) - 1] == '#') 10162 anibuf[strlen(anibuf) - 1] = 0; 10163 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 10164 } 10165 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10166 } 10167 10168 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 10169 if (ast_strlen_zero(exten)) 10170 ast_copy_string(exten, "s", sizeof(exten)); 10171 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 10172 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 10173 if (exten[0] == '*') { 10174 char *stringp=NULL; 10175 ast_copy_string(exten2, exten, sizeof(exten2)); 10176 /* Parse out extension and callerid */ 10177 stringp=exten2 +1; 10178 s1 = strsep(&stringp, "*"); 10179 s2 = strsep(&stringp, "*"); 10180 if (s2) { 10181 if (!ast_strlen_zero(p->cid_num)) 10182 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10183 else 10184 ast_set_callerid(chan, s1, NULL, s1); 10185 ast_copy_string(exten, s2, sizeof(exten)); 10186 } else 10187 ast_copy_string(exten, s1, sizeof(exten)); 10188 } else if (p->sig == SIG_FEATD) 10189 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10190 } 10191 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10192 if (exten[0] == '*') { 10193 char *stringp=NULL; 10194 ast_copy_string(exten2, exten, sizeof(exten2)); 10195 /* Parse out extension and callerid */ 10196 stringp=exten2 +1; 10197 s1 = strsep(&stringp, "#"); 10198 s2 = strsep(&stringp, "#"); 10199 if (s2) { 10200 if (!ast_strlen_zero(p->cid_num)) 10201 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10202 else 10203 if (*(s1 + 2)) 10204 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 10205 ast_copy_string(exten, s2 + 1, sizeof(exten)); 10206 } else 10207 ast_copy_string(exten, s1 + 2, sizeof(exten)); 10208 } else 10209 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10210 } 10211 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 10212 if (exten[0] == '*') { 10213 char *stringp=NULL; 10214 ast_copy_string(exten2, exten, sizeof(exten2)); 10215 /* Parse out extension and callerid */ 10216 stringp=exten2 +1; 10217 s1 = strsep(&stringp, "#"); 10218 s2 = strsep(&stringp, "#"); 10219 if (s2 && (*(s2 + 1) == '0')) { 10220 if (*(s2 + 2)) 10221 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 10222 } 10223 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 10224 else ast_copy_string(exten, "911", sizeof(exten)); 10225 } else 10226 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 10227 } 10228 if (p->sig == SIG_FEATB) { 10229 if (exten[0] == '*') { 10230 char *stringp=NULL; 10231 ast_copy_string(exten2, exten, sizeof(exten2)); 10232 /* Parse out extension and callerid */ 10233 stringp=exten2 +1; 10234 s1 = strsep(&stringp, "#"); 10235 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 10236 } else 10237 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 10238 } 10239 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10240 dahdi_wink(p, idx); 10241 /* some switches require a minimum guard time between 10242 the last FGD wink and something that answers 10243 immediately. This ensures it */ 10244 if (ast_safe_sleep(chan, 100)) { 10245 ast_hangup(chan); 10246 goto quit; 10247 } 10248 } 10249 dahdi_enable_ec(p); 10250 if (NEED_MFDETECT(p)) { 10251 if (p->dsp) { 10252 if (!p->hardwaredtmf) 10253 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10254 else { 10255 ast_dsp_free(p->dsp); 10256 p->dsp = NULL; 10257 } 10258 } 10259 } 10260 10261 if (ast_exists_extension(chan, chan->context, exten, 1, 10262 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 10263 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10264 if (p->dsp) ast_dsp_digitreset(p->dsp); 10265 res = ast_pbx_run(chan); 10266 if (res) { 10267 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10268 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10269 } 10270 goto quit; 10271 } else { 10272 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 10273 sleep(2); 10274 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 10275 if (res < 0) 10276 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 10277 else 10278 sleep(1); 10279 res = ast_streamfile(chan, "ss-noservice", chan->language); 10280 if (res >= 0) 10281 ast_waitstream(chan, ""); 10282 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10283 ast_hangup(chan); 10284 goto quit; 10285 } 10286 break; 10287 case SIG_FXOLS: 10288 case SIG_FXOGS: 10289 case SIG_FXOKS: 10290 /* Read the first digit */ 10291 timeout = firstdigittimeout; 10292 /* If starting a threeway call, never timeout on the first digit so someone 10293 can use flash-hook as a "hold" feature */ 10294 if (p->subs[SUB_THREEWAY].owner) 10295 timeout = 999999; 10296 while (len < AST_MAX_EXTENSION-1) { 10297 /* Read digit unless it's supposed to be immediate, in which case the 10298 only answer is 's' */ 10299 if (p->immediate) 10300 res = 's'; 10301 else 10302 res = ast_waitfordigit(chan, timeout); 10303 timeout = 0; 10304 if (res < 0) { 10305 ast_debug(1, "waitfordigit returned < 0...\n"); 10306 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10307 ast_hangup(chan); 10308 goto quit; 10309 } else if (res) { 10310 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 10311 exten[len++]=res; 10312 exten[len] = '\0'; 10313 } 10314 if (!ast_ignore_pattern(chan->context, exten)) 10315 tone_zone_play_tone(p->subs[idx].dfd, -1); 10316 else 10317 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10318 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) { 10319 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 10320 if (getforward) { 10321 /* Record this as the forwarding extension */ 10322 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 10323 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 10324 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10325 if (res) 10326 break; 10327 usleep(500000); 10328 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10329 sleep(1); 10330 memset(exten, 0, sizeof(exten)); 10331 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10332 len = 0; 10333 getforward = 0; 10334 } else { 10335 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10336 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10337 if (!ast_strlen_zero(p->cid_num)) { 10338 if (!p->hidecallerid) 10339 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10340 else 10341 ast_set_callerid(chan, NULL, NULL, p->cid_num); 10342 } 10343 if (!ast_strlen_zero(p->cid_name)) { 10344 if (!p->hidecallerid) 10345 ast_set_callerid(chan, NULL, p->cid_name, NULL); 10346 } 10347 ast_setstate(chan, AST_STATE_RING); 10348 dahdi_enable_ec(p); 10349 res = ast_pbx_run(chan); 10350 if (res) { 10351 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10352 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10353 } 10354 goto quit; 10355 } 10356 } else { 10357 /* It's a match, but they just typed a digit, and there is an ambiguous match, 10358 so just set the timeout to matchdigittimeout and wait some more */ 10359 timeout = matchdigittimeout; 10360 } 10361 } else if (res == 0) { 10362 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 10363 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10364 dahdi_wait_event(p->subs[idx].dfd); 10365 ast_hangup(chan); 10366 goto quit; 10367 } else if (p->callwaiting && !strcmp(exten, "*70")) { 10368 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 10369 /* Disable call waiting if enabled */ 10370 p->callwaiting = 0; 10371 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10372 if (res) { 10373 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10374 chan->name, strerror(errno)); 10375 } 10376 len = 0; 10377 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 10378 memset(exten, 0, sizeof(exten)); 10379 timeout = firstdigittimeout; 10380 10381 } else if (!strcmp(exten,ast_pickup_ext())) { 10382 /* Scan all channels and see if there are any 10383 * ringing channels that have call groups 10384 * that equal this channels pickup group 10385 */ 10386 if (idx == SUB_REAL) { 10387 /* Switch us from Third call to Call Wait */ 10388 if (p->subs[SUB_THREEWAY].owner) { 10389 /* If you make a threeway call and the *8# a call, it should actually 10390 look like a callwait */ 10391 alloc_sub(p, SUB_CALLWAIT); 10392 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 10393 unalloc_sub(p, SUB_THREEWAY); 10394 } 10395 dahdi_enable_ec(p); 10396 if (ast_pickup_call(chan)) { 10397 ast_debug(1, "No call pickup possible...\n"); 10398 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10399 dahdi_wait_event(p->subs[idx].dfd); 10400 } 10401 ast_hangup(chan); 10402 goto quit; 10403 } else { 10404 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 10405 ast_hangup(chan); 10406 goto quit; 10407 } 10408 10409 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 10410 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 10411 /* Disable Caller*ID if enabled */ 10412 p->hidecallerid = 1; 10413 ast_party_number_free(&chan->caller.id.number); 10414 ast_party_number_init(&chan->caller.id.number); 10415 ast_party_name_free(&chan->caller.id.name); 10416 ast_party_name_init(&chan->caller.id.name); 10417 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10418 if (res) { 10419 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10420 chan->name, strerror(errno)); 10421 } 10422 len = 0; 10423 memset(exten, 0, sizeof(exten)); 10424 timeout = firstdigittimeout; 10425 } else if (p->callreturn && !strcmp(exten, "*69")) { 10426 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10427 break; 10428 } else if (!strcmp(exten, "*78")) { 10429 dahdi_dnd(p, 1); 10430 /* Do not disturb */ 10431 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10432 getforward = 0; 10433 memset(exten, 0, sizeof(exten)); 10434 len = 0; 10435 } else if (!strcmp(exten, "*79")) { 10436 dahdi_dnd(p, 0); 10437 /* Do not disturb */ 10438 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10439 getforward = 0; 10440 memset(exten, 0, sizeof(exten)); 10441 len = 0; 10442 } else if (p->cancallforward && !strcmp(exten, "*72")) { 10443 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10444 getforward = 1; 10445 memset(exten, 0, sizeof(exten)); 10446 len = 0; 10447 } else if (p->cancallforward && !strcmp(exten, "*73")) { 10448 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 10449 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10450 memset(p->call_forward, 0, sizeof(p->call_forward)); 10451 getforward = 0; 10452 memset(exten, 0, sizeof(exten)); 10453 len = 0; 10454 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) && 10455 p->subs[SUB_THREEWAY].owner && 10456 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 10457 /* This is a three way call, the main call being a real channel, 10458 and we're parking the first call. */ 10459 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), 10460 chan, exten, chan->context, 0, NULL); 10461 ast_verb(3, "Parking call to '%s'\n", chan->name); 10462 break; 10463 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 10464 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 10465 /* Enable Caller*ID if enabled */ 10466 p->hidecallerid = 0; 10467 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 10468 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10469 if (res) { 10470 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10471 chan->name, strerror(errno)); 10472 } 10473 len = 0; 10474 memset(exten, 0, sizeof(exten)); 10475 timeout = firstdigittimeout; 10476 } else if (!strcmp(exten, "*0")) { 10477 struct ast_channel *nbridge = 10478 p->subs[SUB_THREEWAY].owner; 10479 struct dahdi_pvt *pbridge = NULL; 10480 /* set up the private struct of the bridged one, if any */ 10481 if (nbridge && ast_bridged_channel(nbridge)) 10482 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 10483 if (nbridge && pbridge && 10484 (nbridge->tech == &dahdi_tech) && 10485 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 10486 ISTRUNK(pbridge)) { 10487 int func = DAHDI_FLASH; 10488 /* Clear out the dial buffer */ 10489 p->dop.dialstr[0] = '\0'; 10490 /* flash hookswitch */ 10491 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 10492 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 10493 nbridge->name, strerror(errno)); 10494 } 10495 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10496 unalloc_sub(p, SUB_THREEWAY); 10497 p->owner = p->subs[SUB_REAL].owner; 10498 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 10499 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 10500 ast_hangup(chan); 10501 goto quit; 10502 } else { 10503 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10504 dahdi_wait_event(p->subs[idx].dfd); 10505 tone_zone_play_tone(p->subs[idx].dfd, -1); 10506 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10507 unalloc_sub(p, SUB_THREEWAY); 10508 p->owner = p->subs[SUB_REAL].owner; 10509 ast_hangup(chan); 10510 goto quit; 10511 } 10512 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, 10513 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 10514 && !canmatch_featurecode(exten)) { 10515 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, 10516 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 10517 chan->context); 10518 break; 10519 } 10520 if (!timeout) 10521 timeout = gendigittimeout; 10522 if (len && !ast_ignore_pattern(chan->context, exten)) 10523 tone_zone_play_tone(p->subs[idx].dfd, -1); 10524 } 10525 break; 10526 case SIG_FXSLS: 10527 case SIG_FXSGS: 10528 case SIG_FXSKS: 10529 /* check for SMDI messages */ 10530 if (p->use_smdi && p->smdi_iface) { 10531 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 10532 10533 if (smdi_msg != NULL) { 10534 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 10535 10536 if (smdi_msg->type == 'B') 10537 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 10538 else if (smdi_msg->type == 'N') 10539 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 10540 10541 ast_debug(1, "Received SMDI message on %s\n", chan->name); 10542 } else { 10543 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 10544 } 10545 } 10546 10547 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 10548 number = smdi_msg->calling_st; 10549 10550 /* If we want caller id, we're in a prering state due to a polarity reversal 10551 * and we're set to use a polarity reversal to trigger the start of caller id, 10552 * grab the caller id and wait for ringing to start... */ 10553 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 10554 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 10555 /* If set to use DTMF CID signalling, listen for DTMF */ 10556 if (p->cid_signalling == CID_SIG_DTMF) { 10557 int k = 0; 10558 int off_ms; 10559 struct timeval start = ast_tvnow(); 10560 int ms; 10561 cs = NULL; 10562 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 10563 dahdi_setlinear(p->subs[idx].dfd, 0); 10564 /* 10565 * We are the only party interested in the Rx stream since 10566 * we have not answered yet. We don't need or even want DTMF 10567 * emulation. The DTMF digits can come so fast that emulation 10568 * can drop some of them. 10569 */ 10570 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 10571 off_ms = 4000;/* This is a typical OFF time between rings. */ 10572 for (;;) { 10573 struct ast_frame *f; 10574 10575 ms = ast_remaining_ms(start, off_ms); 10576 res = ast_waitfor(chan, ms); 10577 if (res <= 0) { 10578 /* 10579 * We do not need to restore the dahdi_setlinear() 10580 * or AST_FLAG_END_DTMF_ONLY flag settings since we 10581 * are hanging up the channel. 10582 */ 10583 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10584 "Exiting simple switch\n"); 10585 ast_hangup(chan); 10586 goto quit; 10587 } 10588 f = ast_read(chan); 10589 if (!f) 10590 break; 10591 if (f->frametype == AST_FRAME_DTMF) { 10592 if (k < ARRAY_LEN(dtmfbuf) - 1) { 10593 dtmfbuf[k++] = f->subclass.integer; 10594 } 10595 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer); 10596 start = ast_tvnow(); 10597 } 10598 ast_frfree(f); 10599 if (chan->_state == AST_STATE_RING || 10600 chan->_state == AST_STATE_RINGING) 10601 break; /* Got ring */ 10602 } 10603 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 10604 dtmfbuf[k] = '\0'; 10605 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10606 /* Got cid and ring. */ 10607 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 10608 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10609 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 10610 /* If first byte is NULL, we have no cid */ 10611 if (!ast_strlen_zero(dtmfcid)) 10612 number = dtmfcid; 10613 else 10614 number = NULL; 10615 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10616 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 10617 cs = callerid_new(p->cid_signalling); 10618 if (cs) { 10619 int off_ms; 10620 struct timeval start; 10621 int ms; 10622 samples = 0; 10623 #if 1 10624 bump_gains(p); 10625 #endif 10626 /* Take out of linear mode for Caller*ID processing */ 10627 dahdi_setlinear(p->subs[idx].dfd, 0); 10628 10629 /* First we wait and listen for the Caller*ID */ 10630 for (;;) { 10631 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10632 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10633 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10634 callerid_free(cs); 10635 ast_hangup(chan); 10636 goto quit; 10637 } 10638 if (i & DAHDI_IOMUX_SIGEVENT) { 10639 res = dahdi_get_event(p->subs[idx].dfd); 10640 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10641 if (res == DAHDI_EVENT_NOALARM) { 10642 p->inalarm = 0; 10643 } 10644 10645 if (p->cid_signalling == CID_SIG_V23_JP) { 10646 if (res == DAHDI_EVENT_RINGBEGIN) { 10647 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10648 usleep(1); 10649 } 10650 } else { 10651 res = 0; 10652 break; 10653 } 10654 } else if (i & DAHDI_IOMUX_READ) { 10655 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10656 if (res < 0) { 10657 if (errno != ELAST) { 10658 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10659 callerid_free(cs); 10660 ast_hangup(chan); 10661 goto quit; 10662 } 10663 break; 10664 } 10665 samples += res; 10666 10667 if (p->cid_signalling == CID_SIG_V23_JP) { 10668 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 10669 } else { 10670 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10671 } 10672 if (res < 0) { 10673 /* 10674 * The previous diagnostic message output likely 10675 * explains why it failed. 10676 */ 10677 ast_log(LOG_WARNING, 10678 "Failed to decode CallerID on channel '%s'\n", 10679 chan->name); 10680 break; 10681 } else if (res) 10682 break; 10683 else if (samples > (8000 * 10)) 10684 break; 10685 } 10686 } 10687 if (res == 1) { 10688 callerid_get(cs, &name, &number, &flags); 10689 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10690 } 10691 10692 if (p->cid_signalling == CID_SIG_V23_JP) { 10693 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10694 usleep(1); 10695 } 10696 10697 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 10698 start = ast_tvnow(); 10699 off_ms = 4000;/* This is a typical OFF time between rings. */ 10700 for (;;) { 10701 struct ast_frame *f; 10702 10703 ms = ast_remaining_ms(start, off_ms); 10704 res = ast_waitfor(chan, ms); 10705 if (res <= 0) { 10706 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 10707 "Exiting simple switch\n"); 10708 ast_hangup(chan); 10709 goto quit; 10710 } 10711 if (!(f = ast_read(chan))) { 10712 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 10713 ast_hangup(chan); 10714 goto quit; 10715 } 10716 ast_frfree(f); 10717 if (chan->_state == AST_STATE_RING || 10718 chan->_state == AST_STATE_RINGING) 10719 break; /* Got ring */ 10720 } 10721 10722 /* We must have a ring by now, so, if configured, lets try to listen for 10723 * distinctive ringing */ 10724 if (p->usedistinctiveringdetection) { 10725 len = 0; 10726 distMatches = 0; 10727 /* Clear the current ring data array so we don't have old data in it. */ 10728 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10729 curRingData[receivedRingT] = 0; 10730 receivedRingT = 0; 10731 counter = 0; 10732 counter1 = 0; 10733 /* Check to see if context is what it should be, if not set to be. */ 10734 if (strcmp(p->context,p->defcontext) != 0) { 10735 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10736 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10737 } 10738 10739 for (;;) { 10740 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10741 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10742 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10743 callerid_free(cs); 10744 ast_hangup(chan); 10745 goto quit; 10746 } 10747 if (i & DAHDI_IOMUX_SIGEVENT) { 10748 res = dahdi_get_event(p->subs[idx].dfd); 10749 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10750 if (res == DAHDI_EVENT_NOALARM) { 10751 p->inalarm = 0; 10752 } 10753 res = 0; 10754 /* Let us detect distinctive ring */ 10755 10756 curRingData[receivedRingT] = p->ringt; 10757 10758 if (p->ringt < p->ringt_base/2) 10759 break; 10760 /* Increment the ringT counter so we can match it against 10761 values in chan_dahdi.conf for distinctive ring */ 10762 if (++receivedRingT == ARRAY_LEN(curRingData)) 10763 break; 10764 } else if (i & DAHDI_IOMUX_READ) { 10765 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10766 if (res < 0) { 10767 if (errno != ELAST) { 10768 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10769 callerid_free(cs); 10770 ast_hangup(chan); 10771 goto quit; 10772 } 10773 break; 10774 } 10775 if (p->ringt > 0) { 10776 if (!(--p->ringt)) { 10777 res = -1; 10778 break; 10779 } 10780 } 10781 } 10782 } 10783 /* this only shows up if you have n of the dring patterns filled in */ 10784 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10785 for (counter = 0; counter < 3; counter++) { 10786 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10787 channel */ 10788 distMatches = 0; 10789 for (counter1 = 0; counter1 < 3; counter1++) { 10790 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10791 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10792 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10793 curRingData[counter1]); 10794 distMatches++; 10795 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10796 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10797 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10798 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10799 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10800 distMatches++; 10801 } 10802 } 10803 10804 if (distMatches == 3) { 10805 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10806 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10807 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10808 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10809 break; 10810 } 10811 } 10812 } 10813 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10814 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10815 #if 1 10816 restore_gains(p); 10817 #endif 10818 } else 10819 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10820 } else { 10821 ast_log(LOG_WARNING, "Channel %s in prering " 10822 "state, but I have nothing to do. " 10823 "Terminating simple switch, should be " 10824 "restarted by the actual ring.\n", 10825 chan->name); 10826 ast_hangup(chan); 10827 goto quit; 10828 } 10829 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 10830 if (p->cid_signalling == CID_SIG_DTMF) { 10831 int k = 0; 10832 int off_ms; 10833 struct timeval start; 10834 int ms; 10835 cs = NULL; 10836 dahdi_setlinear(p->subs[idx].dfd, 0); 10837 off_ms = 2000; 10838 start = ast_tvnow(); 10839 for (;;) { 10840 struct ast_frame *f; 10841 10842 ms = ast_remaining_ms(start, off_ms); 10843 res = ast_waitfor(chan, ms); 10844 if (res <= 0) { 10845 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10846 "Exiting simple switch\n"); 10847 ast_hangup(chan); 10848 goto quit; 10849 } 10850 f = ast_read(chan); 10851 if (!f) { 10852 /* Hangup received waiting for DTMFCID. Exiting simple switch. */ 10853 ast_hangup(chan); 10854 goto quit; 10855 } 10856 if (f->frametype == AST_FRAME_DTMF) { 10857 dtmfbuf[k++] = f->subclass.integer; 10858 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer); 10859 start = ast_tvnow(); 10860 } 10861 ast_frfree(f); 10862 10863 if (p->ringt_base == p->ringt) 10864 break; 10865 } 10866 dtmfbuf[k] = '\0'; 10867 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10868 /* Got cid and ring. */ 10869 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10870 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 10871 dtmfcid, flags); 10872 /* If first byte is NULL, we have no cid */ 10873 if (!ast_strlen_zero(dtmfcid)) 10874 number = dtmfcid; 10875 else 10876 number = NULL; 10877 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10878 } else { 10879 /* FSK Bell202 callerID */ 10880 cs = callerid_new(p->cid_signalling); 10881 if (cs) { 10882 #if 1 10883 bump_gains(p); 10884 #endif 10885 samples = 0; 10886 len = 0; 10887 distMatches = 0; 10888 /* Clear the current ring data array so we don't have old data in it. */ 10889 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10890 curRingData[receivedRingT] = 0; 10891 receivedRingT = 0; 10892 counter = 0; 10893 counter1 = 0; 10894 /* Check to see if context is what it should be, if not set to be. */ 10895 if (strcmp(p->context,p->defcontext) != 0) { 10896 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10897 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10898 } 10899 10900 /* Take out of linear mode for Caller*ID processing */ 10901 dahdi_setlinear(p->subs[idx].dfd, 0); 10902 for (;;) { 10903 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10904 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10905 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10906 callerid_free(cs); 10907 ast_hangup(chan); 10908 goto quit; 10909 } 10910 if (i & DAHDI_IOMUX_SIGEVENT) { 10911 res = dahdi_get_event(p->subs[idx].dfd); 10912 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10913 if (res == DAHDI_EVENT_NOALARM) { 10914 p->inalarm = 0; 10915 } 10916 /* If we get a PR event, they hung up while processing calerid */ 10917 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 10918 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 10919 p->polarity = POLARITY_IDLE; 10920 callerid_free(cs); 10921 ast_hangup(chan); 10922 goto quit; 10923 } 10924 res = 0; 10925 /* Let us detect callerid when the telco uses distinctive ring */ 10926 10927 curRingData[receivedRingT] = p->ringt; 10928 10929 if (p->ringt < p->ringt_base/2) 10930 break; 10931 /* Increment the ringT counter so we can match it against 10932 values in chan_dahdi.conf for distinctive ring */ 10933 if (++receivedRingT == ARRAY_LEN(curRingData)) 10934 break; 10935 } else if (i & DAHDI_IOMUX_READ) { 10936 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10937 if (res < 0) { 10938 if (errno != ELAST) { 10939 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10940 callerid_free(cs); 10941 ast_hangup(chan); 10942 goto quit; 10943 } 10944 break; 10945 } 10946 if (p->ringt > 0) { 10947 if (!(--p->ringt)) { 10948 res = -1; 10949 break; 10950 } 10951 } 10952 samples += res; 10953 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10954 if (res < 0) { 10955 /* 10956 * The previous diagnostic message output likely 10957 * explains why it failed. 10958 */ 10959 ast_log(LOG_WARNING, 10960 "Failed to decode CallerID on channel '%s'\n", 10961 chan->name); 10962 break; 10963 } else if (res) 10964 break; 10965 else if (samples > (8000 * 10)) 10966 break; 10967 } 10968 } 10969 if (res == 1) { 10970 callerid_get(cs, &name, &number, &flags); 10971 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10972 } 10973 if (distinctiveringaftercid == 1) { 10974 /* Clear the current ring data array so we don't have old data in it. */ 10975 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 10976 curRingData[receivedRingT] = 0; 10977 } 10978 receivedRingT = 0; 10979 ast_verb(3, "Detecting post-CID distinctive ring\n"); 10980 for (;;) { 10981 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10982 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10983 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10984 callerid_free(cs); 10985 ast_hangup(chan); 10986 goto quit; 10987 } 10988 if (i & DAHDI_IOMUX_SIGEVENT) { 10989 res = dahdi_get_event(p->subs[idx].dfd); 10990 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10991 if (res == DAHDI_EVENT_NOALARM) { 10992 p->inalarm = 0; 10993 } 10994 res = 0; 10995 /* Let us detect callerid when the telco uses distinctive ring */ 10996 10997 curRingData[receivedRingT] = p->ringt; 10998 10999 if (p->ringt < p->ringt_base/2) 11000 break; 11001 /* Increment the ringT counter so we can match it against 11002 values in chan_dahdi.conf for distinctive ring */ 11003 if (++receivedRingT == ARRAY_LEN(curRingData)) 11004 break; 11005 } else if (i & DAHDI_IOMUX_READ) { 11006 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 11007 if (res < 0) { 11008 if (errno != ELAST) { 11009 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 11010 callerid_free(cs); 11011 ast_hangup(chan); 11012 goto quit; 11013 } 11014 break; 11015 } 11016 if (p->ringt > 0) { 11017 if (!(--p->ringt)) { 11018 res = -1; 11019 break; 11020 } 11021 } 11022 } 11023 } 11024 } 11025 if (p->usedistinctiveringdetection) { 11026 /* this only shows up if you have n of the dring patterns filled in */ 11027 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 11028 11029 for (counter = 0; counter < 3; counter++) { 11030 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 11031 channel */ 11032 /* this only shows up if you have n of the dring patterns filled in */ 11033 ast_verb(3, "Checking %d,%d,%d\n", 11034 p->drings.ringnum[counter].ring[0], 11035 p->drings.ringnum[counter].ring[1], 11036 p->drings.ringnum[counter].ring[2]); 11037 distMatches = 0; 11038 for (counter1 = 0; counter1 < 3; counter1++) { 11039 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 11040 if (p->drings.ringnum[counter].ring[counter1] == -1) { 11041 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 11042 curRingData[counter1]); 11043 distMatches++; 11044 } 11045 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 11046 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 11047 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 11048 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 11049 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 11050 distMatches++; 11051 } 11052 } 11053 if (distMatches == 3) { 11054 /* The ring matches, set the context to whatever is for distinctive ring.. */ 11055 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 11056 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 11057 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 11058 break; 11059 } 11060 } 11061 } 11062 /* Restore linear mode (if appropriate) for Caller*ID processing */ 11063 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 11064 #if 1 11065 restore_gains(p); 11066 #endif 11067 if (res < 0) { 11068 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 11069 } 11070 } else 11071 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 11072 } 11073 } else 11074 cs = NULL; 11075 11076 if (number) 11077 ast_shrink_phone_number(number); 11078 ast_set_callerid(chan, number, name, number); 11079 11080 if (smdi_msg) 11081 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 11082 11083 if (cs) 11084 callerid_free(cs); 11085 11086 my_handle_notify_message(chan, p, flags, -1); 11087 11088 ast_setstate(chan, AST_STATE_RING); 11089 chan->rings = 1; 11090 p->ringt = p->ringt_base; 11091 res = ast_pbx_run(chan); 11092 if (res) { 11093 ast_hangup(chan); 11094 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 11095 } 11096 goto quit; 11097 default: 11098 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 11099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11100 if (res < 0) 11101 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11102 } 11103 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11104 if (res < 0) 11105 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11106 ast_hangup(chan); 11107 quit: 11108 ast_mutex_lock(&ss_thread_lock); 11109 ss_thread_count--; 11110 ast_cond_signal(&ss_thread_complete); 11111 ast_mutex_unlock(&ss_thread_lock); 11112 return NULL; 11113 }
static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1670 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().
01671 { 01672 switch (tone) { 01673 case ANALOG_TONE_RINGTONE: 01674 return DAHDI_TONE_RINGTONE; 01675 case ANALOG_TONE_STUTTER: 01676 return DAHDI_TONE_STUTTER; 01677 case ANALOG_TONE_CONGESTION: 01678 return DAHDI_TONE_CONGESTION; 01679 case ANALOG_TONE_DIALTONE: 01680 return DAHDI_TONE_DIALTONE; 01681 case ANALOG_TONE_DIALRECALL: 01682 return DAHDI_TONE_DIALRECALL; 01683 case ANALOG_TONE_INFO: 01684 return DAHDI_TONE_INFO; 01685 default: 01686 return -1; 01687 } 01688 }
static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1690 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().
01691 { 01692 int index; 01693 01694 switch (analogsub) { 01695 case ANALOG_SUB_REAL: 01696 index = SUB_REAL; 01697 break; 01698 case ANALOG_SUB_CALLWAIT: 01699 index = SUB_CALLWAIT; 01700 break; 01701 case ANALOG_SUB_THREEWAY: 01702 index = SUB_THREEWAY; 01703 break; 01704 default: 01705 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01706 index = SUB_REAL; 01707 } 01708 01709 return index; 01710 }
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 7685 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().
07686 { 07687 /* In order to transfer, we need at least one of the channels to 07688 actually be in a call bridge. We can't conference two applications 07689 together (but then, why would we want to?) */ 07690 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07691 /* The three-way person we're about to transfer to could still be in MOH, so 07692 stop if now if appropriate */ 07693 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 07694 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 07695 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 07696 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 07697 } 07698 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 07699 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07700 } 07701 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 07702 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07703 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 07704 return -1; 07705 } 07706 /* Orphan the channel after releasing the lock */ 07707 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07708 unalloc_sub(p, SUB_THREEWAY); 07709 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07710 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07711 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 07712 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 07713 } 07714 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 07715 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07716 } 07717 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 07718 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07719 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 07720 return -1; 07721 } 07722 /* Three-way is now the REAL */ 07723 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07724 ast_channel_unlock(p->subs[SUB_REAL].owner); 07725 unalloc_sub(p, SUB_THREEWAY); 07726 /* Tell the caller not to hangup */ 07727 return 1; 07728 } else { 07729 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 07730 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 07731 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07732 return -1; 07733 } 07734 return 0; 07735 }
static int available | ( | struct dahdi_pvt ** | pvt, | |
int | is_specific_channel | |||
) | [static] |
Definition at line 13288 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().
13289 { 13290 struct dahdi_pvt *p = *pvt; 13291 13292 if (p->inalarm) 13293 return 0; 13294 13295 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 13296 return analog_available(p->sig_pvt); 13297 13298 switch (p->sig) { 13299 #if defined(HAVE_PRI) 13300 case SIG_PRI_LIB_HANDLE_CASES: 13301 { 13302 struct sig_pri_chan *pvt_chan; 13303 int res; 13304 13305 pvt_chan = p->sig_pvt; 13306 res = sig_pri_available(&pvt_chan, is_specific_channel); 13307 *pvt = pvt_chan->chan_pvt; 13308 return res; 13309 } 13310 #endif /* defined(HAVE_PRI) */ 13311 #if defined(HAVE_SS7) 13312 case SIG_SS7: 13313 return sig_ss7_available(p->sig_pvt); 13314 #endif /* defined(HAVE_SS7) */ 13315 default: 13316 break; 13317 } 13318 13319 if (p->locallyblocked || p->remotelyblocked) { 13320 return 0; 13321 } 13322 13323 /* If no owner definitely available */ 13324 if (!p->owner) { 13325 #ifdef HAVE_OPENR2 13326 /* Trust MFC/R2 */ 13327 if (p->mfcr2) { 13328 if (p->mfcr2call) { 13329 return 0; 13330 } else { 13331 return 1; 13332 } 13333 } 13334 #endif 13335 return 1; 13336 } 13337 13338 return 0; 13339 }
static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
const char * | value, | |||
int | reload, | |||
int | lineno, | |||
int * | found_pseudo | |||
) | [static] |
Definition at line 17013 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().
17014 { 17015 char *c, *chan; 17016 char *subdir; 17017 int x, start, finish; 17018 struct dahdi_pvt *tmp; 17019 17020 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 17021 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 17022 return -1; 17023 } 17024 17025 c = ast_strdupa(value); 17026 c = parse_spanchan(c, &subdir); 17027 17028 while ((chan = strsep(&c, ","))) { 17029 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 17030 /* Range */ 17031 } else if (sscanf(chan, "%30d", &start)) { 17032 /* Just one */ 17033 finish = start; 17034 } else if (!strcasecmp(chan, "pseudo")) { 17035 finish = start = CHAN_PSEUDO; 17036 if (found_pseudo) 17037 *found_pseudo = 1; 17038 } else { 17039 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 17040 return -1; 17041 } 17042 if (finish < start) { 17043 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 17044 x = finish; 17045 finish = start; 17046 start = x; 17047 } 17048 17049 for (x = start; x <= finish; x++) { 17050 char fn[PATH_MAX]; 17051 int real_channel = x; 17052 17053 if (!ast_strlen_zero(subdir)) { 17054 real_channel = device2chan(subdir, x, fn, sizeof(fn)); 17055 if (real_channel < 0) { 17056 if (conf->ignore_failed_channels) { 17057 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n", 17058 subdir, x, real_channel); 17059 continue; 17060 } else { 17061 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n", 17062 subdir, x, real_channel); 17063 return -1; 17064 } 17065 } 17066 } 17067 tmp = mkintf(real_channel, conf, reload); 17068 17069 if (tmp) { 17070 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig)); 17071 } else { 17072 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 17073 (reload == 1) ? "reconfigure" : "register", value); 17074 return -1; 17075 } 17076 } 17077 } 17078 17079 return 0; 17080 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5164 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().
05165 { 05166 int res; 05167 05168 /* Bump receive gain by value stored in cid_rxgain */ 05169 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05170 if (res) { 05171 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 05172 return -1; 05173 } 05174 05175 return 0; 05176 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
format_t | law | |||
) | [static] |
Definition at line 11121 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 9943 of file chan_dahdi.c.
References ast_pickup_ext(), and pickup_ext.
Referenced by analog_ss_thread().
09944 { 09945 int extlen = strlen(exten); 09946 const char *pickup_ext; 09947 if (!extlen) { 09948 return 1; 09949 } 09950 pickup_ext = ast_pickup_ext(); 09951 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) { 09952 return 1; 09953 } 09954 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */ 09955 if (exten[0] == '*' && extlen < 3) { 09956 if (extlen == 1) { 09957 return 1; 09958 } 09959 /* "*0" should be processed before it gets here */ 09960 switch (exten[1]) { 09961 case '6': 09962 case '7': 09963 case '8': 09964 return 1; 09965 } 09966 } 09967 return 0; 09968 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7737 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().
07738 { 07739 struct dahdi_confinfo ci; 07740 /* Fine if we already have a master, etc */ 07741 if (p->master || (p->confno > -1)) 07742 return 0; 07743 memset(&ci, 0, sizeof(ci)); 07744 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 07745 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 07746 return 0; 07747 } 07748 /* If we have no master and don't have a confno, then 07749 if we're in a conference, it's probably a MeetMe room or 07750 some such, so don't let us 3-way out! */ 07751 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 07752 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 07753 return 1; 07754 } 07755 return 0; 07756 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 4734 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().
04735 { 04736 /* If the conference already exists, and we're already in it 04737 don't bother doing anything */ 04738 struct dahdi_confinfo zi; 04739 04740 memset(&zi, 0, sizeof(zi)); 04741 zi.chan = 0; 04742 04743 if (slavechannel > 0) { 04744 /* If we have only one slave, do a digital mon */ 04745 zi.confmode = DAHDI_CONF_DIGITALMON; 04746 zi.confno = slavechannel; 04747 } else { 04748 if (!idx) { 04749 /* Real-side and pseudo-side both participate in conference */ 04750 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 04751 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 04752 } else 04753 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 04754 zi.confno = p->confno; 04755 } 04756 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 04757 return 0; 04758 if (c->dfd < 0) 04759 return 0; 04760 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04761 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 04762 return -1; 04763 } 04764 if (slavechannel < 1) { 04765 p->confno = zi.confno; 04766 } 04767 c->curconf = zi; 04768 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04769 return 0; 04770 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 4783 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().
04784 { 04785 struct dahdi_confinfo zi; 04786 if (/* Can't delete if there's no dfd */ 04787 (c->dfd < 0) || 04788 /* Don't delete from the conference if it's not our conference */ 04789 !isourconf(p, c) 04790 /* Don't delete if we don't think it's conferenced at all (implied) */ 04791 ) return 0; 04792 memset(&zi, 0, sizeof(zi)); 04793 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04794 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 04795 return -1; 04796 } 04797 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04798 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 04799 return 0; 04800 }
Definition at line 9603 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().
09605 { 09606 struct ast_str *chan_name; 09607 int x, y; 09608 09609 /* Create the new channel name tail. */ 09610 if (!(chan_name = ast_str_create(32))) { 09611 return NULL; 09612 } 09613 if (i->channel == CHAN_PSEUDO) { 09614 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 09615 #if defined(HAVE_PRI) 09616 } else if (i->pri) { 09617 ast_mutex_lock(&i->pri->lock); 09618 y = ++i->pri->new_chan_seq; 09619 if (is_outgoing) { 09620 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y); 09621 address[0] = '\0'; 09622 } else if (ast_strlen_zero(i->cid_subaddr)) { 09623 /* Put in caller-id number only since there is no subaddress. */ 09624 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y); 09625 } else { 09626 /* Put in caller-id number and subaddress. */ 09627 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num, 09628 i->cid_subaddr, (unsigned)y); 09629 } 09630 ast_mutex_unlock(&i->pri->lock); 09631 #endif /* defined(HAVE_PRI) */ 09632 } else { 09633 y = 1; 09634 do { 09635 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 09636 for (x = 0; x < 3; ++x) { 09637 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), 09638 i->subs[x].owner->name + 6)) { 09639 break; 09640 } 09641 } 09642 ++y; 09643 } while (x < 3); 09644 } 09645 return chan_name; 09646 }
static void dahdi_ami_channel_event | ( | struct dahdi_pvt * | p, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2186 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().
02187 { 02188 char ch_name[20]; 02189 02190 if (p->channel < CHAN_PSEUDO) { 02191 /* No B channel */ 02192 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel); 02193 } else if (p->channel == CHAN_PSEUDO) { 02194 /* Pseudo channel */ 02195 strcpy(ch_name, "pseudo"); 02196 } else { 02197 /* Real channel */ 02198 snprintf(ch_name, sizeof(ch_name), "%d", p->channel); 02199 } 02200 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel", 02201 "Channel: %s\r\n" 02202 "Uniqueid: %s\r\n" 02203 "DAHDISpan: %d\r\n" 02204 "DAHDIChannel: %s\r\n", 02205 chan->name, 02206 chan->uniqueid, 02207 p->span, 02208 ch_name); 02209 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6613 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.
06614 { 06615 struct dahdi_pvt *p = ast->tech_pvt; 06616 int res = 0; 06617 int idx; 06618 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */ 06619 ast_mutex_lock(&p->lock); 06620 idx = dahdi_get_index(ast, p, 0); 06621 if (idx < 0) 06622 idx = SUB_REAL; 06623 /* nothing to do if a radio channel */ 06624 if ((p->radio || (p->oprmode < 0))) { 06625 ast_mutex_unlock(&p->lock); 06626 return 0; 06627 } 06628 06629 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06630 res = analog_answer(p->sig_pvt, ast); 06631 ast_mutex_unlock(&p->lock); 06632 return res; 06633 } 06634 06635 switch (p->sig) { 06636 #if defined(HAVE_PRI) 06637 case SIG_PRI_LIB_HANDLE_CASES: 06638 res = sig_pri_answer(p->sig_pvt, ast); 06639 break; 06640 #endif /* defined(HAVE_PRI) */ 06641 #if defined(HAVE_SS7) 06642 case SIG_SS7: 06643 res = sig_ss7_answer(p->sig_pvt, ast); 06644 break; 06645 #endif /* defined(HAVE_SS7) */ 06646 #ifdef HAVE_OPENR2 06647 case SIG_MFCR2: 06648 if (!p->mfcr2_call_accepted) { 06649 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 06650 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 06651 p->mfcr2_answer_pending = 1; 06652 if (p->mfcr2_charge_calls) { 06653 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 06654 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 06655 } else { 06656 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 06657 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 06658 } 06659 } else { 06660 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 06661 dahdi_r2_answer(p); 06662 } 06663 break; 06664 #endif 06665 case 0: 06666 ast_mutex_unlock(&p->lock); 06667 return 0; 06668 default: 06669 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 06670 res = -1; 06671 break; 06672 } 06673 ast_mutex_unlock(&p->lock); 06674 return res; 06675 }
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 7260 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().
07261 { 07262 struct ast_channel *who; 07263 struct dahdi_pvt *p0, *p1, *op0, *op1; 07264 struct dahdi_pvt *master = NULL, *slave = NULL; 07265 struct ast_frame *f; 07266 int inconf = 0; 07267 int nothingok = 1; 07268 int ofd0, ofd1; 07269 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 07270 int os0 = -1, os1 = -1; 07271 int priority = 0; 07272 struct ast_channel *oc0, *oc1; 07273 enum ast_bridge_result res; 07274 struct timeval start = ast_tvnow(); 07275 #ifdef PRI_2BCT 07276 int triedtopribridge = 0; 07277 q931_call *q931c0; 07278 q931_call *q931c1; 07279 #endif 07280 07281 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 07282 There is code below to handle it properly until DTMF is actually seen, 07283 but due to currently unresolved issues it's ignored... 07284 */ 07285 07286 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 07287 return AST_BRIDGE_FAILED_NOWARN; 07288 07289 ast_channel_lock(c0); 07290 while (ast_channel_trylock(c1)) { 07291 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07292 } 07293 07294 p0 = c0->tech_pvt; 07295 p1 = c1->tech_pvt; 07296 /* cant do pseudo-channels here */ 07297 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 07298 ast_channel_unlock(c0); 07299 ast_channel_unlock(c1); 07300 return AST_BRIDGE_FAILED_NOWARN; 07301 } 07302 07303 oi0 = dahdi_get_index(c0, p0, 0); 07304 oi1 = dahdi_get_index(c1, p1, 0); 07305 if ((oi0 < 0) || (oi1 < 0)) { 07306 ast_channel_unlock(c0); 07307 ast_channel_unlock(c1); 07308 return AST_BRIDGE_FAILED; 07309 } 07310 07311 op0 = p0 = c0->tech_pvt; 07312 op1 = p1 = c1->tech_pvt; 07313 ofd0 = c0->fds[0]; 07314 ofd1 = c1->fds[0]; 07315 oc0 = p0->owner; 07316 oc1 = p1->owner; 07317 07318 if (ast_mutex_trylock(&p0->lock)) { 07319 /* Don't block, due to potential for deadlock */ 07320 ast_channel_unlock(c0); 07321 ast_channel_unlock(c1); 07322 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07323 return AST_BRIDGE_RETRY; 07324 } 07325 if (ast_mutex_trylock(&p1->lock)) { 07326 /* Don't block, due to potential for deadlock */ 07327 ast_mutex_unlock(&p0->lock); 07328 ast_channel_unlock(c0); 07329 ast_channel_unlock(c1); 07330 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07331 return AST_BRIDGE_RETRY; 07332 } 07333 07334 if ((p0->callwaiting && p0->callwaitingcallerid) 07335 || (p1->callwaiting && p1->callwaitingcallerid)) { 07336 /* 07337 * Call Waiting Caller ID requires DTMF detection to know if it 07338 * can send the CID spill. 07339 * 07340 * For now, don't attempt to native bridge if either channel 07341 * needs DTMF detection. There is code below to handle it 07342 * properly until DTMF is actually seen, but due to currently 07343 * unresolved issues it's ignored... 07344 */ 07345 ast_mutex_unlock(&p0->lock); 07346 ast_mutex_unlock(&p1->lock); 07347 ast_channel_unlock(c0); 07348 ast_channel_unlock(c1); 07349 return AST_BRIDGE_FAILED_NOWARN; 07350 } 07351 07352 #if defined(HAVE_PRI) 07353 if ((dahdi_sig_pri_lib_handles(p0->sig) 07354 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 07355 || (dahdi_sig_pri_lib_handles(p1->sig) 07356 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 07357 /* 07358 * PRI nobch channels (hold and call waiting) are equivalent to 07359 * pseudo channels and cannot be done here. 07360 */ 07361 ast_mutex_unlock(&p0->lock); 07362 ast_mutex_unlock(&p1->lock); 07363 ast_channel_unlock(c0); 07364 ast_channel_unlock(c1); 07365 return AST_BRIDGE_FAILED_NOWARN; 07366 } 07367 #endif /* defined(HAVE_PRI) */ 07368 07369 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07370 if (p0->owner && p1->owner) { 07371 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 07372 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 07373 master = p0; 07374 slave = p1; 07375 inconf = 1; 07376 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 07377 master = p1; 07378 slave = p0; 07379 inconf = 1; 07380 } else { 07381 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 07382 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 07383 p0->channel, 07384 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07385 p0->subs[SUB_REAL].inthreeway, p0->channel, 07386 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07387 p1->subs[SUB_REAL].inthreeway); 07388 } 07389 nothingok = 0; 07390 } 07391 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 07392 if (p1->subs[SUB_THREEWAY].inthreeway) { 07393 master = p1; 07394 slave = p0; 07395 nothingok = 0; 07396 } 07397 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 07398 if (p0->subs[SUB_THREEWAY].inthreeway) { 07399 master = p0; 07400 slave = p1; 07401 nothingok = 0; 07402 } 07403 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 07404 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 07405 don't put us in anything */ 07406 if (p1->subs[SUB_CALLWAIT].inthreeway) { 07407 master = p1; 07408 slave = p0; 07409 nothingok = 0; 07410 } 07411 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 07412 /* Same as previous */ 07413 if (p0->subs[SUB_CALLWAIT].inthreeway) { 07414 master = p0; 07415 slave = p1; 07416 nothingok = 0; 07417 } 07418 } 07419 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 07420 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 07421 if (master && slave) { 07422 /* Stop any tones, or play ringtone as appropriate. If they're bridged 07423 in an active threeway call with a channel that is ringing, we should 07424 indicate ringing. */ 07425 if ((oi1 == SUB_THREEWAY) && 07426 p1->subs[SUB_THREEWAY].inthreeway && 07427 p1->subs[SUB_REAL].owner && 07428 p1->subs[SUB_REAL].inthreeway && 07429 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07430 ast_debug(1, 07431 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07432 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07433 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 07434 os1 = p1->subs[SUB_REAL].owner->_state; 07435 } else { 07436 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07437 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07438 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 07439 } 07440 if ((oi0 == SUB_THREEWAY) && 07441 p0->subs[SUB_THREEWAY].inthreeway && 07442 p0->subs[SUB_REAL].owner && 07443 p0->subs[SUB_REAL].inthreeway && 07444 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07445 ast_debug(1, 07446 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07447 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07448 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 07449 os0 = p0->subs[SUB_REAL].owner->_state; 07450 } else { 07451 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07452 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07453 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 07454 } 07455 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07456 if (!p0->echocanbridged || !p1->echocanbridged) { 07457 /* Disable echo cancellation if appropriate */ 07458 dahdi_disable_ec(p0); 07459 dahdi_disable_ec(p1); 07460 } 07461 } 07462 dahdi_link(slave, master); 07463 master->inconference = inconf; 07464 } else if (!nothingok) 07465 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 07466 07467 update_conf(p0); 07468 update_conf(p1); 07469 t0 = p0->subs[SUB_REAL].inthreeway; 07470 t1 = p1->subs[SUB_REAL].inthreeway; 07471 07472 ast_mutex_unlock(&p0->lock); 07473 ast_mutex_unlock(&p1->lock); 07474 07475 ast_channel_unlock(c0); 07476 ast_channel_unlock(c1); 07477 07478 /* Native bridge failed */ 07479 if ((!master || !slave) && !nothingok) { 07480 dahdi_enable_ec(p0); 07481 dahdi_enable_ec(p1); 07482 return AST_BRIDGE_FAILED; 07483 } 07484 07485 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 07486 07487 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07488 disable_dtmf_detect(op0); 07489 07490 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07491 disable_dtmf_detect(op1); 07492 07493 for (;;) { 07494 struct ast_channel *c0_priority[2] = {c0, c1}; 07495 struct ast_channel *c1_priority[2] = {c1, c0}; 07496 int ms; 07497 07498 /* Here's our main loop... Start by locking things, looking for private parts, 07499 and then balking if anything is wrong */ 07500 07501 ast_channel_lock(c0); 07502 while (ast_channel_trylock(c1)) { 07503 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07504 } 07505 07506 p0 = c0->tech_pvt; 07507 p1 = c1->tech_pvt; 07508 07509 if (op0 == p0) 07510 i0 = dahdi_get_index(c0, p0, 1); 07511 if (op1 == p1) 07512 i1 = dahdi_get_index(c1, p1, 1); 07513 07514 ast_channel_unlock(c0); 07515 ast_channel_unlock(c1); 07516 ms = ast_remaining_ms(start, timeoutms); 07517 if (!ms || 07518 (op0 != p0) || 07519 (op1 != p1) || 07520 (ofd0 != c0->fds[0]) || 07521 (ofd1 != c1->fds[0]) || 07522 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 07523 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 07524 (oc0 != p0->owner) || 07525 (oc1 != p1->owner) || 07526 (t0 != p0->subs[SUB_REAL].inthreeway) || 07527 (t1 != p1->subs[SUB_REAL].inthreeway) || 07528 (oi0 != i0) || 07529 (oi1 != i1)) { 07530 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 07531 op0->channel, oi0, op1->channel, oi1); 07532 res = AST_BRIDGE_RETRY; 07533 goto return_from_bridge; 07534 } 07535 07536 #ifdef PRI_2BCT 07537 if (!triedtopribridge) { 07538 triedtopribridge = 1; 07539 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) { 07540 ast_mutex_lock(&p0->pri->lock); 07541 switch (p0->sig) { 07542 case SIG_PRI_LIB_HANDLE_CASES: 07543 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 07544 break; 07545 default: 07546 q931c0 = NULL; 07547 break; 07548 } 07549 switch (p1->sig) { 07550 case SIG_PRI_LIB_HANDLE_CASES: 07551 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 07552 break; 07553 default: 07554 q931c1 = NULL; 07555 break; 07556 } 07557 if (q931c0 && q931c1) { 07558 pri_channel_bridge(q931c0, q931c1); 07559 } 07560 ast_mutex_unlock(&p0->pri->lock); 07561 } 07562 } 07563 #endif 07564 07565 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms); 07566 if (!who) { 07567 ast_debug(1, "Ooh, empty read...\n"); 07568 continue; 07569 } 07570 f = ast_read(who); 07571 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 07572 *fo = f; 07573 *rc = who; 07574 res = AST_BRIDGE_COMPLETE; 07575 goto return_from_bridge; 07576 } 07577 if (f->frametype == AST_FRAME_DTMF) { 07578 if ((who == c0) && p0->pulsedial) { 07579 ast_write(c1, f); 07580 } else if ((who == c1) && p1->pulsedial) { 07581 ast_write(c0, f); 07582 } else { 07583 *fo = f; 07584 *rc = who; 07585 res = AST_BRIDGE_COMPLETE; 07586 goto return_from_bridge; 07587 } 07588 } 07589 ast_frfree(f); 07590 07591 /* Swap who gets priority */ 07592 priority = !priority; 07593 } 07594 07595 return_from_bridge: 07596 if (op0 == p0) 07597 dahdi_enable_ec(p0); 07598 07599 if (op1 == p1) 07600 dahdi_enable_ec(p1); 07601 07602 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07603 enable_dtmf_detect(op0); 07604 07605 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07606 enable_dtmf_detect(op1); 07607 07608 dahdi_unlink(slave, master, 1); 07609 07610 return res; 07611 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 5398 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.
05399 { 05400 struct dahdi_pvt *p = ast->tech_pvt; 05401 int x, res, mysig; 05402 char dest[256]; /* must be same length as p->dialdest */ 05403 05404 ast_mutex_lock(&p->lock); 05405 ast_copy_string(dest, rdest, sizeof(dest)); 05406 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 05407 if ((ast->_state == AST_STATE_BUSY)) { 05408 p->subs[SUB_REAL].needbusy = 1; 05409 ast_mutex_unlock(&p->lock); 05410 return 0; 05411 } 05412 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05413 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 05414 ast_mutex_unlock(&p->lock); 05415 return -1; 05416 } 05417 p->waitingfordt.tv_sec = 0; 05418 p->dialednone = 0; 05419 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 05420 { 05421 /* Special pseudo -- automatically up */ 05422 ast_setstate(ast, AST_STATE_UP); 05423 ast_mutex_unlock(&p->lock); 05424 return 0; 05425 } 05426 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 05427 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 05428 if (res) 05429 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 05430 p->outgoing = 1; 05431 05432 if (IS_DIGITAL(ast->transfercapability)){ 05433 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law); 05434 } else { 05435 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05436 } 05437 05438 #ifdef HAVE_PRI 05439 if (dahdi_sig_pri_lib_handles(p->sig)) { 05440 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, 05441 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW); 05442 ast_mutex_unlock(&p->lock); 05443 return res; 05444 } 05445 #endif 05446 05447 #if defined(HAVE_SS7) 05448 if (p->sig == SIG_SS7) { 05449 res = sig_ss7_call(p->sig_pvt, ast, rdest); 05450 ast_mutex_unlock(&p->lock); 05451 return res; 05452 } 05453 #endif /* defined(HAVE_SS7) */ 05454 05455 /* If this is analog signalling we can exit here */ 05456 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05457 p->callwaitrings = 0; 05458 res = analog_call(p->sig_pvt, ast, rdest, timeout); 05459 ast_mutex_unlock(&p->lock); 05460 return res; 05461 } 05462 05463 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 05464 switch (mysig) { 05465 case 0: 05466 /* Special pseudo -- automatically up*/ 05467 ast_setstate(ast, AST_STATE_UP); 05468 break; 05469 case SIG_MFCR2: 05470 break; 05471 default: 05472 ast_debug(1, "not yet implemented\n"); 05473 ast_mutex_unlock(&p->lock); 05474 return -1; 05475 } 05476 05477 #ifdef HAVE_OPENR2 05478 if (p->mfcr2) { 05479 openr2_calling_party_category_t chancat; 05480 int callres = 0; 05481 char *c, *l; 05482 05483 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 05484 p->dialdest[0] = '\0'; 05485 05486 c = strchr(dest, '/'); 05487 if (c) { 05488 c++; 05489 } else { 05490 c = ""; 05491 } 05492 if (!p->hidecallerid) { 05493 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL; 05494 } else { 05495 l = NULL; 05496 } 05497 if (strlen(c) < p->stripmsd) { 05498 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 05499 ast_mutex_unlock(&p->lock); 05500 return -1; 05501 } 05502 p->dialing = 1; 05503 chancat = dahdi_r2_get_channel_category(ast); 05504 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 05505 if (-1 == callres) { 05506 ast_mutex_unlock(&p->lock); 05507 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 05508 return -1; 05509 } 05510 p->mfcr2_call_accepted = 0; 05511 p->mfcr2_progress = 0; 05512 ast_setstate(ast, AST_STATE_DIALING); 05513 } 05514 #endif /* HAVE_OPENR2 */ 05515 ast_mutex_unlock(&p->lock); 05516 return 0; 05517 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5365 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().
05366 { 05367 struct dahdi_pvt *p = ast->tech_pvt; 05368 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 05369 if (p->cidspill) { 05370 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 05371 ast_free(p->cidspill); 05372 } 05373 05374 /* 05375 * SAS: Subscriber Alert Signal, 440Hz for 300ms 05376 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 05377 */ 05378 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 05379 return -1; 05380 save_conference(p); 05381 /* Silence */ 05382 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 05383 if (!p->callwaitrings && p->callwaitingcallerid) { 05384 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 05385 p->callwaitcas = 1; 05386 p->cidlen = 2400 + 680 + READ_SIZE * 4; 05387 } else { 05388 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 05389 p->callwaitcas = 0; 05390 p->cidlen = 2400 + READ_SIZE * 4; 05391 } 05392 p->cidpos = 0; 05393 send_callerid(p); 05394 05395 return 0; 05396 }
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 13953 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.
13954 { 13955 struct dahdi_pvt *p; 13956 struct dahdi_pvt *exitpvt; 13957 struct dahdi_starting_point start; 13958 int groupmatched = 0; 13959 int channelmatched = 0; 13960 13961 ast_mutex_lock(&iflock); 13962 p = determine_starting_point(dest, &start); 13963 if (!p) { 13964 ast_mutex_unlock(&iflock); 13965 return -1; 13966 } 13967 exitpvt = p; 13968 for (;;) { 13969 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) { 13970 /* We found a potential match. call the callback */ 13971 struct ast_str *device_name; 13972 char *dash; 13973 const char *monitor_type; 13974 char dialstring[AST_CHANNEL_NAME]; 13975 char full_device_name[AST_CHANNEL_NAME]; 13976 13977 switch (ast_get_cc_monitor_policy(p->cc_params)) { 13978 case AST_CC_MONITOR_NEVER: 13979 break; 13980 case AST_CC_MONITOR_NATIVE: 13981 case AST_CC_MONITOR_ALWAYS: 13982 case AST_CC_MONITOR_GENERIC: 13983 #if defined(HAVE_PRI) 13984 if (dahdi_sig_pri_lib_handles(p->sig)) { 13985 /* 13986 * ISDN is in a trunk busy condition so we need to monitor 13987 * the span congestion device state. 13988 */ 13989 snprintf(full_device_name, sizeof(full_device_name), 13990 "DAHDI/I%d/congestion", p->pri->span); 13991 } else 13992 #endif /* defined(HAVE_PRI) */ 13993 { 13994 #if defined(HAVE_PRI) 13995 device_name = create_channel_name(p, 1, ""); 13996 #else 13997 device_name = create_channel_name(p); 13998 #endif /* defined(HAVE_PRI) */ 13999 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", 14000 device_name ? ast_str_buffer(device_name) : ""); 14001 ast_free(device_name); 14002 /* 14003 * The portion after the '-' in the channel name is either a random 14004 * number, a sequence number, or a subchannel number. None are 14005 * necessary so strip them off. 14006 */ 14007 dash = strrchr(full_device_name, '-'); 14008 if (dash) { 14009 *dash = '\0'; 14010 } 14011 } 14012 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest); 14013 14014 /* 14015 * Analog can only do generic monitoring. 14016 * ISDN is in a trunk busy condition and any "device" is going 14017 * to be busy until a B channel becomes available. The generic 14018 * monitor can do this task. 14019 */ 14020 monitor_type = AST_CC_GENERIC_MONITOR_TYPE; 14021 callback(inbound, 14022 #if defined(HAVE_PRI) 14023 p->pri ? p->pri->cc_params : p->cc_params, 14024 #else 14025 p->cc_params, 14026 #endif /* defined(HAVE_PRI) */ 14027 monitor_type, full_device_name, dialstring, NULL); 14028 break; 14029 } 14030 } 14031 p = start.backwards ? p->prev : p->next; 14032 if (!p) { 14033 p = start.backwards ? ifend : iflist; 14034 } 14035 if (p == exitpvt) { 14036 break; 14037 } 14038 } 14039 ast_mutex_unlock(&iflock); 14040 return 0; 14041 }
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 1370 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().
01371 { 01372 /* recall that if a field is not included here it is initialized 01373 * to 0 or equivalent 01374 */ 01375 struct dahdi_chan_conf conf = { 01376 #ifdef HAVE_PRI 01377 .pri.pri = { 01378 .nsf = PRI_NSF_NONE, 01379 .switchtype = PRI_SWITCH_NI2, 01380 .dialplan = PRI_UNKNOWN + 1, 01381 .localdialplan = PRI_NATIONAL_ISDN + 1, 01382 .nodetype = PRI_CPE, 01383 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01384 .inband_on_setup_ack = 1, 01385 .inband_on_proceeding = 1, 01386 01387 #if defined(HAVE_PRI_CCSS) 01388 .cc_ptmp_recall_mode = 1,/* specificRecall */ 01389 .cc_qsig_signaling_link_req = 1,/* retain */ 01390 .cc_qsig_signaling_link_rsp = 1,/* retain */ 01391 #endif /* defined(HAVE_PRI_CCSS) */ 01392 01393 .minunused = 2, 01394 .idleext = "", 01395 .idledial = "", 01396 .internationalprefix = "", 01397 .nationalprefix = "", 01398 .localprefix = "", 01399 .privateprefix = "", 01400 .unknownprefix = "", 01401 .resetinterval = -1, 01402 }, 01403 #endif 01404 #if defined(HAVE_SS7) 01405 .ss7.ss7 = { 01406 .called_nai = SS7_NAI_NATIONAL, 01407 .calling_nai = SS7_NAI_NATIONAL, 01408 .internationalprefix = "", 01409 .nationalprefix = "", 01410 .subscriberprefix = "", 01411 .unknownprefix = "" 01412 }, 01413 #endif /* defined(HAVE_SS7) */ 01414 #ifdef HAVE_OPENR2 01415 .mfcr2 = { 01416 .variant = OR2_VAR_ITU, 01417 .mfback_timeout = -1, 01418 .metering_pulse_timeout = -1, 01419 .max_ani = 10, 01420 .max_dnis = 4, 01421 .get_ani_first = -1, 01422 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01423 .skip_category_request = -1, 01424 #endif 01425 .call_files = 0, 01426 .allow_collect_calls = 0, 01427 .charge_calls = 1, 01428 .accept_on_offer = 1, 01429 .forced_release = 0, 01430 .double_answer = 0, 01431 .immediate_accept = -1, 01432 .logdir = "", 01433 .r2proto_file = "", 01434 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01435 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01436 }, 01437 #endif 01438 .chan = { 01439 .context = "default", 01440 .cid_num = "", 01441 .cid_name = "", 01442 .cid_tag = "", 01443 .mohinterpret = "default", 01444 .mohsuggest = "", 01445 .parkinglot = "", 01446 .transfertobusy = 1, 01447 01448 .cid_signalling = CID_SIG_BELL, 01449 .cid_start = CID_START_RING, 01450 .dahditrcallerid = 0, 01451 .use_callerid = 1, 01452 .sig = -1, 01453 .outsigmod = -1, 01454 01455 .cid_rxgain = +5.0, 01456 01457 .tonezone = -1, 01458 01459 .echocancel.head.tap_length = 1, 01460 01461 .busycount = 3, 01462 .busycompare = 0, 01463 .busytonelength = 0, 01464 .busyquietlength = 0, 01465 .busyfuzziness = 0, 01466 .silencethreshold = 0, 01467 01468 .accountcode = "", 01469 01470 .mailbox = "", 01471 01472 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01473 .mwisend_fsk = 1, 01474 #endif 01475 .polarityonanswerdelay = 600, 01476 01477 .sendcalleridafter = DEFAULT_CIDRINGS, 01478 01479 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01480 .buf_no = numbufs, 01481 .usefaxbuffers = 0, 01482 .cc_params = ast_cc_config_params_init(), 01483 }, 01484 .timing = { 01485 .prewinktime = -1, 01486 .preflashtime = -1, 01487 .winktime = -1, 01488 .flashtime = -1, 01489 .starttime = -1, 01490 .rxwinktime = -1, 01491 .rxflashtime = -1, 01492 .debouncetime = -1 01493 }, 01494 .is_sig_auto = 1, 01495 .smdi_port = "/dev/ttyS0", 01496 }; 01497 01498 return conf; 01499 }
static int dahdi_channels_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18677 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.
18679 { 18680 struct dahdi_pvt *tmp; 18681 struct ast_data *data_channel; 18682 18683 ast_mutex_lock(&iflock); 18684 for (tmp = iflist; tmp; tmp = tmp->next) { 18685 data_channel = ast_data_add_node(data_root, "channel"); 18686 if (!data_channel) { 18687 continue; 18688 } 18689 18690 ast_data_add_structure(dahdi_pvt, data_channel, tmp); 18691 18692 /* if this channel doesn't match remove it. */ 18693 if (!ast_data_search_match(search, data_channel)) { 18694 ast_data_remove_node(data_root, data_channel); 18695 } 18696 } 18697 ast_mutex_unlock(&iflock); 18698 18699 return 0; 18700 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 4416 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 4422 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().
04423 { 04424 dahdi_close(chan_pvt->subs[sub_num].dfd); 04425 chan_pvt->subs[sub_num].dfd = -1; 04426 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 5208 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().
05209 { 05210 int x, res; 05211 05212 x = muted; 05213 #if defined(HAVE_PRI) || defined(HAVE_SS7) 05214 switch (p->sig) { 05215 #if defined(HAVE_PRI) 05216 case SIG_PRI_LIB_HANDLE_CASES: 05217 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 05218 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 05219 break; 05220 } 05221 /* Fall through */ 05222 #endif /* defined(HAVE_PRI) */ 05223 #if defined(HAVE_SS7) 05224 case SIG_SS7: 05225 #endif /* defined(HAVE_SS7) */ 05226 { 05227 int y = 1; 05228 05229 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 05230 if (res) 05231 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 05232 p->channel, strerror(errno)); 05233 } 05234 break; 05235 default: 05236 break; 05237 } 05238 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 05239 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 05240 if (res < 0) 05241 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 05242 return res; 05243 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15193 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.
15194 { 15195 int channel; 15196 int ret; 15197 switch (cmd) { 15198 case CLI_INIT: 15199 e->command = "dahdi destroy channel"; 15200 e->usage = 15201 "Usage: dahdi destroy channel <chan num>\n" 15202 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 15203 return NULL; 15204 case CLI_GENERATE: 15205 return NULL; 15206 } 15207 if (a->argc != 4) 15208 return CLI_SHOWUSAGE; 15209 15210 channel = atoi(a->argv[3]); 15211 ret = dahdi_destroy_channel_bynum(channel); 15212 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 15213 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 11471 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().
11472 { 11473 struct dahdi_pvt *cur; 11474 11475 ast_mutex_lock(&iflock); 11476 for (cur = iflist; cur; cur = cur->next) { 11477 if (cur->channel == channel) { 11478 int x = DAHDI_FLASH; 11479 11480 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 11481 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11482 11483 destroy_channel(cur, 1); 11484 ast_mutex_unlock(&iflock); 11485 ast_module_unref(ast_module_info->self); 11486 return RESULT_SUCCESS; 11487 } 11488 } 11489 ast_mutex_unlock(&iflock); 11490 return RESULT_FAILURE; 11491 }
static int dahdi_devicestate | ( | void * | data | ) | [static] |
Definition at line 13891 of file chan_dahdi.c.
References AST_DEVICE_UNKNOWN.
13892 { 13893 #if defined(HAVE_PRI) 13894 char *device; 13895 unsigned span; 13896 int res; 13897 13898 device = data; 13899 13900 if (*device != 'I') { 13901 /* The request is not for an ISDN span device. */ 13902 return AST_DEVICE_UNKNOWN; 13903 } 13904 res = sscanf(device, "I%30u", &span); 13905 if (res != 1 || !span || NUM_SPANS < span) { 13906 /* Bad format for ISDN span device name. */ 13907 return AST_DEVICE_UNKNOWN; 13908 } 13909 device = strchr(device, '/'); 13910 if (!device) { 13911 /* Bad format for ISDN span device name. */ 13912 return AST_DEVICE_UNKNOWN; 13913 } 13914 13915 /* 13916 * Since there are currently no other span devstate's defined, 13917 * it must be congestion. 13918 */ 13919 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13920 ++device; 13921 if (!strcmp(device, "congestion")) 13922 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13923 { 13924 return pris[span - 1].pri.congestion_devstate; 13925 } 13926 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13927 else if (!strcmp(device, "threshold")) { 13928 return pris[span - 1].pri.threshold_devstate; 13929 } 13930 return AST_DEVICE_UNKNOWN; 13931 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13932 #else 13933 return AST_DEVICE_UNKNOWN; 13934 #endif /* defined(HAVE_PRI) */ 13935 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 4520 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.
04521 { 04522 struct dahdi_pvt *pvt; 04523 int idx; 04524 int dtmf = -1; 04525 int res; 04526 04527 pvt = chan->tech_pvt; 04528 04529 ast_mutex_lock(&pvt->lock); 04530 04531 idx = dahdi_get_index(chan, pvt, 0); 04532 04533 if ((idx != SUB_REAL) || !pvt->owner) 04534 goto out; 04535 04536 #ifdef HAVE_PRI 04537 switch (pvt->sig) { 04538 case SIG_PRI_LIB_HANDLE_CASES: 04539 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 04540 if (!res) 04541 goto out; 04542 break; 04543 default: 04544 break; 04545 } 04546 #endif 04547 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 04548 goto out; 04549 04550 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 04551 struct dahdi_dialoperation zo = { 04552 .op = DAHDI_DIAL_OP_APPEND, 04553 }; 04554 04555 zo.dialstr[0] = 'T'; 04556 zo.dialstr[1] = digit; 04557 zo.dialstr[2] = '\0'; 04558 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 04559 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n", 04560 chan->name, digit, strerror(errno)); 04561 else 04562 pvt->dialing = 1; 04563 } else { 04564 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n", 04565 chan->name, digit); 04566 pvt->dialing = 1; 04567 pvt->begindigit = digit; 04568 } 04569 04570 out: 04571 ast_mutex_unlock(&pvt->lock); 04572 04573 return 0; 04574 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 4576 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.
04577 { 04578 struct dahdi_pvt *pvt; 04579 int res = 0; 04580 int idx; 04581 int x; 04582 04583 pvt = chan->tech_pvt; 04584 04585 ast_mutex_lock(&pvt->lock); 04586 04587 idx = dahdi_get_index(chan, pvt, 0); 04588 04589 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 04590 goto out; 04591 04592 #ifdef HAVE_PRI 04593 /* This means that the digit was already sent via PRI signalling */ 04594 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 04595 goto out; 04596 } 04597 #endif 04598 04599 if (pvt->begindigit) { 04600 x = -1; 04601 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n", 04602 chan->name, digit); 04603 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 04604 pvt->dialing = 0; 04605 pvt->begindigit = 0; 04606 } 04607 04608 out: 04609 ast_mutex_unlock(&pvt->lock); 04610 04611 return res; 04612 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4988 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().
04989 { 04990 int res; 04991 04992 if (p->echocanon) { 04993 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04994 04995 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04996 04997 if (res) 04998 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04999 else 05000 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 05001 } 05002 05003 p->echocanon = 0; 05004 }
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 9920 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().
09921 { 09922 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 09923 return analog_dnd(dahdichan->sig_pvt, flag); 09924 } 09925 09926 if (flag == -1) { 09927 return dahdichan->dnd; 09928 } 09929 09930 /* Do not disturb */ 09931 dahdichan->dnd = flag; 09932 ast_verb(3, "%s DND on channel %d\n", 09933 flag? "Enabled" : "Disabled", 09934 dahdichan->channel); 09935 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 09936 "Channel: DAHDI/%d\r\n" 09937 "Status: %s\r\n", dahdichan->channel, 09938 flag? "enabled" : "disabled"); 09939 09940 return 0; 09941 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4916 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().
04917 { 04918 int res; 04919 if (!p) 04920 return; 04921 if (p->echocanon) { 04922 ast_debug(1, "Echo cancellation already on\n"); 04923 return; 04924 } 04925 if (p->digital) { 04926 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04927 return; 04928 } 04929 if (p->echocancel.head.tap_length) { 04930 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04931 switch (p->sig) { 04932 #if defined(HAVE_PRI) 04933 case SIG_PRI_LIB_HANDLE_CASES: 04934 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04935 /* 04936 * PRI nobch pseudo channel. Does not need ec anyway. 04937 * Does not handle ioctl(DAHDI_AUDIOMODE) 04938 */ 04939 return; 04940 } 04941 /* Fall through */ 04942 #endif /* defined(HAVE_PRI) */ 04943 #if defined(HAVE_SS7) 04944 case SIG_SS7: 04945 #endif /* defined(HAVE_SS7) */ 04946 { 04947 int x = 1; 04948 04949 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04950 if (res) 04951 ast_log(LOG_WARNING, 04952 "Unable to enable audio mode on channel %d (%s)\n", 04953 p->channel, strerror(errno)); 04954 } 04955 break; 04956 default: 04957 break; 04958 } 04959 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04960 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04961 if (res) { 04962 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04963 } else { 04964 p->echocanon = 1; 04965 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04966 } 04967 } else 04968 ast_debug(1, "No echo cancellation requested\n"); 04969 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8941 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.
08942 { 08943 struct dahdi_pvt *p = ast->tech_pvt; 08944 struct ast_frame *f; 08945 ast_mutex_lock(&p->lock); 08946 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08947 struct analog_pvt *analog_p = p->sig_pvt; 08948 f = analog_exception(analog_p, ast); 08949 } else { 08950 f = __dahdi_exception(ast); 08951 } 08952 ast_mutex_unlock(&p->lock); 08953 return f; 08954 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 16058 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().
16059 { 16060 if (p) { 16061 switch (mode) { 16062 case TRANSFER: 16063 p->fake_event = DAHDI_EVENT_WINKFLASH; 16064 break; 16065 case HANGUP: 16066 p->fake_event = DAHDI_EVENT_ONHOOK; 16067 break; 16068 default: 16069 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 16070 } 16071 } 16072 return 0; 16073 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 7613 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().
07614 { 07615 struct dahdi_pvt *p = newchan->tech_pvt; 07616 int x; 07617 07618 ast_mutex_lock(&p->lock); 07619 07620 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 07621 if (p->owner == oldchan) { 07622 p->owner = newchan; 07623 } 07624 for (x = 0; x < 3; x++) { 07625 if (p->subs[x].owner == oldchan) { 07626 if (!x) { 07627 dahdi_unlink(NULL, p, 0); 07628 } 07629 p->subs[x].owner = newchan; 07630 } 07631 } 07632 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07633 analog_fixup(oldchan, newchan, p->sig_pvt); 07634 #if defined(HAVE_PRI) 07635 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 07636 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 07637 #endif /* defined(HAVE_PRI) */ 07638 #if defined(HAVE_SS7) 07639 } else if (p->sig == SIG_SS7) { 07640 sig_ss7_fixup(oldchan, newchan, p->sig_pvt); 07641 #endif /* defined(HAVE_SS7) */ 07642 } 07643 update_conf(p); 07644 07645 ast_mutex_unlock(&p->lock); 07646 07647 if (newchan->_state == AST_STATE_RINGING) { 07648 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 07649 } 07650 return 0; 07651 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 6968 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.
06969 { 06970 struct dahdi_pvt *p = chan->tech_pvt; 06971 int res = 0; 06972 06973 if (!p) { 06974 /* No private structure! */ 06975 *buf = '\0'; 06976 return -1; 06977 } 06978 06979 if (!strcasecmp(data, "rxgain")) { 06980 ast_mutex_lock(&p->lock); 06981 snprintf(buf, len, "%f", p->rxgain); 06982 ast_mutex_unlock(&p->lock); 06983 } else if (!strcasecmp(data, "txgain")) { 06984 ast_mutex_lock(&p->lock); 06985 snprintf(buf, len, "%f", p->txgain); 06986 ast_mutex_unlock(&p->lock); 06987 } else if (!strcasecmp(data, "dahdi_channel")) { 06988 ast_mutex_lock(&p->lock); 06989 snprintf(buf, len, "%d", p->channel); 06990 ast_mutex_unlock(&p->lock); 06991 } else if (!strcasecmp(data, "dahdi_span")) { 06992 ast_mutex_lock(&p->lock); 06993 snprintf(buf, len, "%d", p->span); 06994 ast_mutex_unlock(&p->lock); 06995 } else if (!strcasecmp(data, "dahdi_type")) { 06996 ast_mutex_lock(&p->lock); 06997 switch (p->sig) { 06998 #if defined(HAVE_OPENR2) 06999 case SIG_MFCR2: 07000 ast_copy_string(buf, "mfc/r2", len); 07001 break; 07002 #endif /* defined(HAVE_OPENR2) */ 07003 #if defined(HAVE_PRI) 07004 case SIG_PRI_LIB_HANDLE_CASES: 07005 ast_copy_string(buf, "pri", len); 07006 break; 07007 #endif /* defined(HAVE_PRI) */ 07008 case 0: 07009 ast_copy_string(buf, "pseudo", len); 07010 break; 07011 #if defined(HAVE_SS7) 07012 case SIG_SS7: 07013 ast_copy_string(buf, "ss7", len); 07014 break; 07015 #endif /* defined(HAVE_SS7) */ 07016 default: 07017 /* The only thing left is analog ports. */ 07018 ast_copy_string(buf, "analog", len); 07019 break; 07020 } 07021 ast_mutex_unlock(&p->lock); 07022 #if defined(HAVE_PRI) 07023 #if defined(HAVE_PRI_REVERSE_CHARGE) 07024 } else if (!strcasecmp(data, "reversecharge")) { 07025 ast_mutex_lock(&p->lock); 07026 switch (p->sig) { 07027 case SIG_PRI_LIB_HANDLE_CASES: 07028 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 07029 break; 07030 default: 07031 *buf = '\0'; 07032 res = -1; 07033 break; 07034 } 07035 ast_mutex_unlock(&p->lock); 07036 #endif 07037 #if defined(HAVE_PRI_SETUP_KEYPAD) 07038 } else if (!strcasecmp(data, "keypad_digits")) { 07039 ast_mutex_lock(&p->lock); 07040 switch (p->sig) { 07041 case SIG_PRI_LIB_HANDLE_CASES: 07042 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 07043 len); 07044 break; 07045 default: 07046 *buf = '\0'; 07047 res = -1; 07048 break; 07049 } 07050 ast_mutex_unlock(&p->lock); 07051 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 07052 } else if (!strcasecmp(data, "no_media_path")) { 07053 ast_mutex_lock(&p->lock); 07054 switch (p->sig) { 07055 case SIG_PRI_LIB_HANDLE_CASES: 07056 /* 07057 * TRUE if the call is on hold or is call waiting because 07058 * there is no media path available. 07059 */ 07060 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel); 07061 break; 07062 default: 07063 *buf = '\0'; 07064 res = -1; 07065 break; 07066 } 07067 ast_mutex_unlock(&p->lock); 07068 #endif /* defined(HAVE_PRI) */ 07069 } else { 07070 *buf = '\0'; 07071 res = -1; 07072 } 07073 07074 return res; 07075 }
static int dahdi_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 7107 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.
07108 { 07109 struct dahdi_pvt *p = chan->tech_pvt; 07110 int res = 0; 07111 07112 if (!p) { 07113 /* No private structure! */ 07114 return -1; 07115 } 07116 07117 if (!strcasecmp(data, "buffers")) { 07118 int num_bufs, policy; 07119 07120 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 07121 struct dahdi_bufferinfo bi = { 07122 .txbufpolicy = policy, 07123 .rxbufpolicy = policy, 07124 .bufsize = p->bufsize, 07125 .numbufs = num_bufs, 07126 }; 07127 int bpres; 07128 07129 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07130 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 07131 } else { 07132 p->bufferoverrideinuse = 1; 07133 } 07134 } else { 07135 res = -1; 07136 } 07137 } else if (!strcasecmp(data, "echocan_mode")) { 07138 if (!strcasecmp(value, "on")) { 07139 ast_mutex_lock(&p->lock); 07140 dahdi_enable_ec(p); 07141 ast_mutex_unlock(&p->lock); 07142 } else if (!strcasecmp(value, "off")) { 07143 ast_mutex_lock(&p->lock); 07144 dahdi_disable_ec(p); 07145 ast_mutex_unlock(&p->lock); 07146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07147 } else if (!strcasecmp(value, "fax")) { 07148 int blah = 1; 07149 07150 ast_mutex_lock(&p->lock); 07151 if (!p->echocanon) { 07152 dahdi_enable_ec(p); 07153 } 07154 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07155 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 07156 } 07157 ast_mutex_unlock(&p->lock); 07158 } else if (!strcasecmp(value, "voice")) { 07159 int blah = 0; 07160 07161 ast_mutex_lock(&p->lock); 07162 if (!p->echocanon) { 07163 dahdi_enable_ec(p); 07164 } 07165 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07166 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 07167 } 07168 ast_mutex_unlock(&p->lock); 07169 #endif 07170 } else { 07171 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 07172 res = -1; 07173 } 07174 } else { 07175 res = -1; 07176 } 07177 07178 return res; 07179 }
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 7790 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().
07791 { 07792 struct dahdi_pvt *p = ast->tech_pvt; 07793 struct ast_frame *f = *dest; 07794 07795 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 07796 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 07797 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 07798 07799 if (p->confirmanswer) { 07800 if (f->frametype == AST_FRAME_DTMF_END) { 07801 ast_debug(1, "Confirm answer on %s!\n", ast->name); 07802 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 07803 of a DTMF digit */ 07804 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07805 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07806 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 07807 p->confirmanswer = 0; 07808 } else { 07809 p->subs[idx].f.frametype = AST_FRAME_NULL; 07810 p->subs[idx].f.subclass.integer = 0; 07811 } 07812 *dest = &p->subs[idx].f; 07813 } else if (p->callwaitcas) { 07814 if (f->frametype == AST_FRAME_DTMF_END) { 07815 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) { 07816 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 07817 ast_free(p->cidspill); 07818 p->cidspill = NULL; 07819 send_cwcidspill(p); 07820 } 07821 p->callwaitcas = 0; 07822 } 07823 p->subs[idx].f.frametype = AST_FRAME_NULL; 07824 p->subs[idx].f.subclass.integer = 0; 07825 *dest = &p->subs[idx].f; 07826 } else if (f->subclass.integer == 'f') { 07827 if (f->frametype == AST_FRAME_DTMF_END) { 07828 /* Fax tone -- Handle and return NULL */ 07829 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 07830 /* If faxbuffers are configured, use them for the fax transmission */ 07831 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 07832 struct dahdi_bufferinfo bi = { 07833 .txbufpolicy = p->faxbuf_policy, 07834 .bufsize = p->bufsize, 07835 .numbufs = p->faxbuf_no 07836 }; 07837 int res; 07838 07839 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07840 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 07841 } else { 07842 p->bufferoverrideinuse = 1; 07843 } 07844 } 07845 p->faxhandled = 1; 07846 if (p->dsp) { 07847 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 07848 ast_dsp_set_features(p->dsp, p->dsp_features); 07849 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 07850 } 07851 if (strcmp(ast->exten, "fax")) { 07852 const char *target_context = S_OR(ast->macrocontext, ast->context); 07853 07854 /* We need to unlock 'ast' here because ast_exists_extension has the 07855 * potential to start autoservice on the channel. Such action is prone 07856 * to deadlock. 07857 */ 07858 ast_mutex_unlock(&p->lock); 07859 ast_channel_unlock(ast); 07860 if (ast_exists_extension(ast, target_context, "fax", 1, 07861 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 07862 ast_channel_lock(ast); 07863 ast_mutex_lock(&p->lock); 07864 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 07865 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 07866 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 07867 if (ast_async_goto(ast, target_context, "fax", 1)) 07868 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 07869 } else { 07870 ast_channel_lock(ast); 07871 ast_mutex_lock(&p->lock); 07872 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 07873 } 07874 } else { 07875 ast_debug(1, "Already in a fax extension, not redirecting\n"); 07876 } 07877 } else { 07878 ast_debug(1, "Fax already handled\n"); 07879 } 07880 dahdi_confmute(p, 0); 07881 } 07882 p->subs[idx].f.frametype = AST_FRAME_NULL; 07883 p->subs[idx].f.subclass.integer = 0; 07884 *dest = &p->subs[idx].f; 07885 } 07886 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7916 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().
07917 { 07918 int res, x; 07919 int idx, mysig; 07920 char *c; 07921 struct dahdi_pvt *p = ast->tech_pvt; 07922 pthread_t threadid; 07923 struct ast_channel *chan; 07924 struct ast_frame *f; 07925 07926 idx = dahdi_get_index(ast, p, 0); 07927 if (idx < 0) { 07928 return &ast_null_frame; 07929 } 07930 mysig = p->sig; 07931 if (p->outsigmod > -1) 07932 mysig = p->outsigmod; 07933 p->subs[idx].f.frametype = AST_FRAME_NULL; 07934 p->subs[idx].f.subclass.integer = 0; 07935 p->subs[idx].f.datalen = 0; 07936 p->subs[idx].f.samples = 0; 07937 p->subs[idx].f.mallocd = 0; 07938 p->subs[idx].f.offset = 0; 07939 p->subs[idx].f.src = "dahdi_handle_event"; 07940 p->subs[idx].f.data.ptr = NULL; 07941 f = &p->subs[idx].f; 07942 07943 if (p->fake_event) { 07944 res = p->fake_event; 07945 p->fake_event = 0; 07946 } else 07947 res = dahdi_get_event(p->subs[idx].dfd); 07948 07949 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 07950 07951 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 07952 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 07953 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", 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 /* Unmute conference */ 07964 dahdi_confmute(p, 0); 07965 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 07966 p->subs[idx].f.subclass.integer = res & 0xff; 07967 dahdi_handle_dtmf(ast, idx, &f); 07968 } 07969 return f; 07970 } 07971 07972 if (res & DAHDI_EVENT_DTMFDOWN) { 07973 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07974 #if defined(HAVE_PRI) 07975 if (dahdi_sig_pri_lib_handles(p->sig) 07976 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07977 && p->pri 07978 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07979 /* absorb event */ 07980 } else 07981 #endif /* defined(HAVE_PRI) */ 07982 { 07983 /* Mute conference */ 07984 dahdi_confmute(p, 1); 07985 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07986 p->subs[idx].f.subclass.integer = res & 0xff; 07987 dahdi_handle_dtmf(ast, idx, &f); 07988 } 07989 return &p->subs[idx].f; 07990 } 07991 07992 switch (res) { 07993 case DAHDI_EVENT_EC_DISABLED: 07994 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07995 p->echocanon = 0; 07996 break; 07997 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07998 case DAHDI_EVENT_TX_CED_DETECTED: 07999 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 08000 break; 08001 case DAHDI_EVENT_RX_CED_DETECTED: 08002 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 08003 break; 08004 case DAHDI_EVENT_EC_NLP_DISABLED: 08005 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 08006 break; 08007 case DAHDI_EVENT_EC_NLP_ENABLED: 08008 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 08009 break; 08010 #endif 08011 case DAHDI_EVENT_BITSCHANGED: 08012 #ifdef HAVE_OPENR2 08013 if (p->sig != SIG_MFCR2) { 08014 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 08015 } else { 08016 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 08017 openr2_chan_handle_cas(p->r2chan); 08018 } 08019 #else 08020 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 08021 #endif 08022 break; 08023 case DAHDI_EVENT_PULSE_START: 08024 /* Stop tone if there's a pulse start and the PBX isn't started */ 08025 if (!ast->pbx) 08026 tone_zone_play_tone(p->subs[idx].dfd, -1); 08027 break; 08028 case DAHDI_EVENT_DIALCOMPLETE: 08029 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */ 08030 #if defined(HAVE_PRI) 08031 if (dahdi_sig_pri_lib_handles(p->sig)) { 08032 if (p->inalarm) { 08033 break; 08034 } 08035 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) { 08036 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name, 08037 strerror(errno)); 08038 return NULL; 08039 } 08040 if (x) { 08041 /* Still dialing in DAHDI driver */ 08042 break; 08043 } 08044 /* 08045 * The ast channel is locked and the private may be locked more 08046 * than once. 08047 */ 08048 sig_pri_dial_complete(p->sig_pvt, ast); 08049 break; 08050 } 08051 #endif /* defined(HAVE_PRI) */ 08052 #ifdef HAVE_OPENR2 08053 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 08054 /* we don't need to do anything for this event for R2 signaling 08055 if the call is being setup */ 08056 break; 08057 } 08058 #endif 08059 if (p->inalarm) break; 08060 if ((p->radio || (p->oprmode < 0))) break; 08061 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 08062 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 08063 return NULL; 08064 } 08065 if (!x) { /* if not still dialing in driver */ 08066 dahdi_enable_ec(p); 08067 if (p->echobreak) { 08068 dahdi_train_ec(p); 08069 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 08070 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08071 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08072 p->echobreak = 0; 08073 } else { 08074 p->dialing = 0; 08075 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 08076 /* if thru with dialing after offhook */ 08077 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 08078 ast_setstate(ast, AST_STATE_UP); 08079 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08080 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08081 break; 08082 } else { /* if to state wait for offhook to dial rest */ 08083 /* we now wait for off hook */ 08084 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 08085 } 08086 } 08087 if (ast->_state == AST_STATE_DIALING) { 08088 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 08089 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 08090 } else if (p->confirmanswer || (!p->dialednone 08091 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 08092 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 08093 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 08094 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 08095 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 08096 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 08097 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 08098 || (mysig == SIG_SF_FEATB)))) { 08099 ast_setstate(ast, AST_STATE_RINGING); 08100 } else if (!p->answeronpolarityswitch) { 08101 ast_setstate(ast, AST_STATE_UP); 08102 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08103 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08104 /* If aops=0 and hops=1, this is necessary */ 08105 p->polarity = POLARITY_REV; 08106 } else { 08107 /* Start clean, so we can catch the change to REV polarity when party answers */ 08108 p->polarity = POLARITY_IDLE; 08109 } 08110 } 08111 } 08112 } 08113 break; 08114 case DAHDI_EVENT_ALARM: 08115 switch (p->sig) { 08116 #if defined(HAVE_PRI) 08117 case SIG_PRI_LIB_HANDLE_CASES: 08118 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 08119 break; 08120 #endif /* defined(HAVE_PRI) */ 08121 #if defined(HAVE_SS7) 08122 case SIG_SS7: 08123 sig_ss7_set_alarm(p->sig_pvt, 1); 08124 break; 08125 #endif /* defined(HAVE_SS7) */ 08126 default: 08127 p->inalarm = 1; 08128 break; 08129 } 08130 res = get_alarms(p); 08131 handle_alarms(p, res); 08132 #ifdef HAVE_PRI 08133 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 08134 /* fall through intentionally */ 08135 } else { 08136 break; 08137 } 08138 #endif 08139 #if defined(HAVE_SS7) 08140 if (p->sig == SIG_SS7) 08141 break; 08142 #endif /* defined(HAVE_SS7) */ 08143 #ifdef HAVE_OPENR2 08144 if (p->sig == SIG_MFCR2) 08145 break; 08146 #endif 08147 case DAHDI_EVENT_ONHOOK: 08148 if (p->radio) { 08149 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08150 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08151 break; 08152 } 08153 if (p->oprmode < 0) 08154 { 08155 if (p->oprmode != -1) break; 08156 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08157 { 08158 /* Make sure it starts ringing */ 08159 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08160 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 08161 save_conference(p->oprpeer); 08162 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08163 } 08164 break; 08165 } 08166 switch (p->sig) { 08167 case SIG_FXOLS: 08168 case SIG_FXOGS: 08169 case SIG_FXOKS: 08170 /* Check for some special conditions regarding call waiting */ 08171 if (idx == SUB_REAL) { 08172 /* The normal line was hung up */ 08173 if (p->subs[SUB_CALLWAIT].owner) { 08174 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 08175 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 08176 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 08177 unalloc_sub(p, SUB_CALLWAIT); 08178 #if 0 08179 p->subs[idx].needanswer = 0; 08180 p->subs[idx].needringing = 0; 08181 #endif 08182 p->callwaitingrepeat = 0; 08183 p->cidcwexpire = 0; 08184 p->cid_suppress_expire = 0; 08185 p->owner = NULL; 08186 /* Don't start streaming audio yet if the incoming call isn't up yet */ 08187 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 08188 p->dialing = 1; 08189 dahdi_ring_phone(p); 08190 } else if (p->subs[SUB_THREEWAY].owner) { 08191 unsigned int mssinceflash; 08192 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 08193 the private structure -- not especially easy or clean */ 08194 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 08195 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 08196 DLA_UNLOCK(&p->lock); 08197 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08198 /* We can grab ast and p in that order, without worry. We should make sure 08199 nothing seriously bad has happened though like some sort of bizarre double 08200 masquerade! */ 08201 DLA_LOCK(&p->lock); 08202 if (p->owner != ast) { 08203 ast_log(LOG_WARNING, "This isn't good...\n"); 08204 return NULL; 08205 } 08206 } 08207 if (!p->subs[SUB_THREEWAY].owner) { 08208 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 08209 return NULL; 08210 } 08211 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 08212 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash); 08213 if (mssinceflash < MIN_MS_SINCE_FLASH) { 08214 /* It hasn't been long enough since the last flashook. This is probably a bounce on 08215 hanging up. Hangup both channels now */ 08216 if (p->subs[SUB_THREEWAY].owner) 08217 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 08218 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08219 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 08220 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08221 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 08222 if (p->transfer) { 08223 /* In any case this isn't a threeway call anymore */ 08224 p->subs[SUB_REAL].inthreeway = 0; 08225 p->subs[SUB_THREEWAY].inthreeway = 0; 08226 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 08227 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 08228 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08229 /* Swap subs and dis-own channel */ 08230 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08231 p->owner = NULL; 08232 /* Ring the phone */ 08233 dahdi_ring_phone(p); 08234 } else { 08235 if ((res = attempt_transfer(p)) < 0) { 08236 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08237 if (p->subs[SUB_THREEWAY].owner) 08238 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08239 } else if (res) { 08240 /* Don't actually hang up at this point */ 08241 if (p->subs[SUB_THREEWAY].owner) 08242 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08243 break; 08244 } 08245 } 08246 } else { 08247 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08248 if (p->subs[SUB_THREEWAY].owner) 08249 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08250 } 08251 } else { 08252 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08253 /* Swap subs and dis-own channel */ 08254 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08255 p->owner = NULL; 08256 /* Ring the phone */ 08257 dahdi_ring_phone(p); 08258 } 08259 } 08260 } else { 08261 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 08262 } 08263 /* Fall through */ 08264 default: 08265 dahdi_disable_ec(p); 08266 return NULL; 08267 } 08268 break; 08269 case DAHDI_EVENT_RINGOFFHOOK: 08270 if (p->inalarm) break; 08271 if (p->oprmode < 0) 08272 { 08273 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08274 { 08275 /* Make sure it stops ringing */ 08276 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08277 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 08278 restore_conference(p->oprpeer); 08279 } 08280 break; 08281 } 08282 if (p->radio) 08283 { 08284 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08285 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08286 break; 08287 } 08288 /* for E911, its supposed to wait for offhook then dial 08289 the second half of the dial string */ 08290 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 08291 c = strchr(p->dialdest, '/'); 08292 if (c) 08293 c++; 08294 else 08295 c = p->dialdest; 08296 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 08297 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 08298 if (strlen(p->dop.dialstr) > 4) { 08299 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 08300 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 08301 p->echorest[sizeof(p->echorest) - 1] = '\0'; 08302 p->echobreak = 1; 08303 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 08304 } else 08305 p->echobreak = 0; 08306 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 08307 int saveerr = errno; 08308 08309 x = DAHDI_ONHOOK; 08310 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 08311 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 08312 return NULL; 08313 } 08314 p->dialing = 1; 08315 return &p->subs[idx].f; 08316 } 08317 switch (p->sig) { 08318 case SIG_FXOLS: 08319 case SIG_FXOGS: 08320 case SIG_FXOKS: 08321 switch (ast->_state) { 08322 case AST_STATE_RINGING: 08323 dahdi_enable_ec(p); 08324 dahdi_train_ec(p); 08325 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08326 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08327 /* Make sure it stops ringing */ 08328 p->subs[SUB_REAL].needringing = 0; 08329 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08330 ast_debug(1, "channel %d answered\n", p->channel); 08331 08332 /* Cancel any running CallerID spill */ 08333 ast_free(p->cidspill); 08334 p->cidspill = NULL; 08335 restore_conference(p); 08336 08337 p->dialing = 0; 08338 p->callwaitcas = 0; 08339 if (p->confirmanswer) { 08340 /* Ignore answer if "confirm answer" is enabled */ 08341 p->subs[idx].f.frametype = AST_FRAME_NULL; 08342 p->subs[idx].f.subclass.integer = 0; 08343 } else if (!ast_strlen_zero(p->dop.dialstr)) { 08344 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 08345 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08346 if (res < 0) { 08347 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08348 p->dop.dialstr[0] = '\0'; 08349 return NULL; 08350 } else { 08351 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 08352 p->subs[idx].f.frametype = AST_FRAME_NULL; 08353 p->subs[idx].f.subclass.integer = 0; 08354 p->dialing = 1; 08355 } 08356 p->dop.dialstr[0] = '\0'; 08357 ast_setstate(ast, AST_STATE_DIALING); 08358 } else 08359 ast_setstate(ast, AST_STATE_UP); 08360 return &p->subs[idx].f; 08361 case AST_STATE_DOWN: 08362 ast_setstate(ast, AST_STATE_RING); 08363 ast->rings = 1; 08364 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08365 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK; 08366 ast_debug(1, "channel %d picked up\n", p->channel); 08367 return &p->subs[idx].f; 08368 case AST_STATE_UP: 08369 /* Make sure it stops ringing */ 08370 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08371 /* Okay -- probably call waiting*/ 08372 if (ast_bridged_channel(p->owner)) 08373 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08374 p->subs[idx].needunhold = 1; 08375 break; 08376 case AST_STATE_RESERVED: 08377 /* Start up dialtone */ 08378 if (has_voicemail(p)) 08379 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08380 else 08381 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08382 break; 08383 default: 08384 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state); 08385 } 08386 break; 08387 case SIG_FXSLS: 08388 case SIG_FXSGS: 08389 case SIG_FXSKS: 08390 if (ast->_state == AST_STATE_RING) { 08391 p->ringt = p->ringt_base; 08392 } 08393 08394 /* If we get a ring then we cannot be in 08395 * reversed polarity. So we reset to idle */ 08396 ast_debug(1, "Setting IDLE polarity due " 08397 "to ring. Old polarity was %d\n", 08398 p->polarity); 08399 p->polarity = POLARITY_IDLE; 08400 08401 /* Fall through */ 08402 case SIG_EM: 08403 case SIG_EM_E1: 08404 case SIG_EMWINK: 08405 case SIG_FEATD: 08406 case SIG_FEATDMF: 08407 case SIG_FEATDMF_TA: 08408 case SIG_E911: 08409 case SIG_FGC_CAMA: 08410 case SIG_FGC_CAMAMF: 08411 case SIG_FEATB: 08412 case SIG_SF: 08413 case SIG_SFWINK: 08414 case SIG_SF_FEATD: 08415 case SIG_SF_FEATDMF: 08416 case SIG_SF_FEATB: 08417 if (ast->_state == AST_STATE_PRERING) 08418 ast_setstate(ast, AST_STATE_RING); 08419 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 08420 ast_debug(1, "Ring detected\n"); 08421 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08422 p->subs[idx].f.subclass.integer = AST_CONTROL_RING; 08423 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 08424 ast_debug(1, "Line answered\n"); 08425 if (p->confirmanswer) { 08426 p->subs[idx].f.frametype = AST_FRAME_NULL; 08427 p->subs[idx].f.subclass.integer = 0; 08428 } else { 08429 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08430 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08431 ast_setstate(ast, AST_STATE_UP); 08432 } 08433 } else if (ast->_state != AST_STATE_RING) 08434 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel); 08435 break; 08436 default: 08437 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08438 } 08439 break; 08440 case DAHDI_EVENT_RINGBEGIN: 08441 switch (p->sig) { 08442 case SIG_FXSLS: 08443 case SIG_FXSGS: 08444 case SIG_FXSKS: 08445 if (ast->_state == AST_STATE_RING) { 08446 p->ringt = p->ringt_base; 08447 } 08448 break; 08449 } 08450 break; 08451 case DAHDI_EVENT_RINGERON: 08452 break; 08453 case DAHDI_EVENT_NOALARM: 08454 switch (p->sig) { 08455 #if defined(HAVE_PRI) 08456 case SIG_PRI_LIB_HANDLE_CASES: 08457 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 08458 break; 08459 #endif /* defined(HAVE_PRI) */ 08460 #if defined(HAVE_SS7) 08461 case SIG_SS7: 08462 sig_ss7_set_alarm(p->sig_pvt, 0); 08463 break; 08464 #endif /* defined(HAVE_SS7) */ 08465 default: 08466 p->inalarm = 0; 08467 break; 08468 } 08469 handle_clear_alarms(p); 08470 break; 08471 case DAHDI_EVENT_WINKFLASH: 08472 if (p->inalarm) break; 08473 if (p->radio) break; 08474 if (p->oprmode < 0) break; 08475 if (p->oprmode > 1) 08476 { 08477 struct dahdi_params par; 08478 08479 memset(&par, 0, sizeof(par)); 08480 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 08481 { 08482 if (!par.rxisoffhook) 08483 { 08484 /* Make sure it stops ringing */ 08485 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08486 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 08487 save_conference(p); 08488 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08489 } 08490 } 08491 break; 08492 } 08493 /* Remember last time we got a flash-hook */ 08494 p->flashtime = ast_tvnow(); 08495 switch (mysig) { 08496 case SIG_FXOLS: 08497 case SIG_FXOGS: 08498 case SIG_FXOKS: 08499 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 08500 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 08501 08502 /* Cancel any running CallerID spill */ 08503 ast_free(p->cidspill); 08504 p->cidspill = NULL; 08505 restore_conference(p); 08506 p->callwaitcas = 0; 08507 08508 if (idx != SUB_REAL) { 08509 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 08510 goto winkflashdone; 08511 } 08512 08513 if (p->subs[SUB_CALLWAIT].owner) { 08514 /* Swap to call-wait */ 08515 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 08516 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 08517 p->owner = p->subs[SUB_REAL].owner; 08518 ast_debug(1, "Making %s the new owner\n", p->owner->name); 08519 if (p->owner->_state == AST_STATE_RINGING) { 08520 ast_setstate(p->owner, AST_STATE_UP); 08521 p->subs[SUB_REAL].needanswer = 1; 08522 } 08523 p->callwaitingrepeat = 0; 08524 p->cidcwexpire = 0; 08525 p->cid_suppress_expire = 0; 08526 /* Start music on hold if appropriate */ 08527 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 08528 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 08529 S_OR(p->mohsuggest, NULL), 08530 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08531 } 08532 p->subs[SUB_CALLWAIT].needhold = 1; 08533 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 08534 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 08535 S_OR(p->mohsuggest, NULL), 08536 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08537 } 08538 p->subs[SUB_REAL].needunhold = 1; 08539 } else if (!p->subs[SUB_THREEWAY].owner) { 08540 if (!p->threewaycalling) { 08541 /* Just send a flash if no 3-way calling */ 08542 p->subs[SUB_REAL].needflash = 1; 08543 goto winkflashdone; 08544 } else if (!check_for_conference(p)) { 08545 char cid_num[256]; 08546 char cid_name[256]; 08547 08548 cid_num[0] = 0; 08549 cid_name[0] = 0; 08550 if (p->dahditrcallerid && p->owner) { 08551 if (p->owner->caller.id.number.valid 08552 && p->owner->caller.id.number.str) { 08553 ast_copy_string(cid_num, p->owner->caller.id.number.str, 08554 sizeof(cid_num)); 08555 } 08556 if (p->owner->caller.id.name.valid 08557 && p->owner->caller.id.name.str) { 08558 ast_copy_string(cid_name, p->owner->caller.id.name.str, 08559 sizeof(cid_name)); 08560 } 08561 } 08562 /* XXX This section needs much more error checking!!! XXX */ 08563 /* Start a 3-way call if feasible */ 08564 if (!((ast->pbx) || 08565 (ast->_state == AST_STATE_UP) || 08566 (ast->_state == AST_STATE_RING))) { 08567 ast_debug(1, "Flash when call not up or ringing\n"); 08568 goto winkflashdone; 08569 } 08570 if (alloc_sub(p, SUB_THREEWAY)) { 08571 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 08572 goto winkflashdone; 08573 } 08574 08575 /* 08576 * Make new channel 08577 * 08578 * We cannot hold the p or ast locks while creating a new 08579 * channel. 08580 */ 08581 ast_mutex_unlock(&p->lock); 08582 ast_channel_unlock(ast); 08583 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL); 08584 ast_channel_lock(ast); 08585 ast_mutex_lock(&p->lock); 08586 if (p->dahditrcallerid) { 08587 if (!p->origcid_num) 08588 p->origcid_num = ast_strdup(p->cid_num); 08589 if (!p->origcid_name) 08590 p->origcid_name = ast_strdup(p->cid_name); 08591 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 08592 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 08593 } 08594 /* Swap things around between the three-way and real call */ 08595 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08596 /* Disable echo canceller for better dialing */ 08597 dahdi_disable_ec(p); 08598 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 08599 if (res) 08600 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 08601 p->owner = chan; 08602 if (!chan) { 08603 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 08604 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 08605 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 08606 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08607 dahdi_enable_ec(p); 08608 ast_hangup(chan); 08609 } else { 08610 ast_verb(3, "Started three way call on channel %d\n", p->channel); 08611 08612 /* Start music on hold if appropriate */ 08613 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08614 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 08615 S_OR(p->mohsuggest, NULL), 08616 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08617 } 08618 p->subs[SUB_THREEWAY].needhold = 1; 08619 } 08620 } 08621 } else { 08622 /* Already have a 3 way call */ 08623 if (p->subs[SUB_THREEWAY].inthreeway) { 08624 /* Call is already up, drop the last person */ 08625 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 08626 /* If the primary call isn't answered yet, use it */ 08627 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 08628 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 08629 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08630 p->owner = p->subs[SUB_REAL].owner; 08631 } 08632 /* Drop the last call and stop the conference */ 08633 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 08634 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08635 p->subs[SUB_REAL].inthreeway = 0; 08636 p->subs[SUB_THREEWAY].inthreeway = 0; 08637 } else { 08638 /* Lets see what we're up to */ 08639 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 08640 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 08641 int otherindex = SUB_THREEWAY; 08642 08643 ast_verb(3, "Building conference call with %s and %s\n", 08644 p->subs[SUB_THREEWAY].owner->name, 08645 p->subs[SUB_REAL].owner->name); 08646 /* Put them in the threeway, and flip */ 08647 p->subs[SUB_THREEWAY].inthreeway = 1; 08648 p->subs[SUB_REAL].inthreeway = 1; 08649 if (ast->_state == AST_STATE_UP) { 08650 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08651 otherindex = SUB_REAL; 08652 } 08653 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 08654 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 08655 p->subs[otherindex].needunhold = 1; 08656 p->owner = p->subs[SUB_REAL].owner; 08657 } else { 08658 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 08659 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08660 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08661 p->owner = p->subs[SUB_REAL].owner; 08662 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 08663 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08664 p->subs[SUB_REAL].needunhold = 1; 08665 dahdi_enable_ec(p); 08666 } 08667 } 08668 } 08669 winkflashdone: 08670 update_conf(p); 08671 break; 08672 case SIG_EM: 08673 case SIG_EM_E1: 08674 case SIG_FEATD: 08675 case SIG_SF: 08676 case SIG_SFWINK: 08677 case SIG_SF_FEATD: 08678 case SIG_FXSLS: 08679 case SIG_FXSGS: 08680 if (p->dialing) 08681 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 08682 else 08683 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel); 08684 break; 08685 case SIG_FEATDMF_TA: 08686 switch (p->whichwink) { 08687 case 0: 08688 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2, 08689 S_COR(p->owner->caller.ani.number.valid, 08690 p->owner->caller.ani.number.str, "")); 08691 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", 08692 p->owner->caller.ani2, 08693 S_COR(p->owner->caller.ani.number.valid, 08694 p->owner->caller.ani.number.str, "")); 08695 break; 08696 case 1: 08697 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 08698 break; 08699 case 2: 08700 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 08701 return NULL; 08702 } 08703 p->whichwink++; 08704 /* Fall through */ 08705 case SIG_FEATDMF: 08706 case SIG_E911: 08707 case SIG_FGC_CAMAMF: 08708 case SIG_FGC_CAMA: 08709 case SIG_FEATB: 08710 case SIG_SF_FEATDMF: 08711 case SIG_SF_FEATB: 08712 case SIG_EMWINK: 08713 /* FGD MF and EMWINK *Must* wait for wink */ 08714 if (!ast_strlen_zero(p->dop.dialstr)) { 08715 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08716 if (res < 0) { 08717 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08718 p->dop.dialstr[0] = '\0'; 08719 return NULL; 08720 } else 08721 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08722 } 08723 p->dop.dialstr[0] = '\0'; 08724 break; 08725 default: 08726 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08727 } 08728 break; 08729 case DAHDI_EVENT_HOOKCOMPLETE: 08730 if (p->inalarm) break; 08731 if ((p->radio || (p->oprmode < 0))) break; 08732 if (p->waitingfordt.tv_sec) break; 08733 switch (mysig) { 08734 case SIG_FXSLS: /* only interesting for FXS */ 08735 case SIG_FXSGS: 08736 case SIG_FXSKS: 08737 case SIG_EM: 08738 case SIG_EM_E1: 08739 case SIG_EMWINK: 08740 case SIG_FEATD: 08741 case SIG_SF: 08742 case SIG_SFWINK: 08743 case SIG_SF_FEATD: 08744 if (!ast_strlen_zero(p->dop.dialstr)) { 08745 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08746 if (res < 0) { 08747 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08748 p->dop.dialstr[0] = '\0'; 08749 return NULL; 08750 } else 08751 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08752 } 08753 p->dop.dialstr[0] = '\0'; 08754 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08755 break; 08756 case SIG_FEATDMF: 08757 case SIG_FEATDMF_TA: 08758 case SIG_E911: 08759 case SIG_FGC_CAMA: 08760 case SIG_FGC_CAMAMF: 08761 case SIG_FEATB: 08762 case SIG_SF_FEATDMF: 08763 case SIG_SF_FEATB: 08764 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 08765 break; 08766 default: 08767 break; 08768 } 08769 break; 08770 case DAHDI_EVENT_POLARITY: 08771 /* 08772 * If we get a Polarity Switch event, check to see 08773 * if we should change the polarity state and 08774 * mark the channel as UP or if this is an indication 08775 * of remote end disconnect. 08776 */ 08777 if (p->polarity == POLARITY_IDLE) { 08778 p->polarity = POLARITY_REV; 08779 if (p->answeronpolarityswitch && 08780 ((ast->_state == AST_STATE_DIALING) || 08781 (ast->_state == AST_STATE_RINGING))) { 08782 ast_debug(1, "Answering on polarity switch!\n"); 08783 ast_setstate(p->owner, AST_STATE_UP); 08784 if (p->hanguponpolarityswitch) { 08785 p->polaritydelaytv = ast_tvnow(); 08786 } 08787 } else 08788 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state); 08789 } 08790 /* Removed else statement from here as it was preventing hangups from ever happening*/ 08791 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 08792 if (p->hanguponpolarityswitch && 08793 (p->polarityonanswerdelay > 0) && 08794 (p->polarity == POLARITY_REV) && 08795 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 08796 /* Added log_debug information below to provide a better indication of what is going on */ 08797 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) ); 08798 08799 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 08800 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 08801 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 08802 p->polarity = POLARITY_IDLE; 08803 } else 08804 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); 08805 08806 } else { 08807 p->polarity = POLARITY_IDLE; 08808 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state); 08809 } 08810 /* Added more log_debug information below to provide a better indication of what is going on */ 08811 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) ); 08812 break; 08813 default: 08814 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 08815 } 08816 return &p->subs[idx].f; 08817 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6191 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.
06192 { 06193 int res = 0; 06194 int idx,x; 06195 int law; 06196 /*static int restore_gains(struct dahdi_pvt *p);*/ 06197 struct dahdi_pvt *p = ast->tech_pvt; 06198 struct dahdi_params par; 06199 06200 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 06201 if (!ast->tech_pvt) { 06202 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 06203 return 0; 06204 } 06205 06206 ast_mutex_lock(&p->lock); 06207 p->exten[0] = '\0'; 06208 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06209 dahdi_confmute(p, 0); 06210 restore_gains(p); 06211 p->ignoredtmf = 0; 06212 p->waitingfordt.tv_sec = 0; 06213 06214 res = analog_hangup(p->sig_pvt, ast); 06215 revert_fax_buffers(p, ast); 06216 06217 goto hangup_out; 06218 } else { 06219 p->cid_num[0] = '\0'; 06220 p->cid_name[0] = '\0'; 06221 p->cid_subaddr[0] = '\0'; 06222 } 06223 06224 #if defined(HAVE_PRI) 06225 if (dahdi_sig_pri_lib_handles(p->sig)) { 06226 x = 1; 06227 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06228 06229 dahdi_confmute(p, 0); 06230 p->muting = 0; 06231 restore_gains(p); 06232 if (p->dsp) { 06233 ast_dsp_free(p->dsp); 06234 p->dsp = NULL; 06235 } 06236 p->ignoredtmf = 0; 06237 06238 /* Real channel, do some fixup */ 06239 p->subs[SUB_REAL].owner = NULL; 06240 p->subs[SUB_REAL].needbusy = 0; 06241 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06242 06243 p->owner = NULL; 06244 p->cid_tag[0] = '\0'; 06245 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06246 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06247 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06248 p->outgoing = 0; 06249 p->digital = 0; 06250 p->faxhandled = 0; 06251 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06252 06253 revert_fax_buffers(p, ast); 06254 06255 p->law = p->law_default; 06256 law = p->law_default; 06257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06258 if (res < 0) { 06259 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06260 p->channel, strerror(errno)); 06261 } 06262 06263 sig_pri_hangup(p->sig_pvt, ast); 06264 06265 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06266 dahdi_disable_ec(p); 06267 06268 x = 0; 06269 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06270 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06271 06272 p->rdnis[0] = '\0'; 06273 update_conf(p); 06274 reset_conf(p); 06275 06276 /* Restore data mode */ 06277 x = 0; 06278 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06279 06280 if (num_restart_pending == 0) { 06281 restart_monitor(); 06282 } 06283 goto hangup_out; 06284 } 06285 #endif /* defined(HAVE_PRI) */ 06286 06287 #if defined(HAVE_SS7) 06288 if (p->sig == SIG_SS7) { 06289 x = 1; 06290 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06291 06292 dahdi_confmute(p, 0); 06293 p->muting = 0; 06294 restore_gains(p); 06295 if (p->dsp) { 06296 ast_dsp_free(p->dsp); 06297 p->dsp = NULL; 06298 } 06299 p->ignoredtmf = 0; 06300 06301 /* Real channel, do some fixup */ 06302 p->subs[SUB_REAL].owner = NULL; 06303 p->subs[SUB_REAL].needbusy = 0; 06304 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06305 06306 p->owner = NULL; 06307 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06308 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06309 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06310 p->outgoing = 0; 06311 p->digital = 0; 06312 p->faxhandled = 0; 06313 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06314 06315 revert_fax_buffers(p, ast); 06316 06317 p->law = p->law_default; 06318 law = p->law_default; 06319 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06320 if (res < 0) { 06321 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06322 p->channel, strerror(errno)); 06323 } 06324 06325 sig_ss7_hangup(p->sig_pvt, ast); 06326 06327 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06328 dahdi_disable_ec(p); 06329 06330 x = 0; 06331 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06332 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06333 06334 update_conf(p); 06335 reset_conf(p); 06336 06337 /* Restore data mode */ 06338 x = 0; 06339 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06340 06341 if (num_restart_pending == 0) { 06342 restart_monitor(); 06343 } 06344 goto hangup_out; 06345 } 06346 #endif /* defined(HAVE_SS7) */ 06347 06348 idx = dahdi_get_index(ast, p, 1); 06349 06350 dahdi_confmute(p, 0); 06351 p->muting = 0; 06352 restore_gains(p); 06353 if (p->origcid_num) { 06354 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 06355 ast_free(p->origcid_num); 06356 p->origcid_num = NULL; 06357 } 06358 if (p->origcid_name) { 06359 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 06360 ast_free(p->origcid_name); 06361 p->origcid_name = NULL; 06362 } 06363 if (p->dsp) 06364 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06365 06366 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 06367 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06368 p->ignoredtmf = 0; 06369 06370 if (idx > -1) { 06371 /* Real channel, do some fixup */ 06372 p->subs[idx].owner = NULL; 06373 p->subs[idx].needanswer = 0; 06374 p->subs[idx].needflash = 0; 06375 p->subs[idx].needringing = 0; 06376 p->subs[idx].needbusy = 0; 06377 p->subs[idx].needcongestion = 0; 06378 p->subs[idx].linear = 0; 06379 p->polarity = POLARITY_IDLE; 06380 dahdi_setlinear(p->subs[idx].dfd, 0); 06381 if (idx == SUB_REAL) { 06382 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 06383 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 06384 if (p->subs[SUB_CALLWAIT].inthreeway) { 06385 /* We had flipped over to answer a callwait and now it's gone */ 06386 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 06387 /* Move to the call-wait, but un-own us until they flip back. */ 06388 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06389 unalloc_sub(p, SUB_CALLWAIT); 06390 p->owner = NULL; 06391 } else { 06392 /* The three way hung up, but we still have a call wait */ 06393 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 06394 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06395 unalloc_sub(p, SUB_THREEWAY); 06396 if (p->subs[SUB_REAL].inthreeway) { 06397 /* This was part of a three way call. Immediately make way for 06398 another call */ 06399 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06400 p->owner = p->subs[SUB_REAL].owner; 06401 } else { 06402 /* This call hasn't been completed yet... Set owner to NULL */ 06403 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06404 p->owner = NULL; 06405 } 06406 p->subs[SUB_REAL].inthreeway = 0; 06407 } 06408 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 06409 /* Move to the call-wait and switch back to them. */ 06410 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06411 unalloc_sub(p, SUB_CALLWAIT); 06412 p->owner = p->subs[SUB_REAL].owner; 06413 if (p->owner->_state != AST_STATE_UP) 06414 p->subs[SUB_REAL].needanswer = 1; 06415 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06416 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06417 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 06418 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06419 unalloc_sub(p, SUB_THREEWAY); 06420 if (p->subs[SUB_REAL].inthreeway) { 06421 /* This was part of a three way call. Immediately make way for 06422 another call */ 06423 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06424 p->owner = p->subs[SUB_REAL].owner; 06425 } else { 06426 /* This call hasn't been completed yet... Set owner to NULL */ 06427 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06428 p->owner = NULL; 06429 } 06430 p->subs[SUB_REAL].inthreeway = 0; 06431 } 06432 } else if (idx == SUB_CALLWAIT) { 06433 /* Ditch the holding callwait call, and immediately make it availabe */ 06434 if (p->subs[SUB_CALLWAIT].inthreeway) { 06435 /* This is actually part of a three way, placed on hold. Place the third part 06436 on music on hold now */ 06437 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06438 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06439 S_OR(p->mohsuggest, NULL), 06440 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06441 } 06442 p->subs[SUB_THREEWAY].inthreeway = 0; 06443 /* Make it the call wait now */ 06444 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06445 unalloc_sub(p, SUB_THREEWAY); 06446 } else 06447 unalloc_sub(p, SUB_CALLWAIT); 06448 } else if (idx == SUB_THREEWAY) { 06449 if (p->subs[SUB_CALLWAIT].inthreeway) { 06450 /* The other party of the three way call is currently in a call-wait state. 06451 Start music on hold for them, and take the main guy out of the third call */ 06452 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06453 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06454 S_OR(p->mohsuggest, NULL), 06455 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06456 } 06457 p->subs[SUB_CALLWAIT].inthreeway = 0; 06458 } 06459 p->subs[SUB_REAL].inthreeway = 0; 06460 /* If this was part of a three way call index, let us make 06461 another three way call */ 06462 unalloc_sub(p, SUB_THREEWAY); 06463 } else { 06464 /* This wasn't any sort of call, but how are we an index? */ 06465 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 06466 } 06467 } 06468 06469 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 06470 p->owner = NULL; 06471 p->ringt = 0; 06472 p->distinctivering = 0; 06473 p->confirmanswer = 0; 06474 p->outgoing = 0; 06475 p->digital = 0; 06476 p->faxhandled = 0; 06477 p->pulsedial = 0; 06478 if (p->dsp) { 06479 ast_dsp_free(p->dsp); 06480 p->dsp = NULL; 06481 } 06482 06483 revert_fax_buffers(p, ast); 06484 06485 p->law = p->law_default; 06486 law = p->law_default; 06487 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06488 if (res < 0) 06489 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06490 /* Perform low level hangup if no owner left */ 06491 #ifdef HAVE_OPENR2 06492 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 06493 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 06494 /* If it's an incoming call, check the mfcr2_forced_release setting */ 06495 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 06496 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 06497 } else { 06498 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 06499 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 06500 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 06501 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 06502 dahdi_r2_disconnect_call(p, r2cause); 06503 } 06504 } else if (p->mfcr2call) { 06505 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 06506 /* since ast_request() was called but not ast_call() we have not yet dialed 06507 and the openr2 stack will not call on_call_end callback, we need to unset 06508 the mfcr2call flag and bump the monitor count so the monitor thread can take 06509 care of this channel events from now on */ 06510 p->mfcr2call = 0; 06511 } 06512 #endif 06513 switch (p->sig) { 06514 case SIG_SS7: 06515 case SIG_MFCR2: 06516 case SIG_PRI_LIB_HANDLE_CASES: 06517 case 0: 06518 break; 06519 default: 06520 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06521 break; 06522 } 06523 if (res < 0) { 06524 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 06525 } 06526 switch (p->sig) { 06527 case SIG_FXOGS: 06528 case SIG_FXOLS: 06529 case SIG_FXOKS: 06530 memset(&par, 0, sizeof(par)); 06531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 06532 if (!res) { 06533 struct analog_pvt *analog_p = p->sig_pvt; 06534 #if 0 06535 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 06536 #endif 06537 /* If they're off hook, try playing congestion */ 06538 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 06539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06540 else 06541 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06542 analog_p->fxsoffhookstate = par.rxisoffhook; 06543 } 06544 break; 06545 case SIG_FXSGS: 06546 case SIG_FXSLS: 06547 case SIG_FXSKS: 06548 /* Make sure we're not made available for at least two seconds assuming 06549 we were actually used for an inbound or outbound call. */ 06550 if (ast->_state != AST_STATE_RESERVED) { 06551 time(&p->guardtime); 06552 p->guardtime += 2; 06553 } 06554 break; 06555 default: 06556 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06557 break; 06558 } 06559 if (p->sig) 06560 dahdi_disable_ec(p); 06561 x = 0; 06562 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06563 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06564 p->didtdd = 0; 06565 p->callwaitcas = 0; 06566 p->callwaiting = p->permcallwaiting; 06567 p->hidecallerid = p->permhidecallerid; 06568 p->waitingfordt.tv_sec = 0; 06569 p->dialing = 0; 06570 p->rdnis[0] = '\0'; 06571 update_conf(p); 06572 reset_conf(p); 06573 /* Restore data mode */ 06574 switch (p->sig) { 06575 case SIG_PRI_LIB_HANDLE_CASES: 06576 case SIG_SS7: 06577 x = 0; 06578 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06579 break; 06580 default: 06581 break; 06582 } 06583 if (num_restart_pending == 0) 06584 restart_monitor(); 06585 } 06586 06587 p->callwaitingrepeat = 0; 06588 p->cidcwexpire = 0; 06589 p->cid_suppress_expire = 0; 06590 p->oprmode = 0; 06591 hangup_out: 06592 ast->tech_pvt = NULL; 06593 ast_free(p->cidspill); 06594 p->cidspill = NULL; 06595 06596 ast_mutex_unlock(&p->lock); 06597 ast_verb(3, "Hungup '%s'\n", ast->name); 06598 06599 ast_mutex_lock(&iflock); 06600 if (p->restartpending) { 06601 num_restart_pending--; 06602 } 06603 06604 if (p->destroy) { 06605 destroy_channel(p, 0); 06606 } 06607 ast_mutex_unlock(&iflock); 06608 06609 ast_module_unref(ast_module_info->self); 06610 return 0; 06611 }
static void dahdi_iflist_extract | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5584 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().
05585 { 05586 /* Extract from the forward chain. */ 05587 if (pvt->prev) { 05588 pvt->prev->next = pvt->next; 05589 } else if (iflist == pvt) { 05590 /* Node is at the head of the list. */ 05591 iflist = pvt->next; 05592 } 05593 05594 /* Extract from the reverse chain. */ 05595 if (pvt->next) { 05596 pvt->next->prev = pvt->prev; 05597 } else if (ifend == pvt) { 05598 /* Node is at the end of the list. */ 05599 ifend = pvt->prev; 05600 } 05601 05602 /* Node is no longer in the list. */ 05603 pvt->which_iflist = DAHDI_IFLIST_NONE; 05604 pvt->prev = NULL; 05605 pvt->next = NULL; 05606 }
static void dahdi_iflist_insert | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5534 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().
05535 { 05536 struct dahdi_pvt *cur; 05537 05538 pvt->which_iflist = DAHDI_IFLIST_MAIN; 05539 05540 /* Find place in middle of list for the new interface. */ 05541 for (cur = iflist; cur; cur = cur->next) { 05542 if (pvt->channel < cur->channel) { 05543 /* New interface goes before the current interface. */ 05544 pvt->prev = cur->prev; 05545 pvt->next = cur; 05546 if (cur->prev) { 05547 /* Insert into the middle of the list. */ 05548 cur->prev->next = pvt; 05549 } else { 05550 /* Insert at head of list. */ 05551 iflist = pvt; 05552 } 05553 cur->prev = pvt; 05554 return; 05555 } 05556 } 05557 05558 /* New interface goes onto the end of the list */ 05559 pvt->prev = ifend; 05560 pvt->next = NULL; 05561 if (ifend) { 05562 ifend->next = pvt; 05563 } 05564 ifend = pvt; 05565 if (!iflist) { 05566 /* List was empty */ 05567 iflist = pvt; 05568 } 05569 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 9479 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().
09480 { 09481 struct dahdi_pvt *p = chan->tech_pvt; 09482 int res=-1; 09483 int idx; 09484 int func = DAHDI_FLASH; 09485 09486 ast_mutex_lock(&p->lock); 09487 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 09488 switch (p->sig) { 09489 #if defined(HAVE_PRI) 09490 case SIG_PRI_LIB_HANDLE_CASES: 09491 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen); 09492 ast_mutex_unlock(&p->lock); 09493 return res; 09494 #endif /* defined(HAVE_PRI) */ 09495 #if defined(HAVE_SS7) 09496 case SIG_SS7: 09497 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen); 09498 ast_mutex_unlock(&p->lock); 09499 return res; 09500 #endif /* defined(HAVE_SS7) */ 09501 default: 09502 break; 09503 } 09504 #ifdef HAVE_OPENR2 09505 if (p->mfcr2 && !p->mfcr2_call_accepted) { 09506 ast_mutex_unlock(&p->lock); 09507 /* if this is an R2 call and the call is not yet accepted, we don't want the 09508 tone indications to mess up with the MF tones */ 09509 return 0; 09510 } 09511 #endif 09512 idx = dahdi_get_index(chan, p, 0); 09513 if (idx == SUB_REAL) { 09514 switch (condition) { 09515 case AST_CONTROL_BUSY: 09516 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 09517 break; 09518 case AST_CONTROL_RINGING: 09519 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 09520 09521 if (chan->_state != AST_STATE_UP) { 09522 if ((chan->_state != AST_STATE_RING) || 09523 ((p->sig != SIG_FXSKS) && 09524 (p->sig != SIG_FXSLS) && 09525 (p->sig != SIG_FXSGS))) 09526 ast_setstate(chan, AST_STATE_RINGING); 09527 } 09528 break; 09529 case AST_CONTROL_INCOMPLETE: 09530 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name); 09531 /* act as a progress or proceeding, allowing the caller to enter additional numbers */ 09532 res = 0; 09533 break; 09534 case AST_CONTROL_PROCEEDING: 09535 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name); 09536 /* don't continue in ast_indicate */ 09537 res = 0; 09538 break; 09539 case AST_CONTROL_PROGRESS: 09540 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name); 09541 /* don't continue in ast_indicate */ 09542 res = 0; 09543 break; 09544 case AST_CONTROL_CONGESTION: 09545 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 09546 switch (chan->hangupcause) { 09547 case AST_CAUSE_USER_BUSY: 09548 case AST_CAUSE_NORMAL_CLEARING: 09549 case 0:/* Cause has not been set. */ 09550 /* Supply a more appropriate cause. */ 09551 chan->hangupcause = AST_CAUSE_CONGESTION; 09552 break; 09553 default: 09554 break; 09555 } 09556 break; 09557 case AST_CONTROL_HOLD: 09558 ast_moh_start(chan, data, p->mohinterpret); 09559 break; 09560 case AST_CONTROL_UNHOLD: 09561 ast_moh_stop(chan); 09562 break; 09563 case AST_CONTROL_RADIO_KEY: 09564 if (p->radio) 09565 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 09566 res = 0; 09567 break; 09568 case AST_CONTROL_RADIO_UNKEY: 09569 if (p->radio) 09570 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 09571 res = 0; 09572 break; 09573 case AST_CONTROL_FLASH: 09574 /* flash hookswitch */ 09575 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 09576 /* Clear out the dial buffer */ 09577 p->dop.dialstr[0] = '\0'; 09578 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09579 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09580 chan->name, strerror(errno)); 09581 } else 09582 res = 0; 09583 } else 09584 res = 0; 09585 break; 09586 case AST_CONTROL_SRCUPDATE: 09587 res = 0; 09588 break; 09589 case -1: 09590 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09591 break; 09592 } 09593 } else { 09594 res = 0; 09595 } 09596 ast_mutex_unlock(&p->lock); 09597 return res; 09598 }
Definition at line 7237 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().
07237 { 07238 int x; 07239 if (!slave || !master) { 07240 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 07241 return; 07242 } 07243 for (x = 0; x < MAX_SLAVES; x++) { 07244 if (!master->slaves[x]) { 07245 master->slaves[x] = slave; 07246 break; 07247 } 07248 } 07249 if (x >= MAX_SLAVES) { 07250 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 07251 master->slaves[MAX_SLAVES - 1] = slave; 07252 } 07253 if (slave->master) 07254 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 07255 slave->master = master; 07256 07257 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 07258 }
static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
int | sub_idx | |||
) | [static] |
Definition at line 3832 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().
03833 { 03834 for (;;) { 03835 if (!pvt->subs[sub_idx].owner) { 03836 /* No subchannel owner pointer */ 03837 break; 03838 } 03839 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) { 03840 /* Got subchannel owner lock */ 03841 break; 03842 } 03843 /* We must unlock the private to avoid the possibility of a deadlock */ 03844 DEADLOCK_AVOIDANCE(&pvt->lock); 03845 } 03846 }
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 9648 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_compare(), 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_dsp_set_threshold(), 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::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, 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, dahdi_pvt::silencethreshold, 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().
09649 { 09650 struct ast_channel *tmp; 09651 format_t deflaw; 09652 int x; 09653 int features; 09654 struct ast_str *chan_name; 09655 struct ast_variable *v; 09656 char *dashptr; 09657 char device_name[AST_CHANNEL_NAME]; 09658 09659 if (i->subs[idx].owner) { 09660 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 09661 return NULL; 09662 } 09663 09664 #if defined(HAVE_PRI) 09665 /* 09666 * The dnid has been stuffed with the called-number[:subaddress] 09667 * by dahdi_request() for outgoing calls. 09668 */ 09669 chan_name = create_channel_name(i, i->outgoing, i->dnid); 09670 #else 09671 chan_name = create_channel_name(i); 09672 #endif /* defined(HAVE_PRI) */ 09673 if (!chan_name) { 09674 return NULL; 09675 } 09676 09677 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)); 09678 ast_free(chan_name); 09679 if (!tmp) 09680 return NULL; 09681 tmp->tech = &dahdi_tech; 09682 #if defined(HAVE_PRI) 09683 if (i->pri) { 09684 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params); 09685 } 09686 #endif /* defined(HAVE_PRI) */ 09687 ast_channel_cc_params_init(tmp, i->cc_params); 09688 if (law) { 09689 i->law = law; 09690 if (law == DAHDI_LAW_ALAW) { 09691 deflaw = AST_FORMAT_ALAW; 09692 } else { 09693 deflaw = AST_FORMAT_ULAW; 09694 } 09695 } else { 09696 switch (i->sig) { 09697 case SIG_PRI_LIB_HANDLE_CASES: 09698 /* Make sure companding law is known. */ 09699 i->law = (i->law_default == DAHDI_LAW_ALAW) 09700 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW; 09701 break; 09702 default: 09703 i->law = i->law_default; 09704 break; 09705 } 09706 if (i->law_default == DAHDI_LAW_ALAW) { 09707 deflaw = AST_FORMAT_ALAW; 09708 } else { 09709 deflaw = AST_FORMAT_ULAW; 09710 } 09711 } 09712 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 09713 tmp->nativeformats = deflaw; 09714 /* Start out assuming ulaw since it's smaller :) */ 09715 tmp->rawreadformat = deflaw; 09716 tmp->readformat = deflaw; 09717 tmp->rawwriteformat = deflaw; 09718 tmp->writeformat = deflaw; 09719 i->subs[idx].linear = 0; 09720 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 09721 features = 0; 09722 if (idx == SUB_REAL) { 09723 if (i->busydetect && CANBUSYDETECT(i)) 09724 features |= DSP_FEATURE_BUSY_DETECT; 09725 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 09726 features |= DSP_FEATURE_CALL_PROGRESS; 09727 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 09728 features |= DSP_FEATURE_WAITDIALTONE; 09729 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 09730 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 09731 features |= DSP_FEATURE_FAX_DETECT; 09732 } 09733 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 09734 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 09735 i->hardwaredtmf = 0; 09736 features |= DSP_FEATURE_DIGIT_DETECT; 09737 } else if (NEED_MFDETECT(i)) { 09738 i->hardwaredtmf = 1; 09739 features |= DSP_FEATURE_DIGIT_DETECT; 09740 } 09741 } 09742 if (features) { 09743 if (i->dsp) { 09744 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 09745 } else { 09746 if (i->channel != CHAN_PSEUDO) 09747 i->dsp = ast_dsp_new(); 09748 else 09749 i->dsp = NULL; 09750 if (i->dsp) { 09751 i->dsp_features = features; 09752 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09753 /* We cannot do progress detection until receive PROGRESS message */ 09754 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) { 09755 /* Remember requested DSP features, don't treat 09756 talking as ANSWER */ 09757 i->dsp_features = features & ~DSP_PROGRESS_TALK; 09758 features = 0; 09759 } 09760 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09761 ast_dsp_set_features(i->dsp, features); 09762 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 09763 if (!ast_strlen_zero(progzone)) 09764 ast_dsp_set_call_progress_zone(i->dsp, progzone); 09765 if (i->busydetect && CANBUSYDETECT(i)) { 09766 if(i->silencethreshold > 0) 09767 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 09768 ast_dsp_set_busy_count(i->dsp, i->busycount); 09769 if(i->busytonelength > 0) 09770 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 09771 if((i->busytonelength == i->busyquietlength) && i->busycompare) 09772 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 09773 } 09774 } 09775 } 09776 } 09777 09778 if (state == AST_STATE_RING) 09779 tmp->rings = 1; 09780 tmp->tech_pvt = i; 09781 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 09782 /* Only FXO signalled stuff can be picked up */ 09783 tmp->callgroup = i->callgroup; 09784 tmp->pickupgroup = i->pickupgroup; 09785 } 09786 if (!ast_strlen_zero(i->parkinglot)) 09787 ast_string_field_set(tmp, parkinglot, i->parkinglot); 09788 if (!ast_strlen_zero(i->language)) 09789 ast_string_field_set(tmp, language, i->language); 09790 if (!i->owner) 09791 i->owner = tmp; 09792 if (!ast_strlen_zero(i->accountcode)) 09793 ast_string_field_set(tmp, accountcode, i->accountcode); 09794 if (i->amaflags) 09795 tmp->amaflags = i->amaflags; 09796 i->subs[idx].owner = tmp; 09797 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 09798 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) { 09799 ast_string_field_set(tmp, call_forward, i->call_forward); 09800 } 09801 /* If we've been told "no ADSI" then enforce it */ 09802 if (!i->adsi) 09803 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 09804 if (!ast_strlen_zero(i->exten)) 09805 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 09806 if (!ast_strlen_zero(i->rdnis)) { 09807 tmp->redirecting.from.number.valid = 1; 09808 tmp->redirecting.from.number.str = ast_strdup(i->rdnis); 09809 } 09810 if (!ast_strlen_zero(i->dnid)) { 09811 tmp->dialed.number.str = ast_strdup(i->dnid); 09812 } 09813 09814 /* Don't use ast_set_callerid() here because it will 09815 * generate a needless NewCallerID event */ 09816 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09817 if (!ast_strlen_zero(i->cid_ani)) { 09818 tmp->caller.ani.number.valid = 1; 09819 tmp->caller.ani.number.str = ast_strdup(i->cid_ani); 09820 } else if (!ast_strlen_zero(i->cid_num)) { 09821 tmp->caller.ani.number.valid = 1; 09822 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09823 } 09824 #else 09825 if (!ast_strlen_zero(i->cid_num)) { 09826 tmp->caller.ani.number.valid = 1; 09827 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09828 } 09829 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09830 tmp->caller.id.name.presentation = i->callingpres; 09831 tmp->caller.id.number.presentation = i->callingpres; 09832 tmp->caller.id.number.plan = i->cid_ton; 09833 tmp->caller.ani2 = i->cid_ani2; 09834 tmp->caller.id.tag = ast_strdup(i->cid_tag); 09835 /* clear the fake event in case we posted one before we had ast_channel */ 09836 i->fake_event = 0; 09837 /* Assure there is no confmute on this channel */ 09838 dahdi_confmute(i, 0); 09839 i->muting = 0; 09840 /* Configure the new channel jb */ 09841 ast_jb_configure(tmp, &global_jbconf); 09842 09843 /* Set initial device state */ 09844 ast_copy_string(device_name, tmp->name, sizeof(device_name)); 09845 dashptr = strrchr(device_name, '-'); 09846 if (dashptr) { 09847 *dashptr = '\0'; 09848 } 09849 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; 09850 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name); 09851 09852 for (v = i->vars ; v ; v = v->next) 09853 pbx_builtin_setvar_helper(tmp, v->name, v->value); 09854 09855 ast_module_ref(ast_module_info->self); 09856 09857 dahdi_ami_channel_event(i, tmp); 09858 if (startpbx) { 09859 #ifdef HAVE_OPENR2 09860 if (i->mfcr2call) { 09861 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 09862 } 09863 #endif 09864 if (ast_pbx_start(tmp)) { 09865 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 09866 ast_hangup(tmp); 09867 return NULL; 09868 } 09869 } 09870 return tmp; 09871 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 4369 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), duplicate_pseudo(), and mkintf().
04370 { 04371 int fd; 04372 int isnum; 04373 int chan = 0; 04374 int bs; 04375 int x; 04376 isnum = 1; 04377 for (x = 0; x < strlen(fn); x++) { 04378 if (!isdigit(fn[x])) { 04379 isnum = 0; 04380 break; 04381 } 04382 } 04383 if (isnum) { 04384 chan = atoi(fn); 04385 if (chan < 1) { 04386 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 04387 return -1; 04388 } 04389 fn = "/dev/dahdi/channel"; 04390 } 04391 fd = open(fn, O_RDWR | O_NONBLOCK); 04392 if (fd < 0) { 04393 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 04394 return -1; 04395 } 04396 if (chan) { 04397 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 04398 x = errno; 04399 close(fd); 04400 errno = x; 04401 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 04402 return -1; 04403 } 04404 } 04405 bs = READ_SIZE; 04406 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 04407 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 04408 x = errno; 04409 close(fd); 04410 errno = x; 04411 return -1; 04412 } 04413 return fd; 04414 }
static int dahdi_queryoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int * | datalen | |||
) | [static] |
Definition at line 6708 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.
06709 { 06710 char *cp; 06711 struct dahdi_pvt *p = chan->tech_pvt; 06712 06713 /* all supported options require data */ 06714 if (!p || !data || (*datalen < 1)) { 06715 errno = EINVAL; 06716 return -1; 06717 } 06718 06719 switch (option) { 06720 case AST_OPTION_DIGIT_DETECT: 06721 cp = (char *) data; 06722 *cp = p->ignoredtmf ? 0 : 1; 06723 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06724 break; 06725 case AST_OPTION_FAX_DETECT: 06726 cp = (char *) data; 06727 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1; 06728 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06729 break; 06730 case AST_OPTION_CC_AGENT_TYPE: 06731 #if defined(HAVE_PRI) 06732 #if defined(HAVE_PRI_CCSS) 06733 if (dahdi_sig_pri_lib_handles(p->sig)) { 06734 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen); 06735 break; 06736 } 06737 #endif /* defined(HAVE_PRI_CCSS) */ 06738 #endif /* defined(HAVE_PRI) */ 06739 return -1; 06740 default: 06741 return -1; 06742 } 06743 06744 errno = 0; 06745 06746 return 0; 06747 }
Definition at line 3857 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().
03858 { 03859 for (;;) { 03860 if (p->owner) { 03861 if (ast_channel_trylock(p->owner)) { 03862 DEADLOCK_AVOIDANCE(&p->lock); 03863 } else { 03864 ast_queue_frame(p->owner, f); 03865 ast_channel_unlock(p->owner); 03866 break; 03867 } 03868 } else 03869 break; 03870 } 03871 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8956 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.
08957 { 08958 struct dahdi_pvt *p; 08959 int res; 08960 int idx; 08961 void *readbuf; 08962 struct ast_frame *f; 08963 08964 /* 08965 * For analog channels, we must do deadlock avoidance because 08966 * analog ports can have more than one Asterisk channel using 08967 * the same private structure. 08968 */ 08969 p = ast->tech_pvt; 08970 while (ast_mutex_trylock(&p->lock)) { 08971 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08972 08973 /* 08974 * Check to see if the channel is still associated with the same 08975 * private structure. While the Asterisk channel was unlocked 08976 * the following events may have occured: 08977 * 08978 * 1) A masquerade may have associated the channel with another 08979 * technology or private structure. 08980 * 08981 * 2) For PRI calls, call signaling could change the channel 08982 * association to another B channel (private structure). 08983 */ 08984 if (ast->tech_pvt != p) { 08985 /* The channel is no longer associated. Quit gracefully. */ 08986 return &ast_null_frame; 08987 } 08988 } 08989 08990 idx = dahdi_get_index(ast, p, 0); 08991 08992 /* Hang up if we don't really exist */ 08993 if (idx < 0) { 08994 ast_log(LOG_WARNING, "We don't exist?\n"); 08995 ast_mutex_unlock(&p->lock); 08996 return NULL; 08997 } 08998 08999 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 09000 ast_mutex_unlock(&p->lock); 09001 return NULL; 09002 } 09003 09004 p->subs[idx].f.frametype = AST_FRAME_NULL; 09005 p->subs[idx].f.datalen = 0; 09006 p->subs[idx].f.samples = 0; 09007 p->subs[idx].f.mallocd = 0; 09008 p->subs[idx].f.offset = 0; 09009 p->subs[idx].f.subclass.integer = 0; 09010 p->subs[idx].f.delivery = ast_tv(0,0); 09011 p->subs[idx].f.src = "dahdi_read"; 09012 p->subs[idx].f.data.ptr = NULL; 09013 09014 /* make sure it sends initial key state as first frame */ 09015 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 09016 { 09017 struct dahdi_params ps; 09018 09019 memset(&ps, 0, sizeof(ps)); 09020 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 09021 ast_mutex_unlock(&p->lock); 09022 return NULL; 09023 } 09024 p->firstradio = 1; 09025 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09026 if (ps.rxisoffhook) 09027 { 09028 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 09029 } 09030 else 09031 { 09032 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 09033 } 09034 ast_mutex_unlock(&p->lock); 09035 return &p->subs[idx].f; 09036 } 09037 if (p->ringt > 0) { 09038 if (!(--p->ringt)) { 09039 ast_mutex_unlock(&p->lock); 09040 return NULL; 09041 } 09042 } 09043 09044 #ifdef HAVE_OPENR2 09045 if (p->mfcr2) { 09046 openr2_chan_process_event(p->r2chan); 09047 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) { 09048 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, }; 09049 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING 09050 * now enqueue a progress frame to bridge the media up */ 09051 if (p->mfcr2_call_accepted && 09052 !p->mfcr2_progress && 09053 ast->_state == AST_STATE_RINGING) { 09054 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel); 09055 ast_queue_frame(p->owner, &f); 09056 p->mfcr2_progress = 1; 09057 } 09058 } 09059 } 09060 #endif 09061 09062 if (p->subs[idx].needringing) { 09063 /* Send ringing frame if requested */ 09064 p->subs[idx].needringing = 0; 09065 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09066 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING; 09067 ast_setstate(ast, AST_STATE_RINGING); 09068 ast_mutex_unlock(&p->lock); 09069 return &p->subs[idx].f; 09070 } 09071 09072 if (p->subs[idx].needbusy) { 09073 /* Send busy frame if requested */ 09074 p->subs[idx].needbusy = 0; 09075 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09076 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY; 09077 ast_mutex_unlock(&p->lock); 09078 return &p->subs[idx].f; 09079 } 09080 09081 if (p->subs[idx].needcongestion) { 09082 /* Send congestion frame if requested */ 09083 p->subs[idx].needcongestion = 0; 09084 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09085 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION; 09086 ast_mutex_unlock(&p->lock); 09087 return &p->subs[idx].f; 09088 } 09089 09090 if (p->subs[idx].needanswer) { 09091 /* Send answer frame if requested */ 09092 p->subs[idx].needanswer = 0; 09093 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09094 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 09095 ast_mutex_unlock(&p->lock); 09096 return &p->subs[idx].f; 09097 } 09098 #ifdef HAVE_OPENR2 09099 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 09100 /* openr2 took care of reading and handling any event 09101 (needanswer, needbusy etc), if we continue we will read() 09102 twice, lets just return a null frame. This should only 09103 happen when openr2 is dialing out */ 09104 ast_mutex_unlock(&p->lock); 09105 return &ast_null_frame; 09106 } 09107 #endif 09108 09109 if (p->subs[idx].needflash) { 09110 /* Send answer frame if requested */ 09111 p->subs[idx].needflash = 0; 09112 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09113 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH; 09114 ast_mutex_unlock(&p->lock); 09115 return &p->subs[idx].f; 09116 } 09117 09118 if (p->subs[idx].needhold) { 09119 /* Send answer frame if requested */ 09120 p->subs[idx].needhold = 0; 09121 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09122 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD; 09123 ast_mutex_unlock(&p->lock); 09124 ast_debug(1, "Sending hold on '%s'\n", ast->name); 09125 return &p->subs[idx].f; 09126 } 09127 09128 if (p->subs[idx].needunhold) { 09129 /* Send answer frame if requested */ 09130 p->subs[idx].needunhold = 0; 09131 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09132 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD; 09133 ast_mutex_unlock(&p->lock); 09134 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 09135 return &p->subs[idx].f; 09136 } 09137 09138 /* 09139 * If we have a fake_event, fake an exception to handle it only 09140 * if this channel owns the private. 09141 */ 09142 if (p->fake_event && p->owner == ast) { 09143 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09144 struct analog_pvt *analog_p = p->sig_pvt; 09145 09146 f = analog_exception(analog_p, ast); 09147 } else { 09148 f = __dahdi_exception(ast); 09149 } 09150 ast_mutex_unlock(&p->lock); 09151 return f; 09152 } 09153 09154 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 09155 if (!p->subs[idx].linear) { 09156 p->subs[idx].linear = 1; 09157 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09158 if (res) 09159 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 09160 } 09161 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 09162 (ast->rawreadformat == AST_FORMAT_ALAW)) { 09163 if (p->subs[idx].linear) { 09164 p->subs[idx].linear = 0; 09165 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09166 if (res) 09167 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 09168 } 09169 } else { 09170 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 09171 ast_mutex_unlock(&p->lock); 09172 return NULL; 09173 } 09174 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 09175 CHECK_BLOCKING(ast); 09176 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09177 ast_clear_flag(ast, AST_FLAG_BLOCKING); 09178 /* Check for hangup */ 09179 if (res < 0) { 09180 f = NULL; 09181 if (res == -1) { 09182 if (errno == EAGAIN) { 09183 /* Return "NULL" frame if there is nobody there */ 09184 ast_mutex_unlock(&p->lock); 09185 return &p->subs[idx].f; 09186 } else if (errno == ELAST) { 09187 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09188 struct analog_pvt *analog_p = p->sig_pvt; 09189 f = analog_exception(analog_p, ast); 09190 } else { 09191 f = __dahdi_exception(ast); 09192 } 09193 } else 09194 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 09195 } 09196 ast_mutex_unlock(&p->lock); 09197 return f; 09198 } 09199 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 09200 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09201 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09202 struct analog_pvt *analog_p = p->sig_pvt; 09203 f = analog_exception(analog_p, ast); 09204 } else { 09205 f = __dahdi_exception(ast); 09206 } 09207 ast_mutex_unlock(&p->lock); 09208 return f; 09209 } 09210 if (p->tdd) { /* if in TDD mode, see if we receive that */ 09211 int c; 09212 09213 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 09214 if (c < 0) { 09215 ast_debug(1,"tdd_feed failed\n"); 09216 ast_mutex_unlock(&p->lock); 09217 return NULL; 09218 } 09219 if (c) { /* if a char to return */ 09220 p->subs[idx].f.subclass.integer = 0; 09221 p->subs[idx].f.frametype = AST_FRAME_TEXT; 09222 p->subs[idx].f.mallocd = 0; 09223 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09224 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 09225 p->subs[idx].f.datalen = 1; 09226 *((char *) p->subs[idx].f.data.ptr) = c; 09227 ast_mutex_unlock(&p->lock); 09228 return &p->subs[idx].f; 09229 } 09230 } 09231 if (idx == SUB_REAL) { 09232 /* Ensure the CW timers decrement only on a single subchannel */ 09233 if (p->cidcwexpire) { 09234 if (!--p->cidcwexpire) { 09235 /* Expired CID/CW */ 09236 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 09237 restore_conference(p); 09238 } 09239 } 09240 if (p->cid_suppress_expire) { 09241 --p->cid_suppress_expire; 09242 } 09243 if (p->callwaitingrepeat) { 09244 if (!--p->callwaitingrepeat) { 09245 /* Expired, Repeat callwaiting tone */ 09246 ++p->callwaitrings; 09247 dahdi_callwait(ast); 09248 } 09249 } 09250 } 09251 if (p->subs[idx].linear) { 09252 p->subs[idx].f.datalen = READ_SIZE * 2; 09253 } else 09254 p->subs[idx].f.datalen = READ_SIZE; 09255 09256 /* Handle CallerID Transmission */ 09257 if ((p->owner == ast) && p->cidspill) { 09258 send_callerid(p); 09259 } 09260 09261 p->subs[idx].f.frametype = AST_FRAME_VOICE; 09262 p->subs[idx].f.subclass.codec = ast->rawreadformat; 09263 p->subs[idx].f.samples = READ_SIZE; 09264 p->subs[idx].f.mallocd = 0; 09265 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09266 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 09267 #if 0 09268 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 09269 #endif 09270 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */ 09271 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 09272 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 09273 ) { 09274 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 09275 don't send anything */ 09276 p->subs[idx].f.frametype = AST_FRAME_NULL; 09277 p->subs[idx].f.subclass.integer = 0; 09278 p->subs[idx].f.samples = 0; 09279 p->subs[idx].f.mallocd = 0; 09280 p->subs[idx].f.offset = 0; 09281 p->subs[idx].f.data.ptr = NULL; 09282 p->subs[idx].f.datalen= 0; 09283 } 09284 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 09285 /* Perform busy detection etc on the dahdi line */ 09286 int mute; 09287 09288 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 09289 09290 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 09291 mute = ast_dsp_was_muted(p->dsp); 09292 if (p->muting != mute) { 09293 p->muting = mute; 09294 dahdi_confmute(p, mute); 09295 } 09296 09297 if (f) { 09298 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { 09299 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 09300 /* Treat this as a "hangup" instead of a "busy" on the assumption that 09301 a busy */ 09302 ast_frfree(f); 09303 f = NULL; 09304 } 09305 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 09306 || f->frametype == AST_FRAME_DTMF_END) { 09307 #ifdef HAVE_PRI 09308 if (dahdi_sig_pri_lib_handles(p->sig) 09309 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 09310 && p->pri 09311 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 09312 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 09313 /* Don't accept in-band DTMF when in overlap dial mode */ 09314 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 09315 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 09316 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 09317 09318 f->frametype = AST_FRAME_NULL; 09319 f->subclass.integer = 0; 09320 } 09321 #endif 09322 /* DSP clears us of being pulse */ 09323 p->pulsedial = 0; 09324 } else if (p->waitingfordt.tv_sec) { 09325 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 09326 p->waitingfordt.tv_sec = 0; 09327 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 09328 ast_frfree(f); 09329 f = NULL; 09330 } else if (f->frametype == AST_FRAME_VOICE) { 09331 f->frametype = AST_FRAME_NULL; 09332 f->subclass.integer = 0; 09333 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) { 09334 p->waitingfordt.tv_sec = 0; 09335 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 09336 ast_dsp_set_features(p->dsp, p->dsp_features); 09337 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 09338 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 09339 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 09340 if (res < 0) { 09341 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 09342 p->dop.dialstr[0] = '\0'; 09343 ast_mutex_unlock(&p->lock); 09344 ast_frfree(f); 09345 return NULL; 09346 } else { 09347 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 09348 p->dialing = 1; 09349 p->dop.dialstr[0] = '\0'; 09350 p->dop.op = DAHDI_DIAL_OP_REPLACE; 09351 ast_setstate(ast, AST_STATE_DIALING); 09352 } 09353 } 09354 } 09355 } 09356 } 09357 } 09358 } else 09359 f = &p->subs[idx].f; 09360 09361 if (f) { 09362 switch (f->frametype) { 09363 case AST_FRAME_DTMF_BEGIN: 09364 case AST_FRAME_DTMF_END: 09365 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09366 analog_handle_dtmf(p->sig_pvt, ast, idx, &f); 09367 } else { 09368 dahdi_handle_dtmf(ast, idx, &f); 09369 } 09370 break; 09371 case AST_FRAME_VOICE: 09372 if (p->cidspill || p->cid_suppress_expire) { 09373 /* We are/were sending a caller id spill. Suppress any echo. */ 09374 p->subs[idx].f.frametype = AST_FRAME_NULL; 09375 p->subs[idx].f.subclass.integer = 0; 09376 p->subs[idx].f.samples = 0; 09377 p->subs[idx].f.mallocd = 0; 09378 p->subs[idx].f.offset = 0; 09379 p->subs[idx].f.data.ptr = NULL; 09380 p->subs[idx].f.datalen= 0; 09381 } 09382 break; 09383 default: 09384 break; 09385 } 09386 } 09387 09388 ast_mutex_unlock(&p->lock); 09389 return f; 09390 }
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 13721 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.
13722 { 13723 int callwait = 0; 13724 struct dahdi_pvt *p; 13725 struct ast_channel *tmp = NULL; 13726 struct dahdi_pvt *exitpvt; 13727 int channelmatched = 0; 13728 int groupmatched = 0; 13729 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13730 int transcapdigital = 0; 13731 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13732 struct dahdi_starting_point start; 13733 13734 ast_mutex_lock(&iflock); 13735 p = determine_starting_point(data, &start); 13736 if (!p) { 13737 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */ 13738 ast_mutex_unlock(&iflock); 13739 return NULL; 13740 } 13741 13742 /* Search for an unowned channel */ 13743 exitpvt = p; 13744 while (p && !tmp) { 13745 if (start.roundrobin) 13746 round_robin[start.rr_starting_point] = p; 13747 13748 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched) 13749 && available(&p, channelmatched)) { 13750 ast_debug(1, "Using channel %d\n", p->channel); 13751 13752 callwait = (p->owner != NULL); 13753 #ifdef HAVE_OPENR2 13754 if (p->mfcr2) { 13755 ast_mutex_lock(&p->lock); 13756 if (p->mfcr2call) { 13757 ast_mutex_unlock(&p->lock); 13758 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 13759 goto next; 13760 } 13761 p->mfcr2call = 1; 13762 ast_mutex_unlock(&p->lock); 13763 } 13764 #endif 13765 if (p->channel == CHAN_PSEUDO) { 13766 p = duplicate_pseudo(p); 13767 if (!p) { 13768 break; 13769 } 13770 } 13771 13772 p->distinctivering = 0; 13773 /* Make special notes */ 13774 switch (start.opt) { 13775 case '\0': 13776 /* No option present. */ 13777 break; 13778 case 'c': 13779 /* Confirm answer */ 13780 p->confirmanswer = 1; 13781 break; 13782 case 'r': 13783 /* Distinctive ring */ 13784 p->distinctivering = start.cadance; 13785 break; 13786 case 'd': 13787 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13788 /* If this is an ISDN call, make it digital */ 13789 transcapdigital = AST_TRANS_CAP_DIGITAL; 13790 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13791 break; 13792 default: 13793 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data); 13794 break; 13795 } 13796 13797 p->outgoing = 1; 13798 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 13799 tmp = analog_request(p->sig_pvt, &callwait, requestor); 13800 #ifdef HAVE_PRI 13801 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 13802 /* 13803 * We already have the B channel reserved for this call. We 13804 * just need to make sure that dahdi_hangup() has completed 13805 * cleaning up before continuing. 13806 */ 13807 ast_mutex_lock(&p->lock); 13808 ast_mutex_unlock(&p->lock); 13809 13810 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid, 13811 sizeof(p->dnid)); 13812 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital); 13813 #endif 13814 #if defined(HAVE_SS7) 13815 } else if (p->sig == SIG_SS7) { 13816 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital); 13817 #endif /* defined(HAVE_SS7) */ 13818 } else { 13819 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : ""); 13820 } 13821 if (!tmp) { 13822 p->outgoing = 0; 13823 #if defined(HAVE_PRI) 13824 switch (p->sig) { 13825 case SIG_PRI_LIB_HANDLE_CASES: 13826 #if defined(HAVE_PRI_CALL_WAITING) 13827 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) { 13828 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0; 13829 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); 13830 } 13831 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 13832 /* 13833 * This should be the last thing to clear when we are done with 13834 * the channel. 13835 */ 13836 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0; 13837 break; 13838 default: 13839 break; 13840 } 13841 #endif /* defined(HAVE_PRI) */ 13842 } else { 13843 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data); 13844 } 13845 break; 13846 } 13847 #ifdef HAVE_OPENR2 13848 next: 13849 #endif 13850 if (start.backwards) { 13851 p = p->prev; 13852 if (!p) 13853 p = ifend; 13854 } else { 13855 p = p->next; 13856 if (!p) 13857 p = iflist; 13858 } 13859 /* stop when you roll to the one that we started from */ 13860 if (p == exitpvt) 13861 break; 13862 } 13863 ast_mutex_unlock(&iflock); 13864 restart_monitor(); 13865 if (cause && !tmp) { 13866 if (callwait || channelmatched) { 13867 *cause = AST_CAUSE_BUSY; 13868 } else if (groupmatched) { 13869 *cause = AST_CAUSE_CONGESTION; 13870 } else { 13871 /* 13872 * We did not match any channel requested. 13873 * Dialplan error requesting non-existant channel? 13874 */ 13875 } 13876 } 13877 13878 return tmp; 13879 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 15244 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().
15245 { 15246 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15247 int i, j; 15248 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 15249 int cancel_code; 15250 struct dahdi_pvt *p; 15251 15252 ast_mutex_lock(&restart_lock); 15253 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 15254 dahdi_softhangup_all(); 15255 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 15256 #ifdef HAVE_OPENR2 15257 dahdi_r2_destroy_links(); 15258 #endif 15259 15260 #if defined(HAVE_PRI) 15261 for (i = 0; i < NUM_SPANS; i++) { 15262 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 15263 cancel_code = pthread_cancel(pris[i].pri.master); 15264 pthread_kill(pris[i].pri.master, SIGURG); 15265 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); 15266 pthread_join(pris[i].pri.master, NULL); 15267 ast_debug(4, "Joined thread of span %d\n", i); 15268 } 15269 } 15270 #endif 15271 15272 #if defined(HAVE_SS7) 15273 for (i = 0; i < NUM_SPANS; i++) { 15274 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 15275 cancel_code = pthread_cancel(linksets[i].ss7.master); 15276 pthread_kill(linksets[i].ss7.master, SIGURG); 15277 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); 15278 pthread_join(linksets[i].ss7.master, NULL); 15279 ast_debug(4, "Joined thread of span %d\n", i); 15280 } 15281 } 15282 #endif /* defined(HAVE_SS7) */ 15283 15284 ast_mutex_lock(&monlock); 15285 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 15286 cancel_code = pthread_cancel(monitor_thread); 15287 pthread_kill(monitor_thread, SIGURG); 15288 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 15289 pthread_join(monitor_thread, NULL); 15290 ast_debug(4, "Joined monitor thread\n"); 15291 } 15292 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 15293 15294 ast_mutex_lock(&ss_thread_lock); 15295 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 15296 int x = DAHDI_FLASH; 15297 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count); 15298 15299 ast_mutex_lock(&iflock); 15300 for (p = iflist; p; p = p->next) { 15301 if (p->owner) { 15302 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 15303 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 15304 } 15305 } 15306 ast_mutex_unlock(&iflock); 15307 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 15308 } 15309 15310 /* ensure any created channels before monitor threads were stopped are hungup */ 15311 dahdi_softhangup_all(); 15312 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 15313 destroy_all_channels(); 15314 memset(round_robin, 0, sizeof(round_robin)); 15315 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 15316 15317 ast_mutex_unlock(&monlock); 15318 15319 #ifdef HAVE_PRI 15320 for (i = 0; i < NUM_SPANS; i++) { 15321 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) 15322 dahdi_close_pri_fd(&(pris[i]), j); 15323 } 15324 15325 memset(pris, 0, sizeof(pris)); 15326 for (i = 0; i < NUM_SPANS; i++) { 15327 sig_pri_init_pri(&pris[i].pri); 15328 } 15329 pri_set_error(dahdi_pri_error); 15330 pri_set_message(dahdi_pri_message); 15331 #endif 15332 #if defined(HAVE_SS7) 15333 for (i = 0; i < NUM_SPANS; i++) { 15334 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) 15335 dahdi_close_ss7_fd(&(linksets[i]), j); 15336 } 15337 15338 memset(linksets, 0, sizeof(linksets)); 15339 for (i = 0; i < NUM_SPANS; i++) { 15340 sig_ss7_init_linkset(&linksets[i].ss7); 15341 } 15342 ss7_set_error(dahdi_ss7_error); 15343 ss7_set_message(dahdi_ss7_message); 15344 #endif /* defined(HAVE_SS7) */ 15345 15346 if (setup_dahdi(2) != 0) { 15347 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 15348 ast_mutex_unlock(&ss_thread_lock); 15349 return 1; 15350 } 15351 ast_mutex_unlock(&ss_thread_lock); 15352 ast_mutex_unlock(&restart_lock); 15353 return 0; 15354 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15356 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.
15357 { 15358 switch (cmd) { 15359 case CLI_INIT: 15360 e->command = "dahdi restart"; 15361 e->usage = 15362 "Usage: dahdi restart\n" 15363 " Restarts the DAHDI channels: destroys them all and then\n" 15364 " re-reads them from chan_dahdi.conf.\n" 15365 " Note that this will STOP any running CALL on DAHDI channels.\n" 15366 ""; 15367 return NULL; 15368 case CLI_GENERATE: 15369 return NULL; 15370 } 15371 if (a->argc != 2) 15372 return CLI_SHOWUSAGE; 15373 15374 if (dahdi_restart() != 0) 15375 return CLI_FAILURE; 15376 return CLI_SUCCESS; 15377 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7653 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().
07654 { 07655 int x; 07656 int res; 07657 /* Make sure our transmit state is on hook */ 07658 x = 0; 07659 x = DAHDI_ONHOOK; 07660 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07661 do { 07662 x = DAHDI_RING; 07663 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07664 if (res) { 07665 switch (errno) { 07666 case EBUSY: 07667 case EINTR: 07668 /* Wait just in case */ 07669 usleep(10000); 07670 continue; 07671 case EINPROGRESS: 07672 res = 0; 07673 break; 07674 default: 07675 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 07676 res = 0; 07677 } 07678 } 07679 } while (res); 07680 return res; 07681 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 18837 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.
18838 { 18839 #define END_SILENCE_LEN 400 18840 #define HEADER_MS 50 18841 #define TRAILER_MS 5 18842 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 18843 #define ASCII_BYTES_PER_CHAR 80 18844 18845 unsigned char *buf,*mybuf; 18846 struct dahdi_pvt *p = c->tech_pvt; 18847 struct pollfd fds[1]; 18848 int size,res,fd,len,x; 18849 int bytes=0; 18850 /* Initial carrier (imaginary) */ 18851 float cr = 1.0; 18852 float ci = 0.0; 18853 float scont = 0.0; 18854 int idx; 18855 18856 idx = dahdi_get_index(c, p, 0); 18857 if (idx < 0) { 18858 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 18859 return -1; 18860 } 18861 if (!text[0]) return(0); /* if nothing to send, don't */ 18862 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 18863 if (p->mate) 18864 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 18865 else 18866 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 18867 if (!buf) 18868 return -1; 18869 mybuf = buf; 18870 if (p->mate) { 18871 int codec = AST_LAW(p); 18872 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 18873 PUT_CLID_MARKMS; 18874 } 18875 /* Put actual message */ 18876 for (x = 0; text[x]; x++) { 18877 PUT_CLID(text[x]); 18878 } 18879 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 18880 PUT_CLID_MARKMS; 18881 } 18882 len = bytes; 18883 buf = mybuf; 18884 } else { 18885 len = tdd_generate(p->tdd, buf, text); 18886 if (len < 1) { 18887 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 18888 ast_free(mybuf); 18889 return -1; 18890 } 18891 } 18892 memset(buf + len, 0x7f, END_SILENCE_LEN); 18893 len += END_SILENCE_LEN; 18894 fd = p->subs[idx].dfd; 18895 while (len) { 18896 if (ast_check_hangup(c)) { 18897 ast_free(mybuf); 18898 return -1; 18899 } 18900 size = len; 18901 if (size > READ_SIZE) 18902 size = READ_SIZE; 18903 fds[0].fd = fd; 18904 fds[0].events = POLLOUT | POLLPRI; 18905 fds[0].revents = 0; 18906 res = poll(fds, 1, -1); 18907 if (!res) { 18908 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 18909 continue; 18910 } 18911 /* if got exception */ 18912 if (fds[0].revents & POLLPRI) { 18913 ast_free(mybuf); 18914 return -1; 18915 } 18916 if (!(fds[0].revents & POLLOUT)) { 18917 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 18918 continue; 18919 } 18920 res = write(fd, buf, size); 18921 if (res != size) { 18922 if (res == -1) { 18923 ast_free(mybuf); 18924 return -1; 18925 } 18926 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 18927 break; 18928 } 18929 len -= size; 18930 buf += size; 18931 } 18932 ast_free(mybuf); 18933 return(0); 18934 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15985 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.
15986 { 15987 int channel; 15988 int on; 15989 struct dahdi_pvt *dahdi_chan = NULL; 15990 15991 switch (cmd) { 15992 case CLI_INIT: 15993 e->command = "dahdi set dnd"; 15994 e->usage = 15995 "Usage: dahdi set dnd <chan#> <on|off>\n" 15996 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15997 " Changes take effect immediately.\n" 15998 " <chan num> is the channel number\n" 15999 " <on|off> Enable or disable DND mode?\n" 16000 ; 16001 return NULL; 16002 case CLI_GENERATE: 16003 return NULL; 16004 } 16005 16006 if (a->argc != 5) 16007 return CLI_SHOWUSAGE; 16008 16009 if ((channel = atoi(a->argv[3])) <= 0) { 16010 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 16011 return CLI_SHOWUSAGE; 16012 } 16013 16014 if (ast_true(a->argv[4])) 16015 on = 1; 16016 else if (ast_false(a->argv[4])) 16017 on = 0; 16018 else { 16019 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 16020 return CLI_SHOWUSAGE; 16021 } 16022 16023 ast_mutex_lock(&iflock); 16024 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 16025 if (dahdi_chan->channel != channel) 16026 continue; 16027 16028 /* Found the channel. Actually set it */ 16029 dahdi_dnd(dahdi_chan, on); 16030 break; 16031 } 16032 ast_mutex_unlock(&iflock); 16033 16034 if (!dahdi_chan) { 16035 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 16036 return CLI_FAILURE; 16037 } 16038 16039 return CLI_SUCCESS; 16040 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 5191 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().
05192 { 05193 int x, res; 05194 05195 x = hs; 05196 res = ioctl(fd, DAHDI_HOOK, &x); 05197 05198 if (res < 0) { 05199 if (errno == EINPROGRESS) 05200 return 0; 05201 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 05202 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 05203 } 05204 05205 return res; 05206 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15833 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.
15834 { 15835 int channel; 15836 int gain; 15837 int tx; 15838 struct dahdi_hwgain hwgain; 15839 struct dahdi_pvt *tmp = NULL; 15840 15841 switch (cmd) { 15842 case CLI_INIT: 15843 e->command = "dahdi set hwgain {rx|tx}"; 15844 e->usage = 15845 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 15846 " Sets the hardware gain on a given channel. Changes take effect\n" 15847 " immediately whether the channel is in use or not.\n" 15848 "\n" 15849 " <rx|tx> which direction do you want to change (relative to our module)\n" 15850 " <chan num> is the channel number relative to the device\n" 15851 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n" 15852 "\n" 15853 " Please note:\n" 15854 " * This is currently the only way to set hwgain by the channel driver.\n" 15855 " * hwgain is only supportable by hardware with analog ports because\n" 15856 " hwgain works on the analog side of an analog-digital conversion.\n"; 15857 return NULL; 15858 case CLI_GENERATE: 15859 return NULL; 15860 } 15861 15862 if (a->argc != 6) 15863 return CLI_SHOWUSAGE; 15864 15865 if (!strcasecmp("rx", a->argv[3])) 15866 tx = 0; /* rx */ 15867 else if (!strcasecmp("tx", a->argv[3])) 15868 tx = 1; /* tx */ 15869 else 15870 return CLI_SHOWUSAGE; 15871 15872 channel = atoi(a->argv[4]); 15873 gain = atof(a->argv[5])*10.0; 15874 15875 ast_mutex_lock(&iflock); 15876 15877 for (tmp = iflist; tmp; tmp = tmp->next) { 15878 15879 if (tmp->channel != channel) 15880 continue; 15881 15882 if (tmp->subs[SUB_REAL].dfd == -1) 15883 break; 15884 15885 hwgain.newgain = gain; 15886 hwgain.tx = tx; 15887 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15888 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15889 ast_mutex_unlock(&iflock); 15890 return CLI_FAILURE; 15891 } 15892 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15893 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15894 break; 15895 } 15896 15897 ast_mutex_unlock(&iflock); 15898 15899 if (tmp) 15900 return CLI_SUCCESS; 15901 15902 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15903 return CLI_FAILURE; 15904 15905 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15907 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.
15908 { 15909 int channel; 15910 float gain; 15911 int tx; 15912 int res; 15913 struct dahdi_pvt *tmp = NULL; 15914 15915 switch (cmd) { 15916 case CLI_INIT: 15917 e->command = "dahdi set swgain {rx|tx}"; 15918 e->usage = 15919 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15920 " Sets the software gain on a given channel and overrides the\n" 15921 " value provided at module loadtime. Changes take effect\n" 15922 " immediately whether the channel is in use or not.\n" 15923 "\n" 15924 " <rx|tx> which direction do you want to change (relative to our module)\n" 15925 " <chan num> is the channel number relative to the device\n" 15926 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15927 return NULL; 15928 case CLI_GENERATE: 15929 return NULL; 15930 } 15931 15932 if (a->argc != 6) 15933 return CLI_SHOWUSAGE; 15934 15935 if (!strcasecmp("rx", a->argv[3])) 15936 tx = 0; /* rx */ 15937 else if (!strcasecmp("tx", a->argv[3])) 15938 tx = 1; /* tx */ 15939 else 15940 return CLI_SHOWUSAGE; 15941 15942 channel = atoi(a->argv[4]); 15943 gain = atof(a->argv[5]); 15944 15945 ast_mutex_lock(&iflock); 15946 for (tmp = iflist; tmp; tmp = tmp->next) { 15947 15948 if (tmp->channel != channel) 15949 continue; 15950 15951 if (tmp->subs[SUB_REAL].dfd == -1) 15952 break; 15953 15954 if (tx) 15955 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law); 15956 else 15957 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law); 15958 15959 if (res) { 15960 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15961 ast_mutex_unlock(&iflock); 15962 return CLI_FAILURE; 15963 } 15964 15965 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15966 tx ? "tx" : "rx", gain, channel); 15967 15968 if (tx) { 15969 tmp->txgain = gain; 15970 } else { 15971 tmp->rxgain = gain; 15972 } 15973 break; 15974 } 15975 ast_mutex_unlock(&iflock); 15976 15977 if (tmp) 15978 return CLI_SUCCESS; 15979 15980 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15981 return CLI_FAILURE; 15982 15983 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 4444 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 6749 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.
06750 { 06751 char *cp; 06752 signed char *scp; 06753 int x; 06754 int idx; 06755 struct dahdi_pvt *p = chan->tech_pvt, *pp; 06756 struct oprmode *oprmode; 06757 06758 06759 /* all supported options require data */ 06760 if (!p || !data || (datalen < 1)) { 06761 errno = EINVAL; 06762 return -1; 06763 } 06764 06765 switch (option) { 06766 case AST_OPTION_TXGAIN: 06767 scp = (signed char *) data; 06768 idx = dahdi_get_index(chan, p, 0); 06769 if (idx < 0) { 06770 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 06771 return -1; 06772 } 06773 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 06774 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law); 06775 case AST_OPTION_RXGAIN: 06776 scp = (signed char *) data; 06777 idx = dahdi_get_index(chan, p, 0); 06778 if (idx < 0) { 06779 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 06780 return -1; 06781 } 06782 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 06783 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law); 06784 case AST_OPTION_TONE_VERIFY: 06785 if (!p->dsp) 06786 break; 06787 cp = (char *) data; 06788 switch (*cp) { 06789 case 1: 06790 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 06791 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 06792 break; 06793 case 2: 06794 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 06795 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 06796 break; 06797 default: 06798 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 06799 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 06800 break; 06801 } 06802 break; 06803 case AST_OPTION_TDD: 06804 /* turn on or off TDD */ 06805 cp = (char *) data; 06806 p->mate = 0; 06807 if (!*cp) { /* turn it off */ 06808 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 06809 if (p->tdd) 06810 tdd_free(p->tdd); 06811 p->tdd = 0; 06812 break; 06813 } 06814 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 06815 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 06816 dahdi_disable_ec(p); 06817 /* otherwise, turn it on */ 06818 if (!p->didtdd) { /* if havent done it yet */ 06819 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 06820 unsigned char *buf; 06821 int size, res, fd, len; 06822 struct pollfd fds[1]; 06823 06824 buf = mybuf; 06825 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 06826 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 06827 len = 40000; 06828 idx = dahdi_get_index(chan, p, 0); 06829 if (idx < 0) { 06830 ast_log(LOG_WARNING, "No index in TDD?\n"); 06831 return -1; 06832 } 06833 fd = p->subs[idx].dfd; 06834 while (len) { 06835 if (ast_check_hangup(chan)) 06836 return -1; 06837 size = len; 06838 if (size > READ_SIZE) 06839 size = READ_SIZE; 06840 fds[0].fd = fd; 06841 fds[0].events = POLLPRI | POLLOUT; 06842 fds[0].revents = 0; 06843 res = poll(fds, 1, -1); 06844 if (!res) { 06845 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 06846 continue; 06847 } 06848 /* if got exception */ 06849 if (fds[0].revents & POLLPRI) 06850 return -1; 06851 if (!(fds[0].revents & POLLOUT)) { 06852 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 06853 continue; 06854 } 06855 res = write(fd, buf, size); 06856 if (res != size) { 06857 if (res == -1) return -1; 06858 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06859 break; 06860 } 06861 len -= size; 06862 buf += size; 06863 } 06864 p->didtdd = 1; /* set to have done it now */ 06865 } 06866 if (*cp == 2) { /* Mate mode */ 06867 if (p->tdd) 06868 tdd_free(p->tdd); 06869 p->tdd = 0; 06870 p->mate = 1; 06871 break; 06872 } 06873 if (!p->tdd) { /* if we don't have one yet */ 06874 p->tdd = tdd_new(); /* allocate one */ 06875 } 06876 break; 06877 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 06878 if (!p->dsp) 06879 break; 06880 cp = (char *) data; 06881 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 06882 *cp ? "ON" : "OFF", (int) *cp, chan->name); 06883 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 06884 break; 06885 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 06886 #if defined(HAVE_PRI) 06887 if (dahdi_sig_pri_lib_handles(p->sig) 06888 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 06889 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 06890 break; 06891 } 06892 #endif /* defined(HAVE_PRI) */ 06893 06894 cp = (char *) data; 06895 if (!*cp) { 06896 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 06897 x = 0; 06898 dahdi_disable_ec(p); 06899 } else { 06900 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 06901 x = 1; 06902 } 06903 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 06904 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 06905 break; 06906 case AST_OPTION_OPRMODE: /* Operator services mode */ 06907 oprmode = (struct oprmode *) data; 06908 /* We don't support operator mode across technologies */ 06909 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 06910 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 06911 chan->tech->type, oprmode->peer->tech->type); 06912 errno = EINVAL; 06913 return -1; 06914 } 06915 pp = oprmode->peer->tech_pvt; 06916 p->oprmode = pp->oprmode = 0; 06917 /* setup peers */ 06918 p->oprpeer = pp; 06919 pp->oprpeer = p; 06920 /* setup modes, if any */ 06921 if (oprmode->mode) 06922 { 06923 pp->oprmode = oprmode->mode; 06924 p->oprmode = -oprmode->mode; 06925 } 06926 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 06927 oprmode->mode, chan->name,oprmode->peer->name); 06928 break; 06929 case AST_OPTION_ECHOCAN: 06930 cp = (char *) data; 06931 if (*cp) { 06932 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name); 06933 dahdi_enable_ec(p); 06934 } else { 06935 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name); 06936 dahdi_disable_ec(p); 06937 } 06938 break; 06939 case AST_OPTION_DIGIT_DETECT: 06940 cp = (char *) data; 06941 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); 06942 if (*cp) { 06943 enable_dtmf_detect(p); 06944 } else { 06945 disable_dtmf_detect(p); 06946 } 06947 break; 06948 case AST_OPTION_FAX_DETECT: 06949 cp = (char *) data; 06950 if (p->dsp) { 06951 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name); 06952 if (*cp) { 06953 p->dsp_features |= DSP_FEATURE_FAX_DETECT; 06954 } else { 06955 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06956 } 06957 ast_dsp_set_features(p->dsp, p->dsp_features); 06958 } 06959 break; 06960 default: 06961 return -1; 06962 } 06963 errno = 0; 06964 06965 return 0; 06966 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15476 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, ast_strlen_zero(), dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, sig_pri_chan::call, dahdi_pvt::callprogress, 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, ISTRUNK, 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.
15477 { 15478 int channel; 15479 struct dahdi_pvt *tmp = NULL; 15480 struct dahdi_confinfo ci; 15481 struct dahdi_params ps; 15482 int x; 15483 15484 switch (cmd) { 15485 case CLI_INIT: 15486 e->command = "dahdi show channel"; 15487 e->usage = 15488 "Usage: dahdi show channel <chan num>\n" 15489 " Detailed information about a given channel\n"; 15490 return NULL; 15491 case CLI_GENERATE: 15492 return NULL; 15493 } 15494 15495 if (a->argc != 4) 15496 return CLI_SHOWUSAGE; 15497 15498 channel = atoi(a->argv[3]); 15499 15500 ast_mutex_lock(&iflock); 15501 for (tmp = iflist; tmp; tmp = tmp->next) { 15502 if (tmp->channel == channel) { 15503 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 15504 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 15505 ast_cli(a->fd, "Span: %d\n", tmp->span); 15506 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 15507 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 15508 ast_cli(a->fd, "Context: %s\n", tmp->context); 15509 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 15510 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 15511 #if defined(HAVE_PRI) 15512 #if defined(HAVE_PRI_SUBADDR) 15513 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr); 15514 #endif /* defined(HAVE_PRI_SUBADDR) */ 15515 #endif /* defined(HAVE_PRI) */ 15516 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 15517 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 15518 if (tmp->vars) { 15519 struct ast_variable *v; 15520 ast_cli(a->fd, "Variables:\n"); 15521 for (v = tmp->vars ; v ; v = v->next) 15522 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 15523 } 15524 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 15525 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 15526 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 15527 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 15528 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 15529 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)" : ""); 15530 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)" : ""); 15531 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)" : ""); 15532 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 15533 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 15534 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 15535 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 15536 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 15537 if (tmp->busydetect) { 15538 #if defined(BUSYDETECT_TONEONLY) 15539 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 15540 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 15541 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 15542 #endif 15543 #ifdef BUSYDETECT_DEBUG 15544 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 15545 #endif 15546 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 15547 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 15548 } 15549 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 15550 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 15551 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 15552 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 15553 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 15554 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 15555 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain); 15556 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc); 15557 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no"); 15558 ast_cli(a->fd, "Echo Cancellation:\n"); 15559 15560 if (tmp->echocancel.head.tap_length) { 15561 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length); 15562 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 15563 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 15564 } 15565 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 15566 } else { 15567 ast_cli(a->fd, "\tnone\n"); 15568 } 15569 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 15570 if (tmp->master) 15571 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 15572 for (x = 0; x < MAX_SLAVES; x++) { 15573 if (tmp->slaves[x]) 15574 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 15575 } 15576 #ifdef HAVE_OPENR2 15577 if (tmp->mfcr2) { 15578 char calldir[OR2_MAX_PATH]; 15579 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 15580 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 15581 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 15582 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 15583 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 15584 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 15585 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 15586 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 15587 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 15588 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 15589 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 15590 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 15591 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 15592 #endif 15593 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 15594 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 15595 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 15596 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 15597 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 15598 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 15599 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 15600 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 15601 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 15602 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 15603 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 15604 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 15605 } 15606 #endif 15607 #if defined(HAVE_SS7) 15608 if (tmp->ss7) { 15609 struct sig_ss7_chan *chan = tmp->sig_pvt; 15610 15611 ast_cli(a->fd, "CIC: %d\n", chan->cic); 15612 } 15613 #endif /* defined(HAVE_SS7) */ 15614 #ifdef HAVE_PRI 15615 if (tmp->pri) { 15616 struct sig_pri_chan *chan = tmp->sig_pvt; 15617 15618 ast_cli(a->fd, "PRI Flags: "); 15619 if (chan->resetting != SIG_PRI_RESET_IDLE) { 15620 ast_cli(a->fd, "Resetting=%u ", chan->resetting); 15621 } 15622 if (chan->call) 15623 ast_cli(a->fd, "Call "); 15624 if (chan->allocated) { 15625 ast_cli(a->fd, "Allocated "); 15626 } 15627 ast_cli(a->fd, "\n"); 15628 if (tmp->logicalspan) 15629 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 15630 else 15631 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 15632 } 15633 #endif 15634 memset(&ci, 0, sizeof(ci)); 15635 ps.channo = tmp->channel; 15636 if (tmp->subs[SUB_REAL].dfd > -1) { 15637 memset(&ci, 0, sizeof(ci)); 15638 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 15639 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode); 15640 } 15641 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 15642 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 15643 } 15644 memset(&ps, 0, sizeof(ps)); 15645 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 15646 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 15647 } else { 15648 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 15649 } 15650 } 15651 if (ISTRUNK(tmp)) { 15652 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 15653 if (!ast_strlen_zero(progzone)) 15654 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 15655 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 15656 if(tmp->busydetect) { 15657 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 15658 if(tmp->busytonelength > 0) { 15659 ast_cli(a->fd, "Busy Pattern:\n"); 15660 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 15661 if (tmp->busyquietlength > 0) 15662 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 15663 else 15664 ast_cli(a->fd, " -- Detect Tone Only\n"); 15665 if(tmp->busyfuzziness > 0) 15666 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 15667 } 15668 } 15669 } 15670 ast_mutex_unlock(&iflock); 15671 return CLI_SUCCESS; 15672 } 15673 } 15674 ast_mutex_unlock(&iflock); 15675 15676 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15677 return CLI_FAILURE; 15678 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15389 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.
15390 { 15391 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15392 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15393 ast_group_t targetnum = 0; 15394 int filtertype = 0; 15395 struct dahdi_pvt *tmp = NULL; 15396 char tmps[20] = ""; 15397 char statestr[20] = ""; 15398 char blockstr[20] = ""; 15399 15400 switch (cmd) { 15401 case CLI_INIT: 15402 e->command = "dahdi show channels [group|context]"; 15403 e->usage = 15404 "Usage: dahdi show channels [ group <group> | context <context> ]\n" 15405 " Shows a list of available channels with optional filtering\n" 15406 " <group> must be a number between 0 and 63\n"; 15407 return NULL; 15408 case CLI_GENERATE: 15409 return NULL; 15410 } 15411 15412 /* syntax: dahdi show channels [ group <group> | context <context> ] */ 15413 15414 if (!((a->argc == 3) || (a->argc == 5))) 15415 return CLI_SHOWUSAGE; 15416 15417 if (a->argc == 5) { 15418 if (!strcasecmp(a->argv[3], "group")) { 15419 targetnum = atoi(a->argv[4]); 15420 if (63 < targetnum) { 15421 return CLI_SHOWUSAGE; 15422 } 15423 targetnum = ((ast_group_t) 1) << targetnum; 15424 filtertype = 1; 15425 } else if (!strcasecmp(a->argv[3], "context")) { 15426 filtertype = 2; 15427 } 15428 } 15429 15430 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 15431 ast_mutex_lock(&iflock); 15432 for (tmp = iflist; tmp; tmp = tmp->next) { 15433 if (filtertype) { 15434 switch(filtertype) { 15435 case 1: /* dahdi show channels group <group> */ 15436 if (!(tmp->group & targetnum)) { 15437 continue; 15438 } 15439 break; 15440 case 2: /* dahdi show channels context <context> */ 15441 if (strcasecmp(tmp->context, a->argv[4])) { 15442 continue; 15443 } 15444 break; 15445 default: 15446 break; 15447 } 15448 } 15449 if (tmp->channel > 0) { 15450 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 15451 } else 15452 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 15453 15454 if (tmp->locallyblocked) 15455 blockstr[0] = 'L'; 15456 else 15457 blockstr[0] = ' '; 15458 15459 if (tmp->remotelyblocked) 15460 blockstr[1] = 'R'; 15461 else 15462 blockstr[1] = ' '; 15463 15464 blockstr[2] = '\0'; 15465 15466 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 15467 15468 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 15469 } 15470 ast_mutex_unlock(&iflock); 15471 return CLI_SUCCESS; 15472 #undef FORMAT 15473 #undef FORMAT2 15474 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15717 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.
15718 { 15719 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 15720 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 15721 int span; 15722 int res; 15723 char alarmstr[50]; 15724 15725 int ctl; 15726 struct dahdi_spaninfo s; 15727 15728 switch (cmd) { 15729 case CLI_INIT: 15730 e->command = "dahdi show status"; 15731 e->usage = 15732 "Usage: dahdi show status\n" 15733 " Shows a list of DAHDI cards with status\n"; 15734 return NULL; 15735 case CLI_GENERATE: 15736 return NULL; 15737 } 15738 ctl = open("/dev/dahdi/ctl", O_RDWR); 15739 if (ctl < 0) { 15740 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 15741 return CLI_FAILURE; 15742 } 15743 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO"); 15744 15745 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 15746 s.spanno = span; 15747 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 15748 if (res) { 15749 continue; 15750 } 15751 alarmstr[0] = '\0'; 15752 if (s.alarms > 0) { 15753 if (s.alarms & DAHDI_ALARM_BLUE) 15754 strcat(alarmstr, "BLU/"); 15755 if (s.alarms & DAHDI_ALARM_YELLOW) 15756 strcat(alarmstr, "YEL/"); 15757 if (s.alarms & DAHDI_ALARM_RED) 15758 strcat(alarmstr, "RED/"); 15759 if (s.alarms & DAHDI_ALARM_LOOPBACK) 15760 strcat(alarmstr, "LB/"); 15761 if (s.alarms & DAHDI_ALARM_RECOVER) 15762 strcat(alarmstr, "REC/"); 15763 if (s.alarms & DAHDI_ALARM_NOTOPEN) 15764 strcat(alarmstr, "NOP/"); 15765 if (!strlen(alarmstr)) 15766 strcat(alarmstr, "UUU/"); 15767 if (strlen(alarmstr)) { 15768 /* Strip trailing / */ 15769 alarmstr[strlen(alarmstr) - 1] = '\0'; 15770 } 15771 } else { 15772 if (s.numchans) 15773 strcpy(alarmstr, "OK"); 15774 else 15775 strcpy(alarmstr, "UNCONFIGURED"); 15776 } 15777 15778 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 15779 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 15780 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 15781 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 15782 "CAS", 15783 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 15784 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 15785 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 15786 "Unk", 15787 s.lineconfig & DAHDI_CONFIG_CRC4 ? 15788 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 15789 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "", 15790 lbostr[s.lbo] 15791 ); 15792 } 15793 close(ctl); 15794 15795 return CLI_SUCCESS; 15796 #undef FORMAT 15797 #undef FORMAT2 15798 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15800 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.
15801 { 15802 int pseudo_fd = -1; 15803 struct dahdi_versioninfo vi; 15804 15805 switch (cmd) { 15806 case CLI_INIT: 15807 e->command = "dahdi show version"; 15808 e->usage = 15809 "Usage: dahdi show version\n" 15810 " Shows the DAHDI version in use\n"; 15811 return NULL; 15812 case CLI_GENERATE: 15813 return NULL; 15814 } 15815 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 15816 ast_cli(a->fd, "Failed to open control file to get version.\n"); 15817 return CLI_SUCCESS; 15818 } 15819 15820 strcpy(vi.version, "Unknown"); 15821 strcpy(vi.echo_canceller, "Unknown"); 15822 15823 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 15824 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 15825 else 15826 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 15827 15828 close(pseudo_fd); 15829 15830 return CLI_SUCCESS; 15831 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 4668 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().
04669 { 04670 static char buf[256]; 04671 switch (sig) { 04672 case SIG_EM: 04673 return "E & M Immediate"; 04674 case SIG_EMWINK: 04675 return "E & M Wink"; 04676 case SIG_EM_E1: 04677 return "E & M E1"; 04678 case SIG_FEATD: 04679 return "Feature Group D (DTMF)"; 04680 case SIG_FEATDMF: 04681 return "Feature Group D (MF)"; 04682 case SIG_FEATDMF_TA: 04683 return "Feature Groud D (MF) Tandem Access"; 04684 case SIG_FEATB: 04685 return "Feature Group B (MF)"; 04686 case SIG_E911: 04687 return "E911 (MF)"; 04688 case SIG_FGC_CAMA: 04689 return "FGC/CAMA (Dialpulse)"; 04690 case SIG_FGC_CAMAMF: 04691 return "FGC/CAMA (MF)"; 04692 case SIG_FXSLS: 04693 return "FXS Loopstart"; 04694 case SIG_FXSGS: 04695 return "FXS Groundstart"; 04696 case SIG_FXSKS: 04697 return "FXS Kewlstart"; 04698 case SIG_FXOLS: 04699 return "FXO Loopstart"; 04700 case SIG_FXOGS: 04701 return "FXO Groundstart"; 04702 case SIG_FXOKS: 04703 return "FXO Kewlstart"; 04704 case SIG_PRI: 04705 return "ISDN PRI"; 04706 case SIG_BRI: 04707 return "ISDN BRI Point to Point"; 04708 case SIG_BRI_PTMP: 04709 return "ISDN BRI Point to MultiPoint"; 04710 case SIG_SS7: 04711 return "SS7"; 04712 case SIG_MFCR2: 04713 return "MFC/R2"; 04714 case SIG_SF: 04715 return "SF (Tone) Immediate"; 04716 case SIG_SFWINK: 04717 return "SF (Tone) Wink"; 04718 case SIG_SF_FEATD: 04719 return "SF (Tone) with Feature Group D (DTMF)"; 04720 case SIG_SF_FEATDMF: 04721 return "SF (Tone) with Feature Group D (MF)"; 04722 case SIG_SF_FEATB: 04723 return "SF (Tone) with Feature Group B (MF)"; 04724 case 0: 04725 return "Pseudo"; 04726 default: 04727 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 04728 return buf; 04729 } 04730 }
static int dahdi_sig_pri_lib_handles | ( | int | signaling | ) | [inline, static] |
Definition at line 1562 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().
01563 { 01564 int handles; 01565 01566 switch (signaling) { 01567 case SIG_PRI_LIB_HANDLE_CASES: 01568 handles = 1; 01569 break; 01570 default: 01571 handles = 0; 01572 break; 01573 } 01574 01575 return handles; 01576 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 15215 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().
15216 { 15217 struct dahdi_pvt *p; 15218 retry: 15219 ast_mutex_lock(&iflock); 15220 for (p = iflist; p; p = p->next) { 15221 ast_mutex_lock(&p->lock); 15222 if (p->owner && !p->restartpending) { 15223 if (ast_channel_trylock(p->owner)) { 15224 if (option_debug > 2) 15225 ast_verbose("Avoiding deadlock\n"); 15226 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 15227 ast_mutex_unlock(&p->lock); 15228 ast_mutex_unlock(&iflock); 15229 goto retry; 15230 } 15231 if (option_debug > 2) 15232 ast_verbose("Softhanging up on %s\n", p->owner->name); 15233 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 15234 p->restartpending = 1; 15235 num_restart_pending++; 15236 ast_channel_unlock(p->owner); 15237 } 15238 ast_mutex_unlock(&p->lock); 15239 } 15240 ast_mutex_unlock(&iflock); 15241 }
static int dahdi_status_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18606 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.
18608 { 18609 int ctl, res, span; 18610 struct ast_data *data_span, *data_alarms; 18611 struct dahdi_spaninfo s; 18612 18613 ctl = open("/dev/dahdi/ctl", O_RDWR); 18614 if (ctl < 0) { 18615 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 18616 return -1; 18617 } 18618 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 18619 s.spanno = span; 18620 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 18621 if (res) { 18622 continue; 18623 } 18624 18625 data_span = ast_data_add_node(data_root, "span"); 18626 if (!data_span) { 18627 continue; 18628 } 18629 ast_data_add_str(data_span, "description", s.desc); 18630 18631 /* insert the alarms status */ 18632 data_alarms = ast_data_add_node(data_span, "alarms"); 18633 if (!data_alarms) { 18634 continue; 18635 } 18636 18637 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE); 18638 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW); 18639 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED); 18640 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK); 18641 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER); 18642 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN); 18643 18644 ast_data_add_int(data_span, "irqmisses", s.irqmisses); 18645 ast_data_add_int(data_span, "bpviol", s.bpvcount); 18646 ast_data_add_int(data_span, "crc4", s.crc4count); 18647 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 18648 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 18649 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 18650 "CAS"); 18651 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 18652 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 18653 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 18654 "Unknown"); 18655 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ? 18656 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 18657 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : ""); 18658 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]); 18659 18660 /* if this span doesn't match remove it. */ 18661 if (!ast_data_search_match(search, data_span)) { 18662 ast_data_remove_node(data_root, data_span); 18663 } 18664 } 18665 close(ctl); 18666 18667 return 0; 18668 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4971 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().
04972 { 04973 int x; 04974 int res; 04975 04976 if (p && p->echocanon && p->echotraining) { 04977 x = p->echotraining; 04978 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 04979 if (res) 04980 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 04981 else 04982 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 04983 } else { 04984 ast_debug(1, "No echo training requested\n"); 04985 } 04986 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 7181 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().
07182 { 07183 /* Unlink a specific slave or all slaves/masters from a given master */ 07184 int x; 07185 int hasslaves; 07186 if (!master) 07187 return; 07188 if (needlock) { 07189 ast_mutex_lock(&master->lock); 07190 if (slave) { 07191 while (ast_mutex_trylock(&slave->lock)) { 07192 DEADLOCK_AVOIDANCE(&master->lock); 07193 } 07194 } 07195 } 07196 hasslaves = 0; 07197 for (x = 0; x < MAX_SLAVES; x++) { 07198 if (master->slaves[x]) { 07199 if (!slave || (master->slaves[x] == slave)) { 07200 /* Take slave out of the conference */ 07201 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 07202 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 07203 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 07204 master->slaves[x]->master = NULL; 07205 master->slaves[x] = NULL; 07206 } else 07207 hasslaves = 1; 07208 } 07209 if (!hasslaves) 07210 master->inconference = 0; 07211 } 07212 if (!slave) { 07213 if (master->master) { 07214 /* Take master out of the conference */ 07215 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 07216 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 07217 hasslaves = 0; 07218 for (x = 0; x < MAX_SLAVES; x++) { 07219 if (master->master->slaves[x] == master) 07220 master->master->slaves[x] = NULL; 07221 else if (master->master->slaves[x]) 07222 hasslaves = 1; 07223 } 07224 if (!hasslaves) 07225 master->master->inconference = 0; 07226 } 07227 master->master = NULL; 07228 } 07229 update_conf(master); 07230 if (needlock) { 07231 if (slave) 07232 ast_mutex_unlock(&slave->lock); 07233 ast_mutex_unlock(&master->lock); 07234 } 07235 }
static int dahdi_version_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18709 of file chan_dahdi.c.
References ast_data_add_str(), ast_log(), errno, and LOG_ERROR.
18711 { 18712 int pseudo_fd = -1; 18713 struct dahdi_versioninfo vi = { 18714 .version = "Unknown", 18715 .echo_canceller = "Unknown" 18716 }; 18717 18718 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 18719 ast_log(LOG_ERROR, "Failed to open control file to get version.\n"); 18720 return -1; 18721 } 18722 18723 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) { 18724 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno)); 18725 } 18726 18727 close(pseudo_fd); 18728 18729 ast_data_add_str(data_root, "value", vi.version); 18730 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller); 18731 18732 return 0; 18733 }
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 9893 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), and my_wink().
09894 { 09895 int j; 09896 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 09897 for (;;) 09898 { 09899 /* set bits of interest */ 09900 j = DAHDI_IOMUX_SIGEVENT; 09901 /* wait for some happening */ 09902 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 09903 /* exit loop if we have it */ 09904 if (j & DAHDI_IOMUX_SIGEVENT) break; 09905 } 09906 /* get the event info */ 09907 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 09908 return 0; 09909 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 9414 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.
09415 { 09416 struct dahdi_pvt *p = ast->tech_pvt; 09417 int res; 09418 int idx; 09419 idx = dahdi_get_index(ast, p, 0); 09420 if (idx < 0) { 09421 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 09422 return -1; 09423 } 09424 09425 /* Write a frame of (presumably voice) data */ 09426 if (frame->frametype != AST_FRAME_VOICE) { 09427 if (frame->frametype != AST_FRAME_IMAGE) 09428 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype); 09429 return 0; 09430 } 09431 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && 09432 (frame->subclass.codec != AST_FORMAT_ULAW) && 09433 (frame->subclass.codec != AST_FORMAT_ALAW)) { 09434 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 09435 return -1; 09436 } 09437 if (p->dialing) { 09438 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 09439 return 0; 09440 } 09441 if (!p->owner) { 09442 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 09443 return 0; 09444 } 09445 if (p->cidspill) { 09446 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n", 09447 ast->name); 09448 return 0; 09449 } 09450 /* Return if it's not valid data */ 09451 if (!frame->data.ptr || !frame->datalen) 09452 return 0; 09453 09454 if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 09455 if (!p->subs[idx].linear) { 09456 p->subs[idx].linear = 1; 09457 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09458 if (res) 09459 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 09460 } 09461 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 09462 } else { 09463 /* x-law already */ 09464 if (p->subs[idx].linear) { 09465 p->subs[idx].linear = 0; 09466 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09467 if (res) 09468 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 09469 } 09470 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 09471 } 09472 if (res < 0) { 09473 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 09474 return -1; 09475 } 09476 return 0; 09477 }
static enum analog_event dahdievent_to_analogevent | ( | int | event | ) | [static] |
Definition at line 2796 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().
02797 { 02798 enum analog_event res; 02799 02800 switch (event) { 02801 case DAHDI_EVENT_ONHOOK: 02802 res = ANALOG_EVENT_ONHOOK; 02803 break; 02804 case DAHDI_EVENT_RINGOFFHOOK: 02805 res = ANALOG_EVENT_RINGOFFHOOK; 02806 break; 02807 case DAHDI_EVENT_WINKFLASH: 02808 res = ANALOG_EVENT_WINKFLASH; 02809 break; 02810 case DAHDI_EVENT_ALARM: 02811 res = ANALOG_EVENT_ALARM; 02812 break; 02813 case DAHDI_EVENT_NOALARM: 02814 res = ANALOG_EVENT_NOALARM; 02815 break; 02816 case DAHDI_EVENT_DIALCOMPLETE: 02817 res = ANALOG_EVENT_DIALCOMPLETE; 02818 break; 02819 case DAHDI_EVENT_RINGERON: 02820 res = ANALOG_EVENT_RINGERON; 02821 break; 02822 case DAHDI_EVENT_RINGEROFF: 02823 res = ANALOG_EVENT_RINGEROFF; 02824 break; 02825 case DAHDI_EVENT_HOOKCOMPLETE: 02826 res = ANALOG_EVENT_HOOKCOMPLETE; 02827 break; 02828 case DAHDI_EVENT_PULSE_START: 02829 res = ANALOG_EVENT_PULSE_START; 02830 break; 02831 case DAHDI_EVENT_POLARITY: 02832 res = ANALOG_EVENT_POLARITY; 02833 break; 02834 case DAHDI_EVENT_RINGBEGIN: 02835 res = ANALOG_EVENT_RINGBEGIN; 02836 break; 02837 case DAHDI_EVENT_EC_DISABLED: 02838 res = ANALOG_EVENT_EC_DISABLED; 02839 break; 02840 case DAHDI_EVENT_REMOVED: 02841 res = ANALOG_EVENT_REMOVED; 02842 break; 02843 case DAHDI_EVENT_NEONMWI_ACTIVE: 02844 res = ANALOG_EVENT_NEONMWI_ACTIVE; 02845 break; 02846 case DAHDI_EVENT_NEONMWI_INACTIVE: 02847 res = ANALOG_EVENT_NEONMWI_INACTIVE; 02848 break; 02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 02850 case DAHDI_EVENT_TX_CED_DETECTED: 02851 res = ANALOG_EVENT_TX_CED_DETECTED; 02852 break; 02853 case DAHDI_EVENT_RX_CED_DETECTED: 02854 res = ANALOG_EVENT_RX_CED_DETECTED; 02855 break; 02856 case DAHDI_EVENT_EC_NLP_DISABLED: 02857 res = ANALOG_EVENT_EC_NLP_DISABLED; 02858 break; 02859 case DAHDI_EVENT_EC_NLP_ENABLED: 02860 res = ANALOG_EVENT_EC_NLP_ENABLED; 02861 break; 02862 #endif 02863 case DAHDI_EVENT_PULSEDIGIT: 02864 res = ANALOG_EVENT_PULSEDIGIT; 02865 break; 02866 case DAHDI_EVENT_DTMFDOWN: 02867 res = ANALOG_EVENT_DTMFDOWN; 02868 break; 02869 case DAHDI_EVENT_DTMFUP: 02870 res = ANALOG_EVENT_DTMFUP; 02871 break; 02872 default: 02873 switch(event & 0xFFFF0000) { 02874 case DAHDI_EVENT_PULSEDIGIT: 02875 case DAHDI_EVENT_DTMFDOWN: 02876 case DAHDI_EVENT_DTMFUP: 02877 /* The event includes a digit number in the low word. 02878 * Converting it to a 'enum analog_event' would remove 02879 * that information. Thus it is returned as-is. 02880 */ 02881 return event; 02882 } 02883 02884 res = ANALOG_EVENT_ERROR; 02885 break; 02886 } 02887 02888 return res; 02889 }
static enum analog_sigtype dahdisig_to_analogsig | ( | int | sig | ) | [static] |
Definition at line 1619 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().
01620 { 01621 switch (sig) { 01622 case SIG_FXOLS: 01623 return ANALOG_SIG_FXOLS; 01624 case SIG_FXOGS: 01625 return ANALOG_SIG_FXOGS; 01626 case SIG_FXOKS: 01627 return ANALOG_SIG_FXOKS; 01628 case SIG_FXSLS: 01629 return ANALOG_SIG_FXSLS; 01630 case SIG_FXSGS: 01631 return ANALOG_SIG_FXSGS; 01632 case SIG_FXSKS: 01633 return ANALOG_SIG_FXSKS; 01634 case SIG_EMWINK: 01635 return ANALOG_SIG_EMWINK; 01636 case SIG_EM: 01637 return ANALOG_SIG_EM; 01638 case SIG_EM_E1: 01639 return ANALOG_SIG_EM_E1; 01640 case SIG_FEATD: 01641 return ANALOG_SIG_FEATD; 01642 case SIG_FEATDMF: 01643 return ANALOG_SIG_FEATDMF; 01644 case SIG_E911: 01645 return SIG_E911; 01646 case SIG_FGC_CAMA: 01647 return ANALOG_SIG_FGC_CAMA; 01648 case SIG_FGC_CAMAMF: 01649 return ANALOG_SIG_FGC_CAMAMF; 01650 case SIG_FEATB: 01651 return ANALOG_SIG_FEATB; 01652 case SIG_SFWINK: 01653 return ANALOG_SIG_SFWINK; 01654 case SIG_SF: 01655 return ANALOG_SIG_SF; 01656 case SIG_SF_FEATD: 01657 return ANALOG_SIG_SF_FEATD; 01658 case SIG_SF_FEATDMF: 01659 return ANALOG_SIG_SF_FEATDMF; 01660 case SIG_FEATDMF_TA: 01661 return ANALOG_SIG_FEATDMF_TA; 01662 case SIG_SF_FEATB: 01663 return ANALOG_SIG_FEATB; 01664 default: 01665 return -1; 01666 } 01667 }
static void deep_copy_dahdi_chan_conf | ( | struct dahdi_chan_conf * | dest, | |
const struct dahdi_chan_conf * | src | |||
) | [static] |
Definition at line 18271 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().
18272 { 18273 struct ast_cc_config_params *cc_params; 18274 18275 cc_params = dest->chan.cc_params; 18276 *dest = *src; 18277 dest->chan.cc_params = cc_params; 18278 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params); 18279 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 5866 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().
05867 { 05868 int chan; 05869 #if defined(HAVE_PRI) 05870 unsigned span; 05871 struct sig_pri_span *pri; 05872 #endif /* defined(HAVE_PRI) */ 05873 struct dahdi_pvt *p; 05874 05875 while (num_restart_pending) { 05876 usleep(1); 05877 } 05878 05879 ast_mutex_lock(&iflock); 05880 /* Destroy all the interfaces and free their memory */ 05881 while (iflist) { 05882 p = iflist; 05883 05884 chan = p->channel; 05885 #if defined(HAVE_PRI_SERVICE_MESSAGES) 05886 { 05887 char db_chan_name[20]; 05888 char db_answer[5]; 05889 char state; 05890 int why = -1; 05891 05892 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan); 05893 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 05894 sscanf(db_answer, "%1c:%30d", &state, &why); 05895 } 05896 if (!why) { 05897 /* SRVST persistence is not required */ 05898 ast_db_del(db_chan_name, SRVST_DBKEY); 05899 } 05900 } 05901 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 05902 /* Free associated memory */ 05903 destroy_dahdi_pvt(p); 05904 ast_verb(3, "Unregistered channel %d\n", chan); 05905 } 05906 ifcount = 0; 05907 ast_mutex_unlock(&iflock); 05908 05909 #if defined(HAVE_PRI) 05910 /* Destroy all of the no B channel interface lists */ 05911 for (span = 0; span < NUM_SPANS; ++span) { 05912 if (!pris[span].dchannels[0]) { 05913 break; 05914 } 05915 pri = &pris[span].pri; 05916 ast_mutex_lock(&pri->lock); 05917 while (pri->no_b_chan_iflist) { 05918 p = pri->no_b_chan_iflist; 05919 05920 /* Free associated memory */ 05921 destroy_dahdi_pvt(p); 05922 } 05923 ast_mutex_unlock(&pri->lock); 05924 } 05925 #endif /* defined(HAVE_PRI) */ 05926 }
static void destroy_channel | ( | struct dahdi_pvt * | cur, | |
int | now | |||
) | [static] |
Definition at line 5848 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().
05849 { 05850 int i; 05851 05852 if (!now) { 05853 /* Do not destroy the channel now if it is owned by someone. */ 05854 if (cur->owner) { 05855 return; 05856 } 05857 for (i = 0; i < 3; i++) { 05858 if (cur->subs[i].owner) { 05859 return; 05860 } 05861 } 05862 } 05863 destroy_dahdi_pvt(cur); 05864 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5778 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().
05779 { 05780 struct dahdi_pvt *p = pvt; 05781 05782 if (p->manages_span_alarms) { 05783 struct dahdi_pvt *next = find_next_iface_in_span(p); 05784 if (next) { 05785 next->manages_span_alarms = 1; 05786 } 05787 } 05788 05789 /* Remove channel from the list */ 05790 #if defined(HAVE_PRI) 05791 dahdi_unlink_pri_pvt(p); 05792 #endif /* defined(HAVE_PRI) */ 05793 #if defined(HAVE_SS7) 05794 dahdi_unlink_ss7_pvt(p); 05795 #endif /* defined(HAVE_SS7) */ 05796 switch (pvt->which_iflist) { 05797 case DAHDI_IFLIST_NONE: 05798 break; 05799 case DAHDI_IFLIST_MAIN: 05800 dahdi_iflist_extract(p); 05801 break; 05802 #if defined(HAVE_PRI) 05803 case DAHDI_IFLIST_NO_B_CHAN: 05804 if (p->pri) { 05805 dahdi_nobch_extract(p->pri, p); 05806 } 05807 break; 05808 #endif /* defined(HAVE_PRI) */ 05809 } 05810 05811 if (p->sig_pvt) { 05812 if (analog_lib_handles(p->sig, 0, 0)) { 05813 analog_delete(p->sig_pvt); 05814 } 05815 switch (p->sig) { 05816 #if defined(HAVE_PRI) 05817 case SIG_PRI_LIB_HANDLE_CASES: 05818 sig_pri_chan_delete(p->sig_pvt); 05819 break; 05820 #endif /* defined(HAVE_PRI) */ 05821 #if defined(HAVE_SS7) 05822 case SIG_SS7: 05823 sig_ss7_chan_delete(p->sig_pvt); 05824 break; 05825 #endif /* defined(HAVE_SS7) */ 05826 default: 05827 break; 05828 } 05829 } 05830 ast_free(p->cidspill); 05831 if (p->use_smdi) 05832 ast_smdi_interface_unref(p->smdi_iface); 05833 if (p->mwi_event_sub) 05834 ast_event_unsubscribe(p->mwi_event_sub); 05835 if (p->vars) { 05836 ast_variables_destroy(p->vars); 05837 } 05838 if (p->cc_params) { 05839 ast_cc_config_params_destroy(p->cc_params); 05840 } 05841 ast_mutex_destroy(&p->lock); 05842 dahdi_close_sub(p, SUB_REAL); 05843 if (p->owner) 05844 p->owner->tech_pvt = NULL; 05845 ast_free(p); 05846 }
static struct dahdi_pvt* determine_starting_point | ( | const char * | data, | |
struct dahdi_starting_point * | param | |||
) | [static, read] |
Definition at line 13560 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().
13561 { 13562 char *dest; 13563 char *s; 13564 int x; 13565 int res = 0; 13566 struct dahdi_pvt *p; 13567 char *subdir = NULL; 13568 AST_DECLARE_APP_ARGS(args, 13569 AST_APP_ARG(group); /* channel/group token */ 13570 //AST_APP_ARG(ext); /* extension token */ 13571 //AST_APP_ARG(opts); /* options token */ 13572 AST_APP_ARG(other); /* Any remining unused arguments */ 13573 ); 13574 13575 /* 13576 * data is ---v 13577 * Dial(DAHDI/pseudo[/extension[/options]]) 13578 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]]) 13579 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]]) 13580 * Dial(DAHDI/i<span>[/extension[/options]]) 13581 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]) 13582 * 13583 * i - ISDN span channel restriction. 13584 * Used by CC to ensure that the CC recall goes out the same span. 13585 * Also to make ISDN channel names dialable when the sequence number 13586 * is stripped off. (Used by DTMF attended transfer feature.) 13587 * 13588 * g - channel group allocation search forward 13589 * G - channel group allocation search backward 13590 * r - channel group allocation round robin search forward 13591 * R - channel group allocation round robin search backward 13592 * 13593 * c - Wait for DTMF digit to confirm answer 13594 * r<cadance#> - Set distintive ring cadance number 13595 * d - Force bearer capability for ISDN/SS7 call to digital. 13596 */ 13597 13598 if (data) { 13599 dest = ast_strdupa(data); 13600 } else { 13601 ast_log(LOG_WARNING, "Channel requested with no data\n"); 13602 return NULL; 13603 } 13604 AST_NONSTANDARD_APP_ARGS(args, dest, '/'); 13605 if (!args.argc || ast_strlen_zero(args.group)) { 13606 ast_log(LOG_WARNING, "No channel/group specified\n"); 13607 return NULL; 13608 } 13609 13610 /* Initialize the output parameters */ 13611 memset(param, 0, sizeof(*param)); 13612 param->channelmatch = -1; 13613 13614 if (strchr(args.group, '!') != NULL) { 13615 char *prev = args.group; 13616 while ((s = strchr(prev, '!')) != NULL) { 13617 *s++ = '/'; 13618 prev = s; 13619 } 13620 *(prev - 1) = '\0'; 13621 subdir = args.group; 13622 args.group = prev; 13623 } else if (args.group[0] == 'i') { 13624 /* Extract the ISDN span channel restriction specifier. */ 13625 res = sscanf(args.group + 1, "%30d", &x); 13626 if (res < 1) { 13627 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data); 13628 return NULL; 13629 } 13630 param->span = x; 13631 13632 /* Remove the ISDN span channel restriction specifier. */ 13633 s = strchr(args.group, '-'); 13634 if (!s) { 13635 /* Search all groups since we are ISDN span restricted. */ 13636 return iflist; 13637 } 13638 args.group = s + 1; 13639 res = 0; 13640 } 13641 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { 13642 /* Retrieve the group number */ 13643 s = args.group + 1; 13644 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13645 if (res < 1) { 13646 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data); 13647 return NULL; 13648 } 13649 param->groupmatch = ((ast_group_t) 1 << x); 13650 13651 if (toupper(args.group[0]) == 'G') { 13652 if (args.group[0] == 'G') { 13653 param->backwards = 1; 13654 p = ifend; 13655 } else 13656 p = iflist; 13657 } else { 13658 if (ARRAY_LEN(round_robin) <= x) { 13659 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n", 13660 x, data); 13661 return NULL; 13662 } 13663 if (args.group[0] == 'R') { 13664 param->backwards = 1; 13665 p = round_robin[x] ? round_robin[x]->prev : ifend; 13666 if (!p) 13667 p = ifend; 13668 } else { 13669 p = round_robin[x] ? round_robin[x]->next : iflist; 13670 if (!p) 13671 p = iflist; 13672 } 13673 param->roundrobin = 1; 13674 param->rr_starting_point = x; 13675 } 13676 } else { 13677 s = args.group; 13678 if (!strcasecmp(s, "pseudo")) { 13679 /* Special case for pseudo */ 13680 x = CHAN_PSEUDO; 13681 param->channelmatch = x; 13682 } else { 13683 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13684 if (res < 1) { 13685 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data); 13686 return NULL; 13687 } else { 13688 param->channelmatch = x; 13689 } 13690 } 13691 if (subdir) { 13692 char path[PATH_MAX]; 13693 struct stat stbuf; 13694 13695 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d", 13696 subdir, param->channelmatch); 13697 if (stat(path, &stbuf) < 0) { 13698 ast_log(LOG_WARNING, "stat(%s) failed: %s\n", 13699 path, strerror(errno)); 13700 return NULL; 13701 } 13702 if (!S_ISCHR(stbuf.st_mode)) { 13703 ast_log(LOG_ERROR, "%s: Not a character device file\n", 13704 path); 13705 return NULL; 13706 } 13707 param->channelmatch = minor(stbuf.st_rdev); 13708 } 13709 13710 p = iflist; 13711 } 13712 13713 if (param->opt == 'r' && res < 3) { 13714 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data); 13715 param->opt = '\0'; 13716 } 13717 13718 return p; 13719 }
static int device2chan | ( | const char * | subdir, | |
int | channel, | |||
char * | path, | |||
int | pathlen | |||
) | [static] |
Definition at line 12330 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.
Referenced by build_channels().
12331 { 12332 struct stat stbuf; 12333 int num; 12334 12335 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel); 12336 if (stat(path, &stbuf) < 0) { 12337 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno)); 12338 return -errno; 12339 } 12340 if (!S_ISCHR(stbuf.st_mode)) { 12341 ast_log(LOG_ERROR, "%s: Not a character device file\n", path); 12342 return -EINVAL; 12343 } 12344 num = minor(stbuf.st_rdev); 12345 ast_log(LOG_DEBUG, "%s -> %d\n", path, num); 12346 return num; 12347 12348 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 4504 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
04505 { 04506 if (isdigit(digit)) 04507 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 04508 else if (digit >= 'A' && digit <= 'D') 04509 return DAHDI_TONE_DTMF_A + (digit - 'A'); 04510 else if (digit >= 'a' && digit <= 'd') 04511 return DAHDI_TONE_DTMF_A + (digit - 'a'); 04512 else if (digit == '*') 04513 return DAHDI_TONE_DTMF_s; 04514 else if (digit == '#') 04515 return DAHDI_TONE_DTMF_p; 04516 else 04517 return -1; 04518 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6677 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().
06678 { 06679 int val = 0; 06680 06681 p->ignoredtmf = 1; 06682 06683 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06684 06685 if (!p->hardwaredtmf && p->dsp) { 06686 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 06687 ast_dsp_set_features(p->dsp, p->dsp_features); 06688 } 06689 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 11745 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().
11746 { 11747 int count, res, res2, spoint, pollres=0; 11748 struct dahdi_pvt *i; 11749 struct dahdi_pvt *last = NULL; 11750 struct dahdi_pvt *doomed; 11751 time_t thispass = 0, lastpass = 0; 11752 int found; 11753 char buf[1024]; 11754 struct pollfd *pfds=NULL; 11755 int lastalloc = -1; 11756 /* This thread monitors all the frame relay interfaces which are not yet in use 11757 (and thus do not have a separate thread) indefinitely */ 11758 /* From here on out, we die whenever asked */ 11759 #if 0 11760 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 11761 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 11762 return NULL; 11763 } 11764 ast_debug(1, "Monitor starting...\n"); 11765 #endif 11766 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11767 11768 pthread_cleanup_push(monitor_pfds_clean, &pfds); 11769 for (;;) { 11770 /* Lock the interface list */ 11771 ast_mutex_lock(&iflock); 11772 if (!pfds || (lastalloc != ifcount)) { 11773 if (pfds) { 11774 ast_free(pfds); 11775 pfds = NULL; 11776 } 11777 if (ifcount) { 11778 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 11779 ast_mutex_unlock(&iflock); 11780 return NULL; 11781 } 11782 } 11783 lastalloc = ifcount; 11784 } 11785 /* Build the stuff we're going to poll on, that is the socket of every 11786 dahdi_pvt that does not have an associated owner channel */ 11787 count = 0; 11788 for (i = iflist; i; i = i->next) { 11789 ast_mutex_lock(&i->lock); 11790 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 11791 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11792 struct analog_pvt *p = i->sig_pvt; 11793 11794 if (!p) { 11795 ast_log(LOG_ERROR, "No sig_pvt?\n"); 11796 } else if (!p->owner && !p->subs[SUB_REAL].owner) { 11797 /* This needs to be watched, as it lacks an owner */ 11798 pfds[count].fd = i->subs[SUB_REAL].dfd; 11799 pfds[count].events = POLLPRI; 11800 pfds[count].revents = 0; 11801 /* Message waiting or r2 channels also get watched for reading */ 11802 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11803 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11804 pfds[count].events |= POLLIN; 11805 } 11806 count++; 11807 } 11808 } else { 11809 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 11810 /* This needs to be watched, as it lacks an owner */ 11811 pfds[count].fd = i->subs[SUB_REAL].dfd; 11812 pfds[count].events = POLLPRI; 11813 pfds[count].revents = 0; 11814 /* If we are monitoring for VMWI or sending CID, we need to 11815 read from the channel as well */ 11816 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11817 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11818 pfds[count].events |= POLLIN; 11819 } 11820 count++; 11821 } 11822 } 11823 } 11824 ast_mutex_unlock(&i->lock); 11825 } 11826 /* Okay, now that we know what to do, release the interface lock */ 11827 ast_mutex_unlock(&iflock); 11828 11829 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11830 pthread_testcancel(); 11831 /* Wait at least a second for something to happen */ 11832 res = poll(pfds, count, 1000); 11833 pthread_testcancel(); 11834 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11835 11836 /* Okay, poll has finished. Let's see what happened. */ 11837 if (res < 0) { 11838 if ((errno != EAGAIN) && (errno != EINTR)) 11839 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 11840 continue; 11841 } 11842 /* Alright, lock the interface list again, and let's look and see what has 11843 happened */ 11844 ast_mutex_lock(&iflock); 11845 found = 0; 11846 spoint = 0; 11847 lastpass = thispass; 11848 thispass = time(NULL); 11849 doomed = NULL; 11850 for (i = iflist;; i = i->next) { 11851 if (doomed) { 11852 int res; 11853 res = dahdi_destroy_channel_bynum(doomed->channel); 11854 if (res != RESULT_SUCCESS) { 11855 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 11856 } 11857 doomed = NULL; 11858 } 11859 if (!i) { 11860 break; 11861 } 11862 11863 if (thispass != lastpass) { 11864 if (!found && ((i == last) || ((i == iflist) && !last))) { 11865 last = i; 11866 if (last) { 11867 struct analog_pvt *analog_p = last->sig_pvt; 11868 /* Only allow MWI to be initiated on a quiescent fxs port */ 11869 if (analog_p 11870 && !last->mwisendactive 11871 && (last->sig & __DAHDI_SIG_FXO) 11872 && !analog_p->fxsoffhookstate 11873 && !last->owner 11874 && !ast_strlen_zero(last->mailbox) 11875 && (thispass - analog_p->onhooktime > 3)) { 11876 res = has_voicemail(last); 11877 if (analog_p->msgstate != res) { 11878 /* Set driver resources for signalling VMWI */ 11879 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 11880 if (res2) { 11881 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 11882 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 11883 } 11884 /* If enabled for FSK spill then initiate it */ 11885 if (mwi_send_init(last)) { 11886 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 11887 } 11888 analog_p->msgstate = res; 11889 found ++; 11890 } 11891 } 11892 last = last->next; 11893 } 11894 } 11895 } 11896 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 11897 if (i->radio && !i->owner) 11898 { 11899 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11900 if (res) 11901 { 11902 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 11903 /* Don't hold iflock while handling init events */ 11904 ast_mutex_unlock(&iflock); 11905 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11906 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11907 else 11908 doomed = handle_init_event(i, res); 11909 ast_mutex_lock(&iflock); 11910 } 11911 continue; 11912 } 11913 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 11914 if (pollres & POLLIN) { 11915 if (i->owner || i->subs[SUB_REAL].owner) { 11916 #ifdef HAVE_PRI 11917 if (!i->pri) 11918 #endif 11919 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 11920 continue; 11921 } 11922 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { 11923 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 11924 continue; 11925 } 11926 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 11927 if (res > 0) { 11928 if (i->mwimonitor_fsk) { 11929 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 11930 pthread_attr_t attr; 11931 pthread_t threadid; 11932 struct mwi_thread_data *mtd; 11933 11934 pthread_attr_init(&attr); 11935 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11936 11937 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 11938 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 11939 mtd->pvt = i; 11940 memcpy(mtd->buf, buf, res); 11941 mtd->len = res; 11942 i->mwimonitoractive = 1; 11943 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 11944 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 11945 i->mwimonitoractive = 0; 11946 ast_free(mtd); 11947 } 11948 } 11949 } 11950 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 11951 } else if (i->cid_start == CID_START_DTMF_NOALERT) { 11952 int energy; 11953 struct timeval now; 11954 /* State machine dtmfcid_holdoff_state allows for the line to settle 11955 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 11956 */ 11957 if (1 == i->dtmfcid_holdoff_state) { 11958 gettimeofday(&i->dtmfcid_delay, NULL); 11959 i->dtmfcid_holdoff_state = 2; 11960 } else if (2 == i->dtmfcid_holdoff_state) { 11961 gettimeofday(&now, NULL); 11962 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 11963 i->dtmfcid_holdoff_state = 0; 11964 } 11965 } else { 11966 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 11967 if (!i->mwisendactive && energy > dtmfcid_level) { 11968 pthread_t threadid; 11969 struct ast_channel *chan; 11970 ast_mutex_unlock(&iflock); 11971 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11972 /* just in case this event changes or somehow destroys a channel, set doomed here too */ 11973 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); 11974 i->dtmfcid_holdoff_state = 1; 11975 } else { 11976 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11977 if (!chan) { 11978 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11979 } else { 11980 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11981 if (res) { 11982 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11983 ast_hangup(chan); 11984 } else { 11985 i->dtmfcid_holdoff_state = 1; 11986 } 11987 } 11988 } 11989 ast_mutex_lock(&iflock); 11990 } 11991 } 11992 } 11993 if (i->mwisendactive) { 11994 mwi_send_process_buffer(i, res); 11995 } 11996 } else { 11997 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 11998 } 11999 } 12000 if (pollres & POLLPRI) { 12001 if (i->owner || i->subs[SUB_REAL].owner) { 12002 #ifdef HAVE_PRI 12003 if (!i->pri) 12004 #endif 12005 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 12006 continue; 12007 } 12008 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 12009 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 12010 /* Don't hold iflock while handling init events */ 12011 ast_mutex_unlock(&iflock); 12012 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 12013 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 12014 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 12015 else 12016 doomed = handle_init_event(i, res); 12017 } 12018 ast_mutex_lock(&iflock); 12019 } 12020 } 12021 } 12022 ast_mutex_unlock(&iflock); 12023 } 12024 /* Never reached */ 12025 pthread_cleanup_pop(1); 12026 return NULL; 12027 12028 }
static int drc_sample | ( | int | sample, | |
float | drc | |||
) | [static] |
Definition at line 5007 of file chan_dahdi.c.
Referenced by fill_rxgain(), and fill_txgain().
05008 { 05009 float neg; 05010 float shallow, steep; 05011 float max = SHRT_MAX; 05012 05013 neg = (sample < 0 ? -1 : 1); 05014 steep = drc*sample; 05015 shallow = neg*(max-max/drc)+(float)sample/drc; 05016 if (abs(steep) < abs(shallow)) { 05017 sample = steep; 05018 } 05019 else { 05020 sample = shallow; 05021 } 05022 05023 return sample; 05024 }
Definition at line 13496 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().
13497 { 13498 struct dahdi_pvt *p; 13499 struct dahdi_bufferinfo bi; 13500 int res; 13501 13502 p = ast_malloc(sizeof(*p)); 13503 if (!p) { 13504 return NULL; 13505 } 13506 *p = *src; 13507 13508 /* Must deep copy the cc_params. */ 13509 p->cc_params = ast_cc_config_params_init(); 13510 if (!p->cc_params) { 13511 ast_free(p); 13512 return NULL; 13513 } 13514 ast_cc_copy_config_params(p->cc_params, src->cc_params); 13515 13516 p->which_iflist = DAHDI_IFLIST_NONE; 13517 p->next = NULL; 13518 p->prev = NULL; 13519 ast_mutex_init(&p->lock); 13520 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13521 if (p->subs[SUB_REAL].dfd < 0) { 13522 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 13523 destroy_dahdi_pvt(p); 13524 return NULL; 13525 } 13526 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13527 if (!res) { 13528 bi.txbufpolicy = src->buf_policy; 13529 bi.rxbufpolicy = src->buf_policy; 13530 bi.numbufs = src->buf_no; 13531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13532 if (res < 0) { 13533 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 13534 } 13535 } else 13536 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 13537 p->destroy = 1; 13538 dahdi_iflist_insert(p); 13539 return p; 13540 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6691 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().
06692 { 06693 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06694 06695 if (p->channel == CHAN_PSEUDO) 06696 return; 06697 06698 p->ignoredtmf = 0; 06699 06700 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06701 06702 if (!p->hardwaredtmf && p->dsp) { 06703 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 06704 ast_dsp_set_features(p->dsp, p->dsp_features); 06705 } 06706 }
static const char * event2str | ( | int | event | ) | [static] |
Definition at line 4659 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 5077 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_rxgain().
05078 { 05079 int j; 05080 int k; 05081 float linear_gain = pow(10.0, gain / 20.0); 05082 05083 switch (law) { 05084 case DAHDI_LAW_ALAW: 05085 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05086 if (gain || drc) { 05087 k = AST_ALAW(j); 05088 if (drc) { 05089 k = drc_sample(k, drc); 05090 } 05091 k = (float)k * linear_gain; 05092 if (k > 32767) { 05093 k = 32767; 05094 } else if (k < -32768) { 05095 k = -32768; 05096 } 05097 g->rxgain[j] = AST_LIN2A(k); 05098 } else { 05099 g->rxgain[j] = j; 05100 } 05101 } 05102 break; 05103 case DAHDI_LAW_MULAW: 05104 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05105 if (gain || drc) { 05106 k = AST_MULAW(j); 05107 if (drc) { 05108 k = drc_sample(k, drc); 05109 } 05110 k = (float)k * linear_gain; 05111 if (k > 32767) { 05112 k = 32767; 05113 } else if (k < -32768) { 05114 k = -32768; 05115 } 05116 g->rxgain[j] = AST_LIN2MU(k); 05117 } else { 05118 g->rxgain[j] = j; 05119 } 05120 } 05121 break; 05122 } 05123 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5027 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_txgain().
05028 { 05029 int j; 05030 int k; 05031 05032 float linear_gain = pow(10.0, gain / 20.0); 05033 05034 switch (law) { 05035 case DAHDI_LAW_ALAW: 05036 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05037 if (gain || drc) { 05038 k = AST_ALAW(j); 05039 if (drc) { 05040 k = drc_sample(k, drc); 05041 } 05042 k = (float)k * linear_gain; 05043 if (k > 32767) { 05044 k = 32767; 05045 } else if (k < -32768) { 05046 k = -32768; 05047 } 05048 g->txgain[j] = AST_LIN2A(k); 05049 } else { 05050 g->txgain[j] = j; 05051 } 05052 } 05053 break; 05054 case DAHDI_LAW_MULAW: 05055 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05056 if (gain || drc) { 05057 k = AST_MULAW(j); 05058 if (drc) { 05059 k = drc_sample(k, drc); 05060 } 05061 k = (float)k * linear_gain; 05062 if (k > 32767) { 05063 k = 32767; 05064 } else if (k < -32768) { 05065 k = -32768; 05066 } 05067 g->txgain[j] = AST_LIN2MU(k); 05068 05069 } else { 05070 g->txgain[j] = j; 05071 } 05072 } 05073 break; 05074 } 05075 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 16074 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().
16075 { 16076 struct dahdi_pvt *p; 16077 16078 ast_mutex_lock(&iflock); 16079 for (p = iflist; p; p = p->next) { 16080 if (p->channel == channel) { 16081 break; 16082 } 16083 } 16084 ast_mutex_unlock(&iflock); 16085 return p; 16086 }
static struct dahdi_pvt* find_channel_from_str | ( | const char * | channel | ) | [static, read] |
Definition at line 16097 of file chan_dahdi.c.
References find_channel().
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
16098 { 16099 int chan_num; 16100 16101 if (sscanf(channel, "%30d", &chan_num) != 1) { 16102 /* Not numeric string. */ 16103 return NULL; 16104 } 16105 16106 return find_channel(chan_num); 16107 }
Definition at line 5767 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 7763 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().
07764 { 07765 int res; 07766 struct dahdi_spaninfo zi; 07767 struct dahdi_params params; 07768 07769 memset(&zi, 0, sizeof(zi)); 07770 zi.spanno = p->span; 07771 07772 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 07773 if (zi.alarms != DAHDI_ALARM_NONE) 07774 return zi.alarms; 07775 } else { 07776 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 07777 return 0; 07778 } 07779 07780 /* No alarms on the span. Check for channel alarms. */ 07781 memset(¶ms, 0, sizeof(params)); 07782 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 07783 return params.chan_alarms; 07784 07785 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 07786 07787 return DAHDI_ALARM_NONE; 07788 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 7888 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().
07889 { 07890 const char *alarm_str; 07891 07892 #if defined(HAVE_PRI) 07893 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 07894 return; 07895 } 07896 #endif /* defined(HAVE_PRI) */ 07897 07898 alarm_str = alarm2str(alms); 07899 if (report_alarms & REPORT_CHANNEL_ALARMS) { 07900 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 07901 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 07902 "Alarm: %s\r\n" 07903 "Channel: %d\r\n", 07904 alarm_str, p->channel); 07905 } 07906 07907 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 07908 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); 07909 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", 07910 "Alarm: %s\r\n" 07911 "Span: %d\r\n", 07912 alarm_str, p->span); 07913 } 07914 }
static void handle_clear_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3873 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().
03874 { 03875 #if defined(HAVE_PRI) 03876 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 03877 return; 03878 } 03879 #endif /* defined(HAVE_PRI) */ 03880 03881 if (report_alarms & REPORT_CHANNEL_ALARMS) { 03882 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 03883 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 03884 } 03885 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 03886 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); 03887 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); 03888 } 03889 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15680 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.
15681 { 15682 int i, j; 15683 switch (cmd) { 15684 case CLI_INIT: 15685 e->command = "dahdi show cadences"; 15686 e->usage = 15687 "Usage: dahdi show cadences\n" 15688 " Shows all cadences currently defined\n"; 15689 return NULL; 15690 case CLI_GENERATE: 15691 return NULL; 15692 } 15693 for (i = 0; i < num_cadence; i++) { 15694 char output[1024]; 15695 char tmp[16], tmp2[64]; 15696 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 15697 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 15698 15699 for (j = 0; j < 16; j++) { 15700 if (cadences[i].ringcadence[j] == 0) 15701 break; 15702 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 15703 if (cidrings[i] * 2 - 1 == j) 15704 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 15705 else 15706 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 15707 if (j != 0) 15708 strncat(output, ",", sizeof(output) - strlen(output) - 1); 15709 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 15710 } 15711 ast_cli(a->fd,"%s\n",output); 15712 } 15713 return CLI_SUCCESS; 15714 }
Definition at line 11493 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().
11494 { 11495 int res; 11496 pthread_t threadid; 11497 struct ast_channel *chan; 11498 11499 /* Handle an event on a given channel for the monitor thread. */ 11500 11501 switch (event) { 11502 case DAHDI_EVENT_NONE: 11503 case DAHDI_EVENT_BITSCHANGED: 11504 break; 11505 case DAHDI_EVENT_WINKFLASH: 11506 case DAHDI_EVENT_RINGOFFHOOK: 11507 if (i->inalarm) break; 11508 if (i->radio) break; 11509 /* Got a ring/answer. What kind of channel are we? */ 11510 switch (i->sig) { 11511 case SIG_FXOLS: 11512 case SIG_FXOGS: 11513 case SIG_FXOKS: 11514 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11515 if (res && (errno == EBUSY)) 11516 break; 11517 11518 /* Cancel VMWI spill */ 11519 ast_free(i->cidspill); 11520 i->cidspill = NULL; 11521 restore_conference(i); 11522 11523 if (i->immediate) { 11524 dahdi_enable_ec(i); 11525 /* The channel is immediately up. Start right away */ 11526 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 11527 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL); 11528 if (!chan) { 11529 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 11530 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11531 if (res < 0) 11532 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11533 } 11534 } else { 11535 /* Check for callerid, digits, etc */ 11536 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL); 11537 if (chan) { 11538 if (has_voicemail(i)) 11539 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 11540 else 11541 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 11542 if (res < 0) 11543 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 11544 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11545 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11546 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11547 if (res < 0) 11548 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11549 ast_hangup(chan); 11550 } 11551 } else 11552 ast_log(LOG_WARNING, "Unable to create channel\n"); 11553 } 11554 break; 11555 case SIG_FXSLS: 11556 case SIG_FXSGS: 11557 case SIG_FXSKS: 11558 i->ringt = i->ringt_base; 11559 /* Fall through */ 11560 case SIG_EMWINK: 11561 case SIG_FEATD: 11562 case SIG_FEATDMF: 11563 case SIG_FEATDMF_TA: 11564 case SIG_E911: 11565 case SIG_FGC_CAMA: 11566 case SIG_FGC_CAMAMF: 11567 case SIG_FEATB: 11568 case SIG_EM: 11569 case SIG_EM_E1: 11570 case SIG_SFWINK: 11571 case SIG_SF_FEATD: 11572 case SIG_SF_FEATDMF: 11573 case SIG_SF_FEATB: 11574 case SIG_SF: 11575 /* Check for callerid, digits, etc */ 11576 if (i->cid_start == CID_START_POLARITY_IN) { 11577 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11578 } else { 11579 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL); 11580 } 11581 11582 if (!chan) { 11583 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11584 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11585 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11586 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11587 if (res < 0) { 11588 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11589 } 11590 ast_hangup(chan); 11591 } 11592 break; 11593 default: 11594 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11595 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11596 if (res < 0) 11597 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11598 return NULL; 11599 } 11600 break; 11601 case DAHDI_EVENT_NOALARM: 11602 switch (i->sig) { 11603 #if defined(HAVE_PRI) 11604 case SIG_PRI_LIB_HANDLE_CASES: 11605 ast_mutex_lock(&i->lock); 11606 sig_pri_chan_alarm_notify(i->sig_pvt, 1); 11607 ast_mutex_unlock(&i->lock); 11608 break; 11609 #endif /* defined(HAVE_PRI) */ 11610 #if defined(HAVE_SS7) 11611 case SIG_SS7: 11612 sig_ss7_set_alarm(i->sig_pvt, 0); 11613 break; 11614 #endif /* defined(HAVE_SS7) */ 11615 default: 11616 i->inalarm = 0; 11617 break; 11618 } 11619 handle_clear_alarms(i); 11620 break; 11621 case DAHDI_EVENT_ALARM: 11622 switch (i->sig) { 11623 #if defined(HAVE_PRI) 11624 case SIG_PRI_LIB_HANDLE_CASES: 11625 ast_mutex_lock(&i->lock); 11626 sig_pri_chan_alarm_notify(i->sig_pvt, 0); 11627 ast_mutex_unlock(&i->lock); 11628 break; 11629 #endif /* defined(HAVE_PRI) */ 11630 #if defined(HAVE_SS7) 11631 case SIG_SS7: 11632 sig_ss7_set_alarm(i->sig_pvt, 1); 11633 break; 11634 #endif /* defined(HAVE_SS7) */ 11635 default: 11636 i->inalarm = 1; 11637 break; 11638 } 11639 res = get_alarms(i); 11640 handle_alarms(i, res); 11641 /* fall thru intentionally */ 11642 case DAHDI_EVENT_ONHOOK: 11643 if (i->radio) 11644 break; 11645 /* Back on hook. Hang up. */ 11646 switch (i->sig) { 11647 case SIG_FXOLS: 11648 case SIG_FXOGS: 11649 case SIG_FEATD: 11650 case SIG_FEATDMF: 11651 case SIG_FEATDMF_TA: 11652 case SIG_E911: 11653 case SIG_FGC_CAMA: 11654 case SIG_FGC_CAMAMF: 11655 case SIG_FEATB: 11656 case SIG_EM: 11657 case SIG_EM_E1: 11658 case SIG_EMWINK: 11659 case SIG_SF_FEATD: 11660 case SIG_SF_FEATDMF: 11661 case SIG_SF_FEATB: 11662 case SIG_SF: 11663 case SIG_SFWINK: 11664 case SIG_FXSLS: 11665 case SIG_FXSGS: 11666 case SIG_FXSKS: 11667 case SIG_FXOKS: 11668 dahdi_disable_ec(i); 11669 /* Diddle the battery for the zhone */ 11670 #ifdef ZHONE_HACK 11671 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11672 usleep(1); 11673 #endif 11674 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11675 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 11676 break; 11677 case SIG_SS7: 11678 case SIG_PRI_LIB_HANDLE_CASES: 11679 dahdi_disable_ec(i); 11680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11681 break; 11682 default: 11683 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11685 return NULL; 11686 } 11687 break; 11688 case DAHDI_EVENT_POLARITY: 11689 switch (i->sig) { 11690 case SIG_FXSLS: 11691 case SIG_FXSKS: 11692 case SIG_FXSGS: 11693 /* We have already got a PR before the channel was 11694 created, but it wasn't handled. We need polarity 11695 to be REV for remote hangup detection to work. 11696 At least in Spain */ 11697 if (i->hanguponpolarityswitch) 11698 i->polarity = POLARITY_REV; 11699 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 11700 i->polarity = POLARITY_REV; 11701 ast_verb(2, "Starting post polarity " 11702 "CID detection on channel %d\n", 11703 i->channel); 11704 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11705 if (!chan) { 11706 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11707 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11708 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11709 ast_hangup(chan); 11710 } 11711 } 11712 break; 11713 default: 11714 ast_log(LOG_WARNING, "handle_init_event detected " 11715 "polarity reversal on non-FXO (SIG_FXS) " 11716 "interface %d\n", i->channel); 11717 } 11718 break; 11719 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 11720 ast_log(LOG_NOTICE, 11721 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 11722 i->channel); 11723 return i; 11724 case DAHDI_EVENT_NEONMWI_ACTIVE: 11725 if (i->mwimonitor_neon) { 11726 notify_message(i->mailbox, 1); 11727 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 11728 } 11729 break; 11730 case DAHDI_EVENT_NEONMWI_INACTIVE: 11731 if (i->mwimonitor_neon) { 11732 notify_message(i->mailbox, 0); 11733 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 11734 } 11735 break; 11736 } 11737 return NULL; 11738 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5302 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().
05303 { 05304 int new_msgs; 05305 struct ast_event *event; 05306 char *mailbox, *context; 05307 05308 mailbox = context = ast_strdupa(p->mailbox); 05309 strsep(&context, "@"); 05310 if (ast_strlen_zero(context)) 05311 context = "default"; 05312 05313 event = ast_event_get_cached(AST_EVENT_MWI, 05314 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 05315 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 05316 AST_EVENT_IE_END); 05317 05318 if (event) { 05319 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 05320 ast_event_destroy(event); 05321 } else 05322 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 05323 05324 return new_msgs; 05325 }
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 13255 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::group, and dahdi_pvt::span.
Referenced by dahdi_cc_callback(), and dahdi_request().
13256 { 13257 #if defined(HAVE_PRI) 13258 if (0 < span) { 13259 /* The channel must be on the specified PRI span. */ 13260 if (!p->pri || p->pri->span != span) { 13261 return 0; 13262 } 13263 if (!groupmatch && channelmatch == -1) { 13264 /* Match any group since it only needs to be on the PRI span. */ 13265 *groupmatched = 1; 13266 return 1; 13267 } 13268 } 13269 #endif /* defined(HAVE_PRI) */ 13270 /* check group matching */ 13271 if (groupmatch) { 13272 if ((p->group & groupmatch) != groupmatch) 13273 /* Doesn't match the specified group, try the next one */ 13274 return 0; 13275 *groupmatched = 1; 13276 } 13277 /* Check to see if we have a channel match */ 13278 if (channelmatch != -1) { 13279 if (p->channel != channelmatch) 13280 /* Doesn't match the specified channel, try the next one */ 13281 return 0; 13282 *channelmatched = 1; 13283 } 13284 13285 return 1; 13286 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 4772 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
04773 { 04774 /* If they're listening to our channel, they're ours */ 04775 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 04776 return 1; 04777 /* If they're a talker on our (allocated) conference, they're ours */ 04778 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 04779 return 1; 04780 return 0; 04781 }
Definition at line 4802 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().
04803 { 04804 int x; 04805 int useslavenative; 04806 struct dahdi_pvt *slave = NULL; 04807 /* Start out optimistic */ 04808 useslavenative = 1; 04809 /* Update conference state in a stateless fashion */ 04810 for (x = 0; x < 3; x++) { 04811 /* Any three-way calling makes slave native mode *definitely* out 04812 of the question */ 04813 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 04814 useslavenative = 0; 04815 } 04816 /* If we don't have any 3-way calls, check to see if we have 04817 precisely one slave */ 04818 if (useslavenative) { 04819 for (x = 0; x < MAX_SLAVES; x++) { 04820 if (p->slaves[x]) { 04821 if (slave) { 04822 /* Whoops already have a slave! No 04823 slave native and stop right away */ 04824 slave = NULL; 04825 useslavenative = 0; 04826 break; 04827 } else { 04828 /* We have one slave so far */ 04829 slave = p->slaves[x]; 04830 } 04831 } 04832 } 04833 } 04834 /* If no slave, slave native definitely out */ 04835 if (!slave) 04836 useslavenative = 0; 04837 else if (slave->law != p->law) { 04838 useslavenative = 0; 04839 slave = NULL; 04840 } 04841 if (out) 04842 *out = slave; 04843 return useslavenative; 04844 }
static int load_module | ( | void | ) | [static] |
Definition at line 18756 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().
18757 { 18758 int res; 18759 #if defined(HAVE_PRI) || defined(HAVE_SS7) 18760 int y; 18761 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 18762 18763 #ifdef HAVE_PRI 18764 memset(pris, 0, sizeof(pris)); 18765 for (y = 0; y < NUM_SPANS; y++) { 18766 sig_pri_init_pri(&pris[y].pri); 18767 } 18768 pri_set_error(dahdi_pri_error); 18769 pri_set_message(dahdi_pri_message); 18770 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 18771 #ifdef HAVE_PRI_PROG_W_CAUSE 18772 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 18773 #endif 18774 #if defined(HAVE_PRI_CCSS) 18775 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks) 18776 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) { 18777 __unload_module(); 18778 return AST_MODULE_LOAD_FAILURE; 18779 } 18780 #endif /* defined(HAVE_PRI_CCSS) */ 18781 if (sig_pri_load( 18782 #if defined(HAVE_PRI_CCSS) 18783 dahdi_pri_cc_type 18784 #else 18785 NULL 18786 #endif /* defined(HAVE_PRI_CCSS) */ 18787 )) { 18788 __unload_module(); 18789 return AST_MODULE_LOAD_FAILURE; 18790 } 18791 #endif 18792 #if defined(HAVE_SS7) 18793 memset(linksets, 0, sizeof(linksets)); 18794 for (y = 0; y < NUM_SPANS; y++) { 18795 sig_ss7_init_linkset(&linksets[y].ss7); 18796 } 18797 ss7_set_error(dahdi_ss7_error); 18798 ss7_set_message(dahdi_ss7_message); 18799 #endif /* defined(HAVE_SS7) */ 18800 res = setup_dahdi(0); 18801 /* Make sure we can register our DAHDI channel type */ 18802 if (res) 18803 return AST_MODULE_LOAD_DECLINE; 18804 if (ast_channel_register(&dahdi_tech)) { 18805 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 18806 __unload_module(); 18807 return AST_MODULE_LOAD_FAILURE; 18808 } 18809 #ifdef HAVE_PRI 18810 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 18811 #endif 18812 #if defined(HAVE_SS7) 18813 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 18814 #endif /* defined(HAVE_SS7) */ 18815 #ifdef HAVE_OPENR2 18816 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 18817 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 18818 #endif 18819 18820 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 18821 /* register all the data providers */ 18822 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers)); 18823 memset(round_robin, 0, sizeof(round_robin)); 18824 ast_manager_register_xml("DAHDITransfer", 0, action_transfer); 18825 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup); 18826 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook); 18827 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon); 18828 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff); 18829 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels); 18830 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart); 18831 18832 ast_cond_init(&ss_thread_complete, NULL); 18833 18834 return res; 18835 }
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 12364 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::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, 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(), dahdi_pvt::silencethreshold, 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().
12365 { 12366 /* Make a dahdi_pvt structure for this interface */ 12367 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */ 12368 char fn[80]; 12369 struct dahdi_bufferinfo bi; 12370 12371 int res; 12372 #if defined(HAVE_PRI) 12373 int span = 0; 12374 #endif /* defined(HAVE_PRI) */ 12375 int here = 0;/*!< TRUE if the channel interface already exists. */ 12376 int x; 12377 struct analog_pvt *analog_p = NULL; 12378 struct dahdi_params p; 12379 #if defined(HAVE_PRI) 12380 struct dahdi_spaninfo si; 12381 struct sig_pri_chan *pri_chan = NULL; 12382 #endif /* defined(HAVE_PRI) */ 12383 #if defined(HAVE_SS7) 12384 struct sig_ss7_chan *ss7_chan = NULL; 12385 #endif /* defined(HAVE_SS7) */ 12386 12387 /* Search channel interface list to see if it already exists. */ 12388 for (tmp = iflist; tmp; tmp = tmp->next) { 12389 if (!tmp->destroy) { 12390 if (tmp->channel == channel) { 12391 /* The channel interface already exists. */ 12392 here = 1; 12393 break; 12394 } 12395 if (tmp->channel > channel) { 12396 /* No way it can be in the sorted list. */ 12397 tmp = NULL; 12398 break; 12399 } 12400 } 12401 } 12402 12403 if (!here && reloading != 1) { 12404 tmp = ast_calloc(1, sizeof(*tmp)); 12405 if (!tmp) { 12406 return NULL; 12407 } 12408 tmp->cc_params = ast_cc_config_params_init(); 12409 if (!tmp->cc_params) { 12410 ast_free(tmp); 12411 return NULL; 12412 } 12413 ast_mutex_init(&tmp->lock); 12414 ifcount++; 12415 for (x = 0; x < 3; x++) 12416 tmp->subs[x].dfd = -1; 12417 tmp->channel = channel; 12418 tmp->priindication_oob = conf->chan.priindication_oob; 12419 } 12420 12421 if (tmp) { 12422 int chan_sig = conf->chan.sig; 12423 12424 /* If there are variables in tmp before it is updated to match the new config, clear them */ 12425 if (reloading && tmp->vars) { 12426 ast_variables_destroy(tmp->vars); 12427 tmp->vars = NULL; 12428 } 12429 12430 12431 if (!here) { 12432 /* Can only get here if this is a new channel interface being created. */ 12433 if ((channel != CHAN_PSEUDO)) { 12434 int count = 0; 12435 12436 snprintf(fn, sizeof(fn), "%d", channel); 12437 /* Open non-blocking */ 12438 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12439 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 */ 12440 usleep(1); 12441 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12442 count++; 12443 } 12444 /* Allocate a DAHDI structure */ 12445 if (tmp->subs[SUB_REAL].dfd < 0) { 12446 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); 12447 destroy_dahdi_pvt(tmp); 12448 return NULL; 12449 } 12450 memset(&p, 0, sizeof(p)); 12451 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12452 if (res < 0) { 12453 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 12454 destroy_dahdi_pvt(tmp); 12455 return NULL; 12456 } 12457 if (conf->is_sig_auto) 12458 chan_sig = sigtype_to_signalling(p.sigtype); 12459 if (p.sigtype != (chan_sig & 0x3ffff)) { 12460 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)); 12461 destroy_dahdi_pvt(tmp); 12462 return NULL; 12463 } 12464 tmp->law_default = p.curlaw; 12465 tmp->law = p.curlaw; 12466 tmp->span = p.spanno; 12467 #if defined(HAVE_PRI) 12468 span = p.spanno - 1; 12469 #endif /* defined(HAVE_PRI) */ 12470 } else { 12471 chan_sig = 0; 12472 } 12473 tmp->sig = chan_sig; 12474 tmp->outsigmod = conf->chan.outsigmod; 12475 12476 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) { 12477 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp); 12478 if (!analog_p) { 12479 destroy_dahdi_pvt(tmp); 12480 return NULL; 12481 } 12482 tmp->sig_pvt = analog_p; 12483 } 12484 #if defined(HAVE_SS7) 12485 if (chan_sig == SIG_SS7) { 12486 struct dahdi_ss7 *ss7; 12487 int clear = 0; 12488 12489 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 12490 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12491 destroy_dahdi_pvt(tmp); 12492 return NULL; 12493 } 12494 12495 ss7 = ss7_resolve_linkset(cur_linkset); 12496 if (!ss7) { 12497 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 12498 destroy_dahdi_pvt(tmp); 12499 return NULL; 12500 } 12501 ss7->ss7.span = cur_linkset; 12502 if (cur_cicbeginswith < 0) { 12503 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 12504 destroy_dahdi_pvt(tmp); 12505 return NULL; 12506 } 12507 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7); 12508 if (!ss7_chan) { 12509 destroy_dahdi_pvt(tmp); 12510 return NULL; 12511 } 12512 tmp->sig_pvt = ss7_chan; 12513 tmp->ss7 = &ss7->ss7; 12514 12515 ss7_chan->channel = tmp->channel; 12516 ss7_chan->cic = cur_cicbeginswith++; 12517 12518 /* DB: Add CIC's DPC information */ 12519 ss7_chan->dpc = cur_defaultdpc; 12520 12521 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan; 12522 12523 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix)); 12524 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix)); 12525 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix)); 12526 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix)); 12527 12528 ss7->ss7.called_nai = conf->ss7.ss7.called_nai; 12529 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai; 12530 } 12531 #endif /* defined(HAVE_SS7) */ 12532 #ifdef HAVE_OPENR2 12533 if (chan_sig == SIG_MFCR2) { 12534 struct dahdi_mfcr2 *r2_link; 12535 r2_link = dahdi_r2_get_link(conf); 12536 if (!r2_link) { 12537 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 12538 destroy_dahdi_pvt(tmp); 12539 return NULL; 12540 } 12541 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 12542 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 12543 destroy_dahdi_pvt(tmp); 12544 return NULL; 12545 } 12546 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) { 12547 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 12548 destroy_dahdi_pvt(tmp); 12549 return NULL; 12550 } 12551 r2_link->pvts[r2_link->numchans++] = tmp; 12552 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 12553 tmp->subs[SUB_REAL].dfd, 12554 NULL, NULL); 12555 if (!tmp->r2chan) { 12556 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 12557 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 12558 destroy_dahdi_pvt(tmp); 12559 return NULL; 12560 } 12561 tmp->mfcr2 = r2_link; 12562 if (conf->mfcr2.call_files) { 12563 openr2_chan_enable_call_files(tmp->r2chan); 12564 } 12565 openr2_chan_set_client_data(tmp->r2chan, tmp); 12566 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 12567 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 12568 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 12569 tmp->mfcr2_category = conf->mfcr2.category; 12570 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 12571 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 12572 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 12573 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 12574 tmp->mfcr2call = 0; 12575 tmp->mfcr2_dnis_index = 0; 12576 tmp->mfcr2_ani_index = 0; 12577 } 12578 #endif 12579 #ifdef HAVE_PRI 12580 if (dahdi_sig_pri_lib_handles(chan_sig)) { 12581 int offset; 12582 int matchesdchan; 12583 int x,y; 12584 int myswitchtype = 0; 12585 12586 offset = 0; 12587 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 12588 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12589 destroy_dahdi_pvt(tmp); 12590 return NULL; 12591 } 12592 if (span >= NUM_SPANS) { 12593 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 12594 destroy_dahdi_pvt(tmp); 12595 return NULL; 12596 } else { 12597 si.spanno = 0; 12598 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12599 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12600 destroy_dahdi_pvt(tmp); 12601 return NULL; 12602 } 12603 /* Store the logical span first based upon the real span */ 12604 tmp->logicalspan = pris[span].prilogicalspan; 12605 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 12606 if (span < 0) { 12607 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 12608 destroy_dahdi_pvt(tmp); 12609 return NULL; 12610 } 12611 myswitchtype = conf->pri.pri.switchtype; 12612 /* Make sure this isn't a d-channel */ 12613 matchesdchan=0; 12614 for (x = 0; x < NUM_SPANS; x++) { 12615 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 12616 if (pris[x].dchannels[y] == tmp->channel) { 12617 matchesdchan = 1; 12618 break; 12619 } 12620 } 12621 } 12622 if (!matchesdchan) { 12623 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) { 12624 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype)); 12625 destroy_dahdi_pvt(tmp); 12626 return NULL; 12627 } 12628 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) { 12629 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype)); 12630 destroy_dahdi_pvt(tmp); 12631 return NULL; 12632 } 12633 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) { 12634 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)); 12635 destroy_dahdi_pvt(tmp); 12636 return NULL; 12637 } 12638 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) { 12639 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial); 12640 destroy_dahdi_pvt(tmp); 12641 return NULL; 12642 } 12643 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) { 12644 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext); 12645 destroy_dahdi_pvt(tmp); 12646 return NULL; 12647 } 12648 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) { 12649 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused); 12650 destroy_dahdi_pvt(tmp); 12651 return NULL; 12652 } 12653 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) { 12654 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle); 12655 destroy_dahdi_pvt(tmp); 12656 return NULL; 12657 } 12658 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) { 12659 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 12660 pris[span].pri.trunkgroup); 12661 destroy_dahdi_pvt(tmp); 12662 return NULL; 12663 } 12664 12665 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel); 12666 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup); 12667 if (!pri_chan) { 12668 destroy_dahdi_pvt(tmp); 12669 return NULL; 12670 } 12671 tmp->sig_pvt = pri_chan; 12672 tmp->pri = &pris[span].pri; 12673 12674 tmp->priexclusive = conf->chan.priexclusive; 12675 12676 if (!tmp->pri->cc_params) { 12677 tmp->pri->cc_params = ast_cc_config_params_init(); 12678 if (!tmp->pri->cc_params) { 12679 destroy_dahdi_pvt(tmp); 12680 return NULL; 12681 } 12682 } 12683 ast_cc_copy_config_params(tmp->pri->cc_params, 12684 conf->chan.cc_params); 12685 12686 pris[span].pri.sig = chan_sig; 12687 pris[span].pri.nodetype = conf->pri.pri.nodetype; 12688 pris[span].pri.switchtype = myswitchtype; 12689 pris[span].pri.nsf = conf->pri.pri.nsf; 12690 pris[span].pri.dialplan = conf->pri.pri.dialplan; 12691 pris[span].pri.localdialplan = conf->pri.pri.localdialplan; 12692 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt; 12693 pris[span].pri.minunused = conf->pri.pri.minunused; 12694 pris[span].pri.minidle = conf->pri.pri.minidle; 12695 pris[span].pri.overlapdial = conf->pri.pri.overlapdial; 12696 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping; 12697 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval; 12698 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12699 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support; 12700 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12701 #ifdef HAVE_PRI_INBANDDISCONNECT 12702 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect; 12703 #endif 12704 #if defined(HAVE_PRI_CALL_HOLD) 12705 pris[span].pri.hold_disconnect_transfer = 12706 conf->pri.pri.hold_disconnect_transfer; 12707 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 12708 #if defined(HAVE_PRI_CCSS) 12709 pris[span].pri.cc_ptmp_recall_mode = 12710 conf->pri.pri.cc_ptmp_recall_mode; 12711 pris[span].pri.cc_qsig_signaling_link_req = 12712 conf->pri.pri.cc_qsig_signaling_link_req; 12713 pris[span].pri.cc_qsig_signaling_link_rsp = 12714 conf->pri.pri.cc_qsig_signaling_link_rsp; 12715 #endif /* defined(HAVE_PRI_CCSS) */ 12716 #if defined(HAVE_PRI_CALL_WAITING) 12717 pris[span].pri.max_call_waiting_calls = 12718 conf->pri.pri.max_call_waiting_calls; 12719 pris[span].pri.allow_call_waiting_calls = 12720 conf->pri.pri.allow_call_waiting_calls; 12721 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12722 pris[span].pri.transfer = conf->chan.transfer; 12723 pris[span].pri.facilityenable = conf->pri.pri.facilityenable; 12724 #if defined(HAVE_PRI_L2_PERSISTENCE) 12725 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence; 12726 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 12727 #if defined(HAVE_PRI_AOC_EVENTS) 12728 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag; 12729 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup; 12730 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 12731 if (chan_sig == SIG_BRI_PTMP) { 12732 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored; 12733 } else { 12734 /* Option does not apply to this line type. */ 12735 pris[span].pri.layer1_ignored = 0; 12736 } 12737 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag; 12738 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack; 12739 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding; 12740 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag)); 12741 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list)); 12742 #if defined(HAVE_PRI_MWI) 12743 ast_copy_string(pris[span].pri.mwi_mailboxes, 12744 conf->pri.pri.mwi_mailboxes, 12745 sizeof(pris[span].pri.mwi_mailboxes)); 12746 #endif /* defined(HAVE_PRI_MWI) */ 12747 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial)); 12748 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext)); 12749 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix)); 12750 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix)); 12751 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix)); 12752 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix)); 12753 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix)); 12754 pris[span].pri.resetinterval = conf->pri.pri.resetinterval; 12755 12756 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12757 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x]; 12758 } 12759 12760 #if defined(HAVE_PRI_CALL_WAITING) 12761 /* Channel initial config parameters. */ 12762 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd; 12763 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid; 12764 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname; 12765 pris[span].pri.ch_cfg.immediate = conf->chan.immediate; 12766 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive; 12767 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob; 12768 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid; 12769 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres; 12770 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context)); 12771 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret)); 12772 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12773 } else { 12774 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos); 12775 destroy_dahdi_pvt(tmp); 12776 return NULL; 12777 } 12778 } 12779 } 12780 #endif 12781 } else { 12782 /* already exists in interface list */ 12783 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)); 12784 chan_sig = tmp->sig; 12785 if (tmp->subs[SUB_REAL].dfd > -1) { 12786 memset(&p, 0, sizeof(p)); 12787 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12788 } 12789 } 12790 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 12791 switch (chan_sig) { 12792 case SIG_FXSKS: 12793 case SIG_FXSLS: 12794 case SIG_EM: 12795 case SIG_EM_E1: 12796 case SIG_EMWINK: 12797 case SIG_FEATD: 12798 case SIG_FEATDMF: 12799 case SIG_FEATDMF_TA: 12800 case SIG_FEATB: 12801 case SIG_E911: 12802 case SIG_SF: 12803 case SIG_SFWINK: 12804 case SIG_FGC_CAMA: 12805 case SIG_FGC_CAMAMF: 12806 case SIG_SF_FEATD: 12807 case SIG_SF_FEATDMF: 12808 case SIG_SF_FEATB: 12809 p.starttime = 250; 12810 break; 12811 } 12812 12813 if (tmp->radio) { 12814 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 12815 p.channo = channel; 12816 p.rxwinktime = 1; 12817 p.rxflashtime = 1; 12818 p.starttime = 1; 12819 p.debouncetime = 5; 12820 } else { 12821 p.channo = channel; 12822 /* Override timing settings based on config file */ 12823 if (conf->timing.prewinktime >= 0) 12824 p.prewinktime = conf->timing.prewinktime; 12825 if (conf->timing.preflashtime >= 0) 12826 p.preflashtime = conf->timing.preflashtime; 12827 if (conf->timing.winktime >= 0) 12828 p.winktime = conf->timing.winktime; 12829 if (conf->timing.flashtime >= 0) 12830 p.flashtime = conf->timing.flashtime; 12831 if (conf->timing.starttime >= 0) 12832 p.starttime = conf->timing.starttime; 12833 if (conf->timing.rxwinktime >= 0) 12834 p.rxwinktime = conf->timing.rxwinktime; 12835 if (conf->timing.rxflashtime >= 0) 12836 p.rxflashtime = conf->timing.rxflashtime; 12837 if (conf->timing.debouncetime >= 0) 12838 p.debouncetime = conf->timing.debouncetime; 12839 } 12840 12841 /* don't set parms on a pseudo-channel */ 12842 if (tmp->subs[SUB_REAL].dfd >= 0) 12843 { 12844 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 12845 if (res < 0) { 12846 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 12847 destroy_dahdi_pvt(tmp); 12848 return NULL; 12849 } 12850 } 12851 #if 1 12852 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 12853 memset(&bi, 0, sizeof(bi)); 12854 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 12855 if (!res) { 12856 bi.txbufpolicy = conf->chan.buf_policy; 12857 bi.rxbufpolicy = conf->chan.buf_policy; 12858 bi.numbufs = conf->chan.buf_no; 12859 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 12860 if (res < 0) { 12861 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 12862 } 12863 } else { 12864 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 12865 } 12866 tmp->buf_policy = conf->chan.buf_policy; 12867 tmp->buf_no = conf->chan.buf_no; 12868 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 12869 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 12870 tmp->faxbuf_no = conf->chan.faxbuf_no; 12871 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 12872 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 12873 * The reason the ioctl call above failed should to be determined before worrying about the 12874 * faxbuffer-related ioctl calls */ 12875 tmp->bufsize = bi.bufsize; 12876 } 12877 #endif 12878 tmp->immediate = conf->chan.immediate; 12879 tmp->transfertobusy = conf->chan.transfertobusy; 12880 if (chan_sig & __DAHDI_SIG_FXS) { 12881 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 12882 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 12883 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 12884 } 12885 tmp->ringt_base = ringt_base; 12886 tmp->firstradio = 0; 12887 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 12888 tmp->permcallwaiting = conf->chan.callwaiting; 12889 else 12890 tmp->permcallwaiting = 0; 12891 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 12892 tmp->destroy = 0; 12893 tmp->drings = conf->chan.drings; 12894 12895 /* 10 is a nice default. */ 12896 if (tmp->drings.ringnum[0].range == 0) 12897 tmp->drings.ringnum[0].range = 10; 12898 if (tmp->drings.ringnum[1].range == 0) 12899 tmp->drings.ringnum[1].range = 10; 12900 if (tmp->drings.ringnum[2].range == 0) 12901 tmp->drings.ringnum[2].range = 10; 12902 12903 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 12904 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 12905 tmp->threewaycalling = conf->chan.threewaycalling; 12906 tmp->adsi = conf->chan.adsi; 12907 tmp->use_smdi = conf->chan.use_smdi; 12908 tmp->permhidecallerid = conf->chan.hidecallerid; 12909 tmp->hidecalleridname = conf->chan.hidecalleridname; 12910 tmp->callreturn = conf->chan.callreturn; 12911 tmp->echocancel = conf->chan.echocancel; 12912 tmp->echotraining = conf->chan.echotraining; 12913 tmp->pulse = conf->chan.pulse; 12914 if (tmp->echocancel.head.tap_length) { 12915 tmp->echocanbridged = conf->chan.echocanbridged; 12916 } else { 12917 if (conf->chan.echocanbridged) 12918 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 12919 tmp->echocanbridged = 0; 12920 } 12921 tmp->busydetect = conf->chan.busydetect; 12922 tmp->busycount = conf->chan.busycount; 12923 tmp->busycompare = conf->chan.busycompare; 12924 tmp->busytonelength = conf->chan.busytonelength; 12925 tmp->busyquietlength = conf->chan.busyquietlength; 12926 tmp->busyfuzziness = conf->chan.busyfuzziness; 12927 tmp->silencethreshold = conf->chan.silencethreshold; 12928 tmp->callprogress = conf->chan.callprogress; 12929 tmp->waitfordialtone = conf->chan.waitfordialtone; 12930 tmp->cancallforward = conf->chan.cancallforward; 12931 tmp->dtmfrelax = conf->chan.dtmfrelax; 12932 tmp->callwaiting = tmp->permcallwaiting; 12933 tmp->hidecallerid = tmp->permhidecallerid; 12934 tmp->channel = channel; 12935 tmp->stripmsd = conf->chan.stripmsd; 12936 tmp->use_callerid = conf->chan.use_callerid; 12937 tmp->cid_signalling = conf->chan.cid_signalling; 12938 tmp->cid_start = conf->chan.cid_start; 12939 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 12940 tmp->restrictcid = conf->chan.restrictcid; 12941 tmp->use_callingpres = conf->chan.use_callingpres; 12942 if (tmp->usedistinctiveringdetection) { 12943 if (!tmp->use_callerid) { 12944 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 12945 tmp->use_callerid = 1; 12946 } 12947 } 12948 12949 if (tmp->cid_signalling == CID_SIG_SMDI) { 12950 if (!tmp->use_smdi) { 12951 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 12952 tmp->use_smdi = 1; 12953 } 12954 } 12955 if (tmp->use_smdi) { 12956 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 12957 if (!(tmp->smdi_iface)) { 12958 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 12959 tmp->use_smdi = 0; 12960 } 12961 } 12962 12963 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 12964 tmp->amaflags = conf->chan.amaflags; 12965 if (!here) { 12966 tmp->confno = -1; 12967 tmp->propconfno = -1; 12968 } 12969 tmp->canpark = conf->chan.canpark; 12970 tmp->transfer = conf->chan.transfer; 12971 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 12972 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 12973 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 12974 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 12975 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 12976 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 12977 tmp->cid_ton = 0; 12978 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) { 12979 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 12980 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 12981 } else { 12982 tmp->cid_num[0] = '\0'; 12983 tmp->cid_name[0] = '\0'; 12984 } 12985 #if defined(HAVE_PRI) 12986 if (dahdi_sig_pri_lib_handles(tmp->sig)) { 12987 tmp->cid_tag[0] = '\0'; 12988 } else 12989 #endif /* defined(HAVE_PRI) */ 12990 { 12991 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); 12992 } 12993 tmp->cid_subaddr[0] = '\0'; 12994 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 12995 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 12996 char *mailbox, *context; 12997 mailbox = context = ast_strdupa(tmp->mailbox); 12998 strsep(&context, "@"); 12999 if (ast_strlen_zero(context)) 13000 context = "default"; 13001 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL, 13002 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 13003 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 13004 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 13005 AST_EVENT_IE_END); 13006 } 13007 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 13008 tmp->mwisend_setting = conf->chan.mwisend_setting; 13009 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 13010 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 13011 #endif 13012 13013 tmp->group = conf->chan.group; 13014 tmp->callgroup = conf->chan.callgroup; 13015 tmp->pickupgroup= conf->chan.pickupgroup; 13016 if (conf->chan.vars) { 13017 struct ast_variable *v, *tmpvar; 13018 for (v = conf->chan.vars ; v ; v = v->next) { 13019 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 13020 tmpvar->next = tmp->vars; 13021 tmp->vars = tmpvar; 13022 } 13023 } 13024 } 13025 tmp->cid_rxgain = conf->chan.cid_rxgain; 13026 tmp->rxgain = conf->chan.rxgain; 13027 tmp->txgain = conf->chan.txgain; 13028 tmp->txdrc = conf->chan.txdrc; 13029 tmp->rxdrc = conf->chan.rxdrc; 13030 tmp->tonezone = conf->chan.tonezone; 13031 if (tmp->subs[SUB_REAL].dfd > -1) { 13032 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law); 13033 if (tmp->dsp) 13034 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 13035 update_conf(tmp); 13036 if (!here) { 13037 switch (chan_sig) { 13038 case SIG_PRI_LIB_HANDLE_CASES: 13039 case SIG_SS7: 13040 case SIG_MFCR2: 13041 break; 13042 default: 13043 /* Hang it up to be sure it's good */ 13044 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 13045 break; 13046 } 13047 } 13048 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 13049 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 13050 /* the dchannel is down so put the channel in alarm */ 13051 switch (tmp->sig) { 13052 #ifdef HAVE_PRI 13053 case SIG_PRI_LIB_HANDLE_CASES: 13054 sig_pri_set_alarm(tmp->sig_pvt, 1); 13055 break; 13056 #endif 13057 #if defined(HAVE_SS7) 13058 case SIG_SS7: 13059 sig_ss7_set_alarm(tmp->sig_pvt, 1); 13060 break; 13061 #endif /* defined(HAVE_SS7) */ 13062 default: 13063 /* The only sig submodule left should be sig_analog. */ 13064 analog_p = tmp->sig_pvt; 13065 if (analog_p) { 13066 analog_p->inalarm = 1; 13067 } 13068 tmp->inalarm = 1; 13069 break; 13070 } 13071 handle_alarms(tmp, res); 13072 } 13073 } 13074 13075 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13076 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13077 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13078 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 13079 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); 13080 13081 if (!here) { 13082 tmp->locallyblocked = 0; 13083 tmp->remotelyblocked = 0; 13084 switch (tmp->sig) { 13085 #if defined(HAVE_PRI) 13086 case SIG_PRI_LIB_HANDLE_CASES: 13087 tmp->inservice = 1;/* Inservice until actually implemented. */ 13088 #if defined(HAVE_PRI_SERVICE_MESSAGES) 13089 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0; 13090 if (chan_sig == SIG_PRI) { 13091 char db_chan_name[20]; 13092 char db_answer[5]; 13093 13094 /* 13095 * Initialize the active out-of-service status 13096 * and delete any record if the feature is not enabled. 13097 */ 13098 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); 13099 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 13100 unsigned *why; 13101 13102 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 13103 if (tmp->pri->enable_service_message_support) { 13104 char state; 13105 13106 sscanf(db_answer, "%1c:%30u", &state, why); 13107 13108 /* Ensure that only the implemented bits could be set.*/ 13109 *why &= (SRVST_NEAREND | SRVST_FAREND); 13110 } 13111 if (!*why) { 13112 ast_db_del(db_chan_name, SRVST_DBKEY); 13113 } 13114 } 13115 } 13116 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 13117 break; 13118 #endif /* defined(HAVE_PRI) */ 13119 #if defined(HAVE_SS7) 13120 case SIG_SS7: 13121 tmp->inservice = 0; 13122 break; 13123 #endif /* defined(HAVE_SS7) */ 13124 default: 13125 /* We default to in service on protocols that don't have a reset */ 13126 tmp->inservice = 1; 13127 break; 13128 } 13129 } 13130 13131 switch (tmp->sig) { 13132 #if defined(HAVE_PRI) 13133 case SIG_PRI_LIB_HANDLE_CASES: 13134 if (pri_chan) { 13135 pri_chan->channel = tmp->channel; 13136 pri_chan->hidecallerid = tmp->hidecallerid; 13137 pri_chan->hidecalleridname = tmp->hidecalleridname; 13138 pri_chan->immediate = tmp->immediate; 13139 pri_chan->inalarm = tmp->inalarm; 13140 pri_chan->priexclusive = tmp->priexclusive; 13141 pri_chan->priindication_oob = tmp->priindication_oob; 13142 pri_chan->use_callerid = tmp->use_callerid; 13143 pri_chan->use_callingpres = tmp->use_callingpres; 13144 ast_copy_string(pri_chan->context, tmp->context, 13145 sizeof(pri_chan->context)); 13146 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret, 13147 sizeof(pri_chan->mohinterpret)); 13148 pri_chan->stripmsd = tmp->stripmsd; 13149 } 13150 break; 13151 #endif /* defined(HAVE_PRI) */ 13152 #if defined(HAVE_SS7) 13153 case SIG_SS7: 13154 if (ss7_chan) { 13155 ss7_chan->inalarm = tmp->inalarm; 13156 13157 ss7_chan->stripmsd = tmp->stripmsd; 13158 ss7_chan->hidecallerid = tmp->hidecallerid; 13159 ss7_chan->use_callerid = tmp->use_callerid; 13160 ss7_chan->use_callingpres = tmp->use_callingpres; 13161 ss7_chan->immediate = tmp->immediate; 13162 ss7_chan->locallyblocked = tmp->locallyblocked; 13163 ss7_chan->remotelyblocked = tmp->remotelyblocked; 13164 ast_copy_string(ss7_chan->context, tmp->context, 13165 sizeof(ss7_chan->context)); 13166 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret, 13167 sizeof(ss7_chan->mohinterpret)); 13168 } 13169 break; 13170 #endif /* defined(HAVE_SS7) */ 13171 default: 13172 /* The only sig submodule left should be sig_analog. */ 13173 analog_p = tmp->sig_pvt; 13174 if (analog_p) { 13175 analog_p->channel = tmp->channel; 13176 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13177 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13178 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13179 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ 13180 analog_p->callreturn = conf->chan.callreturn; 13181 analog_p->cancallforward = conf->chan.cancallforward; 13182 analog_p->canpark = conf->chan.canpark; 13183 analog_p->dahditrcallerid = conf->chan.dahditrcallerid; 13184 analog_p->immediate = conf->chan.immediate; 13185 analog_p->permhidecallerid = conf->chan.permhidecallerid; 13186 analog_p->pulse = conf->chan.pulse; 13187 analog_p->threewaycalling = conf->chan.threewaycalling; 13188 analog_p->transfer = conf->chan.transfer; 13189 analog_p->transfertobusy = conf->chan.transfertobusy; 13190 analog_p->use_callerid = tmp->use_callerid; 13191 analog_p->use_smdi = tmp->use_smdi; 13192 analog_p->smdi_iface = tmp->smdi_iface; 13193 analog_p->outsigmod = ANALOG_SIG_NONE; 13194 analog_p->echotraining = conf->chan.echotraining; 13195 analog_p->cid_signalling = conf->chan.cid_signalling; 13196 analog_p->stripmsd = conf->chan.stripmsd; 13197 switch (conf->chan.cid_start) { 13198 case CID_START_POLARITY: 13199 analog_p->cid_start = ANALOG_CID_START_POLARITY; 13200 break; 13201 case CID_START_POLARITY_IN: 13202 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; 13203 break; 13204 case CID_START_DTMF_NOALERT: 13205 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; 13206 break; 13207 default: 13208 analog_p->cid_start = ANALOG_CID_START_RING; 13209 break; 13210 } 13211 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; 13212 analog_p->ringt = conf->chan.ringt; 13213 analog_p->ringt_base = ringt_base; 13214 analog_p->onhooktime = time(NULL); 13215 if (chan_sig & __DAHDI_SIG_FXO) { 13216 memset(&p, 0, sizeof(p)); 13217 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 13218 if (!res) { 13219 analog_p->fxsoffhookstate = p.rxisoffhook; 13220 } 13221 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 13222 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 13223 #endif 13224 } 13225 analog_p->msgstate = -1; 13226 13227 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); 13228 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); 13229 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); 13230 13231 analog_config_complete(analog_p); 13232 } 13233 break; 13234 } 13235 #if defined(HAVE_PRI) 13236 if (tmp->channel == CHAN_PSEUDO) { 13237 /* 13238 * Save off pseudo channel buffer policy values for dynamic creation of 13239 * no B channel interfaces. 13240 */ 13241 dahdi_pseudo_parms.buf_no = tmp->buf_no; 13242 dahdi_pseudo_parms.buf_policy = tmp->buf_policy; 13243 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no; 13244 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy; 13245 } 13246 #endif /* defined(HAVE_PRI) */ 13247 } 13248 if (tmp && !here) { 13249 /* Add the new channel interface to the sorted channel interface list. */ 13250 dahdi_iflist_insert(tmp); 13251 } 13252 return tmp; 13253 }
static void monitor_pfds_clean | ( | void * | arg | ) | [static] |
Definition at line 11740 of file chan_dahdi.c.
References ast_free.
Referenced by do_monitor().
11740 { 11741 struct pollfd **pfds = arg; 11742 ast_free(*pfds); 11743 }
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 11287 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().
11288 { 11289 int x; 11290 11291 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11292 /* Determine how this spill is to be sent */ 11293 if (pvt->mwisend_rpas) { 11294 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11295 pvt->mwisendactive = 1; 11296 } else if (pvt->mwisend_fsk) { 11297 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11298 pvt->mwisendactive = 1; 11299 } else { 11300 pvt->mwisendactive = 0; 11301 return 0; 11302 } 11303 #else 11304 if (mwisend_rpas) { 11305 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11306 } else { 11307 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11308 } 11309 pvt->mwisendactive = 1; 11310 #endif 11311 11312 if (pvt->cidspill) { 11313 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 11314 ast_free(pvt->cidspill); 11315 pvt->cidspill = NULL; 11316 pvt->cidpos = 0; 11317 pvt->cidlen = 0; 11318 } 11319 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 11320 if (!pvt->cidspill) { 11321 pvt->mwisendactive = 0; 11322 return -1; 11323 } 11324 x = DAHDI_FLUSH_BOTH; 11325 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 11326 x = 3000; 11327 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 11328 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11329 if (pvt->mwisend_fsk) { 11330 #endif 11331 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 11332 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 11333 pvt->cidpos = 0; 11334 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11335 } 11336 #endif 11337 return 0; 11338 }
static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
int | num_read | |||
) | [static] |
Definition at line 11340 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().
11341 { 11342 struct timeval now; 11343 int res; 11344 11345 /* sanity check to catch if this had been interrupted previously 11346 * i.e. state says there is more to do but there is no spill allocated 11347 */ 11348 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 11349 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11350 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11351 /* Normal processing -- Perform mwi send action */ 11352 switch ( pvt->mwisend_data.mwisend_current) { 11353 case MWI_SEND_SA: 11354 /* Send the Ring Pulse Signal Alert */ 11355 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 11356 if (res) { 11357 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 11358 goto quit; 11359 } 11360 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 11361 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 11362 break; 11363 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 11364 break; 11365 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 11366 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11367 if (pvt->mwisend_fsk) { 11368 #endif 11369 gettimeofday(&now, NULL); 11370 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 11371 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11372 } 11373 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11374 } else { /* support for mwisendtype=nofsk */ 11375 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11376 } 11377 #endif 11378 break; 11379 case MWI_SEND_SPILL: 11380 /* We read some number of bytes. Write an equal amount of data */ 11381 if(0 < num_read) { 11382 if (num_read > pvt->cidlen - pvt->cidpos) 11383 num_read = pvt->cidlen - pvt->cidpos; 11384 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 11385 if (res > 0) { 11386 pvt->cidpos += res; 11387 if (pvt->cidpos >= pvt->cidlen) { 11388 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11389 } 11390 } else { 11391 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 11392 goto quit; 11393 } 11394 } 11395 break; 11396 case MWI_SEND_CLEANUP: 11397 /* For now, do nothing */ 11398 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11399 break; 11400 default: 11401 /* Should not get here, punt*/ 11402 goto quit; 11403 } 11404 } 11405 11406 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 11407 if (pvt->cidspill) { 11408 ast_free(pvt->cidspill); 11409 pvt->cidspill = NULL; 11410 pvt->cidpos = 0; 11411 pvt->cidlen = 0; 11412 } 11413 pvt->mwisendactive = 0; 11414 } 11415 return 0; 11416 quit: 11417 if (pvt->cidspill) { 11418 ast_free(pvt->cidspill); 11419 pvt->cidspill = NULL; 11420 pvt->cidpos = 0; 11421 pvt->cidlen = 0; 11422 } 11423 pvt->mwisendactive = 0; 11424 return -1; 11425 }
static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
int | event | |||
) | [static] |
Definition at line 11427 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().
11428 { 11429 int handled = 0; 11430 11431 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11432 switch (event) { 11433 case DAHDI_EVENT_RINGEROFF: 11434 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 11435 handled = 1; 11436 11437 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 11438 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno)); 11439 ast_free(pvt->cidspill); 11440 pvt->cidspill = NULL; 11441 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11442 pvt->mwisendactive = 0; 11443 } else { 11444 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 11445 gettimeofday(&pvt->mwisend_data.pause, NULL); 11446 } 11447 } 11448 break; 11449 /* Going off hook, I need to punt this spill */ 11450 case DAHDI_EVENT_RINGOFFHOOK: 11451 if (pvt->cidspill) { 11452 ast_free(pvt->cidspill); 11453 pvt->cidspill = NULL; 11454 pvt->cidpos = 0; 11455 pvt->cidlen = 0; 11456 } 11457 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11458 pvt->mwisendactive = 0; 11459 break; 11460 case DAHDI_EVENT_RINGERON: 11461 case DAHDI_EVENT_HOOKCOMPLETE: 11462 break; 11463 default: 11464 break; 11465 } 11466 } 11467 return handled; 11468 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 11135 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().
11136 { 11137 struct mwi_thread_data *mtd = data; 11138 struct callerid_state *cs; 11139 pthread_t threadid; 11140 int samples = 0; 11141 char *name, *number; 11142 int flags; 11143 int i, res; 11144 unsigned int spill_done = 0; 11145 int spill_result = -1; 11146 11147 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 11148 goto quit_no_clean; 11149 } 11150 11151 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 11152 11153 bump_gains(mtd->pvt); 11154 11155 for (;;) { 11156 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 11157 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 11158 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 11159 goto quit; 11160 } 11161 11162 if (i & DAHDI_IOMUX_SIGEVENT) { 11163 struct ast_channel *chan; 11164 11165 /* If we get an event, screen out events that we do not act on. 11166 * Otherwise, cancel and go to the simple switch to let it deal with it. 11167 */ 11168 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 11169 11170 switch (res) { 11171 case DAHDI_EVENT_NEONMWI_ACTIVE: 11172 case DAHDI_EVENT_NEONMWI_INACTIVE: 11173 case DAHDI_EVENT_NONE: 11174 case DAHDI_EVENT_BITSCHANGED: 11175 break; 11176 case DAHDI_EVENT_NOALARM: 11177 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11178 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11179 11180 analog_p->inalarm = 0; 11181 } 11182 mtd->pvt->inalarm = 0; 11183 handle_clear_alarms(mtd->pvt); 11184 break; 11185 case DAHDI_EVENT_ALARM: 11186 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11187 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11188 11189 analog_p->inalarm = 1; 11190 } 11191 mtd->pvt->inalarm = 1; 11192 res = get_alarms(mtd->pvt); 11193 handle_alarms(mtd->pvt, res); 11194 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 11195 default: 11196 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res)); 11197 callerid_free(cs); 11198 11199 restore_gains(mtd->pvt); 11200 mtd->pvt->ringt = mtd->pvt->ringt_base; 11201 11202 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) { 11203 int result; 11204 11205 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11206 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan); 11207 } else { 11208 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11209 } 11210 if (result) { 11211 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 11212 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11213 if (res < 0) 11214 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 11215 ast_hangup(chan); 11216 } 11217 } else { 11218 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 11219 } 11220 goto quit_no_clean; 11221 } 11222 } else if (i & DAHDI_IOMUX_READ) { 11223 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 11224 if (errno != ELAST) { 11225 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 11226 goto quit; 11227 } 11228 break; 11229 } 11230 samples += res; 11231 if (!spill_done) { 11232 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 11233 /* 11234 * The previous diagnostic message output likely 11235 * explains why it failed. 11236 */ 11237 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 11238 break; 11239 } else if (spill_result) { 11240 spill_done = 1; 11241 } 11242 } else { 11243 /* keep reading data until the energy level drops below the threshold 11244 so we don't get another 'trigger' on the remaining carrier signal 11245 */ 11246 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 11247 break; 11248 } 11249 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 11250 break; 11251 } 11252 } 11253 11254 if (spill_result == 1) { 11255 callerid_get(cs, &name, &number, &flags); 11256 if (flags & CID_MSGWAITING) { 11257 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 11258 notify_message(mtd->pvt->mailbox, 1); 11259 } else if (flags & CID_NOMSGWAITING) { 11260 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 11261 notify_message(mtd->pvt->mailbox, 0); 11262 } else { 11263 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 11264 } 11265 } 11266 11267 11268 quit: 11269 callerid_free(cs); 11270 11271 restore_gains(mtd->pvt); 11272 11273 quit_no_clean: 11274 mtd->pvt->mwimonitoractive = 0; 11275 ast_free(mtd); 11276 11277 return NULL; 11278 }
static void my_all_subchannels_hungup | ( | void * | pvt | ) | [static] |
Definition at line 2459 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.
02460 { 02461 struct dahdi_pvt *p = pvt; 02462 int res, law; 02463 02464 p->faxhandled = 0; 02465 p->didtdd = 0; 02466 02467 if (p->dsp) { 02468 ast_dsp_free(p->dsp); 02469 p->dsp = NULL; 02470 } 02471 02472 p->law = p->law_default; 02473 law = p->law_default; 02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02475 if (res < 0) 02476 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02477 02478 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02479 02480 #if 1 02481 { 02482 int i; 02483 p->owner = NULL; 02484 /* Cleanup owners here */ 02485 for (i = 0; i < 3; i++) { 02486 p->subs[i].owner = NULL; 02487 } 02488 } 02489 #endif 02490 02491 reset_conf(p); 02492 if (num_restart_pending == 0) { 02493 restart_monitor(); 02494 } 02495 }
static int my_allocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2770 of file chan_dahdi.c.
References alloc_sub(), and analogsub_to_dahdisub().
02771 { 02772 struct dahdi_pvt *p = pvt; 02773 02774 return alloc_sub(p, analogsub_to_dahdisub(analogsub)); 02775 }
static void my_answer_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 3008 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().
03009 { 03010 struct dahdi_pvt *p = pvt; 03011 03012 if (!p->answeronpolarityswitch) { 03013 return; 03014 } 03015 03016 my_set_polarity(pvt, 1); 03017 }
static int my_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1951 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().
01952 { 01953 struct dahdi_pvt *p = pvt; 01954 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01955 if (p->cidspill) { 01956 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01957 ast_free(p->cidspill); 01958 } 01959 01960 /* 01961 * SAS: Subscriber Alert Signal, 440Hz for 300ms 01962 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 01963 */ 01964 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01965 return -1; 01966 save_conference(p); 01967 /* Silence */ 01968 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01969 if (!p->callwaitrings && p->callwaitingcallerid) { 01970 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01971 p->callwaitcas = 1; 01972 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01973 } else { 01974 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01975 p->callwaitcas = 0; 01976 p->cidlen = 2400 + READ_SIZE * 4; 01977 } 01978 p->cidpos = 0; 01979 send_callerid(p); 01980 01981 return 0; 01982 }
static void my_cancel_cidspill | ( | void * | pvt | ) | [static] |
Definition at line 2409 of file chan_dahdi.c.
References ast_free, dahdi_pvt::cidspill, and restore_conference().
02410 { 02411 struct dahdi_pvt *p = pvt; 02412 02413 ast_free(p->cidspill); 02414 p->cidspill = NULL; 02415 restore_conference(p); 02416 }
static int my_check_confirmanswer | ( | void * | pvt | ) | [static] |
Definition at line 2392 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02393 { 02394 struct dahdi_pvt *p = pvt; 02395 if (p->confirmanswer) { 02396 return 1; 02397 } 02398 02399 return 0; 02400 }
static int my_check_for_conference | ( | void * | pvt | ) | [static] |
Definition at line 2569 of file chan_dahdi.c.
References check_for_conference().
02570 { 02571 struct dahdi_pvt *p = pvt; 02572 return check_for_conference(p); 02573 }
static int my_check_waitingfordt | ( | void * | pvt | ) | [static] |
Definition at line 2375 of file chan_dahdi.c.
References dahdi_pvt::waitingfordt.
02376 { 02377 struct dahdi_pvt *p = pvt; 02378 02379 if (p->waitingfordt.tv_sec) { 02380 return 1; 02381 } 02382 02383 return 0; 02384 }
static int my_complete_conference_update | ( | void * | pvt, | |
int | needconference | |||
) | [static] |
Definition at line 2519 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.
02520 { 02521 struct dahdi_pvt *p = pvt; 02522 int needconf = needconference; 02523 int x; 02524 int useslavenative; 02525 struct dahdi_pvt *slave = NULL; 02526 02527 useslavenative = isslavenative(p, &slave); 02528 02529 /* If we have a slave, add him to our conference now. or DAX 02530 if this is slave native */ 02531 for (x = 0; x < MAX_SLAVES; x++) { 02532 if (p->slaves[x]) { 02533 if (useslavenative) 02534 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02535 else { 02536 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02537 needconf++; 02538 } 02539 } 02540 } 02541 /* If we're supposed to be in there, do so now */ 02542 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02543 if (useslavenative) 02544 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02545 else { 02546 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02547 needconf++; 02548 } 02549 } 02550 /* If we have a master, add ourselves to his conference */ 02551 if (p->master) { 02552 if (isslavenative(p->master, NULL)) { 02553 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02554 } else { 02555 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02556 } 02557 } 02558 if (!needconf) { 02559 /* Nobody is left (or should be left) in our conference. 02560 Kill it. */ 02561 p->confno = -1; 02562 } 02563 02564 return 0; 02565 }
static int my_conf_add | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2509 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.
02510 { 02511 struct dahdi_pvt *p = pvt; 02512 int x = analogsub_to_dahdisub(sub); 02513 02514 return conf_add(p, &p->subs[x], x, 0); 02515 }
static int my_conf_del | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2499 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.
02500 { 02501 struct dahdi_pvt *p = pvt; 02502 int x = analogsub_to_dahdisub(sub); 02503 02504 return conf_del(p, &p->subs[x], x); 02505 }
static int my_confmute | ( | void * | pvt, | |
int | mute | |||
) | [static] |
Definition at line 2418 of file chan_dahdi.c.
References dahdi_confmute().
02419 { 02420 struct dahdi_pvt *p = pvt; 02421 return dahdi_confmute(p, mute); 02422 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | idx, | |||
int | linear | |||
) | [static] |
Definition at line 9392 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().
09393 { 09394 int sent=0; 09395 int size; 09396 int res; 09397 int fd; 09398 fd = p->subs[idx].dfd; 09399 while (len) { 09400 size = len; 09401 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 09402 size = (linear ? READ_SIZE * 2 : READ_SIZE); 09403 res = write(fd, buf, size); 09404 if (res != size) { 09405 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 09406 return sent; 09407 } 09408 len -= size; 09409 buf += size; 09410 } 09411 return sent; 09412 }
static void my_deadlock_avoidance_private | ( | void * | pvt | ) | [static] |
Definition at line 2169 of file chan_dahdi.c.
References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.
02170 { 02171 struct dahdi_pvt *p = pvt; 02172 02173 DEADLOCK_AVOIDANCE(&p->lock); 02174 }
static void my_decrease_ss_count | ( | void | ) | [static] |
Definition at line 2451 of file chan_dahdi.c.
References ast_cond_signal, ast_mutex_lock, and ast_mutex_unlock.
02452 { 02453 ast_mutex_lock(&ss_thread_lock); 02454 ss_thread_count--; 02455 ast_cond_signal(&ss_thread_complete); 02456 ast_mutex_unlock(&ss_thread_lock); 02457 }
static int my_dial_digits | ( | void * | pvt, | |
enum analog_sub | sub, | |||
struct analog_dialoperation * | dop | |||
) | [static] |
Definition at line 3042 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.
03043 { 03044 int index = analogsub_to_dahdisub(sub); 03045 int res; 03046 struct dahdi_pvt *p = pvt; 03047 struct dahdi_dialoperation ddop; 03048 03049 if (dop->op != ANALOG_DIAL_OP_REPLACE) { 03050 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n"); 03051 return -1; 03052 } 03053 03054 if (sub != ANALOG_SUB_REAL) { 03055 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n", 03056 dop->dialstr, p->channel, sub); 03057 return -1; 03058 } 03059 03060 ddop.op = DAHDI_DIAL_OP_REPLACE; 03061 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr)); 03062 03063 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr); 03064 03065 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop); 03066 if (res == -1) { 03067 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno)); 03068 } 03069 03070 return res; 03071 }
static int my_distinctive_ring | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | idx, | |||
int * | ringdata | |||
) | [static] |
Definition at line 1815 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.
01816 { 01817 unsigned char buf[256]; 01818 int distMatches; 01819 int curRingData[RING_PATTERNS]; 01820 int receivedRingT; 01821 int counter1; 01822 int counter; 01823 int i; 01824 int res; 01825 int checkaftercid = 0; 01826 01827 struct dahdi_pvt *p = pvt; 01828 struct analog_pvt *analog_p = p->sig_pvt; 01829 01830 if (ringdata == NULL) { 01831 ringdata = curRingData; 01832 } else { 01833 checkaftercid = 1; 01834 } 01835 01836 /* We must have a ring by now, so, if configured, lets try to listen for 01837 * distinctive ringing */ 01838 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { 01839 /* Clear the current ring data array so we don't have old data in it. */ 01840 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++) 01841 ringdata[receivedRingT] = 0; 01842 receivedRingT = 0; 01843 if (checkaftercid && distinctiveringaftercid) 01844 ast_verb(3, "Detecting post-CID distinctive ring\n"); 01845 /* Check to see if context is what it should be, if not set to be. */ 01846 else if (strcmp(p->context,p->defcontext) != 0) { 01847 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 01848 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 01849 } 01850 01851 for (;;) { 01852 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 01853 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 01854 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 01855 ast_hangup(chan); 01856 return 1; 01857 } 01858 if (i & DAHDI_IOMUX_SIGEVENT) { 01859 res = dahdi_get_event(p->subs[idx].dfd); 01860 if (res == DAHDI_EVENT_NOALARM) { 01861 p->inalarm = 0; 01862 analog_p->inalarm = 0; 01863 } 01864 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 01865 res = 0; 01866 /* Let us detect distinctive ring */ 01867 01868 ringdata[receivedRingT] = analog_p->ringt; 01869 01870 if (analog_p->ringt < analog_p->ringt_base/2) 01871 break; 01872 /* Increment the ringT counter so we can match it against 01873 values in chan_dahdi.conf for distinctive ring */ 01874 if (++receivedRingT == RING_PATTERNS) 01875 break; 01876 } else if (i & DAHDI_IOMUX_READ) { 01877 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 01878 if (res < 0) { 01879 if (errno != ELAST) { 01880 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01881 ast_hangup(chan); 01882 return 1; 01883 } 01884 break; 01885 } 01886 if (analog_p->ringt > 0) { 01887 if (!(--analog_p->ringt)) { 01888 res = -1; 01889 break; 01890 } 01891 } 01892 } 01893 } 01894 } 01895 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { 01896 /* this only shows up if you have n of the dring patterns filled in */ 01897 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); 01898 for (counter = 0; counter < 3; counter++) { 01899 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ 01900 distMatches = 0; 01901 /* this only shows up if you have n of the dring patterns filled in */ 01902 ast_verb(3, "Checking %d,%d,%d\n", 01903 p->drings.ringnum[counter].ring[0], 01904 p->drings.ringnum[counter].ring[1], 01905 p->drings.ringnum[counter].ring[2]); 01906 for (counter1 = 0; counter1 < 3; counter1++) { 01907 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 01908 if (p->drings.ringnum[counter].ring[counter1] == -1) { 01909 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 01910 ringdata[counter1]); 01911 distMatches++; 01912 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 01913 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 01914 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 01915 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 01916 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 01917 distMatches++; 01918 } 01919 } 01920 01921 if (distMatches == 3) { 01922 /* The ring matches, set the context to whatever is for distinctive ring.. */ 01923 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 01924 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 01925 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 01926 break; 01927 } 01928 } 01929 } 01930 /* Restore linear mode (if appropriate) for Caller*ID processing */ 01931 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 01932 restore_gains(p); 01933 01934 return 0; 01935 }
static int my_dsp_reset_and_flush_digits | ( | void * | pvt | ) | [static] |
Definition at line 2019 of file chan_dahdi.c.
References ast_dsp_digitreset(), and dahdi_pvt::dsp.
02020 { 02021 struct dahdi_pvt *p = pvt; 02022 if (p->dsp) 02023 ast_dsp_digitreset(p->dsp); 02024 02025 return 0; 02026 }
static int my_dsp_set_digitmode | ( | void * | pvt, | |
enum analog_dsp_digitmode | mode | |||
) | [static] |
Definition at line 2028 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.
02029 { 02030 struct dahdi_pvt *p = pvt; 02031 02032 if (p->channel == CHAN_PSEUDO) 02033 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n"); 02034 02035 if (mode == ANALOG_DIGITMODE_DTMF) { 02036 /* If we do hardware dtmf, no need for a DSP */ 02037 if (p->hardwaredtmf) { 02038 if (p->dsp) { 02039 ast_dsp_free(p->dsp); 02040 p->dsp = NULL; 02041 } 02042 return 0; 02043 } 02044 02045 if (!p->dsp) { 02046 p->dsp = ast_dsp_new(); 02047 if (!p->dsp) { 02048 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02049 return -1; 02050 } 02051 } 02052 02053 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 02054 } else if (mode == ANALOG_DIGITMODE_MF) { 02055 if (!p->dsp) { 02056 p->dsp = ast_dsp_new(); 02057 if (!p->dsp) { 02058 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02059 return -1; 02060 } 02061 } 02062 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 02063 } 02064 return 0; 02065 }
static int my_flash | ( | void * | pvt | ) | [static] |
Definition at line 2967 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 2255 of file chan_dahdi.c.
References get_alarms(), and handle_alarms().
02256 { 02257 int res; 02258 struct dahdi_pvt *p = pvt; 02259 02260 res = get_alarms(p); 02261 handle_alarms(p, res); 02262 }
static int my_get_callerid | ( | void * | pvt, | |
char * | namebuf, | |||
char * | numbuf, | |||
enum analog_event * | ev, | |||
size_t | timeout | |||
) | [static] |
Definition at line 1741 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.
01742 { 01743 struct dahdi_pvt *p = pvt; 01744 struct analog_pvt *analog_p = p->sig_pvt; 01745 struct pollfd poller; 01746 char *name, *num; 01747 int index = SUB_REAL; 01748 int res; 01749 unsigned char buf[256]; 01750 int flags; 01751 01752 poller.fd = p->subs[SUB_REAL].dfd; 01753 poller.events = POLLPRI | POLLIN; 01754 poller.revents = 0; 01755 01756 res = poll(&poller, 1, timeout); 01757 01758 if (poller.revents & POLLPRI) { 01759 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd)); 01760 return 1; 01761 } 01762 01763 if (poller.revents & POLLIN) { 01764 /*** NOTES ***/ 01765 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function 01766 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until 01767 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be 01768 * a failure and die, and returning 2 means no event was received. */ 01769 res = read(p->subs[index].dfd, buf, sizeof(buf)); 01770 if (res < 0) { 01771 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01772 return -1; 01773 } 01774 01775 if (analog_p->ringt > 0) { 01776 if (!(--analog_p->ringt)) { 01777 /* only return if we timeout from a ring event */ 01778 return -1; 01779 } 01780 } 01781 01782 if (p->cid_signalling == CID_SIG_V23_JP) { 01783 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); 01784 } else { 01785 res = callerid_feed(p->cs, buf, res, AST_LAW(p)); 01786 } 01787 if (res < 0) { 01788 /* 01789 * The previous diagnostic message output likely 01790 * explains why it failed. 01791 */ 01792 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 01793 return -1; 01794 } 01795 01796 if (res == 1) { 01797 callerid_get(p->cs, &name, &num, &flags); 01798 if (name) 01799 ast_copy_string(namebuf, name, ANALOG_MAX_CID); 01800 if (num) 01801 ast_copy_string(numbuf, num, ANALOG_MAX_CID); 01802 01803 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags); 01804 return 0; 01805 } 01806 } 01807 01808 *ev = ANALOG_EVENT_NONE; 01809 return 2; 01810 }
static int my_get_event | ( | void * | pvt | ) | [static] |
Definition at line 2900 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.
02901 { 02902 struct dahdi_pvt *p = pvt; 02903 int res; 02904 02905 if (p->fake_event) { 02906 res = p->fake_event; 02907 p->fake_event = 0; 02908 } else 02909 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 02910 02911 return dahdievent_to_analogevent(res); 02912 }
static const char* my_get_orig_dialstring | ( | void * | pvt | ) | [static] |
Definition at line 2437 of file chan_dahdi.c.
References dahdi_pvt::dialstring.
02438 { 02439 struct dahdi_pvt *p = pvt; 02440 02441 return p->dialstring; 02442 }
static void* my_get_sigpvt_bridged_channel | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 2264 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.
02265 { 02266 struct ast_channel *bridged = ast_bridged_channel(chan); 02267 02268 if (bridged && bridged->tech == &dahdi_tech) { 02269 struct dahdi_pvt *p = bridged->tech_pvt; 02270 02271 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 02272 return p->sig_pvt; 02273 } 02274 } 02275 return NULL; 02276 }
static int my_get_sub_fd | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2278 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02279 { 02280 struct dahdi_pvt *p = pvt; 02281 int dahdi_sub = analogsub_to_dahdisub(sub); 02282 return p->subs[dahdi_sub].dfd; 02283 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 9874 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by analog_ss_thread().
09875 { 09876 char c; 09877 09878 *str = 0; /* start with empty output buffer */ 09879 for (;;) 09880 { 09881 /* Wait for the first digit (up to specified ms). */ 09882 c = ast_waitfordigit(chan, ms); 09883 /* if timeout, hangup or error, return as such */ 09884 if (c < 1) 09885 return c; 09886 *str++ = c; 09887 *str = 0; 09888 if (strchr(term, c)) 09889 return 1; 09890 } 09891 }
static void my_handle_dtmf | ( | void * | pvt, | |
struct ast_channel * | ast, | |||
enum analog_sub | analog_index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 2085 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.
02086 { 02087 struct ast_frame *f = *dest; 02088 struct dahdi_pvt *p = pvt; 02089 int idx = analogsub_to_dahdisub(analog_index); 02090 02091 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 02092 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 02093 (unsigned)f->subclass.integer, f->subclass.integer, ast->name); 02094 02095 if (f->subclass.integer == 'f') { 02096 if (f->frametype == AST_FRAME_DTMF_END) { 02097 /* Fax tone -- Handle and return NULL */ 02098 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 02099 /* If faxbuffers are configured, use them for the fax transmission */ 02100 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 02101 struct dahdi_bufferinfo bi = { 02102 .txbufpolicy = p->faxbuf_policy, 02103 .bufsize = p->bufsize, 02104 .numbufs = p->faxbuf_no 02105 }; 02106 int res; 02107 02108 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 02109 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 02110 } else { 02111 p->bufferoverrideinuse = 1; 02112 } 02113 } 02114 p->faxhandled = 1; 02115 if (p->dsp) { 02116 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 02117 ast_dsp_set_features(p->dsp, p->dsp_features); 02118 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 02119 } 02120 if (strcmp(ast->exten, "fax")) { 02121 const char *target_context = S_OR(ast->macrocontext, ast->context); 02122 02123 /* We need to unlock 'ast' here because ast_exists_extension has the 02124 * potential to start autoservice on the channel. Such action is prone 02125 * to deadlock. 02126 */ 02127 ast_mutex_unlock(&p->lock); 02128 ast_channel_unlock(ast); 02129 if (ast_exists_extension(ast, target_context, "fax", 1, 02130 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 02131 ast_channel_lock(ast); 02132 ast_mutex_lock(&p->lock); 02133 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 02134 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 02135 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 02136 if (ast_async_goto(ast, target_context, "fax", 1)) 02137 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 02138 } else { 02139 ast_channel_lock(ast); 02140 ast_mutex_lock(&p->lock); 02141 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 02142 } 02143 } else { 02144 ast_debug(1, "Already in a fax extension, not redirecting\n"); 02145 } 02146 } else { 02147 ast_debug(1, "Fax already handled\n"); 02148 } 02149 dahdi_confmute(p, 0); 02150 } 02151 p->subs[idx].f.frametype = AST_FRAME_NULL; 02152 p->subs[idx].f.subclass.integer = 0; 02153 *dest = &p->subs[idx].f; 02154 } 02155 }
static void my_handle_notify_message | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | cid_flags, | |||
int | neon_mwievent | |||
) | [static] |
Definition at line 3689 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().
03690 { 03691 struct dahdi_pvt *p = pvt; 03692 03693 if (neon_mwievent > -1 && !p->mwimonitor_neon) 03694 return; 03695 03696 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) { 03697 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox); 03698 notify_message(p->mailbox, 1); 03699 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) { 03700 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox); 03701 notify_message(p->mailbox, 0); 03702 } 03703 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 03704 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 03705 if (neon_mwievent == -1 && p->mwimonitor_rpas) { 03706 ast_hangup(chan); 03707 return; 03708 } 03709 }
static void my_hangup_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 3019 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
03020 { 03021 struct dahdi_pvt *p = pvt; 03022 03023 if (!p->hanguponpolarityswitch) { 03024 return; 03025 } 03026 03027 if (p->answeronpolarityswitch) { 03028 my_set_polarity(pvt, 0); 03029 } else { 03030 my_set_polarity(pvt, 1); 03031 } 03032 }
static int my_has_voicemail | ( | void * | pvt | ) | [static] |
Definition at line 2779 of file chan_dahdi.c.
References has_voicemail().
02780 { 02781 struct dahdi_pvt *p = pvt; 02782 02783 return has_voicemail(p); 02784 }
static int my_have_progressdetect | ( | void * | pvt | ) | [static] |
Definition at line 3711 of file chan_dahdi.c.
References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.
03712 { 03713 struct dahdi_pvt *p = pvt; 03714 03715 if ((p->callprogress & CALLPROGRESS_PROGRESS) 03716 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03717 return 1; 03718 } else { 03719 /* Don't have progress detection. */ 03720 return 0; 03721 } 03722 }
static void my_increase_ss_count | ( | void | ) | [static] |
Definition at line 2444 of file chan_dahdi.c.
References ast_mutex_lock, and ast_mutex_unlock.
02445 { 02446 ast_mutex_lock(&ss_thread_lock); 02447 ss_thread_count++; 02448 ast_mutex_unlock(&ss_thread_lock); 02449 }
static int my_is_dialing | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 3084 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 2914 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.
02915 { 02916 struct dahdi_pvt *p = pvt; 02917 int res; 02918 struct dahdi_params par; 02919 02920 memset(&par, 0, sizeof(par)); 02921 02922 if (p->subs[SUB_REAL].dfd > -1) 02923 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02924 else { 02925 /* Assume not off hook on CVRS */ 02926 res = 0; 02927 par.rxisoffhook = 0; 02928 } 02929 if (res) { 02930 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 02931 } 02932 02933 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 02934 /* When "onhook" that means no battery on the line, and thus 02935 it is out of service..., if it's on a TDM card... If it's a channel 02936 bank, there is no telling... */ 02937 return (par.rxbits > -1) || par.rxisoffhook; 02938 } 02939 02940 return par.rxisoffhook; 02941 }
static void my_lock_private | ( | void * | pvt | ) | [static] |
Definition at line 2157 of file chan_dahdi.c.
References ast_mutex_lock, and dahdi_pvt::lock.
02158 { 02159 struct dahdi_pvt *p = pvt; 02160 ast_mutex_lock(&p->lock); 02161 }
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 2609 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and dahdi_new().
02610 { 02611 struct dahdi_pvt *p = pvt; 02612 int dsub = analogsub_to_dahdisub(sub); 02613 02614 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : ""); 02615 }
static int my_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2976 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
02977 { 02978 struct dahdi_pvt *p = pvt; 02979 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02980 }
static int my_on_hook | ( | void * | pvt | ) | [static] |
Definition at line 3100 of file chan_dahdi.c.
References ANALOG_SUB_REAL, dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
03101 { 03102 struct dahdi_pvt *p = pvt; 03103 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK); 03104 }
static int my_play_tone | ( | void * | pvt, | |
enum analog_sub | sub, | |||
enum analog_tone | tone | |||
) | [static] |
Definition at line 2786 of file chan_dahdi.c.
References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02787 { 02788 struct dahdi_pvt *p = pvt; 02789 int index; 02790 02791 index = analogsub_to_dahdisub(sub); 02792 02793 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone)); 02794 }
static int my_ring | ( | void * | pvt | ) | [static] |
Definition at line 2960 of file chan_dahdi.c.
References dahdi_ring_phone().
02961 { 02962 struct dahdi_pvt *p = pvt; 02963 02964 return dahdi_ring_phone(p); 02965 }
static int my_send_callerid | ( | void * | pvt, | |
int | cwcid, | |||
struct ast_party_caller * | caller | |||
) | [static] |
Definition at line 1984 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.
01985 { 01986 struct dahdi_pvt *p = pvt; 01987 01988 ast_debug(2, "Starting cid spill\n"); 01989 01990 if (p->cidspill) { 01991 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01992 ast_free(p->cidspill); 01993 } 01994 01995 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01996 if (cwcid == 0) { 01997 p->cidlen = ast_callerid_generate(p->cidspill, 01998 caller->id.name.str, 01999 caller->id.number.str, 02000 AST_LAW(p)); 02001 } else { 02002 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", 02003 caller->id.name.str, caller->id.number.str); 02004 p->callwaitcas = 0; 02005 p->cidcwexpire = 0; 02006 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, 02007 caller->id.name.str, 02008 caller->id.number.str, 02009 AST_LAW(p)); 02010 p->cidlen += READ_SIZE * 4; 02011 } 02012 p->cidpos = 0; 02013 p->cid_suppress_expire = 0; 02014 send_callerid(p); 02015 } 02016 return 0; 02017 }
static void my_set_alarm | ( | void * | pvt, | |
int | in_alarm | |||
) | [static] |
Definition at line 2301 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 2285 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.
02286 { 02287 struct dahdi_pvt *p = pvt; 02288 02289 /* Choose proper cadence */ 02290 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02291 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02292 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02293 *cid_rings = cidrings[p->distinctivering - 1]; 02294 } else { 02295 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02296 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02297 *cid_rings = p->sendcalleridafter; 02298 } 02299 }
static void my_set_callwaiting | ( | void * | pvt, | |
int | callwaiting_enable | |||
) | [static] |
Definition at line 2402 of file chan_dahdi.c.
References dahdi_pvt::callwaiting.
02403 { 02404 struct dahdi_pvt *p = pvt; 02405 02406 p->callwaiting = callwaiting_enable; 02407 }
static void my_set_confirmanswer | ( | void * | pvt, | |
int | flag | |||
) | [static] |
Definition at line 2386 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02387 { 02388 struct dahdi_pvt *p = pvt; 02389 p->confirmanswer = flag; 02390 }
static void my_set_dialing | ( | void * | pvt, | |
int | is_dialing | |||
) | [static] |
Definition at line 2308 of file chan_dahdi.c.
References dahdi_pvt::dialing.
static int my_set_echocanceller | ( | void * | pvt, | |
int | enable | |||
) | [static] |
Definition at line 2946 of file chan_dahdi.c.
References dahdi_disable_ec(), and dahdi_enable_ec().
02947 { 02948 struct dahdi_pvt *p = pvt; 02949 02950 if (enable) 02951 dahdi_enable_ec(p); 02952 else 02953 dahdi_disable_ec(p); 02954 02955 return 0; 02956 }
static void my_set_inthreeway | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | inthreeway | |||
) | [static] |
Definition at line 2245 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.
02246 { 02247 struct dahdi_pvt *p = pvt; 02248 int idx = analogsub_to_dahdisub(sub); 02249 02250 p->subs[idx].inthreeway = inthreeway; 02251 }
static int my_set_linear_mode | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | linear_mode | |||
) | [static] |
Definition at line 2233 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.
02234 { 02235 struct dahdi_pvt *p = pvt; 02236 int oldval; 02237 int idx = analogsub_to_dahdisub(sub); 02238 02239 dahdi_setlinear(p->subs[idx].dfd, linear_mode); 02240 oldval = p->subs[idx].linear; 02241 p->subs[idx].linear = linear_mode ? 1 : 0; 02242 return oldval; 02243 }
static void my_set_needringing | ( | void * | pvt, | |
int | value | |||
) | [static] |
Definition at line 2982 of file chan_dahdi.c.
References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
02983 { 02984 struct dahdi_pvt *p = pvt; 02985 p->subs[SUB_REAL].needringing = value; 02986 }
static void my_set_new_owner | ( | void * | pvt, | |
struct ast_channel * | new_owner | |||
) | [static] |
Definition at line 2430 of file chan_dahdi.c.
References dahdi_pvt::owner.
static void my_set_outgoing | ( | void * | pvt, | |
int | is_outgoing | |||
) | [static] |
Definition at line 2315 of file chan_dahdi.c.
References dahdi_pvt::outgoing.
static void my_set_polarity | ( | void * | pvt, | |
int | value | |||
) | [static] |
Definition at line 2988 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 2424 of file chan_dahdi.c.
References dahdi_pvt::pulsedial.
static void my_set_ringtimeout | ( | void * | pvt, | |
int | ringt | |||
) | [static] |
Definition at line 2358 of file chan_dahdi.c.
References dahdi_pvt::ringt.
static void my_set_waitingfordt | ( | void * | pvt, | |
struct ast_channel * | ast | |||
) | [static] |
Definition at line 2364 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.
02365 { 02366 struct dahdi_pvt *p = pvt; 02367 02368 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) { 02369 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone); 02370 gettimeofday(&p->waitingfordt, NULL); 02371 ast_setstate(ast, AST_STATE_OFFHOOK); 02372 } 02373 }
static int my_start | ( | void * | pvt | ) | [static] |
Definition at line 3034 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 1716 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.
01717 { 01718 struct dahdi_pvt *p = pvt; 01719 int index = SUB_REAL; 01720 p->cs = callerid_new(cid_signalling); 01721 if (!p->cs) { 01722 ast_log(LOG_ERROR, "Unable to alloc callerid\n"); 01723 return -1; 01724 } 01725 bump_gains(p); 01726 dahdi_setlinear(p->subs[index].dfd, 0); 01727 01728 return 0; 01729 }
static void my_start_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->answeronpolarityswitch || p->hanguponpolarityswitch) { 03004 my_set_polarity(pvt, 0); 03005 } 03006 }
static int my_stop_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1937 of file chan_dahdi.c.
References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.
01938 { 01939 struct dahdi_pvt *p = pvt; 01940 p->callwaitingrepeat = 0; 01941 p->cidcwexpire = 0; 01942 p->cid_suppress_expire = 0; 01943 01944 return 0; 01945 }
static int my_stop_cid_detect | ( | void * | pvt | ) | [static] |
Definition at line 1731 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.
01732 { 01733 struct dahdi_pvt *p = pvt; 01734 int index = SUB_REAL; 01735 if (p->cs) 01736 callerid_free(p->cs); 01737 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 01738 return 0; 01739 }
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 2575 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().
02576 { 02577 struct dahdi_pvt *p = pvt; 02578 int da, db; 02579 int tchan; 02580 int tinthreeway; 02581 02582 da = analogsub_to_dahdisub(a); 02583 db = analogsub_to_dahdisub(b); 02584 02585 tchan = p->subs[da].chan; 02586 p->subs[da].chan = p->subs[db].chan; 02587 p->subs[db].chan = tchan; 02588 02589 tinthreeway = p->subs[da].inthreeway; 02590 p->subs[da].inthreeway = p->subs[db].inthreeway; 02591 p->subs[db].inthreeway = tinthreeway; 02592 02593 p->subs[da].owner = ast_a; 02594 p->subs[db].owner = ast_b; 02595 02596 if (ast_a) 02597 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); 02598 if (ast_b) 02599 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); 02600 02601 wakeup_sub(p, a); 02602 wakeup_sub(p, b); 02603 02604 return; 02605 }
static int my_train_echocanceller | ( | void * | pvt | ) | [static] |
Definition at line 3075 of file chan_dahdi.c.
References dahdi_train_ec().
03076 { 03077 struct dahdi_pvt *p = pvt; 03078 03079 dahdi_train_ec(p); 03080 03081 return 0; 03082 }
static int my_unallocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2761 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and unalloc_sub().
02762 { 02763 struct dahdi_pvt *p = pvt; 02764 02765 return unalloc_sub(p, analogsub_to_dahdisub(analogsub)); 02766 }
static void my_unlock_private | ( | void * | pvt | ) | [static] |
Definition at line 2163 of file chan_dahdi.c.
References ast_mutex_unlock, and dahdi_pvt::lock.
02164 { 02165 struct dahdi_pvt *p = pvt; 02166 ast_mutex_unlock(&p->lock); 02167 }
static int my_wait_event | ( | void * | pvt | ) | [static] |
Definition at line 2893 of file chan_dahdi.c.
References dahdi_wait_event(), dahdi_subchannel::dfd, SUB_REAL, and dahdi_pvt::subs.
02894 { 02895 struct dahdi_pvt *p = pvt; 02896 02897 return dahdi_wait_event(p->subs[SUB_REAL].dfd); 02898 }
static int my_wink | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2069 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.
02070 { 02071 struct dahdi_pvt *p = pvt; 02072 int index = analogsub_to_dahdisub(sub); 02073 if (index != SUB_REAL) { 02074 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n"); 02075 } 02076 return dahdi_wink(p, index); 02077 }
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 3660 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().
03661 { 03662 char s[sizeof(mwimonitornotify) + 80]; 03663 struct ast_event *event; 03664 char *mailbox, *context; 03665 03666 /* Strip off @default */ 03667 context = mailbox = ast_strdupa(mailbox_full); 03668 strsep(&context, "@"); 03669 if (ast_strlen_zero(context)) 03670 context = "default"; 03671 03672 if (!(event = ast_event_new(AST_EVENT_MWI, 03673 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03674 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03675 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03676 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03677 AST_EVENT_IE_END))) { 03678 return; 03679 } 03680 03681 ast_event_queue_and_cache(event); 03682 03683 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 03684 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 03685 ast_safe_system(s); 03686 } 03687 }
static int parse_buffers_policy | ( | const char * | parse, | |
int * | num_buffers, | |||
int * | policy | |||
) | [static] |
Definition at line 7078 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write(), and process_dahdi().
07079 { 07080 int res; 07081 char policy_str[21] = ""; 07082 07083 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) { 07084 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 07085 return 1; 07086 } 07087 if (*num_buffers < 0) { 07088 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 07089 return -1; 07090 } 07091 if (!strcasecmp(policy_str, "full")) { 07092 *policy = DAHDI_POLICY_WHEN_FULL; 07093 } else if (!strcasecmp(policy_str, "immediate")) { 07094 *policy = DAHDI_POLICY_IMMEDIATE; 07095 #if defined(HAVE_DAHDI_HALF_FULL) 07096 } else if (!strcasecmp(policy_str, "half")) { 07097 *policy = DAHDI_POLICY_HALF_FULL; 07098 #endif 07099 } else { 07100 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 07101 return -1; 07102 } 07103 07104 return 0; 07105 }
static char* parse_spanchan | ( | char * | chanstr, | |
char ** | subdir | |||
) | [static] |
Definition at line 16999 of file chan_dahdi.c.
References string_replace().
Referenced by build_channels().
17000 { 17001 char *p; 17002 17003 if ((p = strrchr(chanstr, '!')) == NULL) { 17004 *subdir = NULL; 17005 return chanstr; 17006 } 17007 *p++ = '\0'; 17008 string_replace(chanstr, '!', '/'); 17009 *subdir = chanstr; 17010 return p; 17011 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 17142 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::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, 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_pvt::silencethreshold, 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().
17143 { 17144 struct dahdi_pvt *tmp; 17145 int y; 17146 int found_pseudo = 0; 17147 struct ast_variable *dahdichan = NULL; 17148 17149 for (; v; v = v->next) { 17150 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 17151 continue; 17152 17153 /* Create the interface list */ 17154 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) { 17155 if (options & PROC_DAHDI_OPT_NOCHAN) { 17156 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 17157 continue; 17158 } 17159 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) { 17160 if (confp->ignore_failed_channels) { 17161 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value); 17162 continue; 17163 } else { 17164 return -1; 17165 } 17166 } 17167 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 17168 } else if (!strcasecmp(v->name, "ignore_failed_channels")) { 17169 confp->ignore_failed_channels = ast_true(v->value); 17170 } else if (!strcasecmp(v->name, "buffers")) { 17171 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 17172 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 17173 confp->chan.buf_no = numbufs; 17174 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 17175 } 17176 } else if (!strcasecmp(v->name, "faxbuffers")) { 17177 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) { 17178 confp->chan.usefaxbuffers = 1; 17179 } 17180 } else if (!strcasecmp(v->name, "dahdichan")) { 17181 /* Only process the last dahdichan value. */ 17182 dahdichan = v; 17183 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 17184 usedistinctiveringdetection = ast_true(v->value); 17185 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 17186 distinctiveringaftercid = ast_true(v->value); 17187 } else if (!strcasecmp(v->name, "dring1context")) { 17188 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 17189 } else if (!strcasecmp(v->name, "dring2context")) { 17190 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 17191 } else if (!strcasecmp(v->name, "dring3context")) { 17192 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 17193 } else if (!strcasecmp(v->name, "dring1range")) { 17194 confp->chan.drings.ringnum[0].range = atoi(v->value); 17195 } else if (!strcasecmp(v->name, "dring2range")) { 17196 confp->chan.drings.ringnum[1].range = atoi(v->value); 17197 } else if (!strcasecmp(v->name, "dring3range")) { 17198 confp->chan.drings.ringnum[2].range = atoi(v->value); 17199 } else if (!strcasecmp(v->name, "dring1")) { 17200 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]); 17201 } else if (!strcasecmp(v->name, "dring2")) { 17202 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]); 17203 } else if (!strcasecmp(v->name, "dring3")) { 17204 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]); 17205 } else if (!strcasecmp(v->name, "usecallerid")) { 17206 confp->chan.use_callerid = ast_true(v->value); 17207 } else if (!strcasecmp(v->name, "cidsignalling")) { 17208 if (!strcasecmp(v->value, "bell")) 17209 confp->chan.cid_signalling = CID_SIG_BELL; 17210 else if (!strcasecmp(v->value, "v23")) 17211 confp->chan.cid_signalling = CID_SIG_V23; 17212 else if (!strcasecmp(v->value, "dtmf")) 17213 confp->chan.cid_signalling = CID_SIG_DTMF; 17214 else if (!strcasecmp(v->value, "smdi")) 17215 confp->chan.cid_signalling = CID_SIG_SMDI; 17216 else if (!strcasecmp(v->value, "v23_jp")) 17217 confp->chan.cid_signalling = CID_SIG_V23_JP; 17218 else if (ast_true(v->value)) 17219 confp->chan.cid_signalling = CID_SIG_BELL; 17220 } else if (!strcasecmp(v->name, "cidstart")) { 17221 if (!strcasecmp(v->value, "ring")) 17222 confp->chan.cid_start = CID_START_RING; 17223 else if (!strcasecmp(v->value, "polarity_in")) 17224 confp->chan.cid_start = CID_START_POLARITY_IN; 17225 else if (!strcasecmp(v->value, "polarity")) 17226 confp->chan.cid_start = CID_START_POLARITY; 17227 else if (!strcasecmp(v->value, "dtmf")) 17228 confp->chan.cid_start = CID_START_DTMF_NOALERT; 17229 else if (ast_true(v->value)) 17230 confp->chan.cid_start = CID_START_RING; 17231 } else if (!strcasecmp(v->name, "threewaycalling")) { 17232 confp->chan.threewaycalling = ast_true(v->value); 17233 } else if (!strcasecmp(v->name, "cancallforward")) { 17234 confp->chan.cancallforward = ast_true(v->value); 17235 } else if (!strcasecmp(v->name, "relaxdtmf")) { 17236 if (ast_true(v->value)) 17237 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 17238 else 17239 confp->chan.dtmfrelax = 0; 17240 } else if (!strcasecmp(v->name, "mailbox")) { 17241 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 17242 } else if (!strcasecmp(v->name, "hasvoicemail")) { 17243 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 17244 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 17245 } 17246 } else if (!strcasecmp(v->name, "adsi")) { 17247 confp->chan.adsi = ast_true(v->value); 17248 } else if (!strcasecmp(v->name, "usesmdi")) { 17249 confp->chan.use_smdi = ast_true(v->value); 17250 } else if (!strcasecmp(v->name, "smdiport")) { 17251 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 17252 } else if (!strcasecmp(v->name, "transfer")) { 17253 confp->chan.transfer = ast_true(v->value); 17254 } else if (!strcasecmp(v->name, "canpark")) { 17255 confp->chan.canpark = ast_true(v->value); 17256 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 17257 confp->chan.echocanbridged = ast_true(v->value); 17258 } else if (!strcasecmp(v->name, "busydetect")) { 17259 confp->chan.busydetect = ast_true(v->value); 17260 } else if (!strcasecmp(v->name, "busycount")) { 17261 confp->chan.busycount = atoi(v->value); 17262 } else if (!strcasecmp(v->name, "silencethreshold")) { 17263 confp->chan.silencethreshold = atoi(v->value); 17264 } else if (!strcasecmp(v->name, "busycompare")) { 17265 confp->chan.busycompare = ast_true(v->value); 17266 } else if (!strcasecmp(v->name, "busypattern")) { 17267 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 17268 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 17269 } 17270 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 17271 if (count == 1) 17272 confp->chan.busyquietlength = 0; 17273 else if (count < 1) 17274 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 17275 } else if (!strcasecmp(v->name, "busyfuzziness")) { 17276 confp->chan.busyfuzziness = atoi(v->value); 17277 } else if (!strcasecmp(v->name, "callprogress")) { 17278 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 17279 if (ast_true(v->value)) 17280 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 17281 } else if (!strcasecmp(v->name, "waitfordialtone")) { 17282 confp->chan.waitfordialtone = atoi(v->value); 17283 } else if (!strcasecmp(v->name, "faxdetect")) { 17284 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 17285 if (!strcasecmp(v->value, "incoming")) { 17286 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 17287 } else if (!strcasecmp(v->value, "outgoing")) { 17288 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 17289 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 17290 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 17291 } else if (!strcasecmp(v->name, "echocancel")) { 17292 process_echocancel(confp, v->value, v->lineno); 17293 } else if (!strcasecmp(v->name, "echotraining")) { 17294 if (sscanf(v->value, "%30d", &y) == 1) { 17295 if ((y < 10) || (y > 4000)) { 17296 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 17297 } else { 17298 confp->chan.echotraining = y; 17299 } 17300 } else if (ast_true(v->value)) { 17301 confp->chan.echotraining = 400; 17302 } else 17303 confp->chan.echotraining = 0; 17304 } else if (!strcasecmp(v->name, "hidecallerid")) { 17305 confp->chan.hidecallerid = ast_true(v->value); 17306 } else if (!strcasecmp(v->name, "hidecalleridname")) { 17307 confp->chan.hidecalleridname = ast_true(v->value); 17308 } else if (!strcasecmp(v->name, "pulsedial")) { 17309 confp->chan.pulse = ast_true(v->value); 17310 } else if (!strcasecmp(v->name, "callreturn")) { 17311 confp->chan.callreturn = ast_true(v->value); 17312 } else if (!strcasecmp(v->name, "callwaiting")) { 17313 confp->chan.callwaiting = ast_true(v->value); 17314 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 17315 confp->chan.callwaitingcallerid = ast_true(v->value); 17316 } else if (!strcasecmp(v->name, "context")) { 17317 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 17318 } else if (!strcasecmp(v->name, "language")) { 17319 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 17320 } else if (!strcasecmp(v->name, "progzone")) { 17321 ast_copy_string(progzone, v->value, sizeof(progzone)); 17322 } else if (!strcasecmp(v->name, "mohinterpret") 17323 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 17324 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 17325 } else if (!strcasecmp(v->name, "mohsuggest")) { 17326 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 17327 } else if (!strcasecmp(v->name, "parkinglot")) { 17328 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 17329 } else if (!strcasecmp(v->name, "stripmsd")) { 17330 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 17331 confp->chan.stripmsd = atoi(v->value); 17332 } else if (!strcasecmp(v->name, "jitterbuffers")) { 17333 numbufs = atoi(v->value); 17334 } else if (!strcasecmp(v->name, "group")) { 17335 confp->chan.group = ast_get_group(v->value); 17336 } else if (!strcasecmp(v->name, "callgroup")) { 17337 if (!strcasecmp(v->value, "none")) 17338 confp->chan.callgroup = 0; 17339 else 17340 confp->chan.callgroup = ast_get_group(v->value); 17341 } else if (!strcasecmp(v->name, "pickupgroup")) { 17342 if (!strcasecmp(v->value, "none")) 17343 confp->chan.pickupgroup = 0; 17344 else 17345 confp->chan.pickupgroup = ast_get_group(v->value); 17346 } else if (!strcasecmp(v->name, "setvar")) { 17347 char *varname = ast_strdupa(v->value), *varval = NULL; 17348 struct ast_variable *tmpvar; 17349 if (varname && (varval = strchr(varname, '='))) { 17350 *varval++ = '\0'; 17351 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 17352 tmpvar->next = confp->chan.vars; 17353 confp->chan.vars = tmpvar; 17354 } 17355 } 17356 } else if (!strcasecmp(v->name, "immediate")) { 17357 confp->chan.immediate = ast_true(v->value); 17358 } else if (!strcasecmp(v->name, "transfertobusy")) { 17359 confp->chan.transfertobusy = ast_true(v->value); 17360 } else if (!strcasecmp(v->name, "mwimonitor")) { 17361 confp->chan.mwimonitor_neon = 0; 17362 confp->chan.mwimonitor_fsk = 0; 17363 confp->chan.mwimonitor_rpas = 0; 17364 if (strcasestr(v->value, "fsk")) { 17365 confp->chan.mwimonitor_fsk = 1; 17366 } 17367 if (strcasestr(v->value, "rpas")) { 17368 confp->chan.mwimonitor_rpas = 1; 17369 } 17370 if (strcasestr(v->value, "neon")) { 17371 confp->chan.mwimonitor_neon = 1; 17372 } 17373 /* If set to true or yes, assume that simple fsk is desired */ 17374 if (ast_true(v->value)) { 17375 confp->chan.mwimonitor_fsk = 1; 17376 } 17377 } else if (!strcasecmp(v->name, "cid_rxgain")) { 17378 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 17379 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 17380 } 17381 } else if (!strcasecmp(v->name, "rxgain")) { 17382 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 17383 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 17384 } 17385 } else if (!strcasecmp(v->name, "txgain")) { 17386 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 17387 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 17388 } 17389 } else if (!strcasecmp(v->name, "txdrc")) { 17390 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) { 17391 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value); 17392 } 17393 } else if (!strcasecmp(v->name, "rxdrc")) { 17394 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) { 17395 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value); 17396 } 17397 } else if (!strcasecmp(v->name, "tonezone")) { 17398 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 17399 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 17400 } 17401 } else if (!strcasecmp(v->name, "callerid")) { 17402 if (!strcasecmp(v->value, "asreceived")) { 17403 confp->chan.cid_num[0] = '\0'; 17404 confp->chan.cid_name[0] = '\0'; 17405 } else { 17406 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 17407 } 17408 } else if (!strcasecmp(v->name, "fullname")) { 17409 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 17410 } else if (!strcasecmp(v->name, "cid_number")) { 17411 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 17412 } else if (!strcasecmp(v->name, "cid_tag")) { 17413 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); 17414 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 17415 confp->chan.dahditrcallerid = ast_true(v->value); 17416 } else if (!strcasecmp(v->name, "restrictcid")) { 17417 confp->chan.restrictcid = ast_true(v->value); 17418 } else if (!strcasecmp(v->name, "usecallingpres")) { 17419 confp->chan.use_callingpres = ast_true(v->value); 17420 } else if (!strcasecmp(v->name, "accountcode")) { 17421 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 17422 } else if (!strcasecmp(v->name, "amaflags")) { 17423 y = ast_cdr_amaflags2int(v->value); 17424 if (y < 0) 17425 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 17426 else 17427 confp->chan.amaflags = y; 17428 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 17429 confp->chan.polarityonanswerdelay = atoi(v->value); 17430 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 17431 confp->chan.answeronpolarityswitch = ast_true(v->value); 17432 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 17433 confp->chan.hanguponpolarityswitch = ast_true(v->value); 17434 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 17435 confp->chan.sendcalleridafter = atoi(v->value); 17436 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 17437 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 17438 } else if (ast_cc_is_config_param(v->name)) { 17439 ast_cc_set_param(confp->chan.cc_params, v->name, v->value); 17440 } else if (!strcasecmp(v->name, "mwisendtype")) { 17441 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 17442 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 17443 mwisend_rpas = 1; 17444 } else { 17445 mwisend_rpas = 0; 17446 } 17447 #else 17448 /* Default is fsk, to turn it off you must specify nofsk */ 17449 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 17450 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 17451 confp->chan.mwisend_fsk = 0; 17452 } else { /* Default FSK */ 17453 confp->chan.mwisend_fsk = 1; 17454 } 17455 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 17456 confp->chan.mwisend_rpas = 1; 17457 } else { 17458 confp->chan.mwisend_rpas = 0; 17459 } 17460 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 17461 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 17462 } 17463 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 17464 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 17465 } 17466 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 17467 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 17468 } 17469 #endif 17470 } else if (reload != 1) { 17471 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 17472 int orig_radio = confp->chan.radio; 17473 int orig_outsigmod = confp->chan.outsigmod; 17474 int orig_auto = confp->is_sig_auto; 17475 17476 confp->chan.radio = 0; 17477 confp->chan.outsigmod = -1; 17478 confp->is_sig_auto = 0; 17479 if (!strcasecmp(v->value, "em")) { 17480 confp->chan.sig = SIG_EM; 17481 } else if (!strcasecmp(v->value, "em_e1")) { 17482 confp->chan.sig = SIG_EM_E1; 17483 } else if (!strcasecmp(v->value, "em_w")) { 17484 confp->chan.sig = SIG_EMWINK; 17485 } else if (!strcasecmp(v->value, "fxs_ls")) { 17486 confp->chan.sig = SIG_FXSLS; 17487 } else if (!strcasecmp(v->value, "fxs_gs")) { 17488 confp->chan.sig = SIG_FXSGS; 17489 } else if (!strcasecmp(v->value, "fxs_ks")) { 17490 confp->chan.sig = SIG_FXSKS; 17491 } else if (!strcasecmp(v->value, "fxo_ls")) { 17492 confp->chan.sig = SIG_FXOLS; 17493 } else if (!strcasecmp(v->value, "fxo_gs")) { 17494 confp->chan.sig = SIG_FXOGS; 17495 } else if (!strcasecmp(v->value, "fxo_ks")) { 17496 confp->chan.sig = SIG_FXOKS; 17497 } else if (!strcasecmp(v->value, "fxs_rx")) { 17498 confp->chan.sig = SIG_FXSKS; 17499 confp->chan.radio = 1; 17500 } else if (!strcasecmp(v->value, "fxo_rx")) { 17501 confp->chan.sig = SIG_FXOLS; 17502 confp->chan.radio = 1; 17503 } else if (!strcasecmp(v->value, "fxs_tx")) { 17504 confp->chan.sig = SIG_FXSLS; 17505 confp->chan.radio = 1; 17506 } else if (!strcasecmp(v->value, "fxo_tx")) { 17507 confp->chan.sig = SIG_FXOGS; 17508 confp->chan.radio = 1; 17509 } else if (!strcasecmp(v->value, "em_rx")) { 17510 confp->chan.sig = SIG_EM; 17511 confp->chan.radio = 1; 17512 } else if (!strcasecmp(v->value, "em_tx")) { 17513 confp->chan.sig = SIG_EM; 17514 confp->chan.radio = 1; 17515 } else if (!strcasecmp(v->value, "em_rxtx")) { 17516 confp->chan.sig = SIG_EM; 17517 confp->chan.radio = 2; 17518 } else if (!strcasecmp(v->value, "em_txrx")) { 17519 confp->chan.sig = SIG_EM; 17520 confp->chan.radio = 2; 17521 } else if (!strcasecmp(v->value, "sf")) { 17522 confp->chan.sig = SIG_SF; 17523 } else if (!strcasecmp(v->value, "sf_w")) { 17524 confp->chan.sig = SIG_SFWINK; 17525 } else if (!strcasecmp(v->value, "sf_featd")) { 17526 confp->chan.sig = SIG_FEATD; 17527 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17528 confp->chan.sig = SIG_FEATDMF; 17529 } else if (!strcasecmp(v->value, "sf_featb")) { 17530 confp->chan.sig = SIG_SF_FEATB; 17531 } else if (!strcasecmp(v->value, "sf")) { 17532 confp->chan.sig = SIG_SF; 17533 } else if (!strcasecmp(v->value, "sf_rx")) { 17534 confp->chan.sig = SIG_SF; 17535 confp->chan.radio = 1; 17536 } else if (!strcasecmp(v->value, "sf_tx")) { 17537 confp->chan.sig = SIG_SF; 17538 confp->chan.radio = 1; 17539 } else if (!strcasecmp(v->value, "sf_rxtx")) { 17540 confp->chan.sig = SIG_SF; 17541 confp->chan.radio = 2; 17542 } else if (!strcasecmp(v->value, "sf_txrx")) { 17543 confp->chan.sig = SIG_SF; 17544 confp->chan.radio = 2; 17545 } else if (!strcasecmp(v->value, "featd")) { 17546 confp->chan.sig = SIG_FEATD; 17547 } else if (!strcasecmp(v->value, "featdmf")) { 17548 confp->chan.sig = SIG_FEATDMF; 17549 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17550 confp->chan.sig = SIG_FEATDMF_TA; 17551 } else if (!strcasecmp(v->value, "e911")) { 17552 confp->chan.sig = SIG_E911; 17553 } else if (!strcasecmp(v->value, "fgccama")) { 17554 confp->chan.sig = SIG_FGC_CAMA; 17555 } else if (!strcasecmp(v->value, "fgccamamf")) { 17556 confp->chan.sig = SIG_FGC_CAMAMF; 17557 } else if (!strcasecmp(v->value, "featb")) { 17558 confp->chan.sig = SIG_FEATB; 17559 #ifdef HAVE_PRI 17560 } else if (!strcasecmp(v->value, "pri_net")) { 17561 confp->chan.sig = SIG_PRI; 17562 confp->pri.pri.nodetype = PRI_NETWORK; 17563 } else if (!strcasecmp(v->value, "pri_cpe")) { 17564 confp->chan.sig = SIG_PRI; 17565 confp->pri.pri.nodetype = PRI_CPE; 17566 } else if (!strcasecmp(v->value, "bri_cpe")) { 17567 confp->chan.sig = SIG_BRI; 17568 confp->pri.pri.nodetype = PRI_CPE; 17569 } else if (!strcasecmp(v->value, "bri_net")) { 17570 confp->chan.sig = SIG_BRI; 17571 confp->pri.pri.nodetype = PRI_NETWORK; 17572 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 17573 confp->chan.sig = SIG_BRI_PTMP; 17574 confp->pri.pri.nodetype = PRI_CPE; 17575 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 17576 #if defined(HAVE_PRI_CALL_HOLD) 17577 confp->chan.sig = SIG_BRI_PTMP; 17578 confp->pri.pri.nodetype = PRI_NETWORK; 17579 #else 17580 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 17581 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 17582 #endif 17583 #if defined(HAVE_SS7) 17584 } else if (!strcasecmp(v->value, "ss7")) { 17585 confp->chan.sig = SIG_SS7; 17586 #endif /* defined(HAVE_SS7) */ 17587 #ifdef HAVE_OPENR2 17588 } else if (!strcasecmp(v->value, "mfcr2")) { 17589 confp->chan.sig = SIG_MFCR2; 17590 #endif 17591 } else if (!strcasecmp(v->value, "auto")) { 17592 confp->is_sig_auto = 1; 17593 } else { 17594 confp->chan.outsigmod = orig_outsigmod; 17595 confp->chan.radio = orig_radio; 17596 confp->is_sig_auto = orig_auto; 17597 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17598 } 17599 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 17600 if (!strcasecmp(v->value, "em")) { 17601 confp->chan.outsigmod = SIG_EM; 17602 } else if (!strcasecmp(v->value, "em_e1")) { 17603 confp->chan.outsigmod = SIG_EM_E1; 17604 } else if (!strcasecmp(v->value, "em_w")) { 17605 confp->chan.outsigmod = SIG_EMWINK; 17606 } else if (!strcasecmp(v->value, "sf")) { 17607 confp->chan.outsigmod = SIG_SF; 17608 } else if (!strcasecmp(v->value, "sf_w")) { 17609 confp->chan.outsigmod = SIG_SFWINK; 17610 } else if (!strcasecmp(v->value, "sf_featd")) { 17611 confp->chan.outsigmod = SIG_FEATD; 17612 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17613 confp->chan.outsigmod = SIG_FEATDMF; 17614 } else if (!strcasecmp(v->value, "sf_featb")) { 17615 confp->chan.outsigmod = SIG_SF_FEATB; 17616 } else if (!strcasecmp(v->value, "sf")) { 17617 confp->chan.outsigmod = SIG_SF; 17618 } else if (!strcasecmp(v->value, "featd")) { 17619 confp->chan.outsigmod = SIG_FEATD; 17620 } else if (!strcasecmp(v->value, "featdmf")) { 17621 confp->chan.outsigmod = SIG_FEATDMF; 17622 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17623 confp->chan.outsigmod = SIG_FEATDMF_TA; 17624 } else if (!strcasecmp(v->value, "e911")) { 17625 confp->chan.outsigmod = SIG_E911; 17626 } else if (!strcasecmp(v->value, "fgccama")) { 17627 confp->chan.outsigmod = SIG_FGC_CAMA; 17628 } else if (!strcasecmp(v->value, "fgccamamf")) { 17629 confp->chan.outsigmod = SIG_FGC_CAMAMF; 17630 } else if (!strcasecmp(v->value, "featb")) { 17631 confp->chan.outsigmod = SIG_FEATB; 17632 } else { 17633 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17634 } 17635 #ifdef HAVE_PRI 17636 } else if (!strcasecmp(v->name, "pridialplan")) { 17637 if (!strcasecmp(v->value, "national")) { 17638 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1; 17639 } else if (!strcasecmp(v->value, "unknown")) { 17640 confp->pri.pri.dialplan = PRI_UNKNOWN + 1; 17641 } else if (!strcasecmp(v->value, "private")) { 17642 confp->pri.pri.dialplan = PRI_PRIVATE + 1; 17643 } else if (!strcasecmp(v->value, "international")) { 17644 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 17645 } else if (!strcasecmp(v->value, "local")) { 17646 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1; 17647 } else if (!strcasecmp(v->value, "dynamic")) { 17648 confp->pri.pri.dialplan = -1; 17649 } else if (!strcasecmp(v->value, "redundant")) { 17650 confp->pri.pri.dialplan = -2; 17651 } else { 17652 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 17653 } 17654 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 17655 if (!strcasecmp(v->value, "national")) { 17656 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1; 17657 } else if (!strcasecmp(v->value, "unknown")) { 17658 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1; 17659 } else if (!strcasecmp(v->value, "private")) { 17660 confp->pri.pri.localdialplan = PRI_PRIVATE + 1; 17661 } else if (!strcasecmp(v->value, "international")) { 17662 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 17663 } else if (!strcasecmp(v->value, "local")) { 17664 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1; 17665 } else if (!strcasecmp(v->value, "dynamic")) { 17666 confp->pri.pri.localdialplan = -1; 17667 } else if (!strcasecmp(v->value, "redundant")) { 17668 confp->pri.pri.localdialplan = -2; 17669 } else { 17670 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 17671 } 17672 } else if (!strcasecmp(v->name, "switchtype")) { 17673 if (!strcasecmp(v->value, "national")) 17674 confp->pri.pri.switchtype = PRI_SWITCH_NI2; 17675 else if (!strcasecmp(v->value, "ni1")) 17676 confp->pri.pri.switchtype = PRI_SWITCH_NI1; 17677 else if (!strcasecmp(v->value, "dms100")) 17678 confp->pri.pri.switchtype = PRI_SWITCH_DMS100; 17679 else if (!strcasecmp(v->value, "4ess")) 17680 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS; 17681 else if (!strcasecmp(v->value, "5ess")) 17682 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E; 17683 else if (!strcasecmp(v->value, "euroisdn")) 17684 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1; 17685 else if (!strcasecmp(v->value, "qsig")) 17686 confp->pri.pri.switchtype = PRI_SWITCH_QSIG; 17687 else { 17688 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 17689 return -1; 17690 } 17691 } else if (!strcasecmp(v->name, "msn")) { 17692 ast_copy_string(confp->pri.pri.msn_list, v->value, 17693 sizeof(confp->pri.pri.msn_list)); 17694 } else if (!strcasecmp(v->name, "nsf")) { 17695 if (!strcasecmp(v->value, "sdn")) 17696 confp->pri.pri.nsf = PRI_NSF_SDN; 17697 else if (!strcasecmp(v->value, "megacom")) 17698 confp->pri.pri.nsf = PRI_NSF_MEGACOM; 17699 else if (!strcasecmp(v->value, "tollfreemegacom")) 17700 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 17701 else if (!strcasecmp(v->value, "accunet")) 17702 confp->pri.pri.nsf = PRI_NSF_ACCUNET; 17703 else if (!strcasecmp(v->value, "none")) 17704 confp->pri.pri.nsf = PRI_NSF_NONE; 17705 else { 17706 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 17707 confp->pri.pri.nsf = PRI_NSF_NONE; 17708 } 17709 } else if (!strcasecmp(v->name, "priindication")) { 17710 if (!strcasecmp(v->value, "outofband")) 17711 confp->chan.priindication_oob = 1; 17712 else if (!strcasecmp(v->value, "inband")) 17713 confp->chan.priindication_oob = 0; 17714 else 17715 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 17716 v->value, v->lineno); 17717 } else if (!strcasecmp(v->name, "priexclusive")) { 17718 confp->chan.priexclusive = ast_true(v->value); 17719 } else if (!strcasecmp(v->name, "internationalprefix")) { 17720 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix)); 17721 } else if (!strcasecmp(v->name, "nationalprefix")) { 17722 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix)); 17723 } else if (!strcasecmp(v->name, "localprefix")) { 17724 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix)); 17725 } else if (!strcasecmp(v->name, "privateprefix")) { 17726 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix)); 17727 } else if (!strcasecmp(v->name, "unknownprefix")) { 17728 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix)); 17729 } else if (!strcasecmp(v->name, "resetinterval")) { 17730 if (!strcasecmp(v->value, "never")) 17731 confp->pri.pri.resetinterval = -1; 17732 else if (atoi(v->value) >= 60) 17733 confp->pri.pri.resetinterval = atoi(v->value); 17734 else 17735 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 17736 v->value, v->lineno); 17737 } else if (!strcasecmp(v->name, "minunused")) { 17738 confp->pri.pri.minunused = atoi(v->value); 17739 } else if (!strcasecmp(v->name, "minidle")) { 17740 confp->pri.pri.minidle = atoi(v->value); 17741 } else if (!strcasecmp(v->name, "idleext")) { 17742 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext)); 17743 } else if (!strcasecmp(v->name, "idledial")) { 17744 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial)); 17745 } else if (!strcasecmp(v->name, "overlapdial")) { 17746 if (ast_true(v->value)) { 17747 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17748 } else if (!strcasecmp(v->value, "incoming")) { 17749 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 17750 } else if (!strcasecmp(v->value, "outgoing")) { 17751 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 17752 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 17753 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17754 } else { 17755 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 17756 } 17757 #ifdef HAVE_PRI_PROG_W_CAUSE 17758 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 17759 if (!strcasecmp(v->value, "logical")) { 17760 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 17761 } else if (!strcasecmp(v->value, "physical")) { 17762 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17763 } else { 17764 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17765 } 17766 #endif 17767 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 17768 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value); 17769 #if defined(HAVE_PRI_SERVICE_MESSAGES) 17770 } else if (!strcasecmp(v->name, "service_message_support")) { 17771 /* assuming switchtype for this channel group has been configured already */ 17772 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 17773 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E 17774 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) { 17775 confp->pri.pri.enable_service_message_support = 1; 17776 } else { 17777 confp->pri.pri.enable_service_message_support = 0; 17778 } 17779 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 17780 #ifdef HAVE_PRI_INBANDDISCONNECT 17781 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 17782 confp->pri.pri.inbanddisconnect = ast_true(v->value); 17783 #endif 17784 } else if (!strcasecmp(v->name, "pritimer")) { 17785 #ifdef PRI_GETSET_TIMERS 17786 char tmp[20]; 17787 char *timerc; 17788 char *c; 17789 int timer; 17790 int timeridx; 17791 17792 ast_copy_string(tmp, v->value, sizeof(tmp)); 17793 c = tmp; 17794 timerc = strsep(&c, ","); 17795 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 17796 timeridx = pri_timer2idx(timerc); 17797 timer = atoi(c); 17798 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 17799 ast_log(LOG_WARNING, 17800 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 17801 v->lineno); 17802 } else if (!timer) { 17803 ast_log(LOG_WARNING, 17804 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 17805 c, timerc, v->lineno); 17806 } else { 17807 confp->pri.pri.pritimers[timeridx] = timer; 17808 } 17809 } else { 17810 ast_log(LOG_WARNING, 17811 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 17812 v->value, v->lineno); 17813 } 17814 #endif /* PRI_GETSET_TIMERS */ 17815 } else if (!strcasecmp(v->name, "facilityenable")) { 17816 confp->pri.pri.facilityenable = ast_true(v->value); 17817 #if defined(HAVE_PRI_AOC_EVENTS) 17818 } else if (!strcasecmp(v->name, "aoc_enable")) { 17819 confp->pri.pri.aoc_passthrough_flag = 0; 17820 if (strchr(v->value, 's') || strchr(v->value, 'S')) { 17821 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S; 17822 } 17823 if (strchr(v->value, 'd') || strchr(v->value, 'D')) { 17824 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D; 17825 } 17826 if (strchr(v->value, 'e') || strchr(v->value, 'E')) { 17827 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E; 17828 } 17829 } else if (!strcasecmp(v->name, "aoce_delayhangup")) { 17830 confp->pri.pri.aoce_delayhangup = ast_true(v->value); 17831 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 17832 #if defined(HAVE_PRI_CALL_HOLD) 17833 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) { 17834 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value); 17835 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 17836 #if defined(HAVE_PRI_CCSS) 17837 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) { 17838 if (!strcasecmp(v->value, "global")) { 17839 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */ 17840 } else if (!strcasecmp(v->value, "specific")) { 17841 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17842 } else { 17843 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17844 } 17845 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) { 17846 if (!strcasecmp(v->value, "release")) { 17847 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */ 17848 } else if (!strcasecmp(v->value, "retain")) { 17849 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17850 } else if (!strcasecmp(v->value, "do_not_care")) { 17851 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */ 17852 } else { 17853 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17854 } 17855 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) { 17856 if (!strcasecmp(v->value, "release")) { 17857 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */ 17858 } else if (!strcasecmp(v->value, "retain")) { 17859 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17860 } else { 17861 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17862 } 17863 #endif /* defined(HAVE_PRI_CCSS) */ 17864 #if defined(HAVE_PRI_CALL_WAITING) 17865 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) { 17866 confp->pri.pri.max_call_waiting_calls = atoi(v->value); 17867 if (confp->pri.pri.max_call_waiting_calls < 0) { 17868 /* Negative values are not allowed. */ 17869 confp->pri.pri.max_call_waiting_calls = 0; 17870 } 17871 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) { 17872 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value); 17873 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 17874 #if defined(HAVE_PRI_MWI) 17875 } else if (!strcasecmp(v->name, "mwi_mailboxes")) { 17876 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value, 17877 sizeof(confp->pri.pri.mwi_mailboxes)); 17878 #endif /* defined(HAVE_PRI_MWI) */ 17879 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) { 17880 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value); 17881 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) { 17882 confp->pri.pri.inband_on_setup_ack = ast_true(v->value); 17883 } else if (!strcasecmp(v->name, "inband_on_proceeding")) { 17884 confp->pri.pri.inband_on_proceeding = ast_true(v->value); 17885 } else if (!strcasecmp(v->name, "layer1_presence")) { 17886 if (!strcasecmp(v->value, "required")) { 17887 confp->pri.pri.layer1_ignored = 0; 17888 } else if (!strcasecmp(v->value, "ignore")) { 17889 confp->pri.pri.layer1_ignored = 1; 17890 } else { 17891 /* Default */ 17892 confp->pri.pri.layer1_ignored = 0; 17893 } 17894 #if defined(HAVE_PRI_L2_PERSISTENCE) 17895 } else if (!strcasecmp(v->name, "layer2_persistence")) { 17896 if (!strcasecmp(v->value, "keep_up")) { 17897 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP; 17898 } else if (!strcasecmp(v->value, "leave_down")) { 17899 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN; 17900 } else { 17901 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT; 17902 } 17903 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 17904 #endif /* HAVE_PRI */ 17905 #if defined(HAVE_SS7) 17906 } else if (!strcasecmp(v->name, "ss7type")) { 17907 if (!strcasecmp(v->value, "itu")) { 17908 cur_ss7type = SS7_ITU; 17909 } else if (!strcasecmp(v->value, "ansi")) { 17910 cur_ss7type = SS7_ANSI; 17911 } else 17912 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 17913 } else if (!strcasecmp(v->name, "linkset")) { 17914 cur_linkset = atoi(v->value); 17915 } else if (!strcasecmp(v->name, "pointcode")) { 17916 cur_pointcode = parse_pointcode(v->value); 17917 } else if (!strcasecmp(v->name, "adjpointcode")) { 17918 cur_adjpointcode = parse_pointcode(v->value); 17919 } else if (!strcasecmp(v->name, "defaultdpc")) { 17920 cur_defaultdpc = parse_pointcode(v->value); 17921 } else if (!strcasecmp(v->name, "cicbeginswith")) { 17922 cur_cicbeginswith = atoi(v->value); 17923 } else if (!strcasecmp(v->name, "networkindicator")) { 17924 if (!strcasecmp(v->value, "national")) 17925 cur_networkindicator = SS7_NI_NAT; 17926 else if (!strcasecmp(v->value, "national_spare")) 17927 cur_networkindicator = SS7_NI_NAT_SPARE; 17928 else if (!strcasecmp(v->value, "international")) 17929 cur_networkindicator = SS7_NI_INT; 17930 else if (!strcasecmp(v->value, "international_spare")) 17931 cur_networkindicator = SS7_NI_INT_SPARE; 17932 else 17933 cur_networkindicator = -1; 17934 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 17935 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix)); 17936 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 17937 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix)); 17938 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 17939 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix)); 17940 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 17941 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix)); 17942 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 17943 if (!strcasecmp(v->value, "national")) { 17944 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL; 17945 } else if (!strcasecmp(v->value, "international")) { 17946 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL; 17947 } else if (!strcasecmp(v->value, "subscriber")) { 17948 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER; 17949 } else if (!strcasecmp(v->value, "unknown")) { 17950 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN; 17951 } else if (!strcasecmp(v->value, "dynamic")) { 17952 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC; 17953 } else { 17954 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 17955 } 17956 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 17957 if (!strcasecmp(v->value, "national")) { 17958 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL; 17959 } else if (!strcasecmp(v->value, "international")) { 17960 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL; 17961 } else if (!strcasecmp(v->value, "subscriber")) { 17962 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER; 17963 } else if (!strcasecmp(v->value, "unknown")) { 17964 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN; 17965 } else if (!strcasecmp(v->value, "dynamic")) { 17966 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC; 17967 } else { 17968 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 17969 } 17970 } else if (!strcasecmp(v->name, "sigchan")) { 17971 int sigchan, res; 17972 sigchan = atoi(v->value); 17973 res = linkset_addsigchan(sigchan); 17974 if (res < 0) 17975 return -1; 17976 17977 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 17978 struct dahdi_ss7 *link; 17979 link = ss7_resolve_linkset(cur_linkset); 17980 if (!link) { 17981 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 17982 return -1; 17983 } 17984 if (ast_true(v->value)) 17985 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM; 17986 #endif /* defined(HAVE_SS7) */ 17987 #ifdef HAVE_OPENR2 17988 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 17989 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 17990 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); 17991 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 17992 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 17993 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 17994 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 17995 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 17996 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 17997 confp->mfcr2.variant = OR2_VAR_ITU; 17998 } 17999 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 18000 confp->mfcr2.mfback_timeout = atoi(v->value); 18001 if (!confp->mfcr2.mfback_timeout) { 18002 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 18003 confp->mfcr2.mfback_timeout = -1; 18004 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 18005 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 18006 } 18007 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 18008 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 18009 if (confp->mfcr2.metering_pulse_timeout > 500) { 18010 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 18011 } 18012 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 18013 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 18014 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 18015 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 18016 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 18017 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 18018 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 18019 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 18020 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 18021 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 18022 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 18023 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 18024 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 18025 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 18026 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 18027 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 18028 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0; 18029 #endif 18030 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 18031 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 18032 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 18033 confp->mfcr2.max_ani = atoi(v->value); 18034 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 18035 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 18036 } 18037 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 18038 confp->mfcr2.max_dnis = atoi(v->value); 18039 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 18040 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 18041 } 18042 } else if (!strcasecmp(v->name, "mfcr2_category")) { 18043 confp->mfcr2.category = openr2_proto_get_category(v->value); 18044 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 18045 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 18046 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 18047 v->value, v->lineno); 18048 } 18049 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 18050 openr2_log_level_t tmplevel; 18051 char *clevel; 18052 char *logval = ast_strdupa(v->value); 18053 while (logval) { 18054 clevel = strsep(&logval,","); 18055 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 18056 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 18057 continue; 18058 } 18059 confp->mfcr2.loglevel |= tmplevel; 18060 } 18061 #endif /* HAVE_OPENR2 */ 18062 } else if (!strcasecmp(v->name, "cadence")) { 18063 /* setup to scan our argument */ 18064 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 18065 int i; 18066 struct dahdi_ring_cadence new_cadence; 18067 int cid_location = -1; 18068 int firstcadencepos = 0; 18069 char original_args[80]; 18070 int cadence_is_ok = 1; 18071 18072 ast_copy_string(original_args, v->value, sizeof(original_args)); 18073 /* 16 cadences allowed (8 pairs) */ 18074 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]); 18075 18076 /* Cadence must be even (on/off) */ 18077 if (element_count % 2 == 1) { 18078 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 18079 cadence_is_ok = 0; 18080 } 18081 18082 /* Ring cadences cannot be negative */ 18083 for (i = 0; i < element_count; i++) { 18084 if (c[i] == 0) { 18085 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 18086 cadence_is_ok = 0; 18087 break; 18088 } else if (c[i] < 0) { 18089 if (i % 2 == 1) { 18090 /* Silence duration, negative possibly okay */ 18091 if (cid_location == -1) { 18092 cid_location = i; 18093 c[i] *= -1; 18094 } else { 18095 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 18096 cadence_is_ok = 0; 18097 break; 18098 } 18099 } else { 18100 if (firstcadencepos == 0) { 18101 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 18102 /* duration will be passed negative to the DAHDI driver */ 18103 } else { 18104 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 18105 cadence_is_ok = 0; 18106 break; 18107 } 18108 } 18109 } 18110 } 18111 18112 /* Substitute our scanned cadence */ 18113 for (i = 0; i < 16; i++) { 18114 new_cadence.ringcadence[i] = c[i]; 18115 } 18116 18117 if (cadence_is_ok) { 18118 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 18119 if (element_count < 2) { 18120 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 18121 } else { 18122 if (cid_location == -1) { 18123 /* user didn't say; default to first pause */ 18124 cid_location = 1; 18125 } else { 18126 /* convert element_index to cidrings value */ 18127 cid_location = (cid_location + 1) / 2; 18128 } 18129 /* ---we like their cadence; try to install it--- */ 18130 if (!user_has_defined_cadences++) 18131 /* this is the first user-defined cadence; clear the default user cadences */ 18132 num_cadence = 0; 18133 if ((num_cadence+1) >= NUM_CADENCE_MAX) 18134 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 18135 else { 18136 cadences[num_cadence] = new_cadence; 18137 cidrings[num_cadence++] = cid_location; 18138 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 18139 } 18140 } 18141 } 18142 } else if (!strcasecmp(v->name, "ringtimeout")) { 18143 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 18144 } else if (!strcasecmp(v->name, "prewink")) { 18145 confp->timing.prewinktime = atoi(v->value); 18146 } else if (!strcasecmp(v->name, "preflash")) { 18147 confp->timing.preflashtime = atoi(v->value); 18148 } else if (!strcasecmp(v->name, "wink")) { 18149 confp->timing.winktime = atoi(v->value); 18150 } else if (!strcasecmp(v->name, "flash")) { 18151 confp->timing.flashtime = atoi(v->value); 18152 } else if (!strcasecmp(v->name, "start")) { 18153 confp->timing.starttime = atoi(v->value); 18154 } else if (!strcasecmp(v->name, "rxwink")) { 18155 confp->timing.rxwinktime = atoi(v->value); 18156 } else if (!strcasecmp(v->name, "rxflash")) { 18157 confp->timing.rxflashtime = atoi(v->value); 18158 } else if (!strcasecmp(v->name, "debounce")) { 18159 confp->timing.debouncetime = atoi(v->value); 18160 } else if (!strcasecmp(v->name, "toneduration")) { 18161 int toneduration; 18162 int ctlfd; 18163 int res; 18164 struct dahdi_dialparams dps; 18165 18166 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 18167 if (ctlfd == -1) { 18168 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 18169 return -1; 18170 } 18171 18172 toneduration = atoi(v->value); 18173 if (toneduration > -1) { 18174 memset(&dps, 0, sizeof(dps)); 18175 18176 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 18177 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 18178 if (res < 0) { 18179 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 18180 close(ctlfd); 18181 return -1; 18182 } 18183 } 18184 close(ctlfd); 18185 } else if (!strcasecmp(v->name, "defaultcic")) { 18186 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 18187 } else if (!strcasecmp(v->name, "defaultozz")) { 18188 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 18189 } else if (!strcasecmp(v->name, "mwilevel")) { 18190 mwilevel = atoi(v->value); 18191 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 18192 dtmfcid_level = atoi(v->value); 18193 } else if (!strcasecmp(v->name, "reportalarms")) { 18194 if (!strcasecmp(v->value, "all")) 18195 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; 18196 if (!strcasecmp(v->value, "none")) 18197 report_alarms = 0; 18198 else if (!strcasecmp(v->value, "channels")) 18199 report_alarms = REPORT_CHANNEL_ALARMS; 18200 else if (!strcasecmp(v->value, "spans")) 18201 report_alarms = REPORT_SPAN_ALARMS; 18202 } 18203 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 18204 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 18205 } 18206 18207 /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */ 18208 if (confp->chan.vars) { 18209 ast_variables_destroy(confp->chan.vars); 18210 confp->chan.vars = NULL; 18211 } 18212 18213 if (dahdichan) { 18214 /* Process the deferred dahdichan value. */ 18215 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno, 18216 &found_pseudo)) { 18217 if (confp->ignore_failed_channels) { 18218 ast_log(LOG_WARNING, 18219 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n", 18220 dahdichan->value); 18221 } else { 18222 return -1; 18223 } 18224 } 18225 } 18226 18227 /* mark the first channels of each DAHDI span to watch for their span alarms */ 18228 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { 18229 if (!tmp->destroy && tmp->span != y) { 18230 tmp->manages_span_alarms = 1; 18231 y = tmp->span; 18232 } else { 18233 tmp->manages_span_alarms = 0; 18234 } 18235 } 18236 18237 /*< \todo why check for the pseudo in the per-channel section. 18238 * Any actual use for manual setup of the pseudo channel? */ 18239 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) { 18240 /* use the default configuration for a channel, so 18241 that any settings from real configured channels 18242 don't "leak" into the pseudo channel config 18243 */ 18244 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18245 18246 if (conf.chan.cc_params) { 18247 tmp = mkintf(CHAN_PSEUDO, &conf, reload); 18248 } else { 18249 tmp = NULL; 18250 } 18251 if (tmp) { 18252 ast_verb(3, "Automatically generated pseudo channel\n"); 18253 } else { 18254 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 18255 } 18256 ast_cc_config_params_destroy(conf.chan.cc_params); 18257 } 18258 return 0; 18259 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 17086 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().
17087 { 17088 char *parse = ast_strdupa(data); 17089 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 17090 unsigned int param_count; 17091 unsigned int x; 17092 17093 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 17094 return; 17095 17096 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 17097 17098 /* first parameter is tap length, process it here */ 17099 17100 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 17101 17102 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 17103 confp->chan.echocancel.head.tap_length = x; 17104 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 17105 confp->chan.echocancel.head.tap_length = 128; 17106 17107 /* now process any remaining parameters */ 17108 17109 for (x = 1; x < param_count; x++) { 17110 struct { 17111 char *name; 17112 char *value; 17113 } param; 17114 17115 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 17116 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]); 17117 continue; 17118 } 17119 17120 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 17121 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name); 17122 continue; 17123 } 17124 17125 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 17126 17127 if (param.value) { 17128 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 17129 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value); 17130 continue; 17131 } 17132 } 17133 confp->chan.echocancel.head.param_count++; 17134 } 17135 }
static int reload | ( | void | ) | [static] |
Definition at line 18937 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
18938 { 18939 int res = 0; 18940 18941 res = setup_dahdi(1); 18942 if (res) { 18943 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 18944 return -1; 18945 } 18946 return 0; 18947 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4846 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().
04847 { 04848 p->confno = -1; 04849 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 04850 if (p->subs[SUB_REAL].dfd > -1) { 04851 struct dahdi_confinfo zi; 04852 04853 memset(&zi, 0, sizeof(zi)); 04854 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 04855 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 04856 } 04857 return 0; 04858 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 12030 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().
12031 { 12032 /* If we're supposed to be stopped -- stay stopped */ 12033 if (monitor_thread == AST_PTHREADT_STOP) 12034 return 0; 12035 ast_mutex_lock(&monlock); 12036 if (monitor_thread == pthread_self()) { 12037 ast_mutex_unlock(&monlock); 12038 ast_log(LOG_WARNING, "Cannot kill myself\n"); 12039 return -1; 12040 } 12041 if (monitor_thread != AST_PTHREADT_NULL) { 12042 /* Wake up the thread */ 12043 pthread_kill(monitor_thread, SIGURG); 12044 } else { 12045 /* Start a new monitor */ 12046 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 12047 ast_mutex_unlock(&monlock); 12048 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 12049 return -1; 12050 } 12051 } 12052 ast_mutex_unlock(&monlock); 12053 return 0; 12054 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5271 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().
05272 { 05273 int res; 05274 if (p->saveconf.confmode) { 05275 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 05276 p->saveconf.confmode = 0; 05277 if (res) { 05278 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 05279 return -1; 05280 } 05281 ast_debug(1, "Restored conferencing\n"); 05282 } 05283 return 0; 05284 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5178 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 6169 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().
06170 { 06171 if (p->bufferoverrideinuse) { 06172 /* faxbuffers are in use, revert them */ 06173 struct dahdi_bufferinfo bi = { 06174 .txbufpolicy = p->buf_policy, 06175 .rxbufpolicy = p->buf_policy, 06176 .bufsize = p->bufsize, 06177 .numbufs = p->buf_no 06178 }; 06179 int bpres; 06180 06181 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06182 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno)); 06183 } 06184 p->bufferoverrideinuse = 0; 06185 return bpres; 06186 } 06187 06188 return -1; 06189 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5245 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().
05246 { 05247 struct dahdi_confinfo c; 05248 int res; 05249 if (p->saveconf.confmode) { 05250 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 05251 return -1; 05252 } 05253 p->saveconf.chan = 0; 05254 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 05255 if (res) { 05256 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 05257 p->saveconf.confmode = 0; 05258 return -1; 05259 } 05260 memset(&c, 0, sizeof(c)); 05261 c.confmode = DAHDI_CONF_NORMAL; 05262 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 05263 if (res) { 05264 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 05265 return -1; 05266 } 05267 ast_debug(1, "Disabled conferencing\n"); 05268 return 0; 05269 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5329 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().
05330 { 05331 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 05332 int res; 05333 /* Take out of linear mode if necessary */ 05334 if (p->subs[SUB_REAL].linear) { 05335 p->subs[SUB_REAL].linear = 0; 05336 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 05337 } 05338 while (p->cidpos < p->cidlen) { 05339 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 05340 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res); 05341 if (res < 0) { 05342 if (errno == EAGAIN) 05343 return 0; 05344 else { 05345 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05346 return -1; 05347 } 05348 } 05349 if (!res) 05350 return 0; 05351 p->cidpos += res; 05352 } 05353 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 05354 ast_free(p->cidspill); 05355 p->cidspill = NULL; 05356 if (p->callwaitcas) { 05357 /* Wait for CID/CW to expire */ 05358 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 05359 p->cid_suppress_expire = p->cidcwexpire; 05360 } else 05361 restore_conference(p); 05362 return 0; 05363 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5286 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().
05287 { 05288 p->callwaitcas = 0; 05289 p->cidcwexpire = 0; 05290 p->cid_suppress_expire = 0; 05291 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 05292 return -1; 05293 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 05294 /* Make sure we account for the end */ 05295 p->cidlen += READ_SIZE * 4; 05296 p->cidpos = 0; 05297 send_callerid(p); 05298 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 05299 return 0; 05300 }
static int set_actual_gain | ( | int | fd, | |
float | rxgain, | |||
float | txgain, | |||
float | rxdrc, | |||
float | txdrc, | |||
int | law | |||
) | [static] |
Definition at line 5159 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), and restore_gains().
05160 { 05161 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law); 05162 }
static int set_actual_rxgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5142 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05143 { 05144 struct dahdi_gains g; 05145 int res; 05146 05147 memset(&g, 0, sizeof(g)); 05148 res = ioctl(fd, DAHDI_GETGAINS, &g); 05149 if (res) { 05150 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05151 return res; 05152 } 05153 05154 fill_rxgain(&g, gain, drc, law); 05155 05156 return ioctl(fd, DAHDI_SETGAINS, &g); 05157 }
static int set_actual_txgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5125 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05126 { 05127 struct dahdi_gains g; 05128 int res; 05129 05130 memset(&g, 0, sizeof(g)); 05131 res = ioctl(fd, DAHDI_GETGAINS, &g); 05132 if (res) { 05133 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05134 return res; 05135 } 05136 05137 fill_txgain(&g, gain, drc, law); 05138 05139 return ioctl(fd, DAHDI_SETGAINS, &g); 05140 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 18580 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().
18581 { 18582 int res; 18583 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default(); 18584 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 18585 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18586 18587 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) { 18588 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf); 18589 } else { 18590 res = -1; 18591 } 18592 ast_cc_config_params_destroy(default_conf.chan.cc_params); 18593 ast_cc_config_params_destroy(base_conf.chan.cc_params); 18594 ast_cc_config_params_destroy(conf.chan.cc_params); 18595 18596 return res; 18597 }
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 18293 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().
18294 { 18295 struct ast_config *cfg; 18296 struct ast_config *ucfg; 18297 struct ast_variable *v; 18298 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 18299 const char *chans; 18300 const char *cat; 18301 int res; 18302 18303 #ifdef HAVE_PRI 18304 char *c; 18305 int spanno; 18306 int i; 18307 int logicalspan; 18308 int trunkgroup; 18309 int dchannels[SIG_PRI_NUM_DCHANS]; 18310 #endif 18311 int have_cfg_now; 18312 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */ 18313 18314 cfg = ast_config_load(config, config_flags); 18315 have_cfg_now = !!cfg; 18316 if (!cfg) { 18317 /* Error if we have no config file */ 18318 if (had_cfg_before) { 18319 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 18320 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18321 } 18322 cfg = ast_config_new();/* Dummy config */ 18323 if (!cfg) { 18324 return 0; 18325 } 18326 ucfg = ast_config_load("users.conf", config_flags); 18327 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18328 ast_config_destroy(cfg); 18329 return 0; 18330 } 18331 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18332 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18333 ast_config_destroy(cfg); 18334 return 0; 18335 } 18336 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 18337 ucfg = ast_config_load("users.conf", config_flags); 18338 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18339 return 0; 18340 } 18341 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18342 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18343 return 0; 18344 } 18345 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18346 cfg = ast_config_load(config, config_flags); 18347 have_cfg_now = !!cfg; 18348 if (!cfg) { 18349 if (had_cfg_before) { 18350 /* We should have been able to load the config. */ 18351 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config); 18352 ast_config_destroy(ucfg); 18353 return 0; 18354 } 18355 cfg = ast_config_new();/* Dummy config */ 18356 if (!cfg) { 18357 ast_config_destroy(ucfg); 18358 return 0; 18359 } 18360 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18361 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18362 ast_config_destroy(ucfg); 18363 return 0; 18364 } 18365 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18366 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18367 return 0; 18368 } else { 18369 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18370 ucfg = ast_config_load("users.conf", config_flags); 18371 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18372 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18373 ast_config_destroy(cfg); 18374 return 0; 18375 } 18376 } 18377 had_cfg_before = have_cfg_now; 18378 18379 /* It's a little silly to lock it, but we might as well just to be sure */ 18380 ast_mutex_lock(&iflock); 18381 #ifdef HAVE_PRI 18382 if (reload != 1) { 18383 /* Process trunkgroups first */ 18384 v = ast_variable_browse(cfg, "trunkgroups"); 18385 while (v) { 18386 if (!strcasecmp(v->name, "trunkgroup")) { 18387 trunkgroup = atoi(v->value); 18388 if (trunkgroup > 0) { 18389 if ((c = strchr(v->value, ','))) { 18390 i = 0; 18391 memset(dchannels, 0, sizeof(dchannels)); 18392 while (c && (i < SIG_PRI_NUM_DCHANS)) { 18393 dchannels[i] = atoi(c + 1); 18394 if (dchannels[i] < 0) { 18395 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); 18396 } else 18397 i++; 18398 c = strchr(c + 1, ','); 18399 } 18400 if (i) { 18401 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 18402 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); 18403 } else 18404 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"); 18405 } else 18406 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18407 } else 18408 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18409 } else 18410 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 18411 } else if (!strcasecmp(v->name, "spanmap")) { 18412 spanno = atoi(v->value); 18413 if (spanno > 0) { 18414 if ((c = strchr(v->value, ','))) { 18415 trunkgroup = atoi(c + 1); 18416 if (trunkgroup > 0) { 18417 if ((c = strchr(c + 1, ','))) 18418 logicalspan = atoi(c + 1); 18419 else 18420 logicalspan = 0; 18421 if (logicalspan >= 0) { 18422 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 18423 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18424 } else 18425 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18426 } else 18427 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); 18428 } else 18429 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 18430 } else 18431 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 18432 } else 18433 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 18434 } else { 18435 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 18436 } 18437 v = v->next; 18438 } 18439 } 18440 #endif 18441 18442 /* Copy the default jb config over global_jbconf */ 18443 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 18444 18445 mwimonitornotify[0] = '\0'; 18446 18447 v = ast_variable_browse(cfg, "channels"); 18448 if ((res = process_dahdi(base_conf, 18449 "" /* Must be empty for the channels category. Silly voicemail mailbox. */, 18450 v, reload, 0))) { 18451 ast_mutex_unlock(&iflock); 18452 ast_config_destroy(cfg); 18453 if (ucfg) { 18454 ast_config_destroy(ucfg); 18455 } 18456 return res; 18457 } 18458 18459 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 18460 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 18461 /* [channels] and [trunkgroups] are used. Let's also reserve 18462 * [globals] and [general] for future use 18463 */ 18464 if (!strcasecmp(cat, "general") || 18465 !strcasecmp(cat, "trunkgroups") || 18466 !strcasecmp(cat, "globals") || 18467 !strcasecmp(cat, "channels")) { 18468 continue; 18469 } 18470 18471 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 18472 if (ast_strlen_zero(chans)) { 18473 /* Section is useless without a dahdichan value present. */ 18474 continue; 18475 } 18476 18477 /* Copy base_conf to conf. */ 18478 deep_copy_dahdi_chan_conf(conf, base_conf); 18479 18480 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 18481 ast_mutex_unlock(&iflock); 18482 ast_config_destroy(cfg); 18483 if (ucfg) { 18484 ast_config_destroy(ucfg); 18485 } 18486 return res; 18487 } 18488 } 18489 18490 ast_config_destroy(cfg); 18491 18492 if (ucfg) { 18493 /* Reset base_conf, so things don't leak from chan_dahdi.conf */ 18494 deep_copy_dahdi_chan_conf(base_conf, default_conf); 18495 process_dahdi(base_conf, 18496 "" /* Must be empty for the general category. Silly voicemail mailbox. */, 18497 ast_variable_browse(ucfg, "general"), 1, 0); 18498 18499 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 18500 if (!strcasecmp(cat, "general")) { 18501 continue; 18502 } 18503 18504 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 18505 if (ast_strlen_zero(chans)) { 18506 /* Section is useless without a dahdichan value present. */ 18507 continue; 18508 } 18509 18510 /* Copy base_conf to conf. */ 18511 deep_copy_dahdi_chan_conf(conf, base_conf); 18512 18513 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 18514 ast_config_destroy(ucfg); 18515 ast_mutex_unlock(&iflock); 18516 return res; 18517 } 18518 } 18519 ast_config_destroy(ucfg); 18520 } 18521 ast_mutex_unlock(&iflock); 18522 18523 #ifdef HAVE_PRI 18524 if (reload != 1) { 18525 int x; 18526 for (x = 0; x < NUM_SPANS; x++) { 18527 if (pris[x].pri.pvts[0]) { 18528 prepare_pri(pris + x); 18529 if (sig_pri_start_pri(&pris[x].pri)) { 18530 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 18531 return -1; 18532 } else 18533 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 18534 } 18535 } 18536 } 18537 #endif 18538 #if defined(HAVE_SS7) 18539 if (reload != 1) { 18540 int x; 18541 for (x = 0; x < NUM_SPANS; x++) { 18542 if (linksets[x].ss7.ss7) { 18543 linksets[x].ss7.calls = &dahdi_ss7_callbacks; 18544 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) { 18545 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 18546 return -1; 18547 } else 18548 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 18549 } 18550 } 18551 } 18552 #endif /* defined(HAVE_SS7) */ 18553 #ifdef HAVE_OPENR2 18554 if (reload != 1) { 18555 int x; 18556 for (x = 0; x < r2links_count; x++) { 18557 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 18558 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 18559 return -1; 18560 } else { 18561 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 18562 } 18563 } 18564 } 18565 #endif 18566 /* And start the monitor for the first time */ 18567 restart_monitor(); 18568 return 0; 18569 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 12313 of file chan_dahdi.c.
Referenced by mkintf().
12314 { 12315 return sigtype; 12316 }
static void string_replace | ( | char * | str, | |
int | char1, | |||
int | char2 | |||
) | [static] |
Definition at line 16990 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 4341 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().
04342 { 04343 int tchan; 04344 int tinthreeway; 04345 struct ast_channel *towner; 04346 04347 ast_debug(1, "Swapping %d and %d\n", a, b); 04348 04349 tchan = p->subs[a].chan; 04350 towner = p->subs[a].owner; 04351 tinthreeway = p->subs[a].inthreeway; 04352 04353 p->subs[a].chan = p->subs[b].chan; 04354 p->subs[a].owner = p->subs[b].owner; 04355 p->subs[a].inthreeway = p->subs[b].inthreeway; 04356 04357 p->subs[b].chan = tchan; 04358 p->subs[b].owner = towner; 04359 p->subs[b].inthreeway = tinthreeway; 04360 04361 if (p->subs[a].owner) 04362 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 04363 if (p->subs[b].owner) 04364 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 04365 wakeup_sub(p, a); 04366 wakeup_sub(p, b); 04367 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4487 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().
04488 { 04489 if (!x) { 04490 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 04491 return -1; 04492 } 04493 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 04494 dahdi_close_sub(p, x); 04495 p->subs[x].linear = 0; 04496 p->subs[x].chan = 0; 04497 p->subs[x].owner = NULL; 04498 p->subs[x].inthreeway = 0; 04499 p->polarity = POLARITY_IDLE; 04500 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 04501 return 0; 04502 }
static int unload_module | ( | void | ) | [static] |
Definition at line 16974 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, and sig_pri_span::lock.
16975 { 16976 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16977 int y; 16978 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16979 #ifdef HAVE_PRI 16980 for (y = 0; y < NUM_SPANS; y++) 16981 ast_mutex_destroy(&pris[y].pri.lock); 16982 #endif 16983 #if defined(HAVE_SS7) 16984 for (y = 0; y < NUM_SPANS; y++) 16985 ast_mutex_destroy(&linksets[y].ss7.lock); 16986 #endif /* defined(HAVE_SS7) */ 16987 return __unload_module(); 16988 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4860 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().
04861 { 04862 int needconf = 0; 04863 int x; 04864 int useslavenative; 04865 struct dahdi_pvt *slave = NULL; 04866 04867 useslavenative = isslavenative(p, &slave); 04868 /* Start with the obvious, general stuff */ 04869 for (x = 0; x < 3; x++) { 04870 /* Look for three way calls */ 04871 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 04872 conf_add(p, &p->subs[x], x, 0); 04873 needconf++; 04874 } else { 04875 conf_del(p, &p->subs[x], x); 04876 } 04877 } 04878 /* If we have a slave, add him to our conference now. or DAX 04879 if this is slave native */ 04880 for (x = 0; x < MAX_SLAVES; x++) { 04881 if (p->slaves[x]) { 04882 if (useslavenative) 04883 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 04884 else { 04885 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 04886 needconf++; 04887 } 04888 } 04889 } 04890 /* If we're supposed to be in there, do so now */ 04891 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 04892 if (useslavenative) 04893 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 04894 else { 04895 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 04896 needconf++; 04897 } 04898 } 04899 /* If we have a master, add ourselves to his conference */ 04900 if (p->master) { 04901 if (isslavenative(p->master, NULL)) { 04902 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 04903 } else { 04904 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 04905 } 04906 } 04907 if (!needconf) { 04908 /* Nobody is left (or should be left) in our conference. 04909 Kill it. */ 04910 p->confno = -1; 04911 } 04912 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 04913 return 0; 04914 }
static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
int | a | |||
) | [static] |
Definition at line 3848 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().
03849 { 03850 dahdi_lock_sub_owner(p, a); 03851 if (p->subs[a].owner) { 03852 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 03853 ast_channel_unlock(p->subs[a].owner); 03854 } 03855 }
int alarm |
Definition at line 4637 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 3724 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 18740 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 16042 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 18750 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 18735 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1521 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 18745 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 4614 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 1323 of file chan_dahdi.c.
Main interface list start
Definition at line 1322 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 4638 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 3795 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.