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 %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
#define | FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
#define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
#define | GET_CHANNEL(p) ((p)->channel) |
#define | HANGUP 1 |
#define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
#define | HEADER_MS 50 |
#define | ISTRUNK(p) |
#define | MASK_AVAIL (1 << 0) |
#define | MASK_INUSE (1 << 1) |
#define | MAX_CHANLIST_LEN 80 |
#define | MAX_SLAVES 4 |
#define | MIN_MS_SINCE_FLASH ((2000) ) |
#define | NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro. | |
#define | NUM_CADENCE_MAX 25 |
#define | NUM_SPANS 32 |
#define | POLARITY_IDLE 0 |
#define | POLARITY_REV 1 |
#define | PROC_DAHDI_OPT_NOCHAN (1 << 0) |
#define | PROC_DAHDI_OPT_NOWARN (1 << 1) |
#define | READ_SIZE 160 |
#define | 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 | 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 658 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 659 of file chan_dahdi.c.
#define dahdi_get_index | ( | ast, | |||
p, | |||||
nullok | ) | _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
Definition at line 3792 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 1250 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 %-10.10s %-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 %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), handle_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 1543 of file chan_dahdi.c.
Referenced by my_complete_conference_update(), and update_conf().
#define HANGUP 1 |
Definition at line 15919 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 16941 of file chan_dahdi.c.
#define MAX_SLAVES 4 |
Definition at line 661 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 618 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 619 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 16995 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 16997 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 4727 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 1545 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 614 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 613 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 615 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 15918 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 682 of file chan_dahdi.c.
00682 { 00683 DAHDI_IFLIST_NONE, /*!< The dahdi_pvt is not in any list. */ 00684 DAHDI_IFLIST_MAIN, /*!< The dahdi_pvt is in the main interface list */ 00685 #if defined(HAVE_PRI) 00686 DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */ 00687 #endif /* defined(HAVE_PRI) */ 00688 };
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 666 of file chan_dahdi.c.
00666 { 00667 MWI_SEND_NULL = 0, 00668 MWI_SEND_SA, 00669 MWI_SEND_SA_WAIT, 00670 MWI_SEND_PAUSE, 00671 MWI_SEND_SPILL, 00672 MWI_SEND_CLEANUP, 00673 MWI_SEND_DONE, 00674 } mwisend_states;
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8802 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().
08803 { 08804 int res; 08805 int idx; 08806 struct ast_frame *f; 08807 int usedindex = -1; 08808 struct dahdi_pvt *p = ast->tech_pvt; 08809 08810 if ((idx = dahdi_get_index(ast, p, 0)) < 0) { 08811 idx = SUB_REAL; 08812 } 08813 08814 p->subs[idx].f.frametype = AST_FRAME_NULL; 08815 p->subs[idx].f.datalen = 0; 08816 p->subs[idx].f.samples = 0; 08817 p->subs[idx].f.mallocd = 0; 08818 p->subs[idx].f.offset = 0; 08819 p->subs[idx].f.subclass.integer = 0; 08820 p->subs[idx].f.delivery = ast_tv(0,0); 08821 p->subs[idx].f.src = "dahdi_exception"; 08822 p->subs[idx].f.data.ptr = NULL; 08823 08824 08825 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 08826 /* If nobody owns us, absorb the event appropriately, otherwise 08827 we loop indefinitely. This occurs when, during call waiting, the 08828 other end hangs up our channel so that it no longer exists, but we 08829 have neither FLASH'd nor ONHOOK'd to signify our desire to 08830 change to the other channel. */ 08831 if (p->fake_event) { 08832 res = p->fake_event; 08833 p->fake_event = 0; 08834 } else 08835 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 08836 /* Switch to real if there is one and this isn't something really silly... */ 08837 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 08838 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 08839 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 08840 p->owner = p->subs[SUB_REAL].owner; 08841 if (p->owner && ast_bridged_channel(p->owner)) 08842 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08843 p->subs[SUB_REAL].needunhold = 1; 08844 } 08845 switch (res) { 08846 case DAHDI_EVENT_ONHOOK: 08847 dahdi_disable_ec(p); 08848 if (p->owner) { 08849 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 08850 dahdi_ring_phone(p); 08851 p->callwaitingrepeat = 0; 08852 p->cidcwexpire = 0; 08853 p->cid_suppress_expire = 0; 08854 } else 08855 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08856 update_conf(p); 08857 break; 08858 case DAHDI_EVENT_RINGOFFHOOK: 08859 dahdi_enable_ec(p); 08860 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08861 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 08862 p->subs[SUB_REAL].needanswer = 1; 08863 p->dialing = 0; 08864 } 08865 break; 08866 case DAHDI_EVENT_HOOKCOMPLETE: 08867 case DAHDI_EVENT_RINGERON: 08868 case DAHDI_EVENT_RINGEROFF: 08869 /* Do nothing */ 08870 break; 08871 case DAHDI_EVENT_WINKFLASH: 08872 p->flashtime = ast_tvnow(); 08873 if (p->owner) { 08874 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 08875 if (p->owner->_state != AST_STATE_UP) { 08876 /* Answer if necessary */ 08877 usedindex = dahdi_get_index(p->owner, p, 0); 08878 if (usedindex > -1) { 08879 p->subs[usedindex].needanswer = 1; 08880 } 08881 ast_setstate(p->owner, AST_STATE_UP); 08882 } 08883 p->callwaitingrepeat = 0; 08884 p->cidcwexpire = 0; 08885 p->cid_suppress_expire = 0; 08886 if (ast_bridged_channel(p->owner)) 08887 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08888 p->subs[SUB_REAL].needunhold = 1; 08889 } else 08890 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08891 update_conf(p); 08892 break; 08893 default: 08894 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 08895 } 08896 f = &p->subs[idx].f; 08897 return f; 08898 } 08899 if (!(p->radio || (p->oprmode < 0))) 08900 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 08901 /* If it's not us, return NULL immediately */ 08902 if (ast != p->owner) { 08903 if (p->owner) { 08904 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 08905 } 08906 f = &p->subs[idx].f; 08907 return f; 08908 } 08909 08910 f = dahdi_handle_event(ast); 08911 if (!f) { 08912 const char *name = ast_strdupa(ast->name); 08913 08914 /* Tell the CDR this DAHDI device hung up */ 08915 ast_mutex_unlock(&p->lock); 08916 ast_channel_unlock(ast); 08917 ast_set_hangupsource(ast, name, 0); 08918 ast_channel_lock(ast); 08919 ast_mutex_lock(&p->lock); 08920 } 08921 return f; 08922 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 16741 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, 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().
16742 { 16743 struct dahdi_pvt *p; 16744 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16745 int i, j; 16746 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16747 16748 #ifdef HAVE_PRI 16749 for (i = 0; i < NUM_SPANS; i++) { 16750 if (pris[i].pri.master != AST_PTHREADT_NULL) 16751 pthread_cancel(pris[i].pri.master); 16752 } 16753 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 16754 ast_unregister_application(dahdi_send_keypad_facility_app); 16755 #ifdef HAVE_PRI_PROG_W_CAUSE 16756 ast_unregister_application(dahdi_send_callrerouting_facility_app); 16757 #endif 16758 #endif 16759 #if defined(HAVE_SS7) 16760 for (i = 0; i < NUM_SPANS; i++) { 16761 if (linksets[i].ss7.master != AST_PTHREADT_NULL) 16762 pthread_cancel(linksets[i].ss7.master); 16763 } 16764 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 16765 #endif /* defined(HAVE_SS7) */ 16766 #if defined(HAVE_OPENR2) 16767 dahdi_r2_destroy_links(); 16768 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 16769 ast_unregister_application(dahdi_accept_r2_call_app); 16770 #endif 16771 16772 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 16773 ast_manager_unregister("DAHDIDialOffhook"); 16774 ast_manager_unregister("DAHDIHangup"); 16775 ast_manager_unregister("DAHDITransfer"); 16776 ast_manager_unregister("DAHDIDNDoff"); 16777 ast_manager_unregister("DAHDIDNDon"); 16778 ast_manager_unregister("DAHDIShowChannels"); 16779 ast_manager_unregister("DAHDIRestart"); 16780 ast_data_unregister(NULL); 16781 ast_channel_unregister(&dahdi_tech); 16782 16783 /* Hangup all interfaces if they have an owner */ 16784 ast_mutex_lock(&iflock); 16785 for (p = iflist; p; p = p->next) { 16786 if (p->owner) 16787 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 16788 } 16789 ast_mutex_unlock(&iflock); 16790 16791 ast_mutex_lock(&monlock); 16792 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 16793 pthread_cancel(monitor_thread); 16794 pthread_kill(monitor_thread, SIGURG); 16795 pthread_join(monitor_thread, NULL); 16796 } 16797 monitor_thread = AST_PTHREADT_STOP; 16798 ast_mutex_unlock(&monlock); 16799 16800 destroy_all_channels(); 16801 16802 #if defined(HAVE_PRI) 16803 for (i = 0; i < NUM_SPANS; i++) { 16804 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) 16805 pthread_join(pris[i].pri.master, NULL); 16806 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) { 16807 dahdi_close_pri_fd(&(pris[i]), j); 16808 } 16809 sig_pri_stop_pri(&pris[i].pri); 16810 } 16811 #if defined(HAVE_PRI_CCSS) 16812 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks); 16813 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks); 16814 #endif /* defined(HAVE_PRI_CCSS) */ 16815 sig_pri_unload(); 16816 #endif 16817 16818 #if defined(HAVE_SS7) 16819 for (i = 0; i < NUM_SPANS; i++) { 16820 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) 16821 pthread_join(linksets[i].ss7.master, NULL); 16822 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) { 16823 dahdi_close_ss7_fd(&(linksets[i]), j); 16824 } 16825 } 16826 #endif /* defined(HAVE_SS7) */ 16827 ast_cond_destroy(&ss_thread_complete); 16828 return 0; 16829 }
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 3793 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.
03794 { 03795 int res; 03796 if (p->subs[SUB_REAL].owner == ast) 03797 res = 0; 03798 else if (p->subs[SUB_CALLWAIT].owner == ast) 03799 res = 1; 03800 else if (p->subs[SUB_THREEWAY].owner == ast) 03801 res = 2; 03802 else { 03803 res = -1; 03804 if (!nullok) 03805 ast_log(LOG_WARNING, 03806 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 03807 ast ? ast->name : "", p->channel, fname, line); 03808 } 03809 return res; 03810 }
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16056 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().
16057 { 16058 struct dahdi_pvt *p; 16059 const char *channel = astman_get_header(m, "DAHDIChannel"); 16060 const char *number = astman_get_header(m, "Number"); 16061 int i; 16062 16063 if (ast_strlen_zero(channel)) { 16064 astman_send_error(s, m, "No channel specified"); 16065 return 0; 16066 } 16067 if (ast_strlen_zero(number)) { 16068 astman_send_error(s, m, "No number specified"); 16069 return 0; 16070 } 16071 p = find_channel_from_str(channel); 16072 if (!p) { 16073 astman_send_error(s, m, "No such channel"); 16074 return 0; 16075 } 16076 if (!p->owner) { 16077 astman_send_error(s, m, "Channel does not have it's owner"); 16078 return 0; 16079 } 16080 for (i = 0; i < strlen(number); i++) { 16081 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] }; 16082 dahdi_queue_frame(p, &f); 16083 } 16084 astman_send_ack(s, m, "DAHDIDialOffhook"); 16085 return 0; 16086 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15991 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().
15992 { 15993 struct dahdi_pvt *p; 15994 const char *channel = astman_get_header(m, "DAHDIChannel"); 15995 15996 if (ast_strlen_zero(channel)) { 15997 astman_send_error(s, m, "No channel specified"); 15998 return 0; 15999 } 16000 p = find_channel_from_str(channel); 16001 if (!p) { 16002 astman_send_error(s, m, "No such channel"); 16003 return 0; 16004 } 16005 dahdi_dnd(p, 0); 16006 astman_send_ack(s, m, "DND Disabled"); 16007 return 0; 16008 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15972 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().
15973 { 15974 struct dahdi_pvt *p; 15975 const char *channel = astman_get_header(m, "DAHDIChannel"); 15976 15977 if (ast_strlen_zero(channel)) { 15978 astman_send_error(s, m, "No channel specified"); 15979 return 0; 15980 } 15981 p = find_channel_from_str(channel); 15982 if (!p) { 15983 astman_send_error(s, m, "No such channel"); 15984 return 0; 15985 } 15986 dahdi_dnd(p, 1); 15987 astman_send_ack(s, m, "DND Enabled"); 15988 return 0; 15989 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15254 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
15255 { 15256 if (dahdi_restart() != 0) { 15257 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 15258 return 1; 15259 } 15260 astman_send_ack(s, m, "DAHDIRestart: Success"); 15261 return 0; 15262 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16088 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().
16089 { 16090 struct dahdi_pvt *tmp = NULL; 16091 const char *id = astman_get_header(m, "ActionID"); 16092 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 16093 char idText[256] = ""; 16094 int channels = 0; 16095 int dahdichanquery; 16096 16097 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) { 16098 /* Not numeric string. */ 16099 dahdichanquery = -1; 16100 } 16101 16102 astman_send_ack(s, m, "DAHDI channel status will follow"); 16103 if (!ast_strlen_zero(id)) 16104 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 16105 16106 ast_mutex_lock(&iflock); 16107 16108 for (tmp = iflist; tmp; tmp = tmp->next) { 16109 if (tmp->channel > 0) { 16110 int alm; 16111 16112 /* If a specific channel is queried for, only deliver status for that channel */ 16113 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 16114 continue; 16115 16116 alm = get_alarms(tmp); 16117 channels++; 16118 if (tmp->owner) { 16119 /* Add data if we have a current call */ 16120 astman_append(s, 16121 "Event: DAHDIShowChannels\r\n" 16122 "DAHDIChannel: %d\r\n" 16123 "Channel: %s\r\n" 16124 "Uniqueid: %s\r\n" 16125 "AccountCode: %s\r\n" 16126 "Signalling: %s\r\n" 16127 "SignallingCode: %d\r\n" 16128 "Context: %s\r\n" 16129 "DND: %s\r\n" 16130 "Alarm: %s\r\n" 16131 "%s" 16132 "\r\n", 16133 tmp->channel, 16134 tmp->owner->name, 16135 tmp->owner->uniqueid, 16136 tmp->owner->accountcode, 16137 sig2str(tmp->sig), 16138 tmp->sig, 16139 tmp->context, 16140 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16141 alarm2str(alm), idText); 16142 } else { 16143 astman_append(s, 16144 "Event: DAHDIShowChannels\r\n" 16145 "DAHDIChannel: %d\r\n" 16146 "Signalling: %s\r\n" 16147 "SignallingCode: %d\r\n" 16148 "Context: %s\r\n" 16149 "DND: %s\r\n" 16150 "Alarm: %s\r\n" 16151 "%s" 16152 "\r\n", 16153 tmp->channel, sig2str(tmp->sig), tmp->sig, 16154 tmp->context, 16155 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 16156 alarm2str(alm), idText); 16157 } 16158 } 16159 } 16160 16161 ast_mutex_unlock(&iflock); 16162 16163 astman_append(s, 16164 "Event: DAHDIShowChannelsComplete\r\n" 16165 "%s" 16166 "Items: %d\r\n" 16167 "\r\n", 16168 idText, 16169 channels); 16170 return 0; 16171 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16010 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().
16011 { 16012 struct dahdi_pvt *p; 16013 const char *channel = astman_get_header(m, "DAHDIChannel"); 16014 16015 if (ast_strlen_zero(channel)) { 16016 astman_send_error(s, m, "No channel specified"); 16017 return 0; 16018 } 16019 p = find_channel_from_str(channel); 16020 if (!p) { 16021 astman_send_error(s, m, "No such channel"); 16022 return 0; 16023 } 16024 if (!analog_lib_handles(p->sig, 0, 0)) { 16025 astman_send_error(s, m, "Channel signaling is not analog"); 16026 return 0; 16027 } 16028 dahdi_fake_event(p,TRANSFER); 16029 astman_send_ack(s, m, "DAHDITransfer"); 16030 return 0; 16031 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 16033 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().
16034 { 16035 struct dahdi_pvt *p; 16036 const char *channel = astman_get_header(m, "DAHDIChannel"); 16037 16038 if (ast_strlen_zero(channel)) { 16039 astman_send_error(s, m, "No channel specified"); 16040 return 0; 16041 } 16042 p = find_channel_from_str(channel); 16043 if (!p) { 16044 astman_send_error(s, m, "No such channel"); 16045 return 0; 16046 } 16047 if (!analog_lib_handles(p->sig, 0, 0)) { 16048 astman_send_error(s, m, "Channel signaling is not analog"); 16049 return 0; 16050 } 16051 dahdi_fake_event(p,HANGUP); 16052 astman_send_ack(s, m, "DAHDIHangup"); 16053 return 0; 16054 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 4644 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 4445 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().
04446 { 04447 struct dahdi_bufferinfo bi; 04448 int res; 04449 if (p->subs[x].dfd >= 0) { 04450 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 04451 return -1; 04452 } 04453 04454 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 04455 if (p->subs[x].dfd <= -1) { 04456 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 04457 return -1; 04458 } 04459 04460 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 04461 if (!res) { 04462 bi.txbufpolicy = p->buf_policy; 04463 bi.rxbufpolicy = p->buf_policy; 04464 bi.numbufs = p->buf_no; 04465 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 04466 if (res < 0) { 04467 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 04468 } 04469 } else 04470 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 04471 04472 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 04473 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 04474 dahdi_close_sub(p, x); 04475 p->subs[x].dfd = -1; 04476 return -1; 04477 } 04478 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 04479 return 0; 04480 }
static int analog_lib_handles | ( | int | signalling, | |
int | radio, | |||
int | oprmode | |||
) | [static] |
Definition at line 1575 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().
01576 { 01577 switch (signalling) { 01578 case SIG_FXOLS: 01579 case SIG_FXOGS: 01580 case SIG_FXOKS: 01581 case SIG_FXSLS: 01582 case SIG_FXSGS: 01583 case SIG_FXSKS: 01584 case SIG_EMWINK: 01585 case SIG_EM: 01586 case SIG_EM_E1: 01587 case SIG_FEATD: 01588 case SIG_FEATDMF: 01589 case SIG_E911: 01590 case SIG_FGC_CAMA: 01591 case SIG_FGC_CAMAMF: 01592 case SIG_FEATB: 01593 case SIG_SFWINK: 01594 case SIG_SF: 01595 case SIG_SF_FEATD: 01596 case SIG_SF_FEATDMF: 01597 case SIG_FEATDMF_TA: 01598 case SIG_SF_FEATB: 01599 break; 01600 default: 01601 /* The rest of the function should cover the remainder of signalling types */ 01602 return 0; 01603 } 01604 01605 if (radio) { 01606 return 0; 01607 } 01608 01609 if (oprmode) { 01610 return 0; 01611 } 01612 01613 return 1; 01614 }
static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 9953 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().
09954 { 09955 struct ast_channel *chan = data; 09956 struct dahdi_pvt *p = chan->tech_pvt; 09957 char exten[AST_MAX_EXTENSION] = ""; 09958 char exten2[AST_MAX_EXTENSION] = ""; 09959 unsigned char buf[256]; 09960 char dtmfcid[300]; 09961 char dtmfbuf[300]; 09962 struct callerid_state *cs = NULL; 09963 char *name = NULL, *number = NULL; 09964 int distMatches; 09965 int curRingData[3]; 09966 int receivedRingT; 09967 int counter1; 09968 int counter; 09969 int samples = 0; 09970 struct ast_smdi_md_message *smdi_msg = NULL; 09971 int flags = 0; 09972 int i; 09973 int timeout; 09974 int getforward = 0; 09975 char *s1, *s2; 09976 int len = 0; 09977 int res; 09978 int idx; 09979 09980 ast_mutex_lock(&ss_thread_lock); 09981 ss_thread_count++; 09982 ast_mutex_unlock(&ss_thread_lock); 09983 /* in the bizarre case where the channel has become a zombie before we 09984 even get started here, abort safely 09985 */ 09986 if (!p) { 09987 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 09988 ast_hangup(chan); 09989 goto quit; 09990 } 09991 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 09992 idx = dahdi_get_index(chan, p, 1); 09993 if (idx < 0) { 09994 ast_log(LOG_WARNING, "Huh?\n"); 09995 ast_hangup(chan); 09996 goto quit; 09997 } 09998 if (p->dsp) 09999 ast_dsp_digitreset(p->dsp); 10000 switch (p->sig) { 10001 case SIG_FEATD: 10002 case SIG_FEATDMF: 10003 case SIG_FEATDMF_TA: 10004 case SIG_E911: 10005 case SIG_FGC_CAMAMF: 10006 case SIG_FEATB: 10007 case SIG_EMWINK: 10008 case SIG_SF_FEATD: 10009 case SIG_SF_FEATDMF: 10010 case SIG_SF_FEATB: 10011 case SIG_SFWINK: 10012 if (dahdi_wink(p, idx)) 10013 goto quit; 10014 /* Fall through */ 10015 case SIG_EM: 10016 case SIG_EM_E1: 10017 case SIG_SF: 10018 case SIG_FGC_CAMA: 10019 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10020 if (p->dsp) 10021 ast_dsp_digitreset(p->dsp); 10022 /* set digit mode appropriately */ 10023 if (p->dsp) { 10024 if (NEED_MFDETECT(p)) 10025 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10026 else 10027 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10028 } 10029 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 10030 /* Wait for the first digit only if immediate=no */ 10031 if (!p->immediate) 10032 /* Wait for the first digit (up to 5 seconds). */ 10033 res = ast_waitfordigit(chan, 5000); 10034 else 10035 res = 0; 10036 if (res > 0) { 10037 /* save first char */ 10038 dtmfbuf[0] = res; 10039 switch (p->sig) { 10040 case SIG_FEATD: 10041 case SIG_SF_FEATD: 10042 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10043 if (res > 0) 10044 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10045 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10046 break; 10047 case SIG_FEATDMF_TA: 10048 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10049 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10050 if (dahdi_wink(p, idx)) goto quit; 10051 dtmfbuf[0] = 0; 10052 /* Wait for the first digit (up to 5 seconds). */ 10053 res = ast_waitfordigit(chan, 5000); 10054 if (res <= 0) break; 10055 dtmfbuf[0] = res; 10056 /* fall through intentionally */ 10057 case SIG_FEATDMF: 10058 case SIG_E911: 10059 case SIG_FGC_CAMAMF: 10060 case SIG_SF_FEATDMF: 10061 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10062 /* if international caca, do it again to get real ANO */ 10063 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 10064 { 10065 if (dahdi_wink(p, idx)) goto quit; 10066 dtmfbuf[0] = 0; 10067 /* Wait for the first digit (up to 5 seconds). */ 10068 res = ast_waitfordigit(chan, 5000); 10069 if (res <= 0) break; 10070 dtmfbuf[0] = res; 10071 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10072 } 10073 if (res > 0) { 10074 /* if E911, take off hook */ 10075 if (p->sig == SIG_E911) 10076 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10077 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 10078 } 10079 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10080 break; 10081 case SIG_FEATB: 10082 case SIG_SF_FEATB: 10083 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 10084 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10085 break; 10086 case SIG_EMWINK: 10087 /* if we received a '*', we are actually receiving Feature Group D 10088 dial syntax, so use that mode; otherwise, fall through to normal 10089 mode 10090 */ 10091 if (res == '*') { 10092 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 10093 if (res > 0) 10094 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 10095 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 10096 break; 10097 } 10098 default: 10099 /* If we got the first digit, get the rest */ 10100 len = 1; 10101 dtmfbuf[len] = '\0'; 10102 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10103 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 10104 timeout = matchdigittimeout; 10105 } else { 10106 timeout = gendigittimeout; 10107 } 10108 res = ast_waitfordigit(chan, timeout); 10109 if (res < 0) { 10110 ast_debug(1, "waitfordigit returned < 0...\n"); 10111 ast_hangup(chan); 10112 goto quit; 10113 } else if (res) { 10114 dtmfbuf[len++] = res; 10115 dtmfbuf[len] = '\0'; 10116 } else { 10117 break; 10118 } 10119 } 10120 break; 10121 } 10122 } 10123 if (res == -1) { 10124 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 10125 ast_hangup(chan); 10126 goto quit; 10127 } else if (res < 0) { 10128 ast_debug(1, "Got hung up before digits finished\n"); 10129 ast_hangup(chan); 10130 goto quit; 10131 } 10132 10133 if (p->sig == SIG_FGC_CAMA) { 10134 char anibuf[100]; 10135 10136 if (ast_safe_sleep(chan,1000) == -1) { 10137 ast_hangup(chan); 10138 goto quit; 10139 } 10140 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10141 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 10142 res = my_getsigstr(chan, anibuf, "#", 10000); 10143 if ((res > 0) && (strlen(anibuf) > 2)) { 10144 if (anibuf[strlen(anibuf) - 1] == '#') 10145 anibuf[strlen(anibuf) - 1] = 0; 10146 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 10147 } 10148 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10149 } 10150 10151 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 10152 if (ast_strlen_zero(exten)) 10153 ast_copy_string(exten, "s", sizeof(exten)); 10154 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 10155 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 10156 if (exten[0] == '*') { 10157 char *stringp=NULL; 10158 ast_copy_string(exten2, exten, sizeof(exten2)); 10159 /* Parse out extension and callerid */ 10160 stringp=exten2 +1; 10161 s1 = strsep(&stringp, "*"); 10162 s2 = strsep(&stringp, "*"); 10163 if (s2) { 10164 if (!ast_strlen_zero(p->cid_num)) 10165 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10166 else 10167 ast_set_callerid(chan, s1, NULL, s1); 10168 ast_copy_string(exten, s2, sizeof(exten)); 10169 } else 10170 ast_copy_string(exten, s1, sizeof(exten)); 10171 } else if (p->sig == SIG_FEATD) 10172 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10173 } 10174 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10175 if (exten[0] == '*') { 10176 char *stringp=NULL; 10177 ast_copy_string(exten2, exten, sizeof(exten2)); 10178 /* Parse out extension and callerid */ 10179 stringp=exten2 +1; 10180 s1 = strsep(&stringp, "#"); 10181 s2 = strsep(&stringp, "#"); 10182 if (s2) { 10183 if (!ast_strlen_zero(p->cid_num)) 10184 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10185 else 10186 if (*(s1 + 2)) 10187 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 10188 ast_copy_string(exten, s2 + 1, sizeof(exten)); 10189 } else 10190 ast_copy_string(exten, s1 + 2, sizeof(exten)); 10191 } else 10192 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10193 } 10194 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 10195 if (exten[0] == '*') { 10196 char *stringp=NULL; 10197 ast_copy_string(exten2, exten, sizeof(exten2)); 10198 /* Parse out extension and callerid */ 10199 stringp=exten2 +1; 10200 s1 = strsep(&stringp, "#"); 10201 s2 = strsep(&stringp, "#"); 10202 if (s2 && (*(s2 + 1) == '0')) { 10203 if (*(s2 + 2)) 10204 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 10205 } 10206 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 10207 else ast_copy_string(exten, "911", sizeof(exten)); 10208 } else 10209 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 10210 } 10211 if (p->sig == SIG_FEATB) { 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 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 10219 } else 10220 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 10221 } 10222 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10223 dahdi_wink(p, idx); 10224 /* some switches require a minimum guard time between 10225 the last FGD wink and something that answers 10226 immediately. This ensures it */ 10227 if (ast_safe_sleep(chan, 100)) { 10228 ast_hangup(chan); 10229 goto quit; 10230 } 10231 } 10232 dahdi_enable_ec(p); 10233 if (NEED_MFDETECT(p)) { 10234 if (p->dsp) { 10235 if (!p->hardwaredtmf) 10236 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10237 else { 10238 ast_dsp_free(p->dsp); 10239 p->dsp = NULL; 10240 } 10241 } 10242 } 10243 10244 if (ast_exists_extension(chan, chan->context, exten, 1, 10245 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 10246 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10247 if (p->dsp) ast_dsp_digitreset(p->dsp); 10248 res = ast_pbx_run(chan); 10249 if (res) { 10250 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10251 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10252 } 10253 goto quit; 10254 } else { 10255 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 10256 sleep(2); 10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 10258 if (res < 0) 10259 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 10260 else 10261 sleep(1); 10262 res = ast_streamfile(chan, "ss-noservice", chan->language); 10263 if (res >= 0) 10264 ast_waitstream(chan, ""); 10265 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10266 ast_hangup(chan); 10267 goto quit; 10268 } 10269 break; 10270 case SIG_FXOLS: 10271 case SIG_FXOGS: 10272 case SIG_FXOKS: 10273 /* Read the first digit */ 10274 timeout = firstdigittimeout; 10275 /* If starting a threeway call, never timeout on the first digit so someone 10276 can use flash-hook as a "hold" feature */ 10277 if (p->subs[SUB_THREEWAY].owner) 10278 timeout = 999999; 10279 while (len < AST_MAX_EXTENSION-1) { 10280 /* Read digit unless it's supposed to be immediate, in which case the 10281 only answer is 's' */ 10282 if (p->immediate) 10283 res = 's'; 10284 else 10285 res = ast_waitfordigit(chan, timeout); 10286 timeout = 0; 10287 if (res < 0) { 10288 ast_debug(1, "waitfordigit returned < 0...\n"); 10289 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10290 ast_hangup(chan); 10291 goto quit; 10292 } else if (res) { 10293 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 10294 exten[len++]=res; 10295 exten[len] = '\0'; 10296 } 10297 if (!ast_ignore_pattern(chan->context, exten)) 10298 tone_zone_play_tone(p->subs[idx].dfd, -1); 10299 else 10300 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10301 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) { 10302 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 10303 if (getforward) { 10304 /* Record this as the forwarding extension */ 10305 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 10306 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 10307 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10308 if (res) 10309 break; 10310 usleep(500000); 10311 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10312 sleep(1); 10313 memset(exten, 0, sizeof(exten)); 10314 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10315 len = 0; 10316 getforward = 0; 10317 } else { 10318 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10319 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10320 if (!ast_strlen_zero(p->cid_num)) { 10321 if (!p->hidecallerid) 10322 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10323 else 10324 ast_set_callerid(chan, NULL, NULL, p->cid_num); 10325 } 10326 if (!ast_strlen_zero(p->cid_name)) { 10327 if (!p->hidecallerid) 10328 ast_set_callerid(chan, NULL, p->cid_name, NULL); 10329 } 10330 ast_setstate(chan, AST_STATE_RING); 10331 dahdi_enable_ec(p); 10332 res = ast_pbx_run(chan); 10333 if (res) { 10334 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10335 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10336 } 10337 goto quit; 10338 } 10339 } else { 10340 /* It's a match, but they just typed a digit, and there is an ambiguous match, 10341 so just set the timeout to matchdigittimeout and wait some more */ 10342 timeout = matchdigittimeout; 10343 } 10344 } else if (res == 0) { 10345 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 10346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10347 dahdi_wait_event(p->subs[idx].dfd); 10348 ast_hangup(chan); 10349 goto quit; 10350 } else if (p->callwaiting && !strcmp(exten, "*70")) { 10351 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 10352 /* Disable call waiting if enabled */ 10353 p->callwaiting = 0; 10354 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10355 if (res) { 10356 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10357 chan->name, strerror(errno)); 10358 } 10359 len = 0; 10360 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 10361 memset(exten, 0, sizeof(exten)); 10362 timeout = firstdigittimeout; 10363 10364 } else if (!strcmp(exten,ast_pickup_ext())) { 10365 /* Scan all channels and see if there are any 10366 * ringing channels that have call groups 10367 * that equal this channels pickup group 10368 */ 10369 if (idx == SUB_REAL) { 10370 /* Switch us from Third call to Call Wait */ 10371 if (p->subs[SUB_THREEWAY].owner) { 10372 /* If you make a threeway call and the *8# a call, it should actually 10373 look like a callwait */ 10374 alloc_sub(p, SUB_CALLWAIT); 10375 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 10376 unalloc_sub(p, SUB_THREEWAY); 10377 } 10378 dahdi_enable_ec(p); 10379 if (ast_pickup_call(chan)) { 10380 ast_debug(1, "No call pickup possible...\n"); 10381 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10382 dahdi_wait_event(p->subs[idx].dfd); 10383 } 10384 ast_hangup(chan); 10385 goto quit; 10386 } else { 10387 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 10388 ast_hangup(chan); 10389 goto quit; 10390 } 10391 10392 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 10393 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 10394 /* Disable Caller*ID if enabled */ 10395 p->hidecallerid = 1; 10396 ast_party_number_free(&chan->caller.id.number); 10397 ast_party_number_init(&chan->caller.id.number); 10398 ast_party_name_free(&chan->caller.id.name); 10399 ast_party_name_init(&chan->caller.id.name); 10400 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10401 if (res) { 10402 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10403 chan->name, strerror(errno)); 10404 } 10405 len = 0; 10406 memset(exten, 0, sizeof(exten)); 10407 timeout = firstdigittimeout; 10408 } else if (p->callreturn && !strcmp(exten, "*69")) { 10409 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10410 break; 10411 } else if (!strcmp(exten, "*78")) { 10412 dahdi_dnd(p, 1); 10413 /* Do not disturb */ 10414 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10415 getforward = 0; 10416 memset(exten, 0, sizeof(exten)); 10417 len = 0; 10418 } else if (!strcmp(exten, "*79")) { 10419 dahdi_dnd(p, 0); 10420 /* Do not disturb */ 10421 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10422 getforward = 0; 10423 memset(exten, 0, sizeof(exten)); 10424 len = 0; 10425 } else if (p->cancallforward && !strcmp(exten, "*72")) { 10426 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10427 getforward = 1; 10428 memset(exten, 0, sizeof(exten)); 10429 len = 0; 10430 } else if (p->cancallforward && !strcmp(exten, "*73")) { 10431 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 10432 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10433 memset(p->call_forward, 0, sizeof(p->call_forward)); 10434 getforward = 0; 10435 memset(exten, 0, sizeof(exten)); 10436 len = 0; 10437 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) && 10438 p->subs[SUB_THREEWAY].owner && 10439 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 10440 /* This is a three way call, the main call being a real channel, 10441 and we're parking the first call. */ 10442 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), 10443 chan, exten, chan->context, 0, NULL); 10444 ast_verb(3, "Parking call to '%s'\n", chan->name); 10445 break; 10446 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 10447 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 10448 /* Enable Caller*ID if enabled */ 10449 p->hidecallerid = 0; 10450 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 10451 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10452 if (res) { 10453 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10454 chan->name, strerror(errno)); 10455 } 10456 len = 0; 10457 memset(exten, 0, sizeof(exten)); 10458 timeout = firstdigittimeout; 10459 } else if (!strcmp(exten, "*0")) { 10460 struct ast_channel *nbridge = 10461 p->subs[SUB_THREEWAY].owner; 10462 struct dahdi_pvt *pbridge = NULL; 10463 /* set up the private struct of the bridged one, if any */ 10464 if (nbridge && ast_bridged_channel(nbridge)) 10465 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 10466 if (nbridge && pbridge && 10467 (nbridge->tech == &dahdi_tech) && 10468 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 10469 ISTRUNK(pbridge)) { 10470 int func = DAHDI_FLASH; 10471 /* Clear out the dial buffer */ 10472 p->dop.dialstr[0] = '\0'; 10473 /* flash hookswitch */ 10474 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 10475 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 10476 nbridge->name, strerror(errno)); 10477 } 10478 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10479 unalloc_sub(p, SUB_THREEWAY); 10480 p->owner = p->subs[SUB_REAL].owner; 10481 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 10482 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 10483 ast_hangup(chan); 10484 goto quit; 10485 } else { 10486 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10487 dahdi_wait_event(p->subs[idx].dfd); 10488 tone_zone_play_tone(p->subs[idx].dfd, -1); 10489 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10490 unalloc_sub(p, SUB_THREEWAY); 10491 p->owner = p->subs[SUB_REAL].owner; 10492 ast_hangup(chan); 10493 goto quit; 10494 } 10495 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, 10496 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 10497 && !canmatch_featurecode(exten)) { 10498 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, 10499 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 10500 chan->context); 10501 break; 10502 } 10503 if (!timeout) 10504 timeout = gendigittimeout; 10505 if (len && !ast_ignore_pattern(chan->context, exten)) 10506 tone_zone_play_tone(p->subs[idx].dfd, -1); 10507 } 10508 break; 10509 case SIG_FXSLS: 10510 case SIG_FXSGS: 10511 case SIG_FXSKS: 10512 /* check for SMDI messages */ 10513 if (p->use_smdi && p->smdi_iface) { 10514 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 10515 10516 if (smdi_msg != NULL) { 10517 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 10518 10519 if (smdi_msg->type == 'B') 10520 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 10521 else if (smdi_msg->type == 'N') 10522 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 10523 10524 ast_debug(1, "Received SMDI message on %s\n", chan->name); 10525 } else { 10526 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 10527 } 10528 } 10529 10530 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 10531 number = smdi_msg->calling_st; 10532 10533 /* If we want caller id, we're in a prering state due to a polarity reversal 10534 * and we're set to use a polarity reversal to trigger the start of caller id, 10535 * grab the caller id and wait for ringing to start... */ 10536 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 10537 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 10538 /* If set to use DTMF CID signalling, listen for DTMF */ 10539 if (p->cid_signalling == CID_SIG_DTMF) { 10540 int k = 0; 10541 int off_ms; 10542 struct timeval start = ast_tvnow(); 10543 int ms; 10544 cs = NULL; 10545 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 10546 dahdi_setlinear(p->subs[idx].dfd, 0); 10547 /* 10548 * We are the only party interested in the Rx stream since 10549 * we have not answered yet. We don't need or even want DTMF 10550 * emulation. The DTMF digits can come so fast that emulation 10551 * can drop some of them. 10552 */ 10553 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 10554 off_ms = 4000;/* This is a typical OFF time between rings. */ 10555 for (;;) { 10556 struct ast_frame *f; 10557 10558 ms = ast_remaining_ms(start, off_ms); 10559 res = ast_waitfor(chan, ms); 10560 if (res <= 0) { 10561 /* 10562 * We do not need to restore the dahdi_setlinear() 10563 * or AST_FLAG_END_DTMF_ONLY flag settings since we 10564 * are hanging up the channel. 10565 */ 10566 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10567 "Exiting simple switch\n"); 10568 ast_hangup(chan); 10569 goto quit; 10570 } 10571 f = ast_read(chan); 10572 if (!f) 10573 break; 10574 if (f->frametype == AST_FRAME_DTMF) { 10575 if (k < ARRAY_LEN(dtmfbuf) - 1) { 10576 dtmfbuf[k++] = f->subclass.integer; 10577 } 10578 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer); 10579 start = ast_tvnow(); 10580 } 10581 ast_frfree(f); 10582 if (chan->_state == AST_STATE_RING || 10583 chan->_state == AST_STATE_RINGING) 10584 break; /* Got ring */ 10585 } 10586 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 10587 dtmfbuf[k] = '\0'; 10588 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10589 /* Got cid and ring. */ 10590 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 10591 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10592 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 10593 /* If first byte is NULL, we have no cid */ 10594 if (!ast_strlen_zero(dtmfcid)) 10595 number = dtmfcid; 10596 else 10597 number = NULL; 10598 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10599 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 10600 cs = callerid_new(p->cid_signalling); 10601 if (cs) { 10602 int off_ms; 10603 struct timeval start; 10604 int ms; 10605 samples = 0; 10606 #if 1 10607 bump_gains(p); 10608 #endif 10609 /* Take out of linear mode for Caller*ID processing */ 10610 dahdi_setlinear(p->subs[idx].dfd, 0); 10611 10612 /* First we wait and listen for the Caller*ID */ 10613 for (;;) { 10614 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10615 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10616 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10617 callerid_free(cs); 10618 ast_hangup(chan); 10619 goto quit; 10620 } 10621 if (i & DAHDI_IOMUX_SIGEVENT) { 10622 res = dahdi_get_event(p->subs[idx].dfd); 10623 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10624 if (res == DAHDI_EVENT_NOALARM) { 10625 p->inalarm = 0; 10626 } 10627 10628 if (p->cid_signalling == CID_SIG_V23_JP) { 10629 if (res == DAHDI_EVENT_RINGBEGIN) { 10630 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10631 usleep(1); 10632 } 10633 } else { 10634 res = 0; 10635 break; 10636 } 10637 } else if (i & DAHDI_IOMUX_READ) { 10638 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10639 if (res < 0) { 10640 if (errno != ELAST) { 10641 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10642 callerid_free(cs); 10643 ast_hangup(chan); 10644 goto quit; 10645 } 10646 break; 10647 } 10648 samples += res; 10649 10650 if (p->cid_signalling == CID_SIG_V23_JP) { 10651 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 10652 } else { 10653 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10654 } 10655 if (res < 0) { 10656 /* 10657 * The previous diagnostic message output likely 10658 * explains why it failed. 10659 */ 10660 ast_log(LOG_WARNING, 10661 "Failed to decode CallerID on channel '%s'\n", 10662 chan->name); 10663 break; 10664 } else if (res) 10665 break; 10666 else if (samples > (8000 * 10)) 10667 break; 10668 } 10669 } 10670 if (res == 1) { 10671 callerid_get(cs, &name, &number, &flags); 10672 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10673 } 10674 10675 if (p->cid_signalling == CID_SIG_V23_JP) { 10676 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10677 usleep(1); 10678 } 10679 10680 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 10681 start = ast_tvnow(); 10682 off_ms = 4000;/* This is a typical OFF time between rings. */ 10683 for (;;) { 10684 struct ast_frame *f; 10685 10686 ms = ast_remaining_ms(start, off_ms); 10687 res = ast_waitfor(chan, ms); 10688 if (res <= 0) { 10689 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 10690 "Exiting simple switch\n"); 10691 ast_hangup(chan); 10692 goto quit; 10693 } 10694 if (!(f = ast_read(chan))) { 10695 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 10696 ast_hangup(chan); 10697 goto quit; 10698 } 10699 ast_frfree(f); 10700 if (chan->_state == AST_STATE_RING || 10701 chan->_state == AST_STATE_RINGING) 10702 break; /* Got ring */ 10703 } 10704 10705 /* We must have a ring by now, so, if configured, lets try to listen for 10706 * distinctive ringing */ 10707 if (p->usedistinctiveringdetection) { 10708 len = 0; 10709 distMatches = 0; 10710 /* Clear the current ring data array so we don't have old data in it. */ 10711 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10712 curRingData[receivedRingT] = 0; 10713 receivedRingT = 0; 10714 counter = 0; 10715 counter1 = 0; 10716 /* Check to see if context is what it should be, if not set to be. */ 10717 if (strcmp(p->context,p->defcontext) != 0) { 10718 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10719 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10720 } 10721 10722 for (;;) { 10723 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10724 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10725 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10726 callerid_free(cs); 10727 ast_hangup(chan); 10728 goto quit; 10729 } 10730 if (i & DAHDI_IOMUX_SIGEVENT) { 10731 res = dahdi_get_event(p->subs[idx].dfd); 10732 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10733 if (res == DAHDI_EVENT_NOALARM) { 10734 p->inalarm = 0; 10735 } 10736 res = 0; 10737 /* Let us detect distinctive ring */ 10738 10739 curRingData[receivedRingT] = p->ringt; 10740 10741 if (p->ringt < p->ringt_base/2) 10742 break; 10743 /* Increment the ringT counter so we can match it against 10744 values in chan_dahdi.conf for distinctive ring */ 10745 if (++receivedRingT == ARRAY_LEN(curRingData)) 10746 break; 10747 } else if (i & DAHDI_IOMUX_READ) { 10748 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10749 if (res < 0) { 10750 if (errno != ELAST) { 10751 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10752 callerid_free(cs); 10753 ast_hangup(chan); 10754 goto quit; 10755 } 10756 break; 10757 } 10758 if (p->ringt > 0) { 10759 if (!(--p->ringt)) { 10760 res = -1; 10761 break; 10762 } 10763 } 10764 } 10765 } 10766 /* this only shows up if you have n of the dring patterns filled in */ 10767 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10768 for (counter = 0; counter < 3; counter++) { 10769 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10770 channel */ 10771 distMatches = 0; 10772 for (counter1 = 0; counter1 < 3; counter1++) { 10773 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10774 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10775 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10776 curRingData[counter1]); 10777 distMatches++; 10778 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10779 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10780 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10781 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10782 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10783 distMatches++; 10784 } 10785 } 10786 10787 if (distMatches == 3) { 10788 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10789 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10790 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10791 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10792 break; 10793 } 10794 } 10795 } 10796 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10797 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10798 #if 1 10799 restore_gains(p); 10800 #endif 10801 } else 10802 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10803 } else { 10804 ast_log(LOG_WARNING, "Channel %s in prering " 10805 "state, but I have nothing to do. " 10806 "Terminating simple switch, should be " 10807 "restarted by the actual ring.\n", 10808 chan->name); 10809 ast_hangup(chan); 10810 goto quit; 10811 } 10812 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 10813 if (p->cid_signalling == CID_SIG_DTMF) { 10814 int k = 0; 10815 int off_ms; 10816 struct timeval start; 10817 int ms; 10818 cs = NULL; 10819 dahdi_setlinear(p->subs[idx].dfd, 0); 10820 off_ms = 2000; 10821 start = ast_tvnow(); 10822 for (;;) { 10823 struct ast_frame *f; 10824 10825 ms = ast_remaining_ms(start, off_ms); 10826 res = ast_waitfor(chan, ms); 10827 if (res <= 0) { 10828 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10829 "Exiting simple switch\n"); 10830 ast_hangup(chan); 10831 goto quit; 10832 } 10833 f = ast_read(chan); 10834 if (!f) { 10835 /* Hangup received waiting for DTMFCID. Exiting simple switch. */ 10836 ast_hangup(chan); 10837 goto quit; 10838 } 10839 if (f->frametype == AST_FRAME_DTMF) { 10840 dtmfbuf[k++] = f->subclass.integer; 10841 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer); 10842 start = ast_tvnow(); 10843 } 10844 ast_frfree(f); 10845 10846 if (p->ringt_base == p->ringt) 10847 break; 10848 } 10849 dtmfbuf[k] = '\0'; 10850 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10851 /* Got cid and ring. */ 10852 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10853 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 10854 dtmfcid, flags); 10855 /* If first byte is NULL, we have no cid */ 10856 if (!ast_strlen_zero(dtmfcid)) 10857 number = dtmfcid; 10858 else 10859 number = NULL; 10860 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10861 } else { 10862 /* FSK Bell202 callerID */ 10863 cs = callerid_new(p->cid_signalling); 10864 if (cs) { 10865 #if 1 10866 bump_gains(p); 10867 #endif 10868 samples = 0; 10869 len = 0; 10870 distMatches = 0; 10871 /* Clear the current ring data array so we don't have old data in it. */ 10872 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10873 curRingData[receivedRingT] = 0; 10874 receivedRingT = 0; 10875 counter = 0; 10876 counter1 = 0; 10877 /* Check to see if context is what it should be, if not set to be. */ 10878 if (strcmp(p->context,p->defcontext) != 0) { 10879 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10880 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10881 } 10882 10883 /* Take out of linear mode for Caller*ID processing */ 10884 dahdi_setlinear(p->subs[idx].dfd, 0); 10885 for (;;) { 10886 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10887 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10888 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10889 callerid_free(cs); 10890 ast_hangup(chan); 10891 goto quit; 10892 } 10893 if (i & DAHDI_IOMUX_SIGEVENT) { 10894 res = dahdi_get_event(p->subs[idx].dfd); 10895 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10896 if (res == DAHDI_EVENT_NOALARM) { 10897 p->inalarm = 0; 10898 } 10899 /* If we get a PR event, they hung up while processing calerid */ 10900 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 10901 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 10902 p->polarity = POLARITY_IDLE; 10903 callerid_free(cs); 10904 ast_hangup(chan); 10905 goto quit; 10906 } 10907 res = 0; 10908 /* Let us detect callerid when the telco uses distinctive ring */ 10909 10910 curRingData[receivedRingT] = p->ringt; 10911 10912 if (p->ringt < p->ringt_base/2) 10913 break; 10914 /* Increment the ringT counter so we can match it against 10915 values in chan_dahdi.conf for distinctive ring */ 10916 if (++receivedRingT == ARRAY_LEN(curRingData)) 10917 break; 10918 } else if (i & DAHDI_IOMUX_READ) { 10919 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10920 if (res < 0) { 10921 if (errno != ELAST) { 10922 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10923 callerid_free(cs); 10924 ast_hangup(chan); 10925 goto quit; 10926 } 10927 break; 10928 } 10929 if (p->ringt > 0) { 10930 if (!(--p->ringt)) { 10931 res = -1; 10932 break; 10933 } 10934 } 10935 samples += res; 10936 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10937 if (res < 0) { 10938 /* 10939 * The previous diagnostic message output likely 10940 * explains why it failed. 10941 */ 10942 ast_log(LOG_WARNING, 10943 "Failed to decode CallerID on channel '%s'\n", 10944 chan->name); 10945 break; 10946 } else if (res) 10947 break; 10948 else if (samples > (8000 * 10)) 10949 break; 10950 } 10951 } 10952 if (res == 1) { 10953 callerid_get(cs, &name, &number, &flags); 10954 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10955 } 10956 if (distinctiveringaftercid == 1) { 10957 /* Clear the current ring data array so we don't have old data in it. */ 10958 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 10959 curRingData[receivedRingT] = 0; 10960 } 10961 receivedRingT = 0; 10962 ast_verb(3, "Detecting post-CID distinctive ring\n"); 10963 for (;;) { 10964 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10965 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10966 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10967 callerid_free(cs); 10968 ast_hangup(chan); 10969 goto quit; 10970 } 10971 if (i & DAHDI_IOMUX_SIGEVENT) { 10972 res = dahdi_get_event(p->subs[idx].dfd); 10973 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10974 if (res == DAHDI_EVENT_NOALARM) { 10975 p->inalarm = 0; 10976 } 10977 res = 0; 10978 /* Let us detect callerid when the telco uses distinctive ring */ 10979 10980 curRingData[receivedRingT] = p->ringt; 10981 10982 if (p->ringt < p->ringt_base/2) 10983 break; 10984 /* Increment the ringT counter so we can match it against 10985 values in chan_dahdi.conf for distinctive ring */ 10986 if (++receivedRingT == ARRAY_LEN(curRingData)) 10987 break; 10988 } else if (i & DAHDI_IOMUX_READ) { 10989 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10990 if (res < 0) { 10991 if (errno != ELAST) { 10992 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10993 callerid_free(cs); 10994 ast_hangup(chan); 10995 goto quit; 10996 } 10997 break; 10998 } 10999 if (p->ringt > 0) { 11000 if (!(--p->ringt)) { 11001 res = -1; 11002 break; 11003 } 11004 } 11005 } 11006 } 11007 } 11008 if (p->usedistinctiveringdetection) { 11009 /* this only shows up if you have n of the dring patterns filled in */ 11010 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 11011 11012 for (counter = 0; counter < 3; counter++) { 11013 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 11014 channel */ 11015 /* this only shows up if you have n of the dring patterns filled in */ 11016 ast_verb(3, "Checking %d,%d,%d\n", 11017 p->drings.ringnum[counter].ring[0], 11018 p->drings.ringnum[counter].ring[1], 11019 p->drings.ringnum[counter].ring[2]); 11020 distMatches = 0; 11021 for (counter1 = 0; counter1 < 3; counter1++) { 11022 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 11023 if (p->drings.ringnum[counter].ring[counter1] == -1) { 11024 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 11025 curRingData[counter1]); 11026 distMatches++; 11027 } 11028 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 11029 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 11030 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 11031 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 11032 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 11033 distMatches++; 11034 } 11035 } 11036 if (distMatches == 3) { 11037 /* The ring matches, set the context to whatever is for distinctive ring.. */ 11038 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 11039 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 11040 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 11041 break; 11042 } 11043 } 11044 } 11045 /* Restore linear mode (if appropriate) for Caller*ID processing */ 11046 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 11047 #if 1 11048 restore_gains(p); 11049 #endif 11050 if (res < 0) { 11051 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 11052 } 11053 } else 11054 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 11055 } 11056 } else 11057 cs = NULL; 11058 11059 if (number) 11060 ast_shrink_phone_number(number); 11061 ast_set_callerid(chan, number, name, number); 11062 11063 if (smdi_msg) 11064 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 11065 11066 if (cs) 11067 callerid_free(cs); 11068 11069 my_handle_notify_message(chan, p, flags, -1); 11070 11071 ast_setstate(chan, AST_STATE_RING); 11072 chan->rings = 1; 11073 p->ringt = p->ringt_base; 11074 res = ast_pbx_run(chan); 11075 if (res) { 11076 ast_hangup(chan); 11077 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 11078 } 11079 goto quit; 11080 default: 11081 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 11082 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11083 if (res < 0) 11084 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11085 } 11086 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 11087 if (res < 0) 11088 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 11089 ast_hangup(chan); 11090 quit: 11091 ast_mutex_lock(&ss_thread_lock); 11092 ss_thread_count--; 11093 ast_cond_signal(&ss_thread_complete); 11094 ast_mutex_unlock(&ss_thread_lock); 11095 return NULL; 11096 }
static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1667 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().
01668 { 01669 switch (tone) { 01670 case ANALOG_TONE_RINGTONE: 01671 return DAHDI_TONE_RINGTONE; 01672 case ANALOG_TONE_STUTTER: 01673 return DAHDI_TONE_STUTTER; 01674 case ANALOG_TONE_CONGESTION: 01675 return DAHDI_TONE_CONGESTION; 01676 case ANALOG_TONE_DIALTONE: 01677 return DAHDI_TONE_DIALTONE; 01678 case ANALOG_TONE_DIALRECALL: 01679 return DAHDI_TONE_DIALRECALL; 01680 case ANALOG_TONE_INFO: 01681 return DAHDI_TONE_INFO; 01682 default: 01683 return -1; 01684 } 01685 }
static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1687 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().
01688 { 01689 int index; 01690 01691 switch (analogsub) { 01692 case ANALOG_SUB_REAL: 01693 index = SUB_REAL; 01694 break; 01695 case ANALOG_SUB_CALLWAIT: 01696 index = SUB_CALLWAIT; 01697 break; 01698 case ANALOG_SUB_THREEWAY: 01699 index = SUB_THREEWAY; 01700 break; 01701 default: 01702 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01703 index = SUB_REAL; 01704 } 01705 01706 return index; 01707 }
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 7668 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().
07669 { 07670 /* In order to transfer, we need at least one of the channels to 07671 actually be in a call bridge. We can't conference two applications 07672 together (but then, why would we want to?) */ 07673 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07674 /* The three-way person we're about to transfer to could still be in MOH, so 07675 stop if now if appropriate */ 07676 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 07677 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 07678 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 07679 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 07680 } 07681 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 07682 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07683 } 07684 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 07685 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07686 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 07687 return -1; 07688 } 07689 /* Orphan the channel after releasing the lock */ 07690 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07691 unalloc_sub(p, SUB_THREEWAY); 07692 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07693 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07694 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 07695 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 07696 } 07697 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 07698 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07699 } 07700 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 07701 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07702 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 07703 return -1; 07704 } 07705 /* Three-way is now the REAL */ 07706 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07707 ast_channel_unlock(p->subs[SUB_REAL].owner); 07708 unalloc_sub(p, SUB_THREEWAY); 07709 /* Tell the caller not to hangup */ 07710 return 1; 07711 } else { 07712 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 07713 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 07714 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07715 return -1; 07716 } 07717 return 0; 07718 }
static int available | ( | struct dahdi_pvt ** | pvt, | |
int | is_specific_channel | |||
) | [static] |
Definition at line 13256 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().
13257 { 13258 struct dahdi_pvt *p = *pvt; 13259 13260 if (p->inalarm) 13261 return 0; 13262 13263 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 13264 return analog_available(p->sig_pvt); 13265 13266 switch (p->sig) { 13267 #if defined(HAVE_PRI) 13268 case SIG_PRI_LIB_HANDLE_CASES: 13269 { 13270 struct sig_pri_chan *pvt_chan; 13271 int res; 13272 13273 pvt_chan = p->sig_pvt; 13274 res = sig_pri_available(&pvt_chan, is_specific_channel); 13275 *pvt = pvt_chan->chan_pvt; 13276 return res; 13277 } 13278 #endif /* defined(HAVE_PRI) */ 13279 #if defined(HAVE_SS7) 13280 case SIG_SS7: 13281 return sig_ss7_available(p->sig_pvt); 13282 #endif /* defined(HAVE_SS7) */ 13283 default: 13284 break; 13285 } 13286 13287 if (p->locallyblocked || p->remotelyblocked) { 13288 return 0; 13289 } 13290 13291 /* If no owner definitely available */ 13292 if (!p->owner) { 13293 #ifdef HAVE_OPENR2 13294 /* Trust MFC/R2 */ 13295 if (p->mfcr2) { 13296 if (p->mfcr2call) { 13297 return 0; 13298 } else { 13299 return 1; 13300 } 13301 } 13302 #endif 13303 return 1; 13304 } 13305 13306 return 0; 13307 }
static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
const char * | value, | |||
int | reload, | |||
int | lineno, | |||
int * | found_pseudo | |||
) | [static] |
Definition at line 16870 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().
16871 { 16872 char *c, *chan; 16873 char *subdir; 16874 int x, start, finish; 16875 struct dahdi_pvt *tmp; 16876 16877 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 16878 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 16879 return -1; 16880 } 16881 16882 c = ast_strdupa(value); 16883 c = parse_spanchan(c, &subdir); 16884 16885 while ((chan = strsep(&c, ","))) { 16886 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 16887 /* Range */ 16888 } else if (sscanf(chan, "%30d", &start)) { 16889 /* Just one */ 16890 finish = start; 16891 } else if (!strcasecmp(chan, "pseudo")) { 16892 finish = start = CHAN_PSEUDO; 16893 if (found_pseudo) 16894 *found_pseudo = 1; 16895 } else { 16896 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 16897 return -1; 16898 } 16899 if (finish < start) { 16900 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 16901 x = finish; 16902 finish = start; 16903 start = x; 16904 } 16905 16906 for (x = start; x <= finish; x++) { 16907 char fn[PATH_MAX]; 16908 int real_channel = x; 16909 16910 if (!ast_strlen_zero(subdir)) { 16911 real_channel = device2chan(subdir, x, fn, sizeof(fn)); 16912 if (real_channel < 0) { 16913 if (conf->ignore_failed_channels) { 16914 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n", 16915 subdir, x, real_channel); 16916 continue; 16917 } else { 16918 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n", 16919 subdir, x, real_channel); 16920 return -1; 16921 } 16922 } 16923 } 16924 tmp = mkintf(real_channel, conf, reload); 16925 16926 if (tmp) { 16927 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig)); 16928 } else { 16929 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 16930 (reload == 1) ? "reconfigure" : "register", value); 16931 return -1; 16932 } 16933 } 16934 } 16935 16936 return 0; 16937 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5147 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().
05148 { 05149 int res; 05150 05151 /* Bump receive gain by value stored in cid_rxgain */ 05152 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05153 if (res) { 05154 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 05155 return -1; 05156 } 05157 05158 return 0; 05159 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
format_t | law | |||
) | [static] |
Definition at line 11104 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 9926 of file chan_dahdi.c.
References ast_pickup_ext(), and pickup_ext.
Referenced by analog_ss_thread().
09927 { 09928 int extlen = strlen(exten); 09929 const char *pickup_ext; 09930 if (!extlen) { 09931 return 1; 09932 } 09933 pickup_ext = ast_pickup_ext(); 09934 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) { 09935 return 1; 09936 } 09937 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */ 09938 if (exten[0] == '*' && extlen < 3) { 09939 if (extlen == 1) { 09940 return 1; 09941 } 09942 /* "*0" should be processed before it gets here */ 09943 switch (exten[1]) { 09944 case '6': 09945 case '7': 09946 case '8': 09947 return 1; 09948 } 09949 } 09950 return 0; 09951 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7720 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().
07721 { 07722 struct dahdi_confinfo ci; 07723 /* Fine if we already have a master, etc */ 07724 if (p->master || (p->confno > -1)) 07725 return 0; 07726 memset(&ci, 0, sizeof(ci)); 07727 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 07728 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 07729 return 0; 07730 } 07731 /* If we have no master and don't have a confno, then 07732 if we're in a conference, it's probably a MeetMe room or 07733 some such, so don't let us 3-way out! */ 07734 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 07735 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 07736 return 1; 07737 } 07738 return 0; 07739 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 4729 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().
04730 { 04731 /* If the conference already exists, and we're already in it 04732 don't bother doing anything */ 04733 struct dahdi_confinfo zi; 04734 04735 memset(&zi, 0, sizeof(zi)); 04736 zi.chan = 0; 04737 04738 if (slavechannel > 0) { 04739 /* If we have only one slave, do a digital mon */ 04740 zi.confmode = DAHDI_CONF_DIGITALMON; 04741 zi.confno = slavechannel; 04742 } else { 04743 if (!idx) { 04744 /* Real-side and pseudo-side both participate in conference */ 04745 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 04746 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 04747 } else 04748 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 04749 zi.confno = p->confno; 04750 } 04751 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 04752 return 0; 04753 if (c->dfd < 0) 04754 return 0; 04755 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04756 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 04757 return -1; 04758 } 04759 if (slavechannel < 1) { 04760 p->confno = zi.confno; 04761 } 04762 c->curconf = zi; 04763 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04764 return 0; 04765 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 4778 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().
04779 { 04780 struct dahdi_confinfo zi; 04781 if (/* Can't delete if there's no dfd */ 04782 (c->dfd < 0) || 04783 /* Don't delete from the conference if it's not our conference */ 04784 !isourconf(p, c) 04785 /* Don't delete if we don't think it's conferenced at all (implied) */ 04786 ) return 0; 04787 memset(&zi, 0, sizeof(zi)); 04788 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04789 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 04790 return -1; 04791 } 04792 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04793 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 04794 return 0; 04795 }
Definition at line 9586 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().
09588 { 09589 struct ast_str *chan_name; 09590 int x, y; 09591 09592 /* Create the new channel name tail. */ 09593 if (!(chan_name = ast_str_create(32))) { 09594 return NULL; 09595 } 09596 if (i->channel == CHAN_PSEUDO) { 09597 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 09598 #if defined(HAVE_PRI) 09599 } else if (i->pri) { 09600 ast_mutex_lock(&i->pri->lock); 09601 y = ++i->pri->new_chan_seq; 09602 if (is_outgoing) { 09603 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y); 09604 address[0] = '\0'; 09605 } else if (ast_strlen_zero(i->cid_subaddr)) { 09606 /* Put in caller-id number only since there is no subaddress. */ 09607 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y); 09608 } else { 09609 /* Put in caller-id number and subaddress. */ 09610 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num, 09611 i->cid_subaddr, y); 09612 } 09613 ast_mutex_unlock(&i->pri->lock); 09614 #endif /* defined(HAVE_PRI) */ 09615 } else { 09616 y = 1; 09617 do { 09618 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 09619 for (x = 0; x < 3; ++x) { 09620 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), 09621 i->subs[x].owner->name + 6)) { 09622 break; 09623 } 09624 } 09625 ++y; 09626 } while (x < 3); 09627 } 09628 return chan_name; 09629 }
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 6596 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.
06597 { 06598 struct dahdi_pvt *p = ast->tech_pvt; 06599 int res = 0; 06600 int idx; 06601 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */ 06602 ast_mutex_lock(&p->lock); 06603 idx = dahdi_get_index(ast, p, 0); 06604 if (idx < 0) 06605 idx = SUB_REAL; 06606 /* nothing to do if a radio channel */ 06607 if ((p->radio || (p->oprmode < 0))) { 06608 ast_mutex_unlock(&p->lock); 06609 return 0; 06610 } 06611 06612 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06613 res = analog_answer(p->sig_pvt, ast); 06614 ast_mutex_unlock(&p->lock); 06615 return res; 06616 } 06617 06618 switch (p->sig) { 06619 #if defined(HAVE_PRI) 06620 case SIG_PRI_LIB_HANDLE_CASES: 06621 res = sig_pri_answer(p->sig_pvt, ast); 06622 break; 06623 #endif /* defined(HAVE_PRI) */ 06624 #if defined(HAVE_SS7) 06625 case SIG_SS7: 06626 res = sig_ss7_answer(p->sig_pvt, ast); 06627 break; 06628 #endif /* defined(HAVE_SS7) */ 06629 #ifdef HAVE_OPENR2 06630 case SIG_MFCR2: 06631 if (!p->mfcr2_call_accepted) { 06632 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 06633 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 06634 p->mfcr2_answer_pending = 1; 06635 if (p->mfcr2_charge_calls) { 06636 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 06637 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 06638 } else { 06639 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 06640 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 06641 } 06642 } else { 06643 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 06644 dahdi_r2_answer(p); 06645 } 06646 break; 06647 #endif 06648 case 0: 06649 ast_mutex_unlock(&p->lock); 06650 return 0; 06651 default: 06652 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 06653 res = -1; 06654 break; 06655 } 06656 ast_mutex_unlock(&p->lock); 06657 return res; 06658 }
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 7243 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().
07244 { 07245 struct ast_channel *who; 07246 struct dahdi_pvt *p0, *p1, *op0, *op1; 07247 struct dahdi_pvt *master = NULL, *slave = NULL; 07248 struct ast_frame *f; 07249 int inconf = 0; 07250 int nothingok = 1; 07251 int ofd0, ofd1; 07252 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 07253 int os0 = -1, os1 = -1; 07254 int priority = 0; 07255 struct ast_channel *oc0, *oc1; 07256 enum ast_bridge_result res; 07257 struct timeval start = ast_tvnow(); 07258 #ifdef PRI_2BCT 07259 int triedtopribridge = 0; 07260 q931_call *q931c0; 07261 q931_call *q931c1; 07262 #endif 07263 07264 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 07265 There is code below to handle it properly until DTMF is actually seen, 07266 but due to currently unresolved issues it's ignored... 07267 */ 07268 07269 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 07270 return AST_BRIDGE_FAILED_NOWARN; 07271 07272 ast_channel_lock(c0); 07273 while (ast_channel_trylock(c1)) { 07274 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07275 } 07276 07277 p0 = c0->tech_pvt; 07278 p1 = c1->tech_pvt; 07279 /* cant do pseudo-channels here */ 07280 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 07281 ast_channel_unlock(c0); 07282 ast_channel_unlock(c1); 07283 return AST_BRIDGE_FAILED_NOWARN; 07284 } 07285 07286 oi0 = dahdi_get_index(c0, p0, 0); 07287 oi1 = dahdi_get_index(c1, p1, 0); 07288 if ((oi0 < 0) || (oi1 < 0)) { 07289 ast_channel_unlock(c0); 07290 ast_channel_unlock(c1); 07291 return AST_BRIDGE_FAILED; 07292 } 07293 07294 op0 = p0 = c0->tech_pvt; 07295 op1 = p1 = c1->tech_pvt; 07296 ofd0 = c0->fds[0]; 07297 ofd1 = c1->fds[0]; 07298 oc0 = p0->owner; 07299 oc1 = p1->owner; 07300 07301 if (ast_mutex_trylock(&p0->lock)) { 07302 /* Don't block, due to potential for deadlock */ 07303 ast_channel_unlock(c0); 07304 ast_channel_unlock(c1); 07305 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07306 return AST_BRIDGE_RETRY; 07307 } 07308 if (ast_mutex_trylock(&p1->lock)) { 07309 /* Don't block, due to potential for deadlock */ 07310 ast_mutex_unlock(&p0->lock); 07311 ast_channel_unlock(c0); 07312 ast_channel_unlock(c1); 07313 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07314 return AST_BRIDGE_RETRY; 07315 } 07316 07317 if ((p0->callwaiting && p0->callwaitingcallerid) 07318 || (p1->callwaiting && p1->callwaitingcallerid)) { 07319 /* 07320 * Call Waiting Caller ID requires DTMF detection to know if it 07321 * can send the CID spill. 07322 * 07323 * For now, don't attempt to native bridge if either channel 07324 * needs DTMF detection. There is code below to handle it 07325 * properly until DTMF is actually seen, but due to currently 07326 * unresolved issues it's ignored... 07327 */ 07328 ast_mutex_unlock(&p0->lock); 07329 ast_mutex_unlock(&p1->lock); 07330 ast_channel_unlock(c0); 07331 ast_channel_unlock(c1); 07332 return AST_BRIDGE_FAILED_NOWARN; 07333 } 07334 07335 #if defined(HAVE_PRI) 07336 if ((dahdi_sig_pri_lib_handles(p0->sig) 07337 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 07338 || (dahdi_sig_pri_lib_handles(p1->sig) 07339 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 07340 /* 07341 * PRI nobch channels (hold and call waiting) are equivalent to 07342 * pseudo channels and cannot be done here. 07343 */ 07344 ast_mutex_unlock(&p0->lock); 07345 ast_mutex_unlock(&p1->lock); 07346 ast_channel_unlock(c0); 07347 ast_channel_unlock(c1); 07348 return AST_BRIDGE_FAILED_NOWARN; 07349 } 07350 #endif /* defined(HAVE_PRI) */ 07351 07352 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07353 if (p0->owner && p1->owner) { 07354 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 07355 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 07356 master = p0; 07357 slave = p1; 07358 inconf = 1; 07359 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 07360 master = p1; 07361 slave = p0; 07362 inconf = 1; 07363 } else { 07364 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 07365 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 07366 p0->channel, 07367 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07368 p0->subs[SUB_REAL].inthreeway, p0->channel, 07369 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07370 p1->subs[SUB_REAL].inthreeway); 07371 } 07372 nothingok = 0; 07373 } 07374 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 07375 if (p1->subs[SUB_THREEWAY].inthreeway) { 07376 master = p1; 07377 slave = p0; 07378 nothingok = 0; 07379 } 07380 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 07381 if (p0->subs[SUB_THREEWAY].inthreeway) { 07382 master = p0; 07383 slave = p1; 07384 nothingok = 0; 07385 } 07386 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 07387 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 07388 don't put us in anything */ 07389 if (p1->subs[SUB_CALLWAIT].inthreeway) { 07390 master = p1; 07391 slave = p0; 07392 nothingok = 0; 07393 } 07394 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 07395 /* Same as previous */ 07396 if (p0->subs[SUB_CALLWAIT].inthreeway) { 07397 master = p0; 07398 slave = p1; 07399 nothingok = 0; 07400 } 07401 } 07402 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 07403 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 07404 if (master && slave) { 07405 /* Stop any tones, or play ringtone as appropriate. If they're bridged 07406 in an active threeway call with a channel that is ringing, we should 07407 indicate ringing. */ 07408 if ((oi1 == SUB_THREEWAY) && 07409 p1->subs[SUB_THREEWAY].inthreeway && 07410 p1->subs[SUB_REAL].owner && 07411 p1->subs[SUB_REAL].inthreeway && 07412 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07413 ast_debug(1, 07414 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07415 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07416 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 07417 os1 = p1->subs[SUB_REAL].owner->_state; 07418 } else { 07419 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07420 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07421 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 07422 } 07423 if ((oi0 == SUB_THREEWAY) && 07424 p0->subs[SUB_THREEWAY].inthreeway && 07425 p0->subs[SUB_REAL].owner && 07426 p0->subs[SUB_REAL].inthreeway && 07427 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07428 ast_debug(1, 07429 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07430 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07431 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 07432 os0 = p0->subs[SUB_REAL].owner->_state; 07433 } else { 07434 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07435 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07436 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 07437 } 07438 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07439 if (!p0->echocanbridged || !p1->echocanbridged) { 07440 /* Disable echo cancellation if appropriate */ 07441 dahdi_disable_ec(p0); 07442 dahdi_disable_ec(p1); 07443 } 07444 } 07445 dahdi_link(slave, master); 07446 master->inconference = inconf; 07447 } else if (!nothingok) 07448 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 07449 07450 update_conf(p0); 07451 update_conf(p1); 07452 t0 = p0->subs[SUB_REAL].inthreeway; 07453 t1 = p1->subs[SUB_REAL].inthreeway; 07454 07455 ast_mutex_unlock(&p0->lock); 07456 ast_mutex_unlock(&p1->lock); 07457 07458 ast_channel_unlock(c0); 07459 ast_channel_unlock(c1); 07460 07461 /* Native bridge failed */ 07462 if ((!master || !slave) && !nothingok) { 07463 dahdi_enable_ec(p0); 07464 dahdi_enable_ec(p1); 07465 return AST_BRIDGE_FAILED; 07466 } 07467 07468 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 07469 07470 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07471 disable_dtmf_detect(op0); 07472 07473 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07474 disable_dtmf_detect(op1); 07475 07476 for (;;) { 07477 struct ast_channel *c0_priority[2] = {c0, c1}; 07478 struct ast_channel *c1_priority[2] = {c1, c0}; 07479 int ms; 07480 07481 /* Here's our main loop... Start by locking things, looking for private parts, 07482 and then balking if anything is wrong */ 07483 07484 ast_channel_lock(c0); 07485 while (ast_channel_trylock(c1)) { 07486 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07487 } 07488 07489 p0 = c0->tech_pvt; 07490 p1 = c1->tech_pvt; 07491 07492 if (op0 == p0) 07493 i0 = dahdi_get_index(c0, p0, 1); 07494 if (op1 == p1) 07495 i1 = dahdi_get_index(c1, p1, 1); 07496 07497 ast_channel_unlock(c0); 07498 ast_channel_unlock(c1); 07499 ms = ast_remaining_ms(start, timeoutms); 07500 if (!ms || 07501 (op0 != p0) || 07502 (op1 != p1) || 07503 (ofd0 != c0->fds[0]) || 07504 (ofd1 != c1->fds[0]) || 07505 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 07506 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 07507 (oc0 != p0->owner) || 07508 (oc1 != p1->owner) || 07509 (t0 != p0->subs[SUB_REAL].inthreeway) || 07510 (t1 != p1->subs[SUB_REAL].inthreeway) || 07511 (oi0 != i0) || 07512 (oi1 != i1)) { 07513 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 07514 op0->channel, oi0, op1->channel, oi1); 07515 res = AST_BRIDGE_RETRY; 07516 goto return_from_bridge; 07517 } 07518 07519 #ifdef PRI_2BCT 07520 if (!triedtopribridge) { 07521 triedtopribridge = 1; 07522 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) { 07523 ast_mutex_lock(&p0->pri->lock); 07524 switch (p0->sig) { 07525 case SIG_PRI_LIB_HANDLE_CASES: 07526 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 07527 break; 07528 default: 07529 q931c0 = NULL; 07530 break; 07531 } 07532 switch (p1->sig) { 07533 case SIG_PRI_LIB_HANDLE_CASES: 07534 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 07535 break; 07536 default: 07537 q931c1 = NULL; 07538 break; 07539 } 07540 if (q931c0 && q931c1) { 07541 pri_channel_bridge(q931c0, q931c1); 07542 } 07543 ast_mutex_unlock(&p0->pri->lock); 07544 } 07545 } 07546 #endif 07547 07548 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms); 07549 if (!who) { 07550 ast_debug(1, "Ooh, empty read...\n"); 07551 continue; 07552 } 07553 f = ast_read(who); 07554 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 07555 *fo = f; 07556 *rc = who; 07557 res = AST_BRIDGE_COMPLETE; 07558 goto return_from_bridge; 07559 } 07560 if (f->frametype == AST_FRAME_DTMF) { 07561 if ((who == c0) && p0->pulsedial) { 07562 ast_write(c1, f); 07563 } else if ((who == c1) && p1->pulsedial) { 07564 ast_write(c0, f); 07565 } else { 07566 *fo = f; 07567 *rc = who; 07568 res = AST_BRIDGE_COMPLETE; 07569 goto return_from_bridge; 07570 } 07571 } 07572 ast_frfree(f); 07573 07574 /* Swap who gets priority */ 07575 priority = !priority; 07576 } 07577 07578 return_from_bridge: 07579 if (op0 == p0) 07580 dahdi_enable_ec(p0); 07581 07582 if (op1 == p1) 07583 dahdi_enable_ec(p1); 07584 07585 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07586 enable_dtmf_detect(op0); 07587 07588 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07589 enable_dtmf_detect(op1); 07590 07591 dahdi_unlink(slave, master, 1); 07592 07593 return res; 07594 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 5381 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.
05382 { 05383 struct dahdi_pvt *p = ast->tech_pvt; 05384 int x, res, mysig; 05385 char dest[256]; /* must be same length as p->dialdest */ 05386 05387 ast_mutex_lock(&p->lock); 05388 ast_copy_string(dest, rdest, sizeof(dest)); 05389 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 05390 if ((ast->_state == AST_STATE_BUSY)) { 05391 p->subs[SUB_REAL].needbusy = 1; 05392 ast_mutex_unlock(&p->lock); 05393 return 0; 05394 } 05395 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05396 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 05397 ast_mutex_unlock(&p->lock); 05398 return -1; 05399 } 05400 p->waitingfordt.tv_sec = 0; 05401 p->dialednone = 0; 05402 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 05403 { 05404 /* Special pseudo -- automatically up */ 05405 ast_setstate(ast, AST_STATE_UP); 05406 ast_mutex_unlock(&p->lock); 05407 return 0; 05408 } 05409 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 05410 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 05411 if (res) 05412 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 05413 p->outgoing = 1; 05414 05415 if (IS_DIGITAL(ast->transfercapability)){ 05416 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law); 05417 } else { 05418 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05419 } 05420 05421 #ifdef HAVE_PRI 05422 if (dahdi_sig_pri_lib_handles(p->sig)) { 05423 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, 05424 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW); 05425 ast_mutex_unlock(&p->lock); 05426 return res; 05427 } 05428 #endif 05429 05430 #if defined(HAVE_SS7) 05431 if (p->sig == SIG_SS7) { 05432 res = sig_ss7_call(p->sig_pvt, ast, rdest); 05433 ast_mutex_unlock(&p->lock); 05434 return res; 05435 } 05436 #endif /* defined(HAVE_SS7) */ 05437 05438 /* If this is analog signalling we can exit here */ 05439 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05440 p->callwaitrings = 0; 05441 res = analog_call(p->sig_pvt, ast, rdest, timeout); 05442 ast_mutex_unlock(&p->lock); 05443 return res; 05444 } 05445 05446 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 05447 switch (mysig) { 05448 case 0: 05449 /* Special pseudo -- automatically up*/ 05450 ast_setstate(ast, AST_STATE_UP); 05451 break; 05452 case SIG_MFCR2: 05453 break; 05454 default: 05455 ast_debug(1, "not yet implemented\n"); 05456 ast_mutex_unlock(&p->lock); 05457 return -1; 05458 } 05459 05460 #ifdef HAVE_OPENR2 05461 if (p->mfcr2) { 05462 openr2_calling_party_category_t chancat; 05463 int callres = 0; 05464 char *c, *l; 05465 05466 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 05467 p->dialdest[0] = '\0'; 05468 05469 c = strchr(dest, '/'); 05470 if (c) { 05471 c++; 05472 } else { 05473 c = ""; 05474 } 05475 if (!p->hidecallerid) { 05476 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL; 05477 } else { 05478 l = NULL; 05479 } 05480 if (strlen(c) < p->stripmsd) { 05481 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 05482 ast_mutex_unlock(&p->lock); 05483 return -1; 05484 } 05485 p->dialing = 1; 05486 chancat = dahdi_r2_get_channel_category(ast); 05487 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 05488 if (-1 == callres) { 05489 ast_mutex_unlock(&p->lock); 05490 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 05491 return -1; 05492 } 05493 p->mfcr2_call_accepted = 0; 05494 p->mfcr2_progress = 0; 05495 ast_setstate(ast, AST_STATE_DIALING); 05496 } 05497 #endif /* HAVE_OPENR2 */ 05498 ast_mutex_unlock(&p->lock); 05499 return 0; 05500 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5348 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().
05349 { 05350 struct dahdi_pvt *p = ast->tech_pvt; 05351 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 05352 if (p->cidspill) { 05353 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 05354 ast_free(p->cidspill); 05355 } 05356 05357 /* 05358 * SAS: Subscriber Alert Signal, 440Hz for 300ms 05359 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 05360 */ 05361 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 05362 return -1; 05363 save_conference(p); 05364 /* Silence */ 05365 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 05366 if (!p->callwaitrings && p->callwaitingcallerid) { 05367 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 05368 p->callwaitcas = 1; 05369 p->cidlen = 2400 + 680 + READ_SIZE * 4; 05370 } else { 05371 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 05372 p->callwaitcas = 0; 05373 p->cidlen = 2400 + READ_SIZE * 4; 05374 } 05375 p->cidpos = 0; 05376 send_callerid(p); 05377 05378 return 0; 05379 }
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 13921 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.
13922 { 13923 struct dahdi_pvt *p; 13924 struct dahdi_pvt *exitpvt; 13925 struct dahdi_starting_point start; 13926 int groupmatched = 0; 13927 int channelmatched = 0; 13928 13929 ast_mutex_lock(&iflock); 13930 p = determine_starting_point(dest, &start); 13931 if (!p) { 13932 ast_mutex_unlock(&iflock); 13933 return -1; 13934 } 13935 exitpvt = p; 13936 for (;;) { 13937 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) { 13938 /* We found a potential match. call the callback */ 13939 struct ast_str *device_name; 13940 char *dash; 13941 const char *monitor_type; 13942 char dialstring[AST_CHANNEL_NAME]; 13943 char full_device_name[AST_CHANNEL_NAME]; 13944 13945 switch (ast_get_cc_monitor_policy(p->cc_params)) { 13946 case AST_CC_MONITOR_NEVER: 13947 break; 13948 case AST_CC_MONITOR_NATIVE: 13949 case AST_CC_MONITOR_ALWAYS: 13950 case AST_CC_MONITOR_GENERIC: 13951 #if defined(HAVE_PRI) 13952 if (dahdi_sig_pri_lib_handles(p->sig)) { 13953 /* 13954 * ISDN is in a trunk busy condition so we need to monitor 13955 * the span congestion device state. 13956 */ 13957 snprintf(full_device_name, sizeof(full_device_name), 13958 "DAHDI/I%d/congestion", p->pri->span); 13959 } else 13960 #endif /* defined(HAVE_PRI) */ 13961 { 13962 #if defined(HAVE_PRI) 13963 device_name = create_channel_name(p, 1, ""); 13964 #else 13965 device_name = create_channel_name(p); 13966 #endif /* defined(HAVE_PRI) */ 13967 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", 13968 device_name ? ast_str_buffer(device_name) : ""); 13969 ast_free(device_name); 13970 /* 13971 * The portion after the '-' in the channel name is either a random 13972 * number, a sequence number, or a subchannel number. None are 13973 * necessary so strip them off. 13974 */ 13975 dash = strrchr(full_device_name, '-'); 13976 if (dash) { 13977 *dash = '\0'; 13978 } 13979 } 13980 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest); 13981 13982 /* 13983 * Analog can only do generic monitoring. 13984 * ISDN is in a trunk busy condition and any "device" is going 13985 * to be busy until a B channel becomes available. The generic 13986 * monitor can do this task. 13987 */ 13988 monitor_type = AST_CC_GENERIC_MONITOR_TYPE; 13989 callback(inbound, 13990 #if defined(HAVE_PRI) 13991 p->pri ? p->pri->cc_params : p->cc_params, 13992 #else 13993 p->cc_params, 13994 #endif /* defined(HAVE_PRI) */ 13995 monitor_type, full_device_name, dialstring, NULL); 13996 break; 13997 } 13998 } 13999 p = start.backwards ? p->prev : p->next; 14000 if (!p) { 14001 p = start.backwards ? ifend : iflist; 14002 } 14003 if (p == exitpvt) { 14004 break; 14005 } 14006 } 14007 ast_mutex_unlock(&iflock); 14008 return 0; 14009 }
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 1369 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().
01370 { 01371 /* recall that if a field is not included here it is initialized 01372 * to 0 or equivalent 01373 */ 01374 struct dahdi_chan_conf conf = { 01375 #ifdef HAVE_PRI 01376 .pri.pri = { 01377 .nsf = PRI_NSF_NONE, 01378 .switchtype = PRI_SWITCH_NI2, 01379 .dialplan = PRI_UNKNOWN + 1, 01380 .localdialplan = PRI_NATIONAL_ISDN + 1, 01381 .nodetype = PRI_CPE, 01382 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01383 01384 #if defined(HAVE_PRI_CCSS) 01385 .cc_ptmp_recall_mode = 1,/* specificRecall */ 01386 .cc_qsig_signaling_link_req = 1,/* retain */ 01387 .cc_qsig_signaling_link_rsp = 1,/* retain */ 01388 #endif /* defined(HAVE_PRI_CCSS) */ 01389 01390 .minunused = 2, 01391 .idleext = "", 01392 .idledial = "", 01393 .internationalprefix = "", 01394 .nationalprefix = "", 01395 .localprefix = "", 01396 .privateprefix = "", 01397 .unknownprefix = "", 01398 .resetinterval = -1, 01399 }, 01400 #endif 01401 #if defined(HAVE_SS7) 01402 .ss7.ss7 = { 01403 .called_nai = SS7_NAI_NATIONAL, 01404 .calling_nai = SS7_NAI_NATIONAL, 01405 .internationalprefix = "", 01406 .nationalprefix = "", 01407 .subscriberprefix = "", 01408 .unknownprefix = "" 01409 }, 01410 #endif /* defined(HAVE_SS7) */ 01411 #ifdef HAVE_OPENR2 01412 .mfcr2 = { 01413 .variant = OR2_VAR_ITU, 01414 .mfback_timeout = -1, 01415 .metering_pulse_timeout = -1, 01416 .max_ani = 10, 01417 .max_dnis = 4, 01418 .get_ani_first = -1, 01419 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01420 .skip_category_request = -1, 01421 #endif 01422 .call_files = 0, 01423 .allow_collect_calls = 0, 01424 .charge_calls = 1, 01425 .accept_on_offer = 1, 01426 .forced_release = 0, 01427 .double_answer = 0, 01428 .immediate_accept = -1, 01429 .logdir = "", 01430 .r2proto_file = "", 01431 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01432 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01433 }, 01434 #endif 01435 .chan = { 01436 .context = "default", 01437 .cid_num = "", 01438 .cid_name = "", 01439 .cid_tag = "", 01440 .mohinterpret = "default", 01441 .mohsuggest = "", 01442 .parkinglot = "", 01443 .transfertobusy = 1, 01444 01445 .cid_signalling = CID_SIG_BELL, 01446 .cid_start = CID_START_RING, 01447 .dahditrcallerid = 0, 01448 .use_callerid = 1, 01449 .sig = -1, 01450 .outsigmod = -1, 01451 01452 .cid_rxgain = +5.0, 01453 01454 .tonezone = -1, 01455 01456 .echocancel.head.tap_length = 1, 01457 01458 .busycount = 3, 01459 .busycompare = 0, 01460 .busytonelength = 0, 01461 .busyquietlength = 0, 01462 .busyfuzziness = 0, 01463 .silencethreshold = 0, 01464 01465 .accountcode = "", 01466 01467 .mailbox = "", 01468 01469 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01470 .mwisend_fsk = 1, 01471 #endif 01472 .polarityonanswerdelay = 600, 01473 01474 .sendcalleridafter = DEFAULT_CIDRINGS, 01475 01476 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01477 .buf_no = numbufs, 01478 .usefaxbuffers = 0, 01479 .cc_params = ast_cc_config_params_init(), 01480 }, 01481 .timing = { 01482 .prewinktime = -1, 01483 .preflashtime = -1, 01484 .winktime = -1, 01485 .flashtime = -1, 01486 .starttime = -1, 01487 .rxwinktime = -1, 01488 .rxflashtime = -1, 01489 .debouncetime = -1 01490 }, 01491 .is_sig_auto = 1, 01492 .smdi_port = "/dev/ttyS0", 01493 }; 01494 01495 return conf; 01496 }
static int dahdi_channels_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18530 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.
18532 { 18533 struct dahdi_pvt *tmp; 18534 struct ast_data *data_channel; 18535 18536 ast_mutex_lock(&iflock); 18537 for (tmp = iflist; tmp; tmp = tmp->next) { 18538 data_channel = ast_data_add_node(data_root, "channel"); 18539 if (!data_channel) { 18540 continue; 18541 } 18542 18543 ast_data_add_structure(dahdi_pvt, data_channel, tmp); 18544 18545 /* if this channel doesn't match remove it. */ 18546 if (!ast_data_search_match(search, data_channel)) { 18547 ast_data_remove_node(data_root, data_channel); 18548 } 18549 } 18550 ast_mutex_unlock(&iflock); 18551 18552 return 0; 18553 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 4411 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 4417 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().
04418 { 04419 dahdi_close(chan_pvt->subs[sub_num].dfd); 04420 chan_pvt->subs[sub_num].dfd = -1; 04421 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 5191 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().
05192 { 05193 int x, res; 05194 05195 x = muted; 05196 #if defined(HAVE_PRI) || defined(HAVE_SS7) 05197 switch (p->sig) { 05198 #if defined(HAVE_PRI) 05199 case SIG_PRI_LIB_HANDLE_CASES: 05200 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 05201 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 05202 break; 05203 } 05204 /* Fall through */ 05205 #endif /* defined(HAVE_PRI) */ 05206 #if defined(HAVE_SS7) 05207 case SIG_SS7: 05208 #endif /* defined(HAVE_SS7) */ 05209 { 05210 int y = 1; 05211 05212 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 05213 if (res) 05214 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 05215 p->channel, strerror(errno)); 05216 } 05217 break; 05218 default: 05219 break; 05220 } 05221 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 05222 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 05223 if (res < 0) 05224 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 05225 return res; 05226 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15069 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.
15070 { 15071 int channel; 15072 int ret; 15073 switch (cmd) { 15074 case CLI_INIT: 15075 e->command = "dahdi destroy channel"; 15076 e->usage = 15077 "Usage: dahdi destroy channel <chan num>\n" 15078 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 15079 return NULL; 15080 case CLI_GENERATE: 15081 return NULL; 15082 } 15083 if (a->argc != 4) 15084 return CLI_SHOWUSAGE; 15085 15086 channel = atoi(a->argv[3]); 15087 ret = dahdi_destroy_channel_bynum(channel); 15088 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 15089 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 11454 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().
11455 { 11456 struct dahdi_pvt *cur; 11457 11458 ast_mutex_lock(&iflock); 11459 for (cur = iflist; cur; cur = cur->next) { 11460 if (cur->channel == channel) { 11461 int x = DAHDI_FLASH; 11462 11463 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 11464 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11465 11466 destroy_channel(cur, 1); 11467 ast_mutex_unlock(&iflock); 11468 ast_module_unref(ast_module_info->self); 11469 return RESULT_SUCCESS; 11470 } 11471 } 11472 ast_mutex_unlock(&iflock); 11473 return RESULT_FAILURE; 11474 }
static int dahdi_devicestate | ( | void * | data | ) | [static] |
Definition at line 13859 of file chan_dahdi.c.
References AST_DEVICE_UNKNOWN.
13860 { 13861 #if defined(HAVE_PRI) 13862 char *device; 13863 unsigned span; 13864 int res; 13865 13866 device = data; 13867 13868 if (*device != 'I') { 13869 /* The request is not for an ISDN span device. */ 13870 return AST_DEVICE_UNKNOWN; 13871 } 13872 res = sscanf(device, "I%30u", &span); 13873 if (res != 1 || !span || NUM_SPANS < span) { 13874 /* Bad format for ISDN span device name. */ 13875 return AST_DEVICE_UNKNOWN; 13876 } 13877 device = strchr(device, '/'); 13878 if (!device) { 13879 /* Bad format for ISDN span device name. */ 13880 return AST_DEVICE_UNKNOWN; 13881 } 13882 13883 /* 13884 * Since there are currently no other span devstate's defined, 13885 * it must be congestion. 13886 */ 13887 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13888 ++device; 13889 if (!strcmp(device, "congestion")) 13890 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13891 { 13892 return pris[span - 1].pri.congestion_devstate; 13893 } 13894 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13895 else if (!strcmp(device, "threshold")) { 13896 return pris[span - 1].pri.threshold_devstate; 13897 } 13898 return AST_DEVICE_UNKNOWN; 13899 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13900 #else 13901 return AST_DEVICE_UNKNOWN; 13902 #endif /* defined(HAVE_PRI) */ 13903 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 4515 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.
04516 { 04517 struct dahdi_pvt *pvt; 04518 int idx; 04519 int dtmf = -1; 04520 int res; 04521 04522 pvt = chan->tech_pvt; 04523 04524 ast_mutex_lock(&pvt->lock); 04525 04526 idx = dahdi_get_index(chan, pvt, 0); 04527 04528 if ((idx != SUB_REAL) || !pvt->owner) 04529 goto out; 04530 04531 #ifdef HAVE_PRI 04532 switch (pvt->sig) { 04533 case SIG_PRI_LIB_HANDLE_CASES: 04534 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 04535 if (!res) 04536 goto out; 04537 break; 04538 default: 04539 break; 04540 } 04541 #endif 04542 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 04543 goto out; 04544 04545 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 04546 struct dahdi_dialoperation zo = { 04547 .op = DAHDI_DIAL_OP_APPEND, 04548 }; 04549 04550 zo.dialstr[0] = 'T'; 04551 zo.dialstr[1] = digit; 04552 zo.dialstr[2] = '\0'; 04553 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 04554 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n", 04555 chan->name, digit, strerror(errno)); 04556 else 04557 pvt->dialing = 1; 04558 } else { 04559 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n", 04560 chan->name, digit); 04561 pvt->dialing = 1; 04562 pvt->begindigit = digit; 04563 } 04564 04565 out: 04566 ast_mutex_unlock(&pvt->lock); 04567 04568 return 0; 04569 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 4571 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.
04572 { 04573 struct dahdi_pvt *pvt; 04574 int res = 0; 04575 int idx; 04576 int x; 04577 04578 pvt = chan->tech_pvt; 04579 04580 ast_mutex_lock(&pvt->lock); 04581 04582 idx = dahdi_get_index(chan, pvt, 0); 04583 04584 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 04585 goto out; 04586 04587 #ifdef HAVE_PRI 04588 /* This means that the digit was already sent via PRI signalling */ 04589 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 04590 goto out; 04591 } 04592 #endif 04593 04594 if (pvt->begindigit) { 04595 x = -1; 04596 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n", 04597 chan->name, digit); 04598 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 04599 pvt->dialing = 0; 04600 pvt->begindigit = 0; 04601 } 04602 04603 out: 04604 ast_mutex_unlock(&pvt->lock); 04605 04606 return res; 04607 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4983 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().
04984 { 04985 int res; 04986 04987 if (p->echocanon) { 04988 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04989 04990 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04991 04992 if (res) 04993 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04994 else 04995 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 04996 } 04997 04998 p->echocanon = 0; 04999 }
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 9903 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().
09904 { 09905 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 09906 return analog_dnd(dahdichan->sig_pvt, flag); 09907 } 09908 09909 if (flag == -1) { 09910 return dahdichan->dnd; 09911 } 09912 09913 /* Do not disturb */ 09914 dahdichan->dnd = flag; 09915 ast_verb(3, "%s DND on channel %d\n", 09916 flag? "Enabled" : "Disabled", 09917 dahdichan->channel); 09918 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 09919 "Channel: DAHDI/%d\r\n" 09920 "Status: %s\r\n", dahdichan->channel, 09921 flag? "enabled" : "disabled"); 09922 09923 return 0; 09924 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4911 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().
04912 { 04913 int res; 04914 if (!p) 04915 return; 04916 if (p->echocanon) { 04917 ast_debug(1, "Echo cancellation already on\n"); 04918 return; 04919 } 04920 if (p->digital) { 04921 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04922 return; 04923 } 04924 if (p->echocancel.head.tap_length) { 04925 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04926 switch (p->sig) { 04927 #if defined(HAVE_PRI) 04928 case SIG_PRI_LIB_HANDLE_CASES: 04929 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04930 /* 04931 * PRI nobch pseudo channel. Does not need ec anyway. 04932 * Does not handle ioctl(DAHDI_AUDIOMODE) 04933 */ 04934 return; 04935 } 04936 /* Fall through */ 04937 #endif /* defined(HAVE_PRI) */ 04938 #if defined(HAVE_SS7) 04939 case SIG_SS7: 04940 #endif /* defined(HAVE_SS7) */ 04941 { 04942 int x = 1; 04943 04944 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04945 if (res) 04946 ast_log(LOG_WARNING, 04947 "Unable to enable audio mode on channel %d (%s)\n", 04948 p->channel, strerror(errno)); 04949 } 04950 break; 04951 default: 04952 break; 04953 } 04954 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04955 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04956 if (res) { 04957 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04958 } else { 04959 p->echocanon = 1; 04960 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04961 } 04962 } else 04963 ast_debug(1, "No echo cancellation requested\n"); 04964 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8924 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.
08925 { 08926 struct dahdi_pvt *p = ast->tech_pvt; 08927 struct ast_frame *f; 08928 ast_mutex_lock(&p->lock); 08929 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08930 struct analog_pvt *analog_p = p->sig_pvt; 08931 f = analog_exception(analog_p, ast); 08932 } else { 08933 f = __dahdi_exception(ast); 08934 } 08935 ast_mutex_unlock(&p->lock); 08936 return f; 08937 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 15921 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().
15922 { 15923 if (p) { 15924 switch (mode) { 15925 case TRANSFER: 15926 p->fake_event = DAHDI_EVENT_WINKFLASH; 15927 break; 15928 case HANGUP: 15929 p->fake_event = DAHDI_EVENT_ONHOOK; 15930 break; 15931 default: 15932 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 15933 } 15934 } 15935 return 0; 15936 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 7596 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().
07597 { 07598 struct dahdi_pvt *p = newchan->tech_pvt; 07599 int x; 07600 07601 ast_mutex_lock(&p->lock); 07602 07603 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 07604 if (p->owner == oldchan) { 07605 p->owner = newchan; 07606 } 07607 for (x = 0; x < 3; x++) { 07608 if (p->subs[x].owner == oldchan) { 07609 if (!x) { 07610 dahdi_unlink(NULL, p, 0); 07611 } 07612 p->subs[x].owner = newchan; 07613 } 07614 } 07615 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07616 analog_fixup(oldchan, newchan, p->sig_pvt); 07617 #if defined(HAVE_PRI) 07618 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 07619 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 07620 #endif /* defined(HAVE_PRI) */ 07621 #if defined(HAVE_SS7) 07622 } else if (p->sig == SIG_SS7) { 07623 sig_ss7_fixup(oldchan, newchan, p->sig_pvt); 07624 #endif /* defined(HAVE_SS7) */ 07625 } 07626 update_conf(p); 07627 07628 ast_mutex_unlock(&p->lock); 07629 07630 if (newchan->_state == AST_STATE_RINGING) { 07631 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 07632 } 07633 return 0; 07634 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 6951 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.
06952 { 06953 struct dahdi_pvt *p = chan->tech_pvt; 06954 int res = 0; 06955 06956 if (!p) { 06957 /* No private structure! */ 06958 *buf = '\0'; 06959 return -1; 06960 } 06961 06962 if (!strcasecmp(data, "rxgain")) { 06963 ast_mutex_lock(&p->lock); 06964 snprintf(buf, len, "%f", p->rxgain); 06965 ast_mutex_unlock(&p->lock); 06966 } else if (!strcasecmp(data, "txgain")) { 06967 ast_mutex_lock(&p->lock); 06968 snprintf(buf, len, "%f", p->txgain); 06969 ast_mutex_unlock(&p->lock); 06970 } else if (!strcasecmp(data, "dahdi_channel")) { 06971 ast_mutex_lock(&p->lock); 06972 snprintf(buf, len, "%d", p->channel); 06973 ast_mutex_unlock(&p->lock); 06974 } else if (!strcasecmp(data, "dahdi_span")) { 06975 ast_mutex_lock(&p->lock); 06976 snprintf(buf, len, "%d", p->span); 06977 ast_mutex_unlock(&p->lock); 06978 } else if (!strcasecmp(data, "dahdi_type")) { 06979 ast_mutex_lock(&p->lock); 06980 switch (p->sig) { 06981 #if defined(HAVE_OPENR2) 06982 case SIG_MFCR2: 06983 ast_copy_string(buf, "mfc/r2", len); 06984 break; 06985 #endif /* defined(HAVE_OPENR2) */ 06986 #if defined(HAVE_PRI) 06987 case SIG_PRI_LIB_HANDLE_CASES: 06988 ast_copy_string(buf, "pri", len); 06989 break; 06990 #endif /* defined(HAVE_PRI) */ 06991 case 0: 06992 ast_copy_string(buf, "pseudo", len); 06993 break; 06994 #if defined(HAVE_SS7) 06995 case SIG_SS7: 06996 ast_copy_string(buf, "ss7", len); 06997 break; 06998 #endif /* defined(HAVE_SS7) */ 06999 default: 07000 /* The only thing left is analog ports. */ 07001 ast_copy_string(buf, "analog", len); 07002 break; 07003 } 07004 ast_mutex_unlock(&p->lock); 07005 #if defined(HAVE_PRI) 07006 #if defined(HAVE_PRI_REVERSE_CHARGE) 07007 } else if (!strcasecmp(data, "reversecharge")) { 07008 ast_mutex_lock(&p->lock); 07009 switch (p->sig) { 07010 case SIG_PRI_LIB_HANDLE_CASES: 07011 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 07012 break; 07013 default: 07014 *buf = '\0'; 07015 res = -1; 07016 break; 07017 } 07018 ast_mutex_unlock(&p->lock); 07019 #endif 07020 #if defined(HAVE_PRI_SETUP_KEYPAD) 07021 } else if (!strcasecmp(data, "keypad_digits")) { 07022 ast_mutex_lock(&p->lock); 07023 switch (p->sig) { 07024 case SIG_PRI_LIB_HANDLE_CASES: 07025 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 07026 len); 07027 break; 07028 default: 07029 *buf = '\0'; 07030 res = -1; 07031 break; 07032 } 07033 ast_mutex_unlock(&p->lock); 07034 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 07035 } else if (!strcasecmp(data, "no_media_path")) { 07036 ast_mutex_lock(&p->lock); 07037 switch (p->sig) { 07038 case SIG_PRI_LIB_HANDLE_CASES: 07039 /* 07040 * TRUE if the call is on hold or is call waiting because 07041 * there is no media path available. 07042 */ 07043 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel); 07044 break; 07045 default: 07046 *buf = '\0'; 07047 res = -1; 07048 break; 07049 } 07050 ast_mutex_unlock(&p->lock); 07051 #endif /* defined(HAVE_PRI) */ 07052 } else { 07053 *buf = '\0'; 07054 res = -1; 07055 } 07056 07057 return res; 07058 }
static int dahdi_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 7090 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.
07091 { 07092 struct dahdi_pvt *p = chan->tech_pvt; 07093 int res = 0; 07094 07095 if (!p) { 07096 /* No private structure! */ 07097 return -1; 07098 } 07099 07100 if (!strcasecmp(data, "buffers")) { 07101 int num_bufs, policy; 07102 07103 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 07104 struct dahdi_bufferinfo bi = { 07105 .txbufpolicy = policy, 07106 .rxbufpolicy = policy, 07107 .bufsize = p->bufsize, 07108 .numbufs = num_bufs, 07109 }; 07110 int bpres; 07111 07112 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07113 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 07114 } else { 07115 p->bufferoverrideinuse = 1; 07116 } 07117 } else { 07118 res = -1; 07119 } 07120 } else if (!strcasecmp(data, "echocan_mode")) { 07121 if (!strcasecmp(value, "on")) { 07122 ast_mutex_lock(&p->lock); 07123 dahdi_enable_ec(p); 07124 ast_mutex_unlock(&p->lock); 07125 } else if (!strcasecmp(value, "off")) { 07126 ast_mutex_lock(&p->lock); 07127 dahdi_disable_ec(p); 07128 ast_mutex_unlock(&p->lock); 07129 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07130 } else if (!strcasecmp(value, "fax")) { 07131 int blah = 1; 07132 07133 ast_mutex_lock(&p->lock); 07134 if (!p->echocanon) { 07135 dahdi_enable_ec(p); 07136 } 07137 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07138 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 07139 } 07140 ast_mutex_unlock(&p->lock); 07141 } else if (!strcasecmp(value, "voice")) { 07142 int blah = 0; 07143 07144 ast_mutex_lock(&p->lock); 07145 if (!p->echocanon) { 07146 dahdi_enable_ec(p); 07147 } 07148 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07149 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 07150 } 07151 ast_mutex_unlock(&p->lock); 07152 #endif 07153 } else { 07154 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 07155 res = -1; 07156 } 07157 } else { 07158 res = -1; 07159 } 07160 07161 return res; 07162 }
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 7773 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().
07774 { 07775 struct dahdi_pvt *p = ast->tech_pvt; 07776 struct ast_frame *f = *dest; 07777 07778 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 07779 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 07780 f->subclass.integer, f->subclass.integer, ast->name); 07781 07782 if (p->confirmanswer) { 07783 if (f->frametype == AST_FRAME_DTMF_END) { 07784 ast_debug(1, "Confirm answer on %s!\n", ast->name); 07785 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 07786 of a DTMF digit */ 07787 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07788 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07789 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 07790 p->confirmanswer = 0; 07791 } else { 07792 p->subs[idx].f.frametype = AST_FRAME_NULL; 07793 p->subs[idx].f.subclass.integer = 0; 07794 } 07795 *dest = &p->subs[idx].f; 07796 } else if (p->callwaitcas) { 07797 if (f->frametype == AST_FRAME_DTMF_END) { 07798 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) { 07799 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 07800 ast_free(p->cidspill); 07801 p->cidspill = NULL; 07802 send_cwcidspill(p); 07803 } 07804 p->callwaitcas = 0; 07805 } 07806 p->subs[idx].f.frametype = AST_FRAME_NULL; 07807 p->subs[idx].f.subclass.integer = 0; 07808 *dest = &p->subs[idx].f; 07809 } else if (f->subclass.integer == 'f') { 07810 if (f->frametype == AST_FRAME_DTMF_END) { 07811 /* Fax tone -- Handle and return NULL */ 07812 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 07813 /* If faxbuffers are configured, use them for the fax transmission */ 07814 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 07815 struct dahdi_bufferinfo bi = { 07816 .txbufpolicy = p->faxbuf_policy, 07817 .bufsize = p->bufsize, 07818 .numbufs = p->faxbuf_no 07819 }; 07820 int res; 07821 07822 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07823 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 07824 } else { 07825 p->bufferoverrideinuse = 1; 07826 } 07827 } 07828 p->faxhandled = 1; 07829 if (p->dsp) { 07830 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 07831 ast_dsp_set_features(p->dsp, p->dsp_features); 07832 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 07833 } 07834 if (strcmp(ast->exten, "fax")) { 07835 const char *target_context = S_OR(ast->macrocontext, ast->context); 07836 07837 /* We need to unlock 'ast' here because ast_exists_extension has the 07838 * potential to start autoservice on the channel. Such action is prone 07839 * to deadlock. 07840 */ 07841 ast_mutex_unlock(&p->lock); 07842 ast_channel_unlock(ast); 07843 if (ast_exists_extension(ast, target_context, "fax", 1, 07844 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 07845 ast_channel_lock(ast); 07846 ast_mutex_lock(&p->lock); 07847 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 07848 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 07849 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 07850 if (ast_async_goto(ast, target_context, "fax", 1)) 07851 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 07852 } else { 07853 ast_channel_lock(ast); 07854 ast_mutex_lock(&p->lock); 07855 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 07856 } 07857 } else { 07858 ast_debug(1, "Already in a fax extension, not redirecting\n"); 07859 } 07860 } else { 07861 ast_debug(1, "Fax already handled\n"); 07862 } 07863 dahdi_confmute(p, 0); 07864 } 07865 p->subs[idx].f.frametype = AST_FRAME_NULL; 07866 p->subs[idx].f.subclass.integer = 0; 07867 *dest = &p->subs[idx].f; 07868 } 07869 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7899 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().
07900 { 07901 int res, x; 07902 int idx, mysig; 07903 char *c; 07904 struct dahdi_pvt *p = ast->tech_pvt; 07905 pthread_t threadid; 07906 struct ast_channel *chan; 07907 struct ast_frame *f; 07908 07909 idx = dahdi_get_index(ast, p, 0); 07910 if (idx < 0) { 07911 return &ast_null_frame; 07912 } 07913 mysig = p->sig; 07914 if (p->outsigmod > -1) 07915 mysig = p->outsigmod; 07916 p->subs[idx].f.frametype = AST_FRAME_NULL; 07917 p->subs[idx].f.subclass.integer = 0; 07918 p->subs[idx].f.datalen = 0; 07919 p->subs[idx].f.samples = 0; 07920 p->subs[idx].f.mallocd = 0; 07921 p->subs[idx].f.offset = 0; 07922 p->subs[idx].f.src = "dahdi_handle_event"; 07923 p->subs[idx].f.data.ptr = NULL; 07924 f = &p->subs[idx].f; 07925 07926 if (p->fake_event) { 07927 res = p->fake_event; 07928 p->fake_event = 0; 07929 } else 07930 res = dahdi_get_event(p->subs[idx].dfd); 07931 07932 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 07933 07934 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 07935 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 07936 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 07937 #if defined(HAVE_PRI) 07938 if (dahdi_sig_pri_lib_handles(p->sig) 07939 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07940 && p->pri 07941 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07942 /* absorb event */ 07943 } else 07944 #endif /* defined(HAVE_PRI) */ 07945 { 07946 /* Unmute conference */ 07947 dahdi_confmute(p, 0); 07948 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 07949 p->subs[idx].f.subclass.integer = res & 0xff; 07950 dahdi_handle_dtmf(ast, idx, &f); 07951 } 07952 return f; 07953 } 07954 07955 if (res & DAHDI_EVENT_DTMFDOWN) { 07956 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07957 #if defined(HAVE_PRI) 07958 if (dahdi_sig_pri_lib_handles(p->sig) 07959 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07960 && p->pri 07961 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07962 /* absorb event */ 07963 } else 07964 #endif /* defined(HAVE_PRI) */ 07965 { 07966 /* Mute conference */ 07967 dahdi_confmute(p, 1); 07968 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07969 p->subs[idx].f.subclass.integer = res & 0xff; 07970 dahdi_handle_dtmf(ast, idx, &f); 07971 } 07972 return &p->subs[idx].f; 07973 } 07974 07975 switch (res) { 07976 case DAHDI_EVENT_EC_DISABLED: 07977 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07978 p->echocanon = 0; 07979 break; 07980 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07981 case DAHDI_EVENT_TX_CED_DETECTED: 07982 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 07983 break; 07984 case DAHDI_EVENT_RX_CED_DETECTED: 07985 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 07986 break; 07987 case DAHDI_EVENT_EC_NLP_DISABLED: 07988 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 07989 break; 07990 case DAHDI_EVENT_EC_NLP_ENABLED: 07991 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 07992 break; 07993 #endif 07994 case DAHDI_EVENT_BITSCHANGED: 07995 #ifdef HAVE_OPENR2 07996 if (p->sig != SIG_MFCR2) { 07997 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07998 } else { 07999 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 08000 openr2_chan_handle_cas(p->r2chan); 08001 } 08002 #else 08003 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 08004 #endif 08005 break; 08006 case DAHDI_EVENT_PULSE_START: 08007 /* Stop tone if there's a pulse start and the PBX isn't started */ 08008 if (!ast->pbx) 08009 tone_zone_play_tone(p->subs[idx].dfd, -1); 08010 break; 08011 case DAHDI_EVENT_DIALCOMPLETE: 08012 /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */ 08013 #if defined(HAVE_PRI) 08014 if (dahdi_sig_pri_lib_handles(p->sig)) { 08015 if (p->inalarm) { 08016 break; 08017 } 08018 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) { 08019 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name, 08020 strerror(errno)); 08021 return NULL; 08022 } 08023 if (x) { 08024 /* Still dialing in DAHDI driver */ 08025 break; 08026 } 08027 /* 08028 * The ast channel is locked and the private may be locked more 08029 * than once. 08030 */ 08031 sig_pri_dial_complete(p->sig_pvt, ast); 08032 break; 08033 } 08034 #endif /* defined(HAVE_PRI) */ 08035 #ifdef HAVE_OPENR2 08036 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 08037 /* we don't need to do anything for this event for R2 signaling 08038 if the call is being setup */ 08039 break; 08040 } 08041 #endif 08042 if (p->inalarm) break; 08043 if ((p->radio || (p->oprmode < 0))) break; 08044 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 08045 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 08046 return NULL; 08047 } 08048 if (!x) { /* if not still dialing in driver */ 08049 dahdi_enable_ec(p); 08050 if (p->echobreak) { 08051 dahdi_train_ec(p); 08052 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 08053 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08055 p->echobreak = 0; 08056 } else { 08057 p->dialing = 0; 08058 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 08059 /* if thru with dialing after offhook */ 08060 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 08061 ast_setstate(ast, AST_STATE_UP); 08062 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08063 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08064 break; 08065 } else { /* if to state wait for offhook to dial rest */ 08066 /* we now wait for off hook */ 08067 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 08068 } 08069 } 08070 if (ast->_state == AST_STATE_DIALING) { 08071 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 08072 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 08073 } else if (p->confirmanswer || (!p->dialednone 08074 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 08075 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 08076 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 08077 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 08078 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 08079 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 08080 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 08081 || (mysig == SIG_SF_FEATB)))) { 08082 ast_setstate(ast, AST_STATE_RINGING); 08083 } else if (!p->answeronpolarityswitch) { 08084 ast_setstate(ast, AST_STATE_UP); 08085 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08086 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08087 /* If aops=0 and hops=1, this is necessary */ 08088 p->polarity = POLARITY_REV; 08089 } else { 08090 /* Start clean, so we can catch the change to REV polarity when party answers */ 08091 p->polarity = POLARITY_IDLE; 08092 } 08093 } 08094 } 08095 } 08096 break; 08097 case DAHDI_EVENT_ALARM: 08098 switch (p->sig) { 08099 #if defined(HAVE_PRI) 08100 case SIG_PRI_LIB_HANDLE_CASES: 08101 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 08102 break; 08103 #endif /* defined(HAVE_PRI) */ 08104 #if defined(HAVE_SS7) 08105 case SIG_SS7: 08106 sig_ss7_set_alarm(p->sig_pvt, 1); 08107 break; 08108 #endif /* defined(HAVE_SS7) */ 08109 default: 08110 p->inalarm = 1; 08111 break; 08112 } 08113 res = get_alarms(p); 08114 handle_alarms(p, res); 08115 #ifdef HAVE_PRI 08116 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 08117 /* fall through intentionally */ 08118 } else { 08119 break; 08120 } 08121 #endif 08122 #if defined(HAVE_SS7) 08123 if (p->sig == SIG_SS7) 08124 break; 08125 #endif /* defined(HAVE_SS7) */ 08126 #ifdef HAVE_OPENR2 08127 if (p->sig == SIG_MFCR2) 08128 break; 08129 #endif 08130 case DAHDI_EVENT_ONHOOK: 08131 if (p->radio) { 08132 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08133 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08134 break; 08135 } 08136 if (p->oprmode < 0) 08137 { 08138 if (p->oprmode != -1) break; 08139 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08140 { 08141 /* Make sure it starts ringing */ 08142 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08143 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 08144 save_conference(p->oprpeer); 08145 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08146 } 08147 break; 08148 } 08149 switch (p->sig) { 08150 case SIG_FXOLS: 08151 case SIG_FXOGS: 08152 case SIG_FXOKS: 08153 /* Check for some special conditions regarding call waiting */ 08154 if (idx == SUB_REAL) { 08155 /* The normal line was hung up */ 08156 if (p->subs[SUB_CALLWAIT].owner) { 08157 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 08158 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 08159 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 08160 unalloc_sub(p, SUB_CALLWAIT); 08161 #if 0 08162 p->subs[idx].needanswer = 0; 08163 p->subs[idx].needringing = 0; 08164 #endif 08165 p->callwaitingrepeat = 0; 08166 p->cidcwexpire = 0; 08167 p->cid_suppress_expire = 0; 08168 p->owner = NULL; 08169 /* Don't start streaming audio yet if the incoming call isn't up yet */ 08170 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 08171 p->dialing = 1; 08172 dahdi_ring_phone(p); 08173 } else if (p->subs[SUB_THREEWAY].owner) { 08174 unsigned int mssinceflash; 08175 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 08176 the private structure -- not especially easy or clean */ 08177 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 08178 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 08179 DLA_UNLOCK(&p->lock); 08180 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08181 /* We can grab ast and p in that order, without worry. We should make sure 08182 nothing seriously bad has happened though like some sort of bizarre double 08183 masquerade! */ 08184 DLA_LOCK(&p->lock); 08185 if (p->owner != ast) { 08186 ast_log(LOG_WARNING, "This isn't good...\n"); 08187 return NULL; 08188 } 08189 } 08190 if (!p->subs[SUB_THREEWAY].owner) { 08191 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 08192 return NULL; 08193 } 08194 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 08195 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 08196 if (mssinceflash < MIN_MS_SINCE_FLASH) { 08197 /* It hasn't been long enough since the last flashook. This is probably a bounce on 08198 hanging up. Hangup both channels now */ 08199 if (p->subs[SUB_THREEWAY].owner) 08200 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 08201 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08202 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 08203 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08204 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 08205 if (p->transfer) { 08206 /* In any case this isn't a threeway call anymore */ 08207 p->subs[SUB_REAL].inthreeway = 0; 08208 p->subs[SUB_THREEWAY].inthreeway = 0; 08209 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 08210 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 08211 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08212 /* Swap subs and dis-own channel */ 08213 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08214 p->owner = NULL; 08215 /* Ring the phone */ 08216 dahdi_ring_phone(p); 08217 } else { 08218 if ((res = attempt_transfer(p)) < 0) { 08219 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08220 if (p->subs[SUB_THREEWAY].owner) 08221 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08222 } else if (res) { 08223 /* Don't actually hang up at this point */ 08224 if (p->subs[SUB_THREEWAY].owner) 08225 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08226 break; 08227 } 08228 } 08229 } else { 08230 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08231 if (p->subs[SUB_THREEWAY].owner) 08232 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08233 } 08234 } else { 08235 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08236 /* Swap subs and dis-own channel */ 08237 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08238 p->owner = NULL; 08239 /* Ring the phone */ 08240 dahdi_ring_phone(p); 08241 } 08242 } 08243 } else { 08244 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 08245 } 08246 /* Fall through */ 08247 default: 08248 dahdi_disable_ec(p); 08249 return NULL; 08250 } 08251 break; 08252 case DAHDI_EVENT_RINGOFFHOOK: 08253 if (p->inalarm) break; 08254 if (p->oprmode < 0) 08255 { 08256 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08257 { 08258 /* Make sure it stops ringing */ 08259 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08260 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 08261 restore_conference(p->oprpeer); 08262 } 08263 break; 08264 } 08265 if (p->radio) 08266 { 08267 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08268 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08269 break; 08270 } 08271 /* for E911, its supposed to wait for offhook then dial 08272 the second half of the dial string */ 08273 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 08274 c = strchr(p->dialdest, '/'); 08275 if (c) 08276 c++; 08277 else 08278 c = p->dialdest; 08279 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 08280 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 08281 if (strlen(p->dop.dialstr) > 4) { 08282 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 08283 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 08284 p->echorest[sizeof(p->echorest) - 1] = '\0'; 08285 p->echobreak = 1; 08286 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 08287 } else 08288 p->echobreak = 0; 08289 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 08290 int saveerr = errno; 08291 08292 x = DAHDI_ONHOOK; 08293 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 08294 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 08295 return NULL; 08296 } 08297 p->dialing = 1; 08298 return &p->subs[idx].f; 08299 } 08300 switch (p->sig) { 08301 case SIG_FXOLS: 08302 case SIG_FXOGS: 08303 case SIG_FXOKS: 08304 switch (ast->_state) { 08305 case AST_STATE_RINGING: 08306 dahdi_enable_ec(p); 08307 dahdi_train_ec(p); 08308 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08309 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08310 /* Make sure it stops ringing */ 08311 p->subs[SUB_REAL].needringing = 0; 08312 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08313 ast_debug(1, "channel %d answered\n", p->channel); 08314 08315 /* Cancel any running CallerID spill */ 08316 ast_free(p->cidspill); 08317 p->cidspill = NULL; 08318 restore_conference(p); 08319 08320 p->dialing = 0; 08321 p->callwaitcas = 0; 08322 if (p->confirmanswer) { 08323 /* Ignore answer if "confirm answer" is enabled */ 08324 p->subs[idx].f.frametype = AST_FRAME_NULL; 08325 p->subs[idx].f.subclass.integer = 0; 08326 } else if (!ast_strlen_zero(p->dop.dialstr)) { 08327 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 08328 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08329 if (res < 0) { 08330 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08331 p->dop.dialstr[0] = '\0'; 08332 return NULL; 08333 } else { 08334 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 08335 p->subs[idx].f.frametype = AST_FRAME_NULL; 08336 p->subs[idx].f.subclass.integer = 0; 08337 p->dialing = 1; 08338 } 08339 p->dop.dialstr[0] = '\0'; 08340 ast_setstate(ast, AST_STATE_DIALING); 08341 } else 08342 ast_setstate(ast, AST_STATE_UP); 08343 return &p->subs[idx].f; 08344 case AST_STATE_DOWN: 08345 ast_setstate(ast, AST_STATE_RING); 08346 ast->rings = 1; 08347 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08348 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK; 08349 ast_debug(1, "channel %d picked up\n", p->channel); 08350 return &p->subs[idx].f; 08351 case AST_STATE_UP: 08352 /* Make sure it stops ringing */ 08353 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08354 /* Okay -- probably call waiting*/ 08355 if (ast_bridged_channel(p->owner)) 08356 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08357 p->subs[idx].needunhold = 1; 08358 break; 08359 case AST_STATE_RESERVED: 08360 /* Start up dialtone */ 08361 if (has_voicemail(p)) 08362 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08363 else 08364 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08365 break; 08366 default: 08367 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 08368 } 08369 break; 08370 case SIG_FXSLS: 08371 case SIG_FXSGS: 08372 case SIG_FXSKS: 08373 if (ast->_state == AST_STATE_RING) { 08374 p->ringt = p->ringt_base; 08375 } 08376 08377 /* If we get a ring then we cannot be in 08378 * reversed polarity. So we reset to idle */ 08379 ast_debug(1, "Setting IDLE polarity due " 08380 "to ring. Old polarity was %d\n", 08381 p->polarity); 08382 p->polarity = POLARITY_IDLE; 08383 08384 /* Fall through */ 08385 case SIG_EM: 08386 case SIG_EM_E1: 08387 case SIG_EMWINK: 08388 case SIG_FEATD: 08389 case SIG_FEATDMF: 08390 case SIG_FEATDMF_TA: 08391 case SIG_E911: 08392 case SIG_FGC_CAMA: 08393 case SIG_FGC_CAMAMF: 08394 case SIG_FEATB: 08395 case SIG_SF: 08396 case SIG_SFWINK: 08397 case SIG_SF_FEATD: 08398 case SIG_SF_FEATDMF: 08399 case SIG_SF_FEATB: 08400 if (ast->_state == AST_STATE_PRERING) 08401 ast_setstate(ast, AST_STATE_RING); 08402 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 08403 ast_debug(1, "Ring detected\n"); 08404 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08405 p->subs[idx].f.subclass.integer = AST_CONTROL_RING; 08406 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 08407 ast_debug(1, "Line answered\n"); 08408 if (p->confirmanswer) { 08409 p->subs[idx].f.frametype = AST_FRAME_NULL; 08410 p->subs[idx].f.subclass.integer = 0; 08411 } else { 08412 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08413 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08414 ast_setstate(ast, AST_STATE_UP); 08415 } 08416 } else if (ast->_state != AST_STATE_RING) 08417 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 08418 break; 08419 default: 08420 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08421 } 08422 break; 08423 case DAHDI_EVENT_RINGBEGIN: 08424 switch (p->sig) { 08425 case SIG_FXSLS: 08426 case SIG_FXSGS: 08427 case SIG_FXSKS: 08428 if (ast->_state == AST_STATE_RING) { 08429 p->ringt = p->ringt_base; 08430 } 08431 break; 08432 } 08433 break; 08434 case DAHDI_EVENT_RINGERON: 08435 break; 08436 case DAHDI_EVENT_NOALARM: 08437 switch (p->sig) { 08438 #if defined(HAVE_PRI) 08439 case SIG_PRI_LIB_HANDLE_CASES: 08440 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 08441 break; 08442 #endif /* defined(HAVE_PRI) */ 08443 #if defined(HAVE_SS7) 08444 case SIG_SS7: 08445 sig_ss7_set_alarm(p->sig_pvt, 0); 08446 break; 08447 #endif /* defined(HAVE_SS7) */ 08448 default: 08449 p->inalarm = 0; 08450 break; 08451 } 08452 handle_clear_alarms(p); 08453 break; 08454 case DAHDI_EVENT_WINKFLASH: 08455 if (p->inalarm) break; 08456 if (p->radio) break; 08457 if (p->oprmode < 0) break; 08458 if (p->oprmode > 1) 08459 { 08460 struct dahdi_params par; 08461 08462 memset(&par, 0, sizeof(par)); 08463 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 08464 { 08465 if (!par.rxisoffhook) 08466 { 08467 /* Make sure it stops ringing */ 08468 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08469 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 08470 save_conference(p); 08471 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08472 } 08473 } 08474 break; 08475 } 08476 /* Remember last time we got a flash-hook */ 08477 p->flashtime = ast_tvnow(); 08478 switch (mysig) { 08479 case SIG_FXOLS: 08480 case SIG_FXOGS: 08481 case SIG_FXOKS: 08482 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 08483 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 08484 08485 /* Cancel any running CallerID spill */ 08486 ast_free(p->cidspill); 08487 p->cidspill = NULL; 08488 restore_conference(p); 08489 p->callwaitcas = 0; 08490 08491 if (idx != SUB_REAL) { 08492 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 08493 goto winkflashdone; 08494 } 08495 08496 if (p->subs[SUB_CALLWAIT].owner) { 08497 /* Swap to call-wait */ 08498 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 08499 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 08500 p->owner = p->subs[SUB_REAL].owner; 08501 ast_debug(1, "Making %s the new owner\n", p->owner->name); 08502 if (p->owner->_state == AST_STATE_RINGING) { 08503 ast_setstate(p->owner, AST_STATE_UP); 08504 p->subs[SUB_REAL].needanswer = 1; 08505 } 08506 p->callwaitingrepeat = 0; 08507 p->cidcwexpire = 0; 08508 p->cid_suppress_expire = 0; 08509 /* Start music on hold if appropriate */ 08510 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 08511 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 08512 S_OR(p->mohsuggest, NULL), 08513 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08514 } 08515 p->subs[SUB_CALLWAIT].needhold = 1; 08516 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 08517 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 08518 S_OR(p->mohsuggest, NULL), 08519 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08520 } 08521 p->subs[SUB_REAL].needunhold = 1; 08522 } else if (!p->subs[SUB_THREEWAY].owner) { 08523 if (!p->threewaycalling) { 08524 /* Just send a flash if no 3-way calling */ 08525 p->subs[SUB_REAL].needflash = 1; 08526 goto winkflashdone; 08527 } else if (!check_for_conference(p)) { 08528 char cid_num[256]; 08529 char cid_name[256]; 08530 08531 cid_num[0] = 0; 08532 cid_name[0] = 0; 08533 if (p->dahditrcallerid && p->owner) { 08534 if (p->owner->caller.id.number.valid 08535 && p->owner->caller.id.number.str) { 08536 ast_copy_string(cid_num, p->owner->caller.id.number.str, 08537 sizeof(cid_num)); 08538 } 08539 if (p->owner->caller.id.name.valid 08540 && p->owner->caller.id.name.str) { 08541 ast_copy_string(cid_name, p->owner->caller.id.name.str, 08542 sizeof(cid_name)); 08543 } 08544 } 08545 /* XXX This section needs much more error checking!!! XXX */ 08546 /* Start a 3-way call if feasible */ 08547 if (!((ast->pbx) || 08548 (ast->_state == AST_STATE_UP) || 08549 (ast->_state == AST_STATE_RING))) { 08550 ast_debug(1, "Flash when call not up or ringing\n"); 08551 goto winkflashdone; 08552 } 08553 if (alloc_sub(p, SUB_THREEWAY)) { 08554 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 08555 goto winkflashdone; 08556 } 08557 08558 /* 08559 * Make new channel 08560 * 08561 * We cannot hold the p or ast locks while creating a new 08562 * channel. 08563 */ 08564 ast_mutex_unlock(&p->lock); 08565 ast_channel_unlock(ast); 08566 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL); 08567 ast_channel_lock(ast); 08568 ast_mutex_lock(&p->lock); 08569 if (p->dahditrcallerid) { 08570 if (!p->origcid_num) 08571 p->origcid_num = ast_strdup(p->cid_num); 08572 if (!p->origcid_name) 08573 p->origcid_name = ast_strdup(p->cid_name); 08574 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 08575 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 08576 } 08577 /* Swap things around between the three-way and real call */ 08578 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08579 /* Disable echo canceller for better dialing */ 08580 dahdi_disable_ec(p); 08581 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 08582 if (res) 08583 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 08584 p->owner = chan; 08585 if (!chan) { 08586 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 08587 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 08588 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 08589 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08590 dahdi_enable_ec(p); 08591 ast_hangup(chan); 08592 } else { 08593 ast_verb(3, "Started three way call on channel %d\n", p->channel); 08594 08595 /* Start music on hold if appropriate */ 08596 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08597 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 08598 S_OR(p->mohsuggest, NULL), 08599 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08600 } 08601 p->subs[SUB_THREEWAY].needhold = 1; 08602 } 08603 } 08604 } else { 08605 /* Already have a 3 way call */ 08606 if (p->subs[SUB_THREEWAY].inthreeway) { 08607 /* Call is already up, drop the last person */ 08608 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 08609 /* If the primary call isn't answered yet, use it */ 08610 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 08611 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 08612 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08613 p->owner = p->subs[SUB_REAL].owner; 08614 } 08615 /* Drop the last call and stop the conference */ 08616 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 08617 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08618 p->subs[SUB_REAL].inthreeway = 0; 08619 p->subs[SUB_THREEWAY].inthreeway = 0; 08620 } else { 08621 /* Lets see what we're up to */ 08622 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 08623 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 08624 int otherindex = SUB_THREEWAY; 08625 08626 ast_verb(3, "Building conference call with %s and %s\n", 08627 p->subs[SUB_THREEWAY].owner->name, 08628 p->subs[SUB_REAL].owner->name); 08629 /* Put them in the threeway, and flip */ 08630 p->subs[SUB_THREEWAY].inthreeway = 1; 08631 p->subs[SUB_REAL].inthreeway = 1; 08632 if (ast->_state == AST_STATE_UP) { 08633 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08634 otherindex = SUB_REAL; 08635 } 08636 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 08637 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 08638 p->subs[otherindex].needunhold = 1; 08639 p->owner = p->subs[SUB_REAL].owner; 08640 } else { 08641 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 08642 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08643 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08644 p->owner = p->subs[SUB_REAL].owner; 08645 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 08646 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08647 p->subs[SUB_REAL].needunhold = 1; 08648 dahdi_enable_ec(p); 08649 } 08650 } 08651 } 08652 winkflashdone: 08653 update_conf(p); 08654 break; 08655 case SIG_EM: 08656 case SIG_EM_E1: 08657 case SIG_FEATD: 08658 case SIG_SF: 08659 case SIG_SFWINK: 08660 case SIG_SF_FEATD: 08661 case SIG_FXSLS: 08662 case SIG_FXSGS: 08663 if (p->dialing) 08664 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 08665 else 08666 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 08667 break; 08668 case SIG_FEATDMF_TA: 08669 switch (p->whichwink) { 08670 case 0: 08671 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2, 08672 S_COR(p->owner->caller.ani.number.valid, 08673 p->owner->caller.ani.number.str, "")); 08674 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", 08675 p->owner->caller.ani2, 08676 S_COR(p->owner->caller.ani.number.valid, 08677 p->owner->caller.ani.number.str, "")); 08678 break; 08679 case 1: 08680 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 08681 break; 08682 case 2: 08683 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 08684 return NULL; 08685 } 08686 p->whichwink++; 08687 /* Fall through */ 08688 case SIG_FEATDMF: 08689 case SIG_E911: 08690 case SIG_FGC_CAMAMF: 08691 case SIG_FGC_CAMA: 08692 case SIG_FEATB: 08693 case SIG_SF_FEATDMF: 08694 case SIG_SF_FEATB: 08695 case SIG_EMWINK: 08696 /* FGD MF and EMWINK *Must* wait for wink */ 08697 if (!ast_strlen_zero(p->dop.dialstr)) { 08698 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08699 if (res < 0) { 08700 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08701 p->dop.dialstr[0] = '\0'; 08702 return NULL; 08703 } else 08704 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08705 } 08706 p->dop.dialstr[0] = '\0'; 08707 break; 08708 default: 08709 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08710 } 08711 break; 08712 case DAHDI_EVENT_HOOKCOMPLETE: 08713 if (p->inalarm) break; 08714 if ((p->radio || (p->oprmode < 0))) break; 08715 if (p->waitingfordt.tv_sec) break; 08716 switch (mysig) { 08717 case SIG_FXSLS: /* only interesting for FXS */ 08718 case SIG_FXSGS: 08719 case SIG_FXSKS: 08720 case SIG_EM: 08721 case SIG_EM_E1: 08722 case SIG_EMWINK: 08723 case SIG_FEATD: 08724 case SIG_SF: 08725 case SIG_SFWINK: 08726 case SIG_SF_FEATD: 08727 if (!ast_strlen_zero(p->dop.dialstr)) { 08728 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08729 if (res < 0) { 08730 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08731 p->dop.dialstr[0] = '\0'; 08732 return NULL; 08733 } else 08734 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08735 } 08736 p->dop.dialstr[0] = '\0'; 08737 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08738 break; 08739 case SIG_FEATDMF: 08740 case SIG_FEATDMF_TA: 08741 case SIG_E911: 08742 case SIG_FGC_CAMA: 08743 case SIG_FGC_CAMAMF: 08744 case SIG_FEATB: 08745 case SIG_SF_FEATDMF: 08746 case SIG_SF_FEATB: 08747 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 08748 break; 08749 default: 08750 break; 08751 } 08752 break; 08753 case DAHDI_EVENT_POLARITY: 08754 /* 08755 * If we get a Polarity Switch event, check to see 08756 * if we should change the polarity state and 08757 * mark the channel as UP or if this is an indication 08758 * of remote end disconnect. 08759 */ 08760 if (p->polarity == POLARITY_IDLE) { 08761 p->polarity = POLARITY_REV; 08762 if (p->answeronpolarityswitch && 08763 ((ast->_state == AST_STATE_DIALING) || 08764 (ast->_state == AST_STATE_RINGING))) { 08765 ast_debug(1, "Answering on polarity switch!\n"); 08766 ast_setstate(p->owner, AST_STATE_UP); 08767 if (p->hanguponpolarityswitch) { 08768 p->polaritydelaytv = ast_tvnow(); 08769 } 08770 } else 08771 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 08772 } 08773 /* Removed else statement from here as it was preventing hangups from ever happening*/ 08774 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 08775 if (p->hanguponpolarityswitch && 08776 (p->polarityonanswerdelay > 0) && 08777 (p->polarity == POLARITY_REV) && 08778 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 08779 /* Added log_debug information below to provide a better indication of what is going on */ 08780 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, 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) ); 08781 08782 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 08783 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 08784 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 08785 p->polarity = POLARITY_IDLE; 08786 } else 08787 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state); 08788 08789 } else { 08790 p->polarity = POLARITY_IDLE; 08791 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 08792 } 08793 /* Added more log_debug information below to provide a better indication of what is going on */ 08794 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, 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) ); 08795 break; 08796 default: 08797 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 08798 } 08799 return &p->subs[idx].f; 08800 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6174 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.
06175 { 06176 int res = 0; 06177 int idx,x; 06178 int law; 06179 /*static int restore_gains(struct dahdi_pvt *p);*/ 06180 struct dahdi_pvt *p = ast->tech_pvt; 06181 struct dahdi_params par; 06182 06183 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 06184 if (!ast->tech_pvt) { 06185 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 06186 return 0; 06187 } 06188 06189 ast_mutex_lock(&p->lock); 06190 p->exten[0] = '\0'; 06191 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06192 dahdi_confmute(p, 0); 06193 restore_gains(p); 06194 p->ignoredtmf = 0; 06195 p->waitingfordt.tv_sec = 0; 06196 06197 res = analog_hangup(p->sig_pvt, ast); 06198 revert_fax_buffers(p, ast); 06199 06200 goto hangup_out; 06201 } else { 06202 p->cid_num[0] = '\0'; 06203 p->cid_name[0] = '\0'; 06204 p->cid_subaddr[0] = '\0'; 06205 } 06206 06207 #if defined(HAVE_PRI) 06208 if (dahdi_sig_pri_lib_handles(p->sig)) { 06209 x = 1; 06210 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06211 06212 dahdi_confmute(p, 0); 06213 p->muting = 0; 06214 restore_gains(p); 06215 if (p->dsp) { 06216 ast_dsp_free(p->dsp); 06217 p->dsp = NULL; 06218 } 06219 p->ignoredtmf = 0; 06220 06221 /* Real channel, do some fixup */ 06222 p->subs[SUB_REAL].owner = NULL; 06223 p->subs[SUB_REAL].needbusy = 0; 06224 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06225 06226 p->owner = NULL; 06227 p->cid_tag[0] = '\0'; 06228 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06229 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06230 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06231 p->outgoing = 0; 06232 p->digital = 0; 06233 p->faxhandled = 0; 06234 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06235 06236 revert_fax_buffers(p, ast); 06237 06238 p->law = p->law_default; 06239 law = p->law_default; 06240 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06241 if (res < 0) { 06242 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06243 p->channel, strerror(errno)); 06244 } 06245 06246 sig_pri_hangup(p->sig_pvt, ast); 06247 06248 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06249 dahdi_disable_ec(p); 06250 06251 x = 0; 06252 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06253 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06254 06255 p->rdnis[0] = '\0'; 06256 update_conf(p); 06257 reset_conf(p); 06258 06259 /* Restore data mode */ 06260 x = 0; 06261 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06262 06263 if (num_restart_pending == 0) { 06264 restart_monitor(); 06265 } 06266 goto hangup_out; 06267 } 06268 #endif /* defined(HAVE_PRI) */ 06269 06270 #if defined(HAVE_SS7) 06271 if (p->sig == SIG_SS7) { 06272 x = 1; 06273 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06274 06275 dahdi_confmute(p, 0); 06276 p->muting = 0; 06277 restore_gains(p); 06278 if (p->dsp) { 06279 ast_dsp_free(p->dsp); 06280 p->dsp = NULL; 06281 } 06282 p->ignoredtmf = 0; 06283 06284 /* Real channel, do some fixup */ 06285 p->subs[SUB_REAL].owner = NULL; 06286 p->subs[SUB_REAL].needbusy = 0; 06287 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06288 06289 p->owner = NULL; 06290 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06291 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06292 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06293 p->outgoing = 0; 06294 p->digital = 0; 06295 p->faxhandled = 0; 06296 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06297 06298 revert_fax_buffers(p, ast); 06299 06300 p->law = p->law_default; 06301 law = p->law_default; 06302 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06303 if (res < 0) { 06304 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06305 p->channel, strerror(errno)); 06306 } 06307 06308 sig_ss7_hangup(p->sig_pvt, ast); 06309 06310 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06311 dahdi_disable_ec(p); 06312 06313 x = 0; 06314 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06315 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06316 06317 update_conf(p); 06318 reset_conf(p); 06319 06320 /* Restore data mode */ 06321 x = 0; 06322 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06323 06324 if (num_restart_pending == 0) { 06325 restart_monitor(); 06326 } 06327 goto hangup_out; 06328 } 06329 #endif /* defined(HAVE_SS7) */ 06330 06331 idx = dahdi_get_index(ast, p, 1); 06332 06333 dahdi_confmute(p, 0); 06334 p->muting = 0; 06335 restore_gains(p); 06336 if (p->origcid_num) { 06337 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 06338 ast_free(p->origcid_num); 06339 p->origcid_num = NULL; 06340 } 06341 if (p->origcid_name) { 06342 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 06343 ast_free(p->origcid_name); 06344 p->origcid_name = NULL; 06345 } 06346 if (p->dsp) 06347 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06348 06349 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 06350 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06351 p->ignoredtmf = 0; 06352 06353 if (idx > -1) { 06354 /* Real channel, do some fixup */ 06355 p->subs[idx].owner = NULL; 06356 p->subs[idx].needanswer = 0; 06357 p->subs[idx].needflash = 0; 06358 p->subs[idx].needringing = 0; 06359 p->subs[idx].needbusy = 0; 06360 p->subs[idx].needcongestion = 0; 06361 p->subs[idx].linear = 0; 06362 p->polarity = POLARITY_IDLE; 06363 dahdi_setlinear(p->subs[idx].dfd, 0); 06364 if (idx == SUB_REAL) { 06365 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 06366 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 06367 if (p->subs[SUB_CALLWAIT].inthreeway) { 06368 /* We had flipped over to answer a callwait and now it's gone */ 06369 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 06370 /* Move to the call-wait, but un-own us until they flip back. */ 06371 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06372 unalloc_sub(p, SUB_CALLWAIT); 06373 p->owner = NULL; 06374 } else { 06375 /* The three way hung up, but we still have a call wait */ 06376 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 06377 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06378 unalloc_sub(p, SUB_THREEWAY); 06379 if (p->subs[SUB_REAL].inthreeway) { 06380 /* This was part of a three way call. Immediately make way for 06381 another call */ 06382 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06383 p->owner = p->subs[SUB_REAL].owner; 06384 } else { 06385 /* This call hasn't been completed yet... Set owner to NULL */ 06386 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06387 p->owner = NULL; 06388 } 06389 p->subs[SUB_REAL].inthreeway = 0; 06390 } 06391 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 06392 /* Move to the call-wait and switch back to them. */ 06393 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06394 unalloc_sub(p, SUB_CALLWAIT); 06395 p->owner = p->subs[SUB_REAL].owner; 06396 if (p->owner->_state != AST_STATE_UP) 06397 p->subs[SUB_REAL].needanswer = 1; 06398 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06399 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06400 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 06401 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06402 unalloc_sub(p, SUB_THREEWAY); 06403 if (p->subs[SUB_REAL].inthreeway) { 06404 /* This was part of a three way call. Immediately make way for 06405 another call */ 06406 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06407 p->owner = p->subs[SUB_REAL].owner; 06408 } else { 06409 /* This call hasn't been completed yet... Set owner to NULL */ 06410 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06411 p->owner = NULL; 06412 } 06413 p->subs[SUB_REAL].inthreeway = 0; 06414 } 06415 } else if (idx == SUB_CALLWAIT) { 06416 /* Ditch the holding callwait call, and immediately make it availabe */ 06417 if (p->subs[SUB_CALLWAIT].inthreeway) { 06418 /* This is actually part of a three way, placed on hold. Place the third part 06419 on music on hold now */ 06420 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06421 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06422 S_OR(p->mohsuggest, NULL), 06423 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06424 } 06425 p->subs[SUB_THREEWAY].inthreeway = 0; 06426 /* Make it the call wait now */ 06427 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06428 unalloc_sub(p, SUB_THREEWAY); 06429 } else 06430 unalloc_sub(p, SUB_CALLWAIT); 06431 } else if (idx == SUB_THREEWAY) { 06432 if (p->subs[SUB_CALLWAIT].inthreeway) { 06433 /* The other party of the three way call is currently in a call-wait state. 06434 Start music on hold for them, and take the main guy out of the third call */ 06435 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06436 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06437 S_OR(p->mohsuggest, NULL), 06438 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06439 } 06440 p->subs[SUB_CALLWAIT].inthreeway = 0; 06441 } 06442 p->subs[SUB_REAL].inthreeway = 0; 06443 /* If this was part of a three way call index, let us make 06444 another three way call */ 06445 unalloc_sub(p, SUB_THREEWAY); 06446 } else { 06447 /* This wasn't any sort of call, but how are we an index? */ 06448 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 06449 } 06450 } 06451 06452 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 06453 p->owner = NULL; 06454 p->ringt = 0; 06455 p->distinctivering = 0; 06456 p->confirmanswer = 0; 06457 p->outgoing = 0; 06458 p->digital = 0; 06459 p->faxhandled = 0; 06460 p->pulsedial = 0; 06461 if (p->dsp) { 06462 ast_dsp_free(p->dsp); 06463 p->dsp = NULL; 06464 } 06465 06466 revert_fax_buffers(p, ast); 06467 06468 p->law = p->law_default; 06469 law = p->law_default; 06470 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06471 if (res < 0) 06472 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06473 /* Perform low level hangup if no owner left */ 06474 #ifdef HAVE_OPENR2 06475 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 06476 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 06477 /* If it's an incoming call, check the mfcr2_forced_release setting */ 06478 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 06479 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 06480 } else { 06481 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 06482 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 06483 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 06484 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 06485 dahdi_r2_disconnect_call(p, r2cause); 06486 } 06487 } else if (p->mfcr2call) { 06488 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 06489 /* since ast_request() was called but not ast_call() we have not yet dialed 06490 and the openr2 stack will not call on_call_end callback, we need to unset 06491 the mfcr2call flag and bump the monitor count so the monitor thread can take 06492 care of this channel events from now on */ 06493 p->mfcr2call = 0; 06494 } 06495 #endif 06496 switch (p->sig) { 06497 case SIG_SS7: 06498 case SIG_MFCR2: 06499 case SIG_PRI_LIB_HANDLE_CASES: 06500 case 0: 06501 break; 06502 default: 06503 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06504 break; 06505 } 06506 if (res < 0) { 06507 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 06508 } 06509 switch (p->sig) { 06510 case SIG_FXOGS: 06511 case SIG_FXOLS: 06512 case SIG_FXOKS: 06513 memset(&par, 0, sizeof(par)); 06514 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 06515 if (!res) { 06516 struct analog_pvt *analog_p = p->sig_pvt; 06517 #if 0 06518 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 06519 #endif 06520 /* If they're off hook, try playing congestion */ 06521 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 06522 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06523 else 06524 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06525 analog_p->fxsoffhookstate = par.rxisoffhook; 06526 } 06527 break; 06528 case SIG_FXSGS: 06529 case SIG_FXSLS: 06530 case SIG_FXSKS: 06531 /* Make sure we're not made available for at least two seconds assuming 06532 we were actually used for an inbound or outbound call. */ 06533 if (ast->_state != AST_STATE_RESERVED) { 06534 time(&p->guardtime); 06535 p->guardtime += 2; 06536 } 06537 break; 06538 default: 06539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06540 break; 06541 } 06542 if (p->sig) 06543 dahdi_disable_ec(p); 06544 x = 0; 06545 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06546 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06547 p->didtdd = 0; 06548 p->callwaitcas = 0; 06549 p->callwaiting = p->permcallwaiting; 06550 p->hidecallerid = p->permhidecallerid; 06551 p->waitingfordt.tv_sec = 0; 06552 p->dialing = 0; 06553 p->rdnis[0] = '\0'; 06554 update_conf(p); 06555 reset_conf(p); 06556 /* Restore data mode */ 06557 switch (p->sig) { 06558 case SIG_PRI_LIB_HANDLE_CASES: 06559 case SIG_SS7: 06560 x = 0; 06561 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06562 break; 06563 default: 06564 break; 06565 } 06566 if (num_restart_pending == 0) 06567 restart_monitor(); 06568 } 06569 06570 p->callwaitingrepeat = 0; 06571 p->cidcwexpire = 0; 06572 p->cid_suppress_expire = 0; 06573 p->oprmode = 0; 06574 hangup_out: 06575 ast->tech_pvt = NULL; 06576 ast_free(p->cidspill); 06577 p->cidspill = NULL; 06578 06579 ast_mutex_unlock(&p->lock); 06580 ast_verb(3, "Hungup '%s'\n", ast->name); 06581 06582 ast_mutex_lock(&iflock); 06583 if (p->restartpending) { 06584 num_restart_pending--; 06585 } 06586 06587 if (p->destroy) { 06588 destroy_channel(p, 0); 06589 } 06590 ast_mutex_unlock(&iflock); 06591 06592 ast_module_unref(ast_module_info->self); 06593 return 0; 06594 }
static void dahdi_iflist_extract | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5567 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().
05568 { 05569 /* Extract from the forward chain. */ 05570 if (pvt->prev) { 05571 pvt->prev->next = pvt->next; 05572 } else if (iflist == pvt) { 05573 /* Node is at the head of the list. */ 05574 iflist = pvt->next; 05575 } 05576 05577 /* Extract from the reverse chain. */ 05578 if (pvt->next) { 05579 pvt->next->prev = pvt->prev; 05580 } else if (ifend == pvt) { 05581 /* Node is at the end of the list. */ 05582 ifend = pvt->prev; 05583 } 05584 05585 /* Node is no longer in the list. */ 05586 pvt->which_iflist = DAHDI_IFLIST_NONE; 05587 pvt->prev = NULL; 05588 pvt->next = NULL; 05589 }
static void dahdi_iflist_insert | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5517 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().
05518 { 05519 struct dahdi_pvt *cur; 05520 05521 pvt->which_iflist = DAHDI_IFLIST_MAIN; 05522 05523 /* Find place in middle of list for the new interface. */ 05524 for (cur = iflist; cur; cur = cur->next) { 05525 if (pvt->channel < cur->channel) { 05526 /* New interface goes before the current interface. */ 05527 pvt->prev = cur->prev; 05528 pvt->next = cur; 05529 if (cur->prev) { 05530 /* Insert into the middle of the list. */ 05531 cur->prev->next = pvt; 05532 } else { 05533 /* Insert at head of list. */ 05534 iflist = pvt; 05535 } 05536 cur->prev = pvt; 05537 return; 05538 } 05539 } 05540 05541 /* New interface goes onto the end of the list */ 05542 pvt->prev = ifend; 05543 pvt->next = NULL; 05544 if (ifend) { 05545 ifend->next = pvt; 05546 } 05547 ifend = pvt; 05548 if (!iflist) { 05549 /* List was empty */ 05550 iflist = pvt; 05551 } 05552 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 9462 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().
09463 { 09464 struct dahdi_pvt *p = chan->tech_pvt; 09465 int res=-1; 09466 int idx; 09467 int func = DAHDI_FLASH; 09468 09469 ast_mutex_lock(&p->lock); 09470 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 09471 switch (p->sig) { 09472 #if defined(HAVE_PRI) 09473 case SIG_PRI_LIB_HANDLE_CASES: 09474 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen); 09475 ast_mutex_unlock(&p->lock); 09476 return res; 09477 #endif /* defined(HAVE_PRI) */ 09478 #if defined(HAVE_SS7) 09479 case SIG_SS7: 09480 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen); 09481 ast_mutex_unlock(&p->lock); 09482 return res; 09483 #endif /* defined(HAVE_SS7) */ 09484 default: 09485 break; 09486 } 09487 #ifdef HAVE_OPENR2 09488 if (p->mfcr2 && !p->mfcr2_call_accepted) { 09489 ast_mutex_unlock(&p->lock); 09490 /* if this is an R2 call and the call is not yet accepted, we don't want the 09491 tone indications to mess up with the MF tones */ 09492 return 0; 09493 } 09494 #endif 09495 idx = dahdi_get_index(chan, p, 0); 09496 if (idx == SUB_REAL) { 09497 switch (condition) { 09498 case AST_CONTROL_BUSY: 09499 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 09500 break; 09501 case AST_CONTROL_RINGING: 09502 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 09503 09504 if (chan->_state != AST_STATE_UP) { 09505 if ((chan->_state != AST_STATE_RING) || 09506 ((p->sig != SIG_FXSKS) && 09507 (p->sig != SIG_FXSLS) && 09508 (p->sig != SIG_FXSGS))) 09509 ast_setstate(chan, AST_STATE_RINGING); 09510 } 09511 break; 09512 case AST_CONTROL_INCOMPLETE: 09513 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name); 09514 /* act as a progress or proceeding, allowing the caller to enter additional numbers */ 09515 res = 0; 09516 break; 09517 case AST_CONTROL_PROCEEDING: 09518 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name); 09519 /* don't continue in ast_indicate */ 09520 res = 0; 09521 break; 09522 case AST_CONTROL_PROGRESS: 09523 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name); 09524 /* don't continue in ast_indicate */ 09525 res = 0; 09526 break; 09527 case AST_CONTROL_CONGESTION: 09528 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 09529 switch (chan->hangupcause) { 09530 case AST_CAUSE_USER_BUSY: 09531 case AST_CAUSE_NORMAL_CLEARING: 09532 case 0:/* Cause has not been set. */ 09533 /* Supply a more appropriate cause. */ 09534 chan->hangupcause = AST_CAUSE_CONGESTION; 09535 break; 09536 default: 09537 break; 09538 } 09539 break; 09540 case AST_CONTROL_HOLD: 09541 ast_moh_start(chan, data, p->mohinterpret); 09542 break; 09543 case AST_CONTROL_UNHOLD: 09544 ast_moh_stop(chan); 09545 break; 09546 case AST_CONTROL_RADIO_KEY: 09547 if (p->radio) 09548 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 09549 res = 0; 09550 break; 09551 case AST_CONTROL_RADIO_UNKEY: 09552 if (p->radio) 09553 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 09554 res = 0; 09555 break; 09556 case AST_CONTROL_FLASH: 09557 /* flash hookswitch */ 09558 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 09559 /* Clear out the dial buffer */ 09560 p->dop.dialstr[0] = '\0'; 09561 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09562 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09563 chan->name, strerror(errno)); 09564 } else 09565 res = 0; 09566 } else 09567 res = 0; 09568 break; 09569 case AST_CONTROL_SRCUPDATE: 09570 res = 0; 09571 break; 09572 case -1: 09573 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09574 break; 09575 } 09576 } else { 09577 res = 0; 09578 } 09579 ast_mutex_unlock(&p->lock); 09580 return res; 09581 }
Definition at line 7220 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().
07220 { 07221 int x; 07222 if (!slave || !master) { 07223 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 07224 return; 07225 } 07226 for (x = 0; x < MAX_SLAVES; x++) { 07227 if (!master->slaves[x]) { 07228 master->slaves[x] = slave; 07229 break; 07230 } 07231 } 07232 if (x >= MAX_SLAVES) { 07233 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 07234 master->slaves[MAX_SLAVES - 1] = slave; 07235 } 07236 if (slave->master) 07237 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 07238 slave->master = master; 07239 07240 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 07241 }
static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
int | sub_idx | |||
) | [static] |
Definition at line 3827 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().
03828 { 03829 for (;;) { 03830 if (!pvt->subs[sub_idx].owner) { 03831 /* No subchannel owner pointer */ 03832 break; 03833 } 03834 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) { 03835 /* Got subchannel owner lock */ 03836 break; 03837 } 03838 /* We must unlock the private to avoid the possibility of a deadlock */ 03839 DEADLOCK_AVOIDANCE(&pvt->lock); 03840 } 03841 }
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 9631 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().
09632 { 09633 struct ast_channel *tmp; 09634 format_t deflaw; 09635 int x; 09636 int features; 09637 struct ast_str *chan_name; 09638 struct ast_variable *v; 09639 char *dashptr; 09640 char device_name[AST_CHANNEL_NAME]; 09641 09642 if (i->subs[idx].owner) { 09643 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 09644 return NULL; 09645 } 09646 09647 #if defined(HAVE_PRI) 09648 /* 09649 * The dnid has been stuffed with the called-number[:subaddress] 09650 * by dahdi_request() for outgoing calls. 09651 */ 09652 chan_name = create_channel_name(i, i->outgoing, i->dnid); 09653 #else 09654 chan_name = create_channel_name(i); 09655 #endif /* defined(HAVE_PRI) */ 09656 if (!chan_name) { 09657 return NULL; 09658 } 09659 09660 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)); 09661 ast_free(chan_name); 09662 if (!tmp) 09663 return NULL; 09664 tmp->tech = &dahdi_tech; 09665 #if defined(HAVE_PRI) 09666 if (i->pri) { 09667 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params); 09668 } 09669 #endif /* defined(HAVE_PRI) */ 09670 ast_channel_cc_params_init(tmp, i->cc_params); 09671 if (law) { 09672 i->law = law; 09673 if (law == DAHDI_LAW_ALAW) { 09674 deflaw = AST_FORMAT_ALAW; 09675 } else { 09676 deflaw = AST_FORMAT_ULAW; 09677 } 09678 } else { 09679 switch (i->sig) { 09680 case SIG_PRI_LIB_HANDLE_CASES: 09681 /* Make sure companding law is known. */ 09682 i->law = (i->law_default == DAHDI_LAW_ALAW) 09683 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW; 09684 break; 09685 default: 09686 i->law = i->law_default; 09687 break; 09688 } 09689 if (i->law_default == DAHDI_LAW_ALAW) { 09690 deflaw = AST_FORMAT_ALAW; 09691 } else { 09692 deflaw = AST_FORMAT_ULAW; 09693 } 09694 } 09695 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 09696 tmp->nativeformats = deflaw; 09697 /* Start out assuming ulaw since it's smaller :) */ 09698 tmp->rawreadformat = deflaw; 09699 tmp->readformat = deflaw; 09700 tmp->rawwriteformat = deflaw; 09701 tmp->writeformat = deflaw; 09702 i->subs[idx].linear = 0; 09703 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 09704 features = 0; 09705 if (idx == SUB_REAL) { 09706 if (i->busydetect && CANBUSYDETECT(i)) 09707 features |= DSP_FEATURE_BUSY_DETECT; 09708 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 09709 features |= DSP_FEATURE_CALL_PROGRESS; 09710 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 09711 features |= DSP_FEATURE_WAITDIALTONE; 09712 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 09713 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 09714 features |= DSP_FEATURE_FAX_DETECT; 09715 } 09716 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 09717 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 09718 i->hardwaredtmf = 0; 09719 features |= DSP_FEATURE_DIGIT_DETECT; 09720 } else if (NEED_MFDETECT(i)) { 09721 i->hardwaredtmf = 1; 09722 features |= DSP_FEATURE_DIGIT_DETECT; 09723 } 09724 } 09725 if (features) { 09726 if (i->dsp) { 09727 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 09728 } else { 09729 if (i->channel != CHAN_PSEUDO) 09730 i->dsp = ast_dsp_new(); 09731 else 09732 i->dsp = NULL; 09733 if (i->dsp) { 09734 i->dsp_features = features; 09735 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09736 /* We cannot do progress detection until receive PROGRESS message */ 09737 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) { 09738 /* Remember requested DSP features, don't treat 09739 talking as ANSWER */ 09740 i->dsp_features = features & ~DSP_PROGRESS_TALK; 09741 features = 0; 09742 } 09743 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09744 ast_dsp_set_features(i->dsp, features); 09745 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 09746 if (!ast_strlen_zero(progzone)) 09747 ast_dsp_set_call_progress_zone(i->dsp, progzone); 09748 if (i->busydetect && CANBUSYDETECT(i)) { 09749 if(i->silencethreshold > 0) 09750 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 09751 ast_dsp_set_busy_count(i->dsp, i->busycount); 09752 if(i->busytonelength > 0) 09753 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 09754 if((i->busytonelength == i->busyquietlength) && i->busycompare) 09755 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 09756 } 09757 } 09758 } 09759 } 09760 09761 if (state == AST_STATE_RING) 09762 tmp->rings = 1; 09763 tmp->tech_pvt = i; 09764 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 09765 /* Only FXO signalled stuff can be picked up */ 09766 tmp->callgroup = i->callgroup; 09767 tmp->pickupgroup = i->pickupgroup; 09768 } 09769 if (!ast_strlen_zero(i->parkinglot)) 09770 ast_string_field_set(tmp, parkinglot, i->parkinglot); 09771 if (!ast_strlen_zero(i->language)) 09772 ast_string_field_set(tmp, language, i->language); 09773 if (!i->owner) 09774 i->owner = tmp; 09775 if (!ast_strlen_zero(i->accountcode)) 09776 ast_string_field_set(tmp, accountcode, i->accountcode); 09777 if (i->amaflags) 09778 tmp->amaflags = i->amaflags; 09779 i->subs[idx].owner = tmp; 09780 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 09781 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) { 09782 ast_string_field_set(tmp, call_forward, i->call_forward); 09783 } 09784 /* If we've been told "no ADSI" then enforce it */ 09785 if (!i->adsi) 09786 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 09787 if (!ast_strlen_zero(i->exten)) 09788 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 09789 if (!ast_strlen_zero(i->rdnis)) { 09790 tmp->redirecting.from.number.valid = 1; 09791 tmp->redirecting.from.number.str = ast_strdup(i->rdnis); 09792 } 09793 if (!ast_strlen_zero(i->dnid)) { 09794 tmp->dialed.number.str = ast_strdup(i->dnid); 09795 } 09796 09797 /* Don't use ast_set_callerid() here because it will 09798 * generate a needless NewCallerID event */ 09799 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09800 if (!ast_strlen_zero(i->cid_ani)) { 09801 tmp->caller.ani.number.valid = 1; 09802 tmp->caller.ani.number.str = ast_strdup(i->cid_ani); 09803 } else if (!ast_strlen_zero(i->cid_num)) { 09804 tmp->caller.ani.number.valid = 1; 09805 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09806 } 09807 #else 09808 if (!ast_strlen_zero(i->cid_num)) { 09809 tmp->caller.ani.number.valid = 1; 09810 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09811 } 09812 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09813 tmp->caller.id.name.presentation = i->callingpres; 09814 tmp->caller.id.number.presentation = i->callingpres; 09815 tmp->caller.id.number.plan = i->cid_ton; 09816 tmp->caller.ani2 = i->cid_ani2; 09817 tmp->caller.id.tag = ast_strdup(i->cid_tag); 09818 /* clear the fake event in case we posted one before we had ast_channel */ 09819 i->fake_event = 0; 09820 /* Assure there is no confmute on this channel */ 09821 dahdi_confmute(i, 0); 09822 i->muting = 0; 09823 /* Configure the new channel jb */ 09824 ast_jb_configure(tmp, &global_jbconf); 09825 09826 /* Set initial device state */ 09827 ast_copy_string(device_name, tmp->name, sizeof(device_name)); 09828 dashptr = strrchr(device_name, '-'); 09829 if (dashptr) { 09830 *dashptr = '\0'; 09831 } 09832 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; 09833 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name); 09834 09835 for (v = i->vars ; v ; v = v->next) 09836 pbx_builtin_setvar_helper(tmp, v->name, v->value); 09837 09838 ast_module_ref(ast_module_info->self); 09839 09840 dahdi_ami_channel_event(i, tmp); 09841 if (startpbx) { 09842 #ifdef HAVE_OPENR2 09843 if (i->mfcr2call) { 09844 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 09845 } 09846 #endif 09847 if (ast_pbx_start(tmp)) { 09848 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 09849 ast_hangup(tmp); 09850 return NULL; 09851 } 09852 } 09853 return tmp; 09854 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 4364 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), duplicate_pseudo(), and mkintf().
04365 { 04366 int fd; 04367 int isnum; 04368 int chan = 0; 04369 int bs; 04370 int x; 04371 isnum = 1; 04372 for (x = 0; x < strlen(fn); x++) { 04373 if (!isdigit(fn[x])) { 04374 isnum = 0; 04375 break; 04376 } 04377 } 04378 if (isnum) { 04379 chan = atoi(fn); 04380 if (chan < 1) { 04381 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 04382 return -1; 04383 } 04384 fn = "/dev/dahdi/channel"; 04385 } 04386 fd = open(fn, O_RDWR | O_NONBLOCK); 04387 if (fd < 0) { 04388 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 04389 return -1; 04390 } 04391 if (chan) { 04392 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 04393 x = errno; 04394 close(fd); 04395 errno = x; 04396 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 04397 return -1; 04398 } 04399 } 04400 bs = READ_SIZE; 04401 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 04402 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 04403 x = errno; 04404 close(fd); 04405 errno = x; 04406 return -1; 04407 } 04408 return fd; 04409 }
static int dahdi_queryoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int * | datalen | |||
) | [static] |
Definition at line 6691 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.
06692 { 06693 char *cp; 06694 struct dahdi_pvt *p = chan->tech_pvt; 06695 06696 /* all supported options require data */ 06697 if (!p || !data || (*datalen < 1)) { 06698 errno = EINVAL; 06699 return -1; 06700 } 06701 06702 switch (option) { 06703 case AST_OPTION_DIGIT_DETECT: 06704 cp = (char *) data; 06705 *cp = p->ignoredtmf ? 0 : 1; 06706 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06707 break; 06708 case AST_OPTION_FAX_DETECT: 06709 cp = (char *) data; 06710 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1; 06711 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06712 break; 06713 case AST_OPTION_CC_AGENT_TYPE: 06714 #if defined(HAVE_PRI) 06715 #if defined(HAVE_PRI_CCSS) 06716 if (dahdi_sig_pri_lib_handles(p->sig)) { 06717 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen); 06718 break; 06719 } 06720 #endif /* defined(HAVE_PRI_CCSS) */ 06721 #endif /* defined(HAVE_PRI) */ 06722 return -1; 06723 default: 06724 return -1; 06725 } 06726 06727 errno = 0; 06728 06729 return 0; 06730 }
Definition at line 3852 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().
03853 { 03854 for (;;) { 03855 if (p->owner) { 03856 if (ast_channel_trylock(p->owner)) { 03857 DEADLOCK_AVOIDANCE(&p->lock); 03858 } else { 03859 ast_queue_frame(p->owner, f); 03860 ast_channel_unlock(p->owner); 03861 break; 03862 } 03863 } else 03864 break; 03865 } 03866 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 8939 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.
08940 { 08941 struct dahdi_pvt *p; 08942 int res; 08943 int idx; 08944 void *readbuf; 08945 struct ast_frame *f; 08946 08947 /* 08948 * For analog channels, we must do deadlock avoidance because 08949 * analog ports can have more than one Asterisk channel using 08950 * the same private structure. 08951 */ 08952 p = ast->tech_pvt; 08953 while (ast_mutex_trylock(&p->lock)) { 08954 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08955 08956 /* 08957 * Check to see if the channel is still associated with the same 08958 * private structure. While the Asterisk channel was unlocked 08959 * the following events may have occured: 08960 * 08961 * 1) A masquerade may have associated the channel with another 08962 * technology or private structure. 08963 * 08964 * 2) For PRI calls, call signaling could change the channel 08965 * association to another B channel (private structure). 08966 */ 08967 if (ast->tech_pvt != p) { 08968 /* The channel is no longer associated. Quit gracefully. */ 08969 return &ast_null_frame; 08970 } 08971 } 08972 08973 idx = dahdi_get_index(ast, p, 0); 08974 08975 /* Hang up if we don't really exist */ 08976 if (idx < 0) { 08977 ast_log(LOG_WARNING, "We don't exist?\n"); 08978 ast_mutex_unlock(&p->lock); 08979 return NULL; 08980 } 08981 08982 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 08983 ast_mutex_unlock(&p->lock); 08984 return NULL; 08985 } 08986 08987 p->subs[idx].f.frametype = AST_FRAME_NULL; 08988 p->subs[idx].f.datalen = 0; 08989 p->subs[idx].f.samples = 0; 08990 p->subs[idx].f.mallocd = 0; 08991 p->subs[idx].f.offset = 0; 08992 p->subs[idx].f.subclass.integer = 0; 08993 p->subs[idx].f.delivery = ast_tv(0,0); 08994 p->subs[idx].f.src = "dahdi_read"; 08995 p->subs[idx].f.data.ptr = NULL; 08996 08997 /* make sure it sends initial key state as first frame */ 08998 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 08999 { 09000 struct dahdi_params ps; 09001 09002 memset(&ps, 0, sizeof(ps)); 09003 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 09004 ast_mutex_unlock(&p->lock); 09005 return NULL; 09006 } 09007 p->firstradio = 1; 09008 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09009 if (ps.rxisoffhook) 09010 { 09011 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 09012 } 09013 else 09014 { 09015 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 09016 } 09017 ast_mutex_unlock(&p->lock); 09018 return &p->subs[idx].f; 09019 } 09020 if (p->ringt > 0) { 09021 if (!(--p->ringt)) { 09022 ast_mutex_unlock(&p->lock); 09023 return NULL; 09024 } 09025 } 09026 09027 #ifdef HAVE_OPENR2 09028 if (p->mfcr2) { 09029 openr2_chan_process_event(p->r2chan); 09030 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) { 09031 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, }; 09032 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING 09033 * now enqueue a progress frame to bridge the media up */ 09034 if (p->mfcr2_call_accepted && 09035 !p->mfcr2_progress && 09036 ast->_state == AST_STATE_RINGING) { 09037 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel); 09038 ast_queue_frame(p->owner, &f); 09039 p->mfcr2_progress = 1; 09040 } 09041 } 09042 } 09043 #endif 09044 09045 if (p->subs[idx].needringing) { 09046 /* Send ringing frame if requested */ 09047 p->subs[idx].needringing = 0; 09048 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09049 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING; 09050 ast_setstate(ast, AST_STATE_RINGING); 09051 ast_mutex_unlock(&p->lock); 09052 return &p->subs[idx].f; 09053 } 09054 09055 if (p->subs[idx].needbusy) { 09056 /* Send busy frame if requested */ 09057 p->subs[idx].needbusy = 0; 09058 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09059 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY; 09060 ast_mutex_unlock(&p->lock); 09061 return &p->subs[idx].f; 09062 } 09063 09064 if (p->subs[idx].needcongestion) { 09065 /* Send congestion frame if requested */ 09066 p->subs[idx].needcongestion = 0; 09067 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09068 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION; 09069 ast_mutex_unlock(&p->lock); 09070 return &p->subs[idx].f; 09071 } 09072 09073 if (p->subs[idx].needanswer) { 09074 /* Send answer frame if requested */ 09075 p->subs[idx].needanswer = 0; 09076 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09077 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 09078 ast_mutex_unlock(&p->lock); 09079 return &p->subs[idx].f; 09080 } 09081 #ifdef HAVE_OPENR2 09082 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 09083 /* openr2 took care of reading and handling any event 09084 (needanswer, needbusy etc), if we continue we will read() 09085 twice, lets just return a null frame. This should only 09086 happen when openr2 is dialing out */ 09087 ast_mutex_unlock(&p->lock); 09088 return &ast_null_frame; 09089 } 09090 #endif 09091 09092 if (p->subs[idx].needflash) { 09093 /* Send answer frame if requested */ 09094 p->subs[idx].needflash = 0; 09095 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09096 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH; 09097 ast_mutex_unlock(&p->lock); 09098 return &p->subs[idx].f; 09099 } 09100 09101 if (p->subs[idx].needhold) { 09102 /* Send answer frame if requested */ 09103 p->subs[idx].needhold = 0; 09104 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09105 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD; 09106 ast_mutex_unlock(&p->lock); 09107 ast_debug(1, "Sending hold on '%s'\n", ast->name); 09108 return &p->subs[idx].f; 09109 } 09110 09111 if (p->subs[idx].needunhold) { 09112 /* Send answer frame if requested */ 09113 p->subs[idx].needunhold = 0; 09114 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 09115 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD; 09116 ast_mutex_unlock(&p->lock); 09117 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 09118 return &p->subs[idx].f; 09119 } 09120 09121 /* 09122 * If we have a fake_event, fake an exception to handle it only 09123 * if this channel owns the private. 09124 */ 09125 if (p->fake_event && p->owner == ast) { 09126 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09127 struct analog_pvt *analog_p = p->sig_pvt; 09128 09129 f = analog_exception(analog_p, ast); 09130 } else { 09131 f = __dahdi_exception(ast); 09132 } 09133 ast_mutex_unlock(&p->lock); 09134 return f; 09135 } 09136 09137 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 09138 if (!p->subs[idx].linear) { 09139 p->subs[idx].linear = 1; 09140 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09141 if (res) 09142 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 09143 } 09144 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 09145 (ast->rawreadformat == AST_FORMAT_ALAW)) { 09146 if (p->subs[idx].linear) { 09147 p->subs[idx].linear = 0; 09148 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09149 if (res) 09150 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 09151 } 09152 } else { 09153 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 09154 ast_mutex_unlock(&p->lock); 09155 return NULL; 09156 } 09157 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 09158 CHECK_BLOCKING(ast); 09159 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09160 ast_clear_flag(ast, AST_FLAG_BLOCKING); 09161 /* Check for hangup */ 09162 if (res < 0) { 09163 f = NULL; 09164 if (res == -1) { 09165 if (errno == EAGAIN) { 09166 /* Return "NULL" frame if there is nobody there */ 09167 ast_mutex_unlock(&p->lock); 09168 return &p->subs[idx].f; 09169 } else if (errno == ELAST) { 09170 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09171 struct analog_pvt *analog_p = p->sig_pvt; 09172 f = analog_exception(analog_p, ast); 09173 } else { 09174 f = __dahdi_exception(ast); 09175 } 09176 } else 09177 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 09178 } 09179 ast_mutex_unlock(&p->lock); 09180 return f; 09181 } 09182 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 09183 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09184 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09185 struct analog_pvt *analog_p = p->sig_pvt; 09186 f = analog_exception(analog_p, ast); 09187 } else { 09188 f = __dahdi_exception(ast); 09189 } 09190 ast_mutex_unlock(&p->lock); 09191 return f; 09192 } 09193 if (p->tdd) { /* if in TDD mode, see if we receive that */ 09194 int c; 09195 09196 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 09197 if (c < 0) { 09198 ast_debug(1,"tdd_feed failed\n"); 09199 ast_mutex_unlock(&p->lock); 09200 return NULL; 09201 } 09202 if (c) { /* if a char to return */ 09203 p->subs[idx].f.subclass.integer = 0; 09204 p->subs[idx].f.frametype = AST_FRAME_TEXT; 09205 p->subs[idx].f.mallocd = 0; 09206 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09207 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 09208 p->subs[idx].f.datalen = 1; 09209 *((char *) p->subs[idx].f.data.ptr) = c; 09210 ast_mutex_unlock(&p->lock); 09211 return &p->subs[idx].f; 09212 } 09213 } 09214 if (idx == SUB_REAL) { 09215 /* Ensure the CW timers decrement only on a single subchannel */ 09216 if (p->cidcwexpire) { 09217 if (!--p->cidcwexpire) { 09218 /* Expired CID/CW */ 09219 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 09220 restore_conference(p); 09221 } 09222 } 09223 if (p->cid_suppress_expire) { 09224 --p->cid_suppress_expire; 09225 } 09226 if (p->callwaitingrepeat) { 09227 if (!--p->callwaitingrepeat) { 09228 /* Expired, Repeat callwaiting tone */ 09229 ++p->callwaitrings; 09230 dahdi_callwait(ast); 09231 } 09232 } 09233 } 09234 if (p->subs[idx].linear) { 09235 p->subs[idx].f.datalen = READ_SIZE * 2; 09236 } else 09237 p->subs[idx].f.datalen = READ_SIZE; 09238 09239 /* Handle CallerID Transmission */ 09240 if ((p->owner == ast) && p->cidspill) { 09241 send_callerid(p); 09242 } 09243 09244 p->subs[idx].f.frametype = AST_FRAME_VOICE; 09245 p->subs[idx].f.subclass.codec = ast->rawreadformat; 09246 p->subs[idx].f.samples = READ_SIZE; 09247 p->subs[idx].f.mallocd = 0; 09248 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09249 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 09250 #if 0 09251 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 09252 #endif 09253 if (p->dialing || p->radio || /* Transmitting something */ 09254 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 09255 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 09256 ) { 09257 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 09258 don't send anything */ 09259 p->subs[idx].f.frametype = AST_FRAME_NULL; 09260 p->subs[idx].f.subclass.integer = 0; 09261 p->subs[idx].f.samples = 0; 09262 p->subs[idx].f.mallocd = 0; 09263 p->subs[idx].f.offset = 0; 09264 p->subs[idx].f.data.ptr = NULL; 09265 p->subs[idx].f.datalen= 0; 09266 } 09267 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 09268 /* Perform busy detection etc on the dahdi line */ 09269 int mute; 09270 09271 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 09272 09273 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 09274 mute = ast_dsp_was_muted(p->dsp); 09275 if (p->muting != mute) { 09276 p->muting = mute; 09277 dahdi_confmute(p, mute); 09278 } 09279 09280 if (f) { 09281 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { 09282 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 09283 /* Treat this as a "hangup" instead of a "busy" on the assumption that 09284 a busy */ 09285 ast_frfree(f); 09286 f = NULL; 09287 } 09288 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 09289 || f->frametype == AST_FRAME_DTMF_END) { 09290 #ifdef HAVE_PRI 09291 if (dahdi_sig_pri_lib_handles(p->sig) 09292 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 09293 && p->pri 09294 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 09295 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 09296 /* Don't accept in-band DTMF when in overlap dial mode */ 09297 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 09298 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 09299 f->subclass.integer, f->subclass.integer, ast->name); 09300 09301 f->frametype = AST_FRAME_NULL; 09302 f->subclass.integer = 0; 09303 } 09304 #endif 09305 /* DSP clears us of being pulse */ 09306 p->pulsedial = 0; 09307 } else if (p->waitingfordt.tv_sec) { 09308 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 09309 p->waitingfordt.tv_sec = 0; 09310 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 09311 ast_frfree(f); 09312 f = NULL; 09313 } else if (f->frametype == AST_FRAME_VOICE) { 09314 f->frametype = AST_FRAME_NULL; 09315 f->subclass.integer = 0; 09316 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) { 09317 p->waitingfordt.tv_sec = 0; 09318 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 09319 ast_dsp_set_features(p->dsp, p->dsp_features); 09320 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 09321 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 09322 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 09323 if (res < 0) { 09324 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 09325 p->dop.dialstr[0] = '\0'; 09326 ast_mutex_unlock(&p->lock); 09327 ast_frfree(f); 09328 return NULL; 09329 } else { 09330 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 09331 p->dialing = 1; 09332 p->dop.dialstr[0] = '\0'; 09333 p->dop.op = DAHDI_DIAL_OP_REPLACE; 09334 ast_setstate(ast, AST_STATE_DIALING); 09335 } 09336 } 09337 } 09338 } 09339 } 09340 } 09341 } else 09342 f = &p->subs[idx].f; 09343 09344 if (f) { 09345 switch (f->frametype) { 09346 case AST_FRAME_DTMF_BEGIN: 09347 case AST_FRAME_DTMF_END: 09348 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09349 analog_handle_dtmf(p->sig_pvt, ast, idx, &f); 09350 } else { 09351 dahdi_handle_dtmf(ast, idx, &f); 09352 } 09353 break; 09354 case AST_FRAME_VOICE: 09355 if (p->cidspill || p->cid_suppress_expire) { 09356 /* We are/were sending a caller id spill. Suppress any echo. */ 09357 p->subs[idx].f.frametype = AST_FRAME_NULL; 09358 p->subs[idx].f.subclass.integer = 0; 09359 p->subs[idx].f.samples = 0; 09360 p->subs[idx].f.mallocd = 0; 09361 p->subs[idx].f.offset = 0; 09362 p->subs[idx].f.data.ptr = NULL; 09363 p->subs[idx].f.datalen= 0; 09364 } 09365 break; 09366 default: 09367 break; 09368 } 09369 } 09370 09371 ast_mutex_unlock(&p->lock); 09372 return f; 09373 }
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 13689 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.
13690 { 13691 int callwait = 0; 13692 struct dahdi_pvt *p; 13693 struct ast_channel *tmp = NULL; 13694 struct dahdi_pvt *exitpvt; 13695 int channelmatched = 0; 13696 int groupmatched = 0; 13697 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13698 int transcapdigital = 0; 13699 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13700 struct dahdi_starting_point start; 13701 13702 ast_mutex_lock(&iflock); 13703 p = determine_starting_point(data, &start); 13704 if (!p) { 13705 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */ 13706 ast_mutex_unlock(&iflock); 13707 return NULL; 13708 } 13709 13710 /* Search for an unowned channel */ 13711 exitpvt = p; 13712 while (p && !tmp) { 13713 if (start.roundrobin) 13714 round_robin[start.rr_starting_point] = p; 13715 13716 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched) 13717 && available(&p, channelmatched)) { 13718 ast_debug(1, "Using channel %d\n", p->channel); 13719 13720 callwait = (p->owner != NULL); 13721 #ifdef HAVE_OPENR2 13722 if (p->mfcr2) { 13723 ast_mutex_lock(&p->lock); 13724 if (p->mfcr2call) { 13725 ast_mutex_unlock(&p->lock); 13726 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 13727 goto next; 13728 } 13729 p->mfcr2call = 1; 13730 ast_mutex_unlock(&p->lock); 13731 } 13732 #endif 13733 if (p->channel == CHAN_PSEUDO) { 13734 p = duplicate_pseudo(p); 13735 if (!p) { 13736 break; 13737 } 13738 } 13739 13740 p->distinctivering = 0; 13741 /* Make special notes */ 13742 switch (start.opt) { 13743 case '\0': 13744 /* No option present. */ 13745 break; 13746 case 'c': 13747 /* Confirm answer */ 13748 p->confirmanswer = 1; 13749 break; 13750 case 'r': 13751 /* Distinctive ring */ 13752 p->distinctivering = start.cadance; 13753 break; 13754 case 'd': 13755 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13756 /* If this is an ISDN call, make it digital */ 13757 transcapdigital = AST_TRANS_CAP_DIGITAL; 13758 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13759 break; 13760 default: 13761 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data); 13762 break; 13763 } 13764 13765 p->outgoing = 1; 13766 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 13767 tmp = analog_request(p->sig_pvt, &callwait, requestor); 13768 #ifdef HAVE_PRI 13769 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 13770 /* 13771 * We already have the B channel reserved for this call. We 13772 * just need to make sure that dahdi_hangup() has completed 13773 * cleaning up before continuing. 13774 */ 13775 ast_mutex_lock(&p->lock); 13776 ast_mutex_unlock(&p->lock); 13777 13778 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid, 13779 sizeof(p->dnid)); 13780 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital); 13781 #endif 13782 #if defined(HAVE_SS7) 13783 } else if (p->sig == SIG_SS7) { 13784 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital); 13785 #endif /* defined(HAVE_SS7) */ 13786 } else { 13787 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : ""); 13788 } 13789 if (!tmp) { 13790 p->outgoing = 0; 13791 #if defined(HAVE_PRI) 13792 switch (p->sig) { 13793 case SIG_PRI_LIB_HANDLE_CASES: 13794 #if defined(HAVE_PRI_CALL_WAITING) 13795 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) { 13796 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0; 13797 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); 13798 } 13799 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 13800 /* 13801 * This should be the last thing to clear when we are done with 13802 * the channel. 13803 */ 13804 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0; 13805 break; 13806 default: 13807 break; 13808 } 13809 #endif /* defined(HAVE_PRI) */ 13810 } else { 13811 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data); 13812 } 13813 break; 13814 } 13815 #ifdef HAVE_OPENR2 13816 next: 13817 #endif 13818 if (start.backwards) { 13819 p = p->prev; 13820 if (!p) 13821 p = ifend; 13822 } else { 13823 p = p->next; 13824 if (!p) 13825 p = iflist; 13826 } 13827 /* stop when you roll to the one that we started from */ 13828 if (p == exitpvt) 13829 break; 13830 } 13831 ast_mutex_unlock(&iflock); 13832 restart_monitor(); 13833 if (cause && !tmp) { 13834 if (callwait || channelmatched) { 13835 *cause = AST_CAUSE_BUSY; 13836 } else if (groupmatched) { 13837 *cause = AST_CAUSE_CONGESTION; 13838 } else { 13839 /* 13840 * We did not match any channel requested. 13841 * Dialplan error requesting non-existant channel? 13842 */ 13843 } 13844 } 13845 13846 return tmp; 13847 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 15120 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, 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().
15121 { 15122 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15123 int i, j; 15124 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 15125 int cancel_code; 15126 struct dahdi_pvt *p; 15127 15128 ast_mutex_lock(&restart_lock); 15129 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 15130 dahdi_softhangup_all(); 15131 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 15132 #ifdef HAVE_OPENR2 15133 dahdi_r2_destroy_links(); 15134 #endif 15135 15136 #if defined(HAVE_PRI) 15137 for (i = 0; i < NUM_SPANS; i++) { 15138 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 15139 cancel_code = pthread_cancel(pris[i].pri.master); 15140 pthread_kill(pris[i].pri.master, SIGURG); 15141 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); 15142 pthread_join(pris[i].pri.master, NULL); 15143 ast_debug(4, "Joined thread of span %d\n", i); 15144 } 15145 } 15146 #endif 15147 15148 #if defined(HAVE_SS7) 15149 for (i = 0; i < NUM_SPANS; i++) { 15150 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 15151 cancel_code = pthread_cancel(linksets[i].ss7.master); 15152 pthread_kill(linksets[i].ss7.master, SIGURG); 15153 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); 15154 pthread_join(linksets[i].ss7.master, NULL); 15155 ast_debug(4, "Joined thread of span %d\n", i); 15156 } 15157 } 15158 #endif /* defined(HAVE_SS7) */ 15159 15160 ast_mutex_lock(&monlock); 15161 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 15162 cancel_code = pthread_cancel(monitor_thread); 15163 pthread_kill(monitor_thread, SIGURG); 15164 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 15165 pthread_join(monitor_thread, NULL); 15166 ast_debug(4, "Joined monitor thread\n"); 15167 } 15168 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 15169 15170 ast_mutex_lock(&ss_thread_lock); 15171 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 15172 int x = DAHDI_FLASH; 15173 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count); 15174 15175 ast_mutex_lock(&iflock); 15176 for (p = iflist; p; p = p->next) { 15177 if (p->owner) { 15178 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 15179 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 15180 } 15181 } 15182 ast_mutex_unlock(&iflock); 15183 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 15184 } 15185 15186 /* ensure any created channels before monitor threads were stopped are hungup */ 15187 dahdi_softhangup_all(); 15188 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 15189 destroy_all_channels(); 15190 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 15191 15192 ast_mutex_unlock(&monlock); 15193 15194 #ifdef HAVE_PRI 15195 for (i = 0; i < NUM_SPANS; i++) { 15196 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) 15197 dahdi_close_pri_fd(&(pris[i]), j); 15198 } 15199 15200 memset(pris, 0, sizeof(pris)); 15201 for (i = 0; i < NUM_SPANS; i++) { 15202 sig_pri_init_pri(&pris[i].pri); 15203 } 15204 pri_set_error(dahdi_pri_error); 15205 pri_set_message(dahdi_pri_message); 15206 #endif 15207 #if defined(HAVE_SS7) 15208 for (i = 0; i < NUM_SPANS; i++) { 15209 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) 15210 dahdi_close_ss7_fd(&(linksets[i]), j); 15211 } 15212 15213 memset(linksets, 0, sizeof(linksets)); 15214 for (i = 0; i < NUM_SPANS; i++) { 15215 sig_ss7_init_linkset(&linksets[i].ss7); 15216 } 15217 ss7_set_error(dahdi_ss7_error); 15218 ss7_set_message(dahdi_ss7_message); 15219 #endif /* defined(HAVE_SS7) */ 15220 15221 if (setup_dahdi(2) != 0) { 15222 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 15223 ast_mutex_unlock(&ss_thread_lock); 15224 return 1; 15225 } 15226 ast_mutex_unlock(&ss_thread_lock); 15227 ast_mutex_unlock(&restart_lock); 15228 return 0; 15229 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15231 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.
15232 { 15233 switch (cmd) { 15234 case CLI_INIT: 15235 e->command = "dahdi restart"; 15236 e->usage = 15237 "Usage: dahdi restart\n" 15238 " Restarts the DAHDI channels: destroys them all and then\n" 15239 " re-reads them from chan_dahdi.conf.\n" 15240 " Note that this will STOP any running CALL on DAHDI channels.\n" 15241 ""; 15242 return NULL; 15243 case CLI_GENERATE: 15244 return NULL; 15245 } 15246 if (a->argc != 2) 15247 return CLI_SHOWUSAGE; 15248 15249 if (dahdi_restart() != 0) 15250 return CLI_FAILURE; 15251 return CLI_SUCCESS; 15252 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7636 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().
07637 { 07638 int x; 07639 int res; 07640 /* Make sure our transmit state is on hook */ 07641 x = 0; 07642 x = DAHDI_ONHOOK; 07643 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07644 do { 07645 x = DAHDI_RING; 07646 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07647 if (res) { 07648 switch (errno) { 07649 case EBUSY: 07650 case EINTR: 07651 /* Wait just in case */ 07652 usleep(10000); 07653 continue; 07654 case EINPROGRESS: 07655 res = 0; 07656 break; 07657 default: 07658 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 07659 res = 0; 07660 } 07661 } 07662 } while (res); 07663 return res; 07664 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 18690 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.
18691 { 18692 #define END_SILENCE_LEN 400 18693 #define HEADER_MS 50 18694 #define TRAILER_MS 5 18695 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 18696 #define ASCII_BYTES_PER_CHAR 80 18697 18698 unsigned char *buf,*mybuf; 18699 struct dahdi_pvt *p = c->tech_pvt; 18700 struct pollfd fds[1]; 18701 int size,res,fd,len,x; 18702 int bytes=0; 18703 /* Initial carrier (imaginary) */ 18704 float cr = 1.0; 18705 float ci = 0.0; 18706 float scont = 0.0; 18707 int idx; 18708 18709 idx = dahdi_get_index(c, p, 0); 18710 if (idx < 0) { 18711 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 18712 return -1; 18713 } 18714 if (!text[0]) return(0); /* if nothing to send, don't */ 18715 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 18716 if (p->mate) 18717 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 18718 else 18719 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 18720 if (!buf) 18721 return -1; 18722 mybuf = buf; 18723 if (p->mate) { 18724 int codec = AST_LAW(p); 18725 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 18726 PUT_CLID_MARKMS; 18727 } 18728 /* Put actual message */ 18729 for (x = 0; text[x]; x++) { 18730 PUT_CLID(text[x]); 18731 } 18732 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 18733 PUT_CLID_MARKMS; 18734 } 18735 len = bytes; 18736 buf = mybuf; 18737 } else { 18738 len = tdd_generate(p->tdd, buf, text); 18739 if (len < 1) { 18740 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 18741 ast_free(mybuf); 18742 return -1; 18743 } 18744 } 18745 memset(buf + len, 0x7f, END_SILENCE_LEN); 18746 len += END_SILENCE_LEN; 18747 fd = p->subs[idx].dfd; 18748 while (len) { 18749 if (ast_check_hangup(c)) { 18750 ast_free(mybuf); 18751 return -1; 18752 } 18753 size = len; 18754 if (size > READ_SIZE) 18755 size = READ_SIZE; 18756 fds[0].fd = fd; 18757 fds[0].events = POLLOUT | POLLPRI; 18758 fds[0].revents = 0; 18759 res = poll(fds, 1, -1); 18760 if (!res) { 18761 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 18762 continue; 18763 } 18764 /* if got exception */ 18765 if (fds[0].revents & POLLPRI) { 18766 ast_free(mybuf); 18767 return -1; 18768 } 18769 if (!(fds[0].revents & POLLOUT)) { 18770 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 18771 continue; 18772 } 18773 res = write(fd, buf, size); 18774 if (res != size) { 18775 if (res == -1) { 18776 ast_free(mybuf); 18777 return -1; 18778 } 18779 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 18780 break; 18781 } 18782 len -= size; 18783 buf += size; 18784 } 18785 ast_free(mybuf); 18786 return(0); 18787 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15848 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.
15849 { 15850 int channel; 15851 int on; 15852 struct dahdi_pvt *dahdi_chan = NULL; 15853 15854 switch (cmd) { 15855 case CLI_INIT: 15856 e->command = "dahdi set dnd"; 15857 e->usage = 15858 "Usage: dahdi set dnd <chan#> <on|off>\n" 15859 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15860 " Changes take effect immediately.\n" 15861 " <chan num> is the channel number\n" 15862 " <on|off> Enable or disable DND mode?\n" 15863 ; 15864 return NULL; 15865 case CLI_GENERATE: 15866 return NULL; 15867 } 15868 15869 if (a->argc != 5) 15870 return CLI_SHOWUSAGE; 15871 15872 if ((channel = atoi(a->argv[3])) <= 0) { 15873 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 15874 return CLI_SHOWUSAGE; 15875 } 15876 15877 if (ast_true(a->argv[4])) 15878 on = 1; 15879 else if (ast_false(a->argv[4])) 15880 on = 0; 15881 else { 15882 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 15883 return CLI_SHOWUSAGE; 15884 } 15885 15886 ast_mutex_lock(&iflock); 15887 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 15888 if (dahdi_chan->channel != channel) 15889 continue; 15890 15891 /* Found the channel. Actually set it */ 15892 dahdi_dnd(dahdi_chan, on); 15893 break; 15894 } 15895 ast_mutex_unlock(&iflock); 15896 15897 if (!dahdi_chan) { 15898 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15899 return CLI_FAILURE; 15900 } 15901 15902 return CLI_SUCCESS; 15903 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 5174 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().
05175 { 05176 int x, res; 05177 05178 x = hs; 05179 res = ioctl(fd, DAHDI_HOOK, &x); 05180 05181 if (res < 0) { 05182 if (errno == EINPROGRESS) 05183 return 0; 05184 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 05185 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 05186 } 05187 05188 return res; 05189 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15708 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.
15709 { 15710 int channel; 15711 int gain; 15712 int tx; 15713 struct dahdi_hwgain hwgain; 15714 struct dahdi_pvt *tmp = NULL; 15715 15716 switch (cmd) { 15717 case CLI_INIT: 15718 e->command = "dahdi set hwgain"; 15719 e->usage = 15720 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 15721 " Sets the hardware gain on a a given channel, overriding the\n" 15722 " value provided at module loadtime, whether the channel is in\n" 15723 " use or not. Changes take effect immediately.\n" 15724 " <rx|tx> which direction do you want to change (relative to our module)\n" 15725 " <chan num> is the channel number relative to the device\n" 15726 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15727 return NULL; 15728 case CLI_GENERATE: 15729 return NULL; 15730 } 15731 15732 if (a->argc != 6) 15733 return CLI_SHOWUSAGE; 15734 15735 if (!strcasecmp("rx", a->argv[3])) 15736 tx = 0; /* rx */ 15737 else if (!strcasecmp("tx", a->argv[3])) 15738 tx = 1; /* tx */ 15739 else 15740 return CLI_SHOWUSAGE; 15741 15742 channel = atoi(a->argv[4]); 15743 gain = atof(a->argv[5])*10.0; 15744 15745 ast_mutex_lock(&iflock); 15746 15747 for (tmp = iflist; tmp; tmp = tmp->next) { 15748 15749 if (tmp->channel != channel) 15750 continue; 15751 15752 if (tmp->subs[SUB_REAL].dfd == -1) 15753 break; 15754 15755 hwgain.newgain = gain; 15756 hwgain.tx = tx; 15757 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15758 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15759 ast_mutex_unlock(&iflock); 15760 return CLI_FAILURE; 15761 } 15762 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15763 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15764 break; 15765 } 15766 15767 ast_mutex_unlock(&iflock); 15768 15769 if (tmp) 15770 return CLI_SUCCESS; 15771 15772 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15773 return CLI_FAILURE; 15774 15775 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15777 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, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::txdrc, and ast_cli_entry::usage.
15778 { 15779 int channel; 15780 float gain; 15781 int tx; 15782 int res; 15783 struct dahdi_pvt *tmp = NULL; 15784 15785 switch (cmd) { 15786 case CLI_INIT: 15787 e->command = "dahdi set swgain"; 15788 e->usage = 15789 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15790 " Sets the software gain on a a given channel, overriding the\n" 15791 " value provided at module loadtime, whether the channel is in\n" 15792 " use or not. Changes take effect immediately.\n" 15793 " <rx|tx> which direction do you want to change (relative to our module)\n" 15794 " <chan num> is the channel number relative to the device\n" 15795 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15796 return NULL; 15797 case CLI_GENERATE: 15798 return NULL; 15799 } 15800 15801 if (a->argc != 6) 15802 return CLI_SHOWUSAGE; 15803 15804 if (!strcasecmp("rx", a->argv[3])) 15805 tx = 0; /* rx */ 15806 else if (!strcasecmp("tx", a->argv[3])) 15807 tx = 1; /* tx */ 15808 else 15809 return CLI_SHOWUSAGE; 15810 15811 channel = atoi(a->argv[4]); 15812 gain = atof(a->argv[5]); 15813 15814 ast_mutex_lock(&iflock); 15815 for (tmp = iflist; tmp; tmp = tmp->next) { 15816 15817 if (tmp->channel != channel) 15818 continue; 15819 15820 if (tmp->subs[SUB_REAL].dfd == -1) 15821 break; 15822 15823 if (tx) 15824 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law); 15825 else 15826 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law); 15827 15828 if (res) { 15829 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15830 ast_mutex_unlock(&iflock); 15831 return CLI_FAILURE; 15832 } 15833 15834 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15835 tx ? "tx" : "rx", gain, channel); 15836 break; 15837 } 15838 ast_mutex_unlock(&iflock); 15839 15840 if (tmp) 15841 return CLI_SUCCESS; 15842 15843 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15844 return CLI_FAILURE; 15845 15846 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 4439 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 6732 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.
06733 { 06734 char *cp; 06735 signed char *scp; 06736 int x; 06737 int idx; 06738 struct dahdi_pvt *p = chan->tech_pvt, *pp; 06739 struct oprmode *oprmode; 06740 06741 06742 /* all supported options require data */ 06743 if (!p || !data || (datalen < 1)) { 06744 errno = EINVAL; 06745 return -1; 06746 } 06747 06748 switch (option) { 06749 case AST_OPTION_TXGAIN: 06750 scp = (signed char *) data; 06751 idx = dahdi_get_index(chan, p, 0); 06752 if (idx < 0) { 06753 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 06754 return -1; 06755 } 06756 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 06757 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law); 06758 case AST_OPTION_RXGAIN: 06759 scp = (signed char *) data; 06760 idx = dahdi_get_index(chan, p, 0); 06761 if (idx < 0) { 06762 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 06763 return -1; 06764 } 06765 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 06766 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law); 06767 case AST_OPTION_TONE_VERIFY: 06768 if (!p->dsp) 06769 break; 06770 cp = (char *) data; 06771 switch (*cp) { 06772 case 1: 06773 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 06774 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 06775 break; 06776 case 2: 06777 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 06778 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 06779 break; 06780 default: 06781 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 06782 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 06783 break; 06784 } 06785 break; 06786 case AST_OPTION_TDD: 06787 /* turn on or off TDD */ 06788 cp = (char *) data; 06789 p->mate = 0; 06790 if (!*cp) { /* turn it off */ 06791 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 06792 if (p->tdd) 06793 tdd_free(p->tdd); 06794 p->tdd = 0; 06795 break; 06796 } 06797 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 06798 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 06799 dahdi_disable_ec(p); 06800 /* otherwise, turn it on */ 06801 if (!p->didtdd) { /* if havent done it yet */ 06802 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 06803 unsigned char *buf; 06804 int size, res, fd, len; 06805 struct pollfd fds[1]; 06806 06807 buf = mybuf; 06808 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 06809 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 06810 len = 40000; 06811 idx = dahdi_get_index(chan, p, 0); 06812 if (idx < 0) { 06813 ast_log(LOG_WARNING, "No index in TDD?\n"); 06814 return -1; 06815 } 06816 fd = p->subs[idx].dfd; 06817 while (len) { 06818 if (ast_check_hangup(chan)) 06819 return -1; 06820 size = len; 06821 if (size > READ_SIZE) 06822 size = READ_SIZE; 06823 fds[0].fd = fd; 06824 fds[0].events = POLLPRI | POLLOUT; 06825 fds[0].revents = 0; 06826 res = poll(fds, 1, -1); 06827 if (!res) { 06828 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 06829 continue; 06830 } 06831 /* if got exception */ 06832 if (fds[0].revents & POLLPRI) 06833 return -1; 06834 if (!(fds[0].revents & POLLOUT)) { 06835 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 06836 continue; 06837 } 06838 res = write(fd, buf, size); 06839 if (res != size) { 06840 if (res == -1) return -1; 06841 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06842 break; 06843 } 06844 len -= size; 06845 buf += size; 06846 } 06847 p->didtdd = 1; /* set to have done it now */ 06848 } 06849 if (*cp == 2) { /* Mate mode */ 06850 if (p->tdd) 06851 tdd_free(p->tdd); 06852 p->tdd = 0; 06853 p->mate = 1; 06854 break; 06855 } 06856 if (!p->tdd) { /* if we don't have one yet */ 06857 p->tdd = tdd_new(); /* allocate one */ 06858 } 06859 break; 06860 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 06861 if (!p->dsp) 06862 break; 06863 cp = (char *) data; 06864 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 06865 *cp ? "ON" : "OFF", (int) *cp, chan->name); 06866 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 06867 break; 06868 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 06869 #if defined(HAVE_PRI) 06870 if (dahdi_sig_pri_lib_handles(p->sig) 06871 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 06872 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 06873 break; 06874 } 06875 #endif /* defined(HAVE_PRI) */ 06876 06877 cp = (char *) data; 06878 if (!*cp) { 06879 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 06880 x = 0; 06881 dahdi_disable_ec(p); 06882 } else { 06883 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 06884 x = 1; 06885 } 06886 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 06887 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 06888 break; 06889 case AST_OPTION_OPRMODE: /* Operator services mode */ 06890 oprmode = (struct oprmode *) data; 06891 /* We don't support operator mode across technologies */ 06892 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 06893 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 06894 chan->tech->type, oprmode->peer->tech->type); 06895 errno = EINVAL; 06896 return -1; 06897 } 06898 pp = oprmode->peer->tech_pvt; 06899 p->oprmode = pp->oprmode = 0; 06900 /* setup peers */ 06901 p->oprpeer = pp; 06902 pp->oprpeer = p; 06903 /* setup modes, if any */ 06904 if (oprmode->mode) 06905 { 06906 pp->oprmode = oprmode->mode; 06907 p->oprmode = -oprmode->mode; 06908 } 06909 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 06910 oprmode->mode, chan->name,oprmode->peer->name); 06911 break; 06912 case AST_OPTION_ECHOCAN: 06913 cp = (char *) data; 06914 if (*cp) { 06915 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name); 06916 dahdi_enable_ec(p); 06917 } else { 06918 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name); 06919 dahdi_disable_ec(p); 06920 } 06921 break; 06922 case AST_OPTION_DIGIT_DETECT: 06923 cp = (char *) data; 06924 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); 06925 if (*cp) { 06926 enable_dtmf_detect(p); 06927 } else { 06928 disable_dtmf_detect(p); 06929 } 06930 break; 06931 case AST_OPTION_FAX_DETECT: 06932 cp = (char *) data; 06933 if (p->dsp) { 06934 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name); 06935 if (*cp) { 06936 p->dsp_features |= DSP_FEATURE_FAX_DETECT; 06937 } else { 06938 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06939 } 06940 ast_dsp_set_features(p->dsp, p->dsp_features); 06941 } 06942 break; 06943 default: 06944 return -1; 06945 } 06946 errno = 0; 06947 06948 return 0; 06949 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15351 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.
15352 { 15353 int channel; 15354 struct dahdi_pvt *tmp = NULL; 15355 struct dahdi_confinfo ci; 15356 struct dahdi_params ps; 15357 int x; 15358 15359 switch (cmd) { 15360 case CLI_INIT: 15361 e->command = "dahdi show channel"; 15362 e->usage = 15363 "Usage: dahdi show channel <chan num>\n" 15364 " Detailed information about a given channel\n"; 15365 return NULL; 15366 case CLI_GENERATE: 15367 return NULL; 15368 } 15369 15370 if (a->argc != 4) 15371 return CLI_SHOWUSAGE; 15372 15373 channel = atoi(a->argv[3]); 15374 15375 ast_mutex_lock(&iflock); 15376 for (tmp = iflist; tmp; tmp = tmp->next) { 15377 if (tmp->channel == channel) { 15378 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 15379 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 15380 ast_cli(a->fd, "Span: %d\n", tmp->span); 15381 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 15382 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 15383 ast_cli(a->fd, "Context: %s\n", tmp->context); 15384 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 15385 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 15386 #if defined(HAVE_PRI) 15387 #if defined(HAVE_PRI_SUBADDR) 15388 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr); 15389 #endif /* defined(HAVE_PRI_SUBADDR) */ 15390 #endif /* defined(HAVE_PRI) */ 15391 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 15392 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 15393 if (tmp->vars) { 15394 struct ast_variable *v; 15395 ast_cli(a->fd, "Variables:\n"); 15396 for (v = tmp->vars ; v ; v = v->next) 15397 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 15398 } 15399 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 15400 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 15401 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 15402 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 15403 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 15404 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)" : ""); 15405 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)" : ""); 15406 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)" : ""); 15407 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 15408 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 15409 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 15410 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 15411 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 15412 if (tmp->busydetect) { 15413 #if defined(BUSYDETECT_TONEONLY) 15414 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 15415 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 15416 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 15417 #endif 15418 #ifdef BUSYDETECT_DEBUG 15419 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 15420 #endif 15421 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 15422 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 15423 } 15424 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 15425 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 15426 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 15427 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 15428 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 15429 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 15430 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain); 15431 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc); 15432 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no"); 15433 ast_cli(a->fd, "Echo Cancellation:\n"); 15434 15435 if (tmp->echocancel.head.tap_length) { 15436 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 15437 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 15438 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 15439 } 15440 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 15441 } else { 15442 ast_cli(a->fd, "\tnone\n"); 15443 } 15444 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 15445 if (tmp->master) 15446 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 15447 for (x = 0; x < MAX_SLAVES; x++) { 15448 if (tmp->slaves[x]) 15449 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 15450 } 15451 #ifdef HAVE_OPENR2 15452 if (tmp->mfcr2) { 15453 char calldir[OR2_MAX_PATH]; 15454 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 15455 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 15456 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 15457 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 15458 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 15459 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 15460 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 15461 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 15462 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 15463 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 15464 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 15465 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 15466 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 15467 #endif 15468 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 15469 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 15470 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 15471 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 15472 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 15473 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 15474 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 15475 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 15476 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 15477 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 15478 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 15479 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 15480 } 15481 #endif 15482 #if defined(HAVE_SS7) 15483 if (tmp->ss7) { 15484 struct sig_ss7_chan *chan = tmp->sig_pvt; 15485 15486 ast_cli(a->fd, "CIC: %d\n", chan->cic); 15487 } 15488 #endif /* defined(HAVE_SS7) */ 15489 #ifdef HAVE_PRI 15490 if (tmp->pri) { 15491 struct sig_pri_chan *chan = tmp->sig_pvt; 15492 15493 ast_cli(a->fd, "PRI Flags: "); 15494 if (chan->resetting != SIG_PRI_RESET_IDLE) { 15495 ast_cli(a->fd, "Resetting=%d ", chan->resetting); 15496 } 15497 if (chan->call) 15498 ast_cli(a->fd, "Call "); 15499 if (chan->allocated) { 15500 ast_cli(a->fd, "Allocated "); 15501 } 15502 ast_cli(a->fd, "\n"); 15503 if (tmp->logicalspan) 15504 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 15505 else 15506 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 15507 } 15508 #endif 15509 memset(&ci, 0, sizeof(ci)); 15510 ps.channo = tmp->channel; 15511 if (tmp->subs[SUB_REAL].dfd > -1) { 15512 memset(&ci, 0, sizeof(ci)); 15513 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 15514 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 15515 } 15516 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 15517 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 15518 } 15519 memset(&ps, 0, sizeof(ps)); 15520 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 15521 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 15522 } else { 15523 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 15524 } 15525 } 15526 if (ISTRUNK(tmp)) { 15527 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 15528 if (!ast_strlen_zero(progzone)) 15529 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 15530 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 15531 if(tmp->busydetect) { 15532 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 15533 if(tmp->busytonelength > 0) { 15534 ast_cli(a->fd, "Busy Pattern:\n"); 15535 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 15536 if (tmp->busyquietlength > 0) 15537 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 15538 else 15539 ast_cli(a->fd, " -- Detect Tone Only\n"); 15540 if(tmp->busyfuzziness > 0) 15541 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 15542 } 15543 } 15544 } 15545 ast_mutex_unlock(&iflock); 15546 return CLI_SUCCESS; 15547 } 15548 } 15549 ast_mutex_unlock(&iflock); 15550 15551 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15552 return CLI_FAILURE; 15553 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15264 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.
15265 { 15266 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15267 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15268 ast_group_t targetnum = 0; 15269 int filtertype = 0; 15270 struct dahdi_pvt *tmp = NULL; 15271 char tmps[20] = ""; 15272 char statestr[20] = ""; 15273 char blockstr[20] = ""; 15274 15275 switch (cmd) { 15276 case CLI_INIT: 15277 e->command = "dahdi show channels [group|context]"; 15278 e->usage = 15279 "Usage: dahdi show channels [ group <group> | context <context> ]\n" 15280 " Shows a list of available channels with optional filtering\n" 15281 " <group> must be a number between 0 and 63\n"; 15282 return NULL; 15283 case CLI_GENERATE: 15284 return NULL; 15285 } 15286 15287 /* syntax: dahdi show channels [ group <group> | context <context> ] */ 15288 15289 if (!((a->argc == 3) || (a->argc == 5))) 15290 return CLI_SHOWUSAGE; 15291 15292 if (a->argc == 5) { 15293 if (!strcasecmp(a->argv[3], "group")) { 15294 targetnum = atoi(a->argv[4]); 15295 if (63 < targetnum) { 15296 return CLI_SHOWUSAGE; 15297 } 15298 targetnum = ((ast_group_t) 1) << targetnum; 15299 filtertype = 1; 15300 } else if (!strcasecmp(a->argv[3], "context")) { 15301 filtertype = 2; 15302 } 15303 } 15304 15305 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 15306 ast_mutex_lock(&iflock); 15307 for (tmp = iflist; tmp; tmp = tmp->next) { 15308 if (filtertype) { 15309 switch(filtertype) { 15310 case 1: /* dahdi show channels group <group> */ 15311 if (!(tmp->group & targetnum)) { 15312 continue; 15313 } 15314 break; 15315 case 2: /* dahdi show channels context <context> */ 15316 if (strcasecmp(tmp->context, a->argv[4])) { 15317 continue; 15318 } 15319 break; 15320 default: 15321 break; 15322 } 15323 } 15324 if (tmp->channel > 0) { 15325 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 15326 } else 15327 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 15328 15329 if (tmp->locallyblocked) 15330 blockstr[0] = 'L'; 15331 else 15332 blockstr[0] = ' '; 15333 15334 if (tmp->remotelyblocked) 15335 blockstr[1] = 'R'; 15336 else 15337 blockstr[1] = ' '; 15338 15339 blockstr[2] = '\0'; 15340 15341 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 15342 15343 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 15344 } 15345 ast_mutex_unlock(&iflock); 15346 return CLI_SUCCESS; 15347 #undef FORMAT 15348 #undef FORMAT2 15349 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15592 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.
15593 { 15594 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 15595 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 15596 int span; 15597 int res; 15598 char alarmstr[50]; 15599 15600 int ctl; 15601 struct dahdi_spaninfo s; 15602 15603 switch (cmd) { 15604 case CLI_INIT: 15605 e->command = "dahdi show status"; 15606 e->usage = 15607 "Usage: dahdi show status\n" 15608 " Shows a list of DAHDI cards with status\n"; 15609 return NULL; 15610 case CLI_GENERATE: 15611 return NULL; 15612 } 15613 ctl = open("/dev/dahdi/ctl", O_RDWR); 15614 if (ctl < 0) { 15615 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 15616 return CLI_FAILURE; 15617 } 15618 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO"); 15619 15620 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 15621 s.spanno = span; 15622 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 15623 if (res) { 15624 continue; 15625 } 15626 alarmstr[0] = '\0'; 15627 if (s.alarms > 0) { 15628 if (s.alarms & DAHDI_ALARM_BLUE) 15629 strcat(alarmstr, "BLU/"); 15630 if (s.alarms & DAHDI_ALARM_YELLOW) 15631 strcat(alarmstr, "YEL/"); 15632 if (s.alarms & DAHDI_ALARM_RED) 15633 strcat(alarmstr, "RED/"); 15634 if (s.alarms & DAHDI_ALARM_LOOPBACK) 15635 strcat(alarmstr, "LB/"); 15636 if (s.alarms & DAHDI_ALARM_RECOVER) 15637 strcat(alarmstr, "REC/"); 15638 if (s.alarms & DAHDI_ALARM_NOTOPEN) 15639 strcat(alarmstr, "NOP/"); 15640 if (!strlen(alarmstr)) 15641 strcat(alarmstr, "UUU/"); 15642 if (strlen(alarmstr)) { 15643 /* Strip trailing / */ 15644 alarmstr[strlen(alarmstr) - 1] = '\0'; 15645 } 15646 } else { 15647 if (s.numchans) 15648 strcpy(alarmstr, "OK"); 15649 else 15650 strcpy(alarmstr, "UNCONFIGURED"); 15651 } 15652 15653 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 15654 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 15655 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 15656 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 15657 "CAS", 15658 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 15659 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 15660 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 15661 "Unk", 15662 s.lineconfig & DAHDI_CONFIG_CRC4 ? 15663 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 15664 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "", 15665 lbostr[s.lbo] 15666 ); 15667 } 15668 close(ctl); 15669 15670 return CLI_SUCCESS; 15671 #undef FORMAT 15672 #undef FORMAT2 15673 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15675 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.
15676 { 15677 int pseudo_fd = -1; 15678 struct dahdi_versioninfo vi; 15679 15680 switch (cmd) { 15681 case CLI_INIT: 15682 e->command = "dahdi show version"; 15683 e->usage = 15684 "Usage: dahdi show version\n" 15685 " Shows the DAHDI version in use\n"; 15686 return NULL; 15687 case CLI_GENERATE: 15688 return NULL; 15689 } 15690 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 15691 ast_cli(a->fd, "Failed to open control file to get version.\n"); 15692 return CLI_SUCCESS; 15693 } 15694 15695 strcpy(vi.version, "Unknown"); 15696 strcpy(vi.echo_canceller, "Unknown"); 15697 15698 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 15699 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 15700 else 15701 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 15702 15703 close(pseudo_fd); 15704 15705 return CLI_SUCCESS; 15706 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 4663 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().
04664 { 04665 static char buf[256]; 04666 switch (sig) { 04667 case SIG_EM: 04668 return "E & M Immediate"; 04669 case SIG_EMWINK: 04670 return "E & M Wink"; 04671 case SIG_EM_E1: 04672 return "E & M E1"; 04673 case SIG_FEATD: 04674 return "Feature Group D (DTMF)"; 04675 case SIG_FEATDMF: 04676 return "Feature Group D (MF)"; 04677 case SIG_FEATDMF_TA: 04678 return "Feature Groud D (MF) Tandem Access"; 04679 case SIG_FEATB: 04680 return "Feature Group B (MF)"; 04681 case SIG_E911: 04682 return "E911 (MF)"; 04683 case SIG_FGC_CAMA: 04684 return "FGC/CAMA (Dialpulse)"; 04685 case SIG_FGC_CAMAMF: 04686 return "FGC/CAMA (MF)"; 04687 case SIG_FXSLS: 04688 return "FXS Loopstart"; 04689 case SIG_FXSGS: 04690 return "FXS Groundstart"; 04691 case SIG_FXSKS: 04692 return "FXS Kewlstart"; 04693 case SIG_FXOLS: 04694 return "FXO Loopstart"; 04695 case SIG_FXOGS: 04696 return "FXO Groundstart"; 04697 case SIG_FXOKS: 04698 return "FXO Kewlstart"; 04699 case SIG_PRI: 04700 return "ISDN PRI"; 04701 case SIG_BRI: 04702 return "ISDN BRI Point to Point"; 04703 case SIG_BRI_PTMP: 04704 return "ISDN BRI Point to MultiPoint"; 04705 case SIG_SS7: 04706 return "SS7"; 04707 case SIG_MFCR2: 04708 return "MFC/R2"; 04709 case SIG_SF: 04710 return "SF (Tone) Immediate"; 04711 case SIG_SFWINK: 04712 return "SF (Tone) Wink"; 04713 case SIG_SF_FEATD: 04714 return "SF (Tone) with Feature Group D (DTMF)"; 04715 case SIG_SF_FEATDMF: 04716 return "SF (Tone) with Feature Group D (MF)"; 04717 case SIG_SF_FEATB: 04718 return "SF (Tone) with Feature Group B (MF)"; 04719 case 0: 04720 return "Pseudo"; 04721 default: 04722 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 04723 return buf; 04724 } 04725 }
static int dahdi_sig_pri_lib_handles | ( | int | signaling | ) | [inline, static] |
Definition at line 1559 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().
01560 { 01561 int handles; 01562 01563 switch (signaling) { 01564 case SIG_PRI_LIB_HANDLE_CASES: 01565 handles = 1; 01566 break; 01567 default: 01568 handles = 0; 01569 break; 01570 } 01571 01572 return handles; 01573 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 15091 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().
15092 { 15093 struct dahdi_pvt *p; 15094 retry: 15095 ast_mutex_lock(&iflock); 15096 for (p = iflist; p; p = p->next) { 15097 ast_mutex_lock(&p->lock); 15098 if (p->owner && !p->restartpending) { 15099 if (ast_channel_trylock(p->owner)) { 15100 if (option_debug > 2) 15101 ast_verbose("Avoiding deadlock\n"); 15102 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 15103 ast_mutex_unlock(&p->lock); 15104 ast_mutex_unlock(&iflock); 15105 goto retry; 15106 } 15107 if (option_debug > 2) 15108 ast_verbose("Softhanging up on %s\n", p->owner->name); 15109 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 15110 p->restartpending = 1; 15111 num_restart_pending++; 15112 ast_channel_unlock(p->owner); 15113 } 15114 ast_mutex_unlock(&p->lock); 15115 } 15116 ast_mutex_unlock(&iflock); 15117 }
static int dahdi_status_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18459 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.
18461 { 18462 int ctl, res, span; 18463 struct ast_data *data_span, *data_alarms; 18464 struct dahdi_spaninfo s; 18465 18466 ctl = open("/dev/dahdi/ctl", O_RDWR); 18467 if (ctl < 0) { 18468 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 18469 return -1; 18470 } 18471 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 18472 s.spanno = span; 18473 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 18474 if (res) { 18475 continue; 18476 } 18477 18478 data_span = ast_data_add_node(data_root, "span"); 18479 if (!data_span) { 18480 continue; 18481 } 18482 ast_data_add_str(data_span, "description", s.desc); 18483 18484 /* insert the alarms status */ 18485 data_alarms = ast_data_add_node(data_span, "alarms"); 18486 if (!data_alarms) { 18487 continue; 18488 } 18489 18490 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE); 18491 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW); 18492 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED); 18493 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK); 18494 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER); 18495 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN); 18496 18497 ast_data_add_int(data_span, "irqmisses", s.irqmisses); 18498 ast_data_add_int(data_span, "bpviol", s.bpvcount); 18499 ast_data_add_int(data_span, "crc4", s.crc4count); 18500 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 18501 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 18502 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 18503 "CAS"); 18504 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 18505 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 18506 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 18507 "Unknown"); 18508 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ? 18509 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 18510 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : ""); 18511 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]); 18512 18513 /* if this span doesn't match remove it. */ 18514 if (!ast_data_search_match(search, data_span)) { 18515 ast_data_remove_node(data_root, data_span); 18516 } 18517 } 18518 close(ctl); 18519 18520 return 0; 18521 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4966 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().
04967 { 04968 int x; 04969 int res; 04970 04971 if (p && p->echocanon && p->echotraining) { 04972 x = p->echotraining; 04973 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 04974 if (res) 04975 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 04976 else 04977 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 04978 } else { 04979 ast_debug(1, "No echo training requested\n"); 04980 } 04981 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 7164 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().
07165 { 07166 /* Unlink a specific slave or all slaves/masters from a given master */ 07167 int x; 07168 int hasslaves; 07169 if (!master) 07170 return; 07171 if (needlock) { 07172 ast_mutex_lock(&master->lock); 07173 if (slave) { 07174 while (ast_mutex_trylock(&slave->lock)) { 07175 DEADLOCK_AVOIDANCE(&master->lock); 07176 } 07177 } 07178 } 07179 hasslaves = 0; 07180 for (x = 0; x < MAX_SLAVES; x++) { 07181 if (master->slaves[x]) { 07182 if (!slave || (master->slaves[x] == slave)) { 07183 /* Take slave out of the conference */ 07184 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 07185 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 07186 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 07187 master->slaves[x]->master = NULL; 07188 master->slaves[x] = NULL; 07189 } else 07190 hasslaves = 1; 07191 } 07192 if (!hasslaves) 07193 master->inconference = 0; 07194 } 07195 if (!slave) { 07196 if (master->master) { 07197 /* Take master out of the conference */ 07198 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 07199 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 07200 hasslaves = 0; 07201 for (x = 0; x < MAX_SLAVES; x++) { 07202 if (master->master->slaves[x] == master) 07203 master->master->slaves[x] = NULL; 07204 else if (master->master->slaves[x]) 07205 hasslaves = 1; 07206 } 07207 if (!hasslaves) 07208 master->master->inconference = 0; 07209 } 07210 master->master = NULL; 07211 } 07212 update_conf(master); 07213 if (needlock) { 07214 if (slave) 07215 ast_mutex_unlock(&slave->lock); 07216 ast_mutex_unlock(&master->lock); 07217 } 07218 }
static int dahdi_version_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18562 of file chan_dahdi.c.
References ast_data_add_str(), ast_log(), errno, and LOG_ERROR.
18564 { 18565 int pseudo_fd = -1; 18566 struct dahdi_versioninfo vi = { 18567 .version = "Unknown", 18568 .echo_canceller = "Unknown" 18569 }; 18570 18571 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 18572 ast_log(LOG_ERROR, "Failed to open control file to get version.\n"); 18573 return -1; 18574 } 18575 18576 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) { 18577 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno)); 18578 } 18579 18580 close(pseudo_fd); 18581 18582 ast_data_add_str(data_root, "value", vi.version); 18583 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller); 18584 18585 return 0; 18586 }
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 9876 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), and my_wink().
09877 { 09878 int j; 09879 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 09880 for (;;) 09881 { 09882 /* set bits of interest */ 09883 j = DAHDI_IOMUX_SIGEVENT; 09884 /* wait for some happening */ 09885 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 09886 /* exit loop if we have it */ 09887 if (j & DAHDI_IOMUX_SIGEVENT) break; 09888 } 09889 /* get the event info */ 09890 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 09891 return 0; 09892 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 9397 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.
09398 { 09399 struct dahdi_pvt *p = ast->tech_pvt; 09400 int res; 09401 int idx; 09402 idx = dahdi_get_index(ast, p, 0); 09403 if (idx < 0) { 09404 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 09405 return -1; 09406 } 09407 09408 /* Write a frame of (presumably voice) data */ 09409 if (frame->frametype != AST_FRAME_VOICE) { 09410 if (frame->frametype != AST_FRAME_IMAGE) 09411 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 09412 return 0; 09413 } 09414 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && 09415 (frame->subclass.codec != AST_FORMAT_ULAW) && 09416 (frame->subclass.codec != AST_FORMAT_ALAW)) { 09417 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 09418 return -1; 09419 } 09420 if (p->dialing) { 09421 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 09422 return 0; 09423 } 09424 if (!p->owner) { 09425 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 09426 return 0; 09427 } 09428 if (p->cidspill) { 09429 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n", 09430 ast->name); 09431 return 0; 09432 } 09433 /* Return if it's not valid data */ 09434 if (!frame->data.ptr || !frame->datalen) 09435 return 0; 09436 09437 if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 09438 if (!p->subs[idx].linear) { 09439 p->subs[idx].linear = 1; 09440 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09441 if (res) 09442 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 09443 } 09444 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 09445 } else { 09446 /* x-law already */ 09447 if (p->subs[idx].linear) { 09448 p->subs[idx].linear = 0; 09449 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09450 if (res) 09451 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 09452 } 09453 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 09454 } 09455 if (res < 0) { 09456 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 09457 return -1; 09458 } 09459 return 0; 09460 }
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 1616 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().
01617 { 01618 switch (sig) { 01619 case SIG_FXOLS: 01620 return ANALOG_SIG_FXOLS; 01621 case SIG_FXOGS: 01622 return ANALOG_SIG_FXOGS; 01623 case SIG_FXOKS: 01624 return ANALOG_SIG_FXOKS; 01625 case SIG_FXSLS: 01626 return ANALOG_SIG_FXSLS; 01627 case SIG_FXSGS: 01628 return ANALOG_SIG_FXSGS; 01629 case SIG_FXSKS: 01630 return ANALOG_SIG_FXSKS; 01631 case SIG_EMWINK: 01632 return ANALOG_SIG_EMWINK; 01633 case SIG_EM: 01634 return ANALOG_SIG_EM; 01635 case SIG_EM_E1: 01636 return ANALOG_SIG_EM_E1; 01637 case SIG_FEATD: 01638 return ANALOG_SIG_FEATD; 01639 case SIG_FEATDMF: 01640 return ANALOG_SIG_FEATDMF; 01641 case SIG_E911: 01642 return SIG_E911; 01643 case SIG_FGC_CAMA: 01644 return ANALOG_SIG_FGC_CAMA; 01645 case SIG_FGC_CAMAMF: 01646 return ANALOG_SIG_FGC_CAMAMF; 01647 case SIG_FEATB: 01648 return ANALOG_SIG_FEATB; 01649 case SIG_SFWINK: 01650 return ANALOG_SIG_SFWINK; 01651 case SIG_SF: 01652 return ANALOG_SIG_SF; 01653 case SIG_SF_FEATD: 01654 return ANALOG_SIG_SF_FEATD; 01655 case SIG_SF_FEATDMF: 01656 return ANALOG_SIG_SF_FEATDMF; 01657 case SIG_FEATDMF_TA: 01658 return ANALOG_SIG_FEATDMF_TA; 01659 case SIG_SF_FEATB: 01660 return ANALOG_SIG_FEATB; 01661 default: 01662 return -1; 01663 } 01664 }
static void deep_copy_dahdi_chan_conf | ( | struct dahdi_chan_conf * | dest, | |
const struct dahdi_chan_conf * | src | |||
) | [static] |
Definition at line 18124 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().
18125 { 18126 struct ast_cc_config_params *cc_params; 18127 18128 cc_params = dest->chan.cc_params; 18129 *dest = *src; 18130 dest->chan.cc_params = cc_params; 18131 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params); 18132 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 5849 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().
05850 { 05851 int chan; 05852 #if defined(HAVE_PRI) 05853 unsigned span; 05854 struct sig_pri_span *pri; 05855 #endif /* defined(HAVE_PRI) */ 05856 struct dahdi_pvt *p; 05857 05858 while (num_restart_pending) { 05859 usleep(1); 05860 } 05861 05862 ast_mutex_lock(&iflock); 05863 /* Destroy all the interfaces and free their memory */ 05864 while (iflist) { 05865 p = iflist; 05866 05867 chan = p->channel; 05868 #if defined(HAVE_PRI_SERVICE_MESSAGES) 05869 { 05870 char db_chan_name[20]; 05871 char db_answer[5]; 05872 char state; 05873 int why = -1; 05874 05875 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan); 05876 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 05877 sscanf(db_answer, "%1c:%30d", &state, &why); 05878 } 05879 if (!why) { 05880 /* SRVST persistence is not required */ 05881 ast_db_del(db_chan_name, SRVST_DBKEY); 05882 } 05883 } 05884 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 05885 /* Free associated memory */ 05886 destroy_dahdi_pvt(p); 05887 ast_verb(3, "Unregistered channel %d\n", chan); 05888 } 05889 ifcount = 0; 05890 ast_mutex_unlock(&iflock); 05891 05892 #if defined(HAVE_PRI) 05893 /* Destroy all of the no B channel interface lists */ 05894 for (span = 0; span < NUM_SPANS; ++span) { 05895 if (!pris[span].dchannels[0]) { 05896 break; 05897 } 05898 pri = &pris[span].pri; 05899 ast_mutex_lock(&pri->lock); 05900 while (pri->no_b_chan_iflist) { 05901 p = pri->no_b_chan_iflist; 05902 05903 /* Free associated memory */ 05904 destroy_dahdi_pvt(p); 05905 } 05906 ast_mutex_unlock(&pri->lock); 05907 } 05908 #endif /* defined(HAVE_PRI) */ 05909 }
static void destroy_channel | ( | struct dahdi_pvt * | cur, | |
int | now | |||
) | [static] |
Definition at line 5831 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().
05832 { 05833 int i; 05834 05835 if (!now) { 05836 /* Do not destroy the channel now if it is owned by someone. */ 05837 if (cur->owner) { 05838 return; 05839 } 05840 for (i = 0; i < 3; i++) { 05841 if (cur->subs[i].owner) { 05842 return; 05843 } 05844 } 05845 } 05846 destroy_dahdi_pvt(cur); 05847 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5761 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().
05762 { 05763 struct dahdi_pvt *p = pvt; 05764 05765 if (p->manages_span_alarms) { 05766 struct dahdi_pvt *next = find_next_iface_in_span(p); 05767 if (next) { 05768 next->manages_span_alarms = 1; 05769 } 05770 } 05771 05772 /* Remove channel from the list */ 05773 #if defined(HAVE_PRI) 05774 dahdi_unlink_pri_pvt(p); 05775 #endif /* defined(HAVE_PRI) */ 05776 #if defined(HAVE_SS7) 05777 dahdi_unlink_ss7_pvt(p); 05778 #endif /* defined(HAVE_SS7) */ 05779 switch (pvt->which_iflist) { 05780 case DAHDI_IFLIST_NONE: 05781 break; 05782 case DAHDI_IFLIST_MAIN: 05783 dahdi_iflist_extract(p); 05784 break; 05785 #if defined(HAVE_PRI) 05786 case DAHDI_IFLIST_NO_B_CHAN: 05787 if (p->pri) { 05788 dahdi_nobch_extract(p->pri, p); 05789 } 05790 break; 05791 #endif /* defined(HAVE_PRI) */ 05792 } 05793 05794 if (p->sig_pvt) { 05795 if (analog_lib_handles(p->sig, 0, 0)) { 05796 analog_delete(p->sig_pvt); 05797 } 05798 switch (p->sig) { 05799 #if defined(HAVE_PRI) 05800 case SIG_PRI_LIB_HANDLE_CASES: 05801 sig_pri_chan_delete(p->sig_pvt); 05802 break; 05803 #endif /* defined(HAVE_PRI) */ 05804 #if defined(HAVE_SS7) 05805 case SIG_SS7: 05806 sig_ss7_chan_delete(p->sig_pvt); 05807 break; 05808 #endif /* defined(HAVE_SS7) */ 05809 default: 05810 break; 05811 } 05812 } 05813 ast_free(p->cidspill); 05814 if (p->use_smdi) 05815 ast_smdi_interface_unref(p->smdi_iface); 05816 if (p->mwi_event_sub) 05817 ast_event_unsubscribe(p->mwi_event_sub); 05818 if (p->vars) { 05819 ast_variables_destroy(p->vars); 05820 } 05821 if (p->cc_params) { 05822 ast_cc_config_params_destroy(p->cc_params); 05823 } 05824 ast_mutex_destroy(&p->lock); 05825 dahdi_close_sub(p, SUB_REAL); 05826 if (p->owner) 05827 p->owner->tech_pvt = NULL; 05828 ast_free(p); 05829 }
static struct dahdi_pvt* determine_starting_point | ( | const char * | data, | |
struct dahdi_starting_point * | param | |||
) | [static, read] |
Definition at line 13528 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().
13529 { 13530 char *dest; 13531 char *s; 13532 int x; 13533 int res = 0; 13534 struct dahdi_pvt *p; 13535 char *subdir = NULL; 13536 AST_DECLARE_APP_ARGS(args, 13537 AST_APP_ARG(group); /* channel/group token */ 13538 //AST_APP_ARG(ext); /* extension token */ 13539 //AST_APP_ARG(opts); /* options token */ 13540 AST_APP_ARG(other); /* Any remining unused arguments */ 13541 ); 13542 13543 /* 13544 * data is ---v 13545 * Dial(DAHDI/pseudo[/extension[/options]]) 13546 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]]) 13547 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]]) 13548 * Dial(DAHDI/i<span>[/extension[/options]]) 13549 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]) 13550 * 13551 * i - ISDN span channel restriction. 13552 * Used by CC to ensure that the CC recall goes out the same span. 13553 * Also to make ISDN channel names dialable when the sequence number 13554 * is stripped off. (Used by DTMF attended transfer feature.) 13555 * 13556 * g - channel group allocation search forward 13557 * G - channel group allocation search backward 13558 * r - channel group allocation round robin search forward 13559 * R - channel group allocation round robin search backward 13560 * 13561 * c - Wait for DTMF digit to confirm answer 13562 * r<cadance#> - Set distintive ring cadance number 13563 * d - Force bearer capability for ISDN/SS7 call to digital. 13564 */ 13565 13566 if (data) { 13567 dest = ast_strdupa(data); 13568 } else { 13569 ast_log(LOG_WARNING, "Channel requested with no data\n"); 13570 return NULL; 13571 } 13572 AST_NONSTANDARD_APP_ARGS(args, dest, '/'); 13573 if (!args.argc || ast_strlen_zero(args.group)) { 13574 ast_log(LOG_WARNING, "No channel/group specified\n"); 13575 return NULL; 13576 } 13577 13578 /* Initialize the output parameters */ 13579 memset(param, 0, sizeof(*param)); 13580 param->channelmatch = -1; 13581 13582 if (strchr(args.group, '!') != NULL) { 13583 char *prev = args.group; 13584 while ((s = strchr(prev, '!')) != NULL) { 13585 *s++ = '/'; 13586 prev = s; 13587 } 13588 *(prev - 1) = '\0'; 13589 subdir = args.group; 13590 args.group = prev; 13591 } else if (args.group[0] == 'i') { 13592 /* Extract the ISDN span channel restriction specifier. */ 13593 res = sscanf(args.group + 1, "%30d", &x); 13594 if (res < 1) { 13595 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data); 13596 return NULL; 13597 } 13598 param->span = x; 13599 13600 /* Remove the ISDN span channel restriction specifier. */ 13601 s = strchr(args.group, '-'); 13602 if (!s) { 13603 /* Search all groups since we are ISDN span restricted. */ 13604 return iflist; 13605 } 13606 args.group = s + 1; 13607 res = 0; 13608 } 13609 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { 13610 /* Retrieve the group number */ 13611 s = args.group + 1; 13612 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13613 if (res < 1) { 13614 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data); 13615 return NULL; 13616 } 13617 param->groupmatch = ((ast_group_t) 1 << x); 13618 13619 if (toupper(args.group[0]) == 'G') { 13620 if (args.group[0] == 'G') { 13621 param->backwards = 1; 13622 p = ifend; 13623 } else 13624 p = iflist; 13625 } else { 13626 if (ARRAY_LEN(round_robin) <= x) { 13627 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n", 13628 x, data); 13629 return NULL; 13630 } 13631 if (args.group[0] == 'R') { 13632 param->backwards = 1; 13633 p = round_robin[x] ? round_robin[x]->prev : ifend; 13634 if (!p) 13635 p = ifend; 13636 } else { 13637 p = round_robin[x] ? round_robin[x]->next : iflist; 13638 if (!p) 13639 p = iflist; 13640 } 13641 param->roundrobin = 1; 13642 param->rr_starting_point = x; 13643 } 13644 } else { 13645 s = args.group; 13646 if (!strcasecmp(s, "pseudo")) { 13647 /* Special case for pseudo */ 13648 x = CHAN_PSEUDO; 13649 param->channelmatch = x; 13650 } else { 13651 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13652 if (res < 1) { 13653 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data); 13654 return NULL; 13655 } else { 13656 param->channelmatch = x; 13657 } 13658 } 13659 if (subdir) { 13660 char path[PATH_MAX]; 13661 struct stat stbuf; 13662 13663 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d", 13664 subdir, param->channelmatch); 13665 if (stat(path, &stbuf) < 0) { 13666 ast_log(LOG_WARNING, "stat(%s) failed: %s\n", 13667 path, strerror(errno)); 13668 return NULL; 13669 } 13670 if (!S_ISCHR(stbuf.st_mode)) { 13671 ast_log(LOG_ERROR, "%s: Not a character device file\n", 13672 path); 13673 return NULL; 13674 } 13675 param->channelmatch = minor(stbuf.st_rdev); 13676 } 13677 13678 p = iflist; 13679 } 13680 13681 if (param->opt == 'r' && res < 3) { 13682 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data); 13683 param->opt = '\0'; 13684 } 13685 13686 return p; 13687 }
static int device2chan | ( | const char * | subdir, | |
int | channel, | |||
char * | path, | |||
int | pathlen | |||
) | [static] |
Definition at line 12299 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.
Referenced by build_channels().
12300 { 12301 struct stat stbuf; 12302 int num; 12303 12304 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel); 12305 if (stat(path, &stbuf) < 0) { 12306 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno)); 12307 return -errno; 12308 } 12309 if (!S_ISCHR(stbuf.st_mode)) { 12310 ast_log(LOG_ERROR, "%s: Not a character device file\n", path); 12311 return -EINVAL; 12312 } 12313 num = minor(stbuf.st_rdev); 12314 ast_log(LOG_DEBUG, "%s -> %d\n", path, num); 12315 return num; 12316 12317 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 4499 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
04500 { 04501 if (isdigit(digit)) 04502 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 04503 else if (digit >= 'A' && digit <= 'D') 04504 return DAHDI_TONE_DTMF_A + (digit - 'A'); 04505 else if (digit >= 'a' && digit <= 'd') 04506 return DAHDI_TONE_DTMF_A + (digit - 'a'); 04507 else if (digit == '*') 04508 return DAHDI_TONE_DTMF_s; 04509 else if (digit == '#') 04510 return DAHDI_TONE_DTMF_p; 04511 else 04512 return -1; 04513 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6660 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().
06661 { 06662 int val = 0; 06663 06664 p->ignoredtmf = 1; 06665 06666 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06667 06668 if (!p->hardwaredtmf && p->dsp) { 06669 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 06670 ast_dsp_set_features(p->dsp, p->dsp_features); 06671 } 06672 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 11723 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, 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().
11724 { 11725 int count, res, res2, spoint, pollres=0; 11726 struct dahdi_pvt *i; 11727 struct dahdi_pvt *last = NULL; 11728 struct dahdi_pvt *doomed; 11729 time_t thispass = 0, lastpass = 0; 11730 int found; 11731 char buf[1024]; 11732 struct pollfd *pfds=NULL; 11733 int lastalloc = -1; 11734 /* This thread monitors all the frame relay interfaces which are not yet in use 11735 (and thus do not have a separate thread) indefinitely */ 11736 /* From here on out, we die whenever asked */ 11737 #if 0 11738 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 11739 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 11740 return NULL; 11741 } 11742 ast_debug(1, "Monitor starting...\n"); 11743 #endif 11744 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11745 11746 for (;;) { 11747 /* Lock the interface list */ 11748 ast_mutex_lock(&iflock); 11749 if (!pfds || (lastalloc != ifcount)) { 11750 if (pfds) { 11751 ast_free(pfds); 11752 pfds = NULL; 11753 } 11754 if (ifcount) { 11755 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 11756 ast_mutex_unlock(&iflock); 11757 return NULL; 11758 } 11759 } 11760 lastalloc = ifcount; 11761 } 11762 /* Build the stuff we're going to poll on, that is the socket of every 11763 dahdi_pvt that does not have an associated owner channel */ 11764 count = 0; 11765 for (i = iflist; i; i = i->next) { 11766 ast_mutex_lock(&i->lock); 11767 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 11768 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11769 struct analog_pvt *p = i->sig_pvt; 11770 11771 if (!p) { 11772 ast_log(LOG_ERROR, "No sig_pvt?\n"); 11773 } else if (!p->owner && !p->subs[SUB_REAL].owner) { 11774 /* This needs to be watched, as it lacks an owner */ 11775 pfds[count].fd = i->subs[SUB_REAL].dfd; 11776 pfds[count].events = POLLPRI; 11777 pfds[count].revents = 0; 11778 /* Message waiting or r2 channels also get watched for reading */ 11779 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11780 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11781 pfds[count].events |= POLLIN; 11782 } 11783 count++; 11784 } 11785 } else { 11786 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 11787 /* This needs to be watched, as it lacks an owner */ 11788 pfds[count].fd = i->subs[SUB_REAL].dfd; 11789 pfds[count].events = POLLPRI; 11790 pfds[count].revents = 0; 11791 /* If we are monitoring for VMWI or sending CID, we need to 11792 read from the channel as well */ 11793 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11794 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11795 pfds[count].events |= POLLIN; 11796 } 11797 count++; 11798 } 11799 } 11800 } 11801 ast_mutex_unlock(&i->lock); 11802 } 11803 /* Okay, now that we know what to do, release the interface lock */ 11804 ast_mutex_unlock(&iflock); 11805 11806 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11807 pthread_testcancel(); 11808 /* Wait at least a second for something to happen */ 11809 res = poll(pfds, count, 1000); 11810 pthread_testcancel(); 11811 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11812 11813 /* Okay, poll has finished. Let's see what happened. */ 11814 if (res < 0) { 11815 if ((errno != EAGAIN) && (errno != EINTR)) 11816 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 11817 continue; 11818 } 11819 /* Alright, lock the interface list again, and let's look and see what has 11820 happened */ 11821 ast_mutex_lock(&iflock); 11822 found = 0; 11823 spoint = 0; 11824 lastpass = thispass; 11825 thispass = time(NULL); 11826 doomed = NULL; 11827 for (i = iflist;; i = i->next) { 11828 if (doomed) { 11829 int res; 11830 res = dahdi_destroy_channel_bynum(doomed->channel); 11831 if (res != RESULT_SUCCESS) { 11832 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 11833 } 11834 doomed = NULL; 11835 } 11836 if (!i) { 11837 break; 11838 } 11839 11840 if (thispass != lastpass) { 11841 if (!found && ((i == last) || ((i == iflist) && !last))) { 11842 last = i; 11843 if (last) { 11844 struct analog_pvt *analog_p = last->sig_pvt; 11845 /* Only allow MWI to be initiated on a quiescent fxs port */ 11846 if (analog_p 11847 && !last->mwisendactive 11848 && (last->sig & __DAHDI_SIG_FXO) 11849 && !analog_p->fxsoffhookstate 11850 && !last->owner 11851 && !ast_strlen_zero(last->mailbox) 11852 && (thispass - analog_p->onhooktime > 3)) { 11853 res = has_voicemail(last); 11854 if (analog_p->msgstate != res) { 11855 /* Set driver resources for signalling VMWI */ 11856 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 11857 if (res2) { 11858 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 11859 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 11860 } 11861 /* If enabled for FSK spill then initiate it */ 11862 if (mwi_send_init(last)) { 11863 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 11864 } 11865 analog_p->msgstate = res; 11866 found ++; 11867 } 11868 } 11869 last = last->next; 11870 } 11871 } 11872 } 11873 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 11874 if (i->radio && !i->owner) 11875 { 11876 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11877 if (res) 11878 { 11879 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 11880 /* Don't hold iflock while handling init events */ 11881 ast_mutex_unlock(&iflock); 11882 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11883 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11884 else 11885 doomed = handle_init_event(i, res); 11886 ast_mutex_lock(&iflock); 11887 } 11888 continue; 11889 } 11890 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 11891 if (pollres & POLLIN) { 11892 if (i->owner || i->subs[SUB_REAL].owner) { 11893 #ifdef HAVE_PRI 11894 if (!i->pri) 11895 #endif 11896 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 11897 continue; 11898 } 11899 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { 11900 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 11901 continue; 11902 } 11903 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 11904 if (res > 0) { 11905 if (i->mwimonitor_fsk) { 11906 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 11907 pthread_attr_t attr; 11908 pthread_t threadid; 11909 struct mwi_thread_data *mtd; 11910 11911 pthread_attr_init(&attr); 11912 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11913 11914 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 11915 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 11916 mtd->pvt = i; 11917 memcpy(mtd->buf, buf, res); 11918 mtd->len = res; 11919 i->mwimonitoractive = 1; 11920 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 11921 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 11922 i->mwimonitoractive = 0; 11923 ast_free(mtd); 11924 } 11925 } 11926 } 11927 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 11928 } else if (i->cid_start == CID_START_DTMF_NOALERT) { 11929 int energy; 11930 struct timeval now; 11931 /* State machine dtmfcid_holdoff_state allows for the line to settle 11932 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 11933 */ 11934 if (1 == i->dtmfcid_holdoff_state) { 11935 gettimeofday(&i->dtmfcid_delay, NULL); 11936 i->dtmfcid_holdoff_state = 2; 11937 } else if (2 == i->dtmfcid_holdoff_state) { 11938 gettimeofday(&now, NULL); 11939 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 11940 i->dtmfcid_holdoff_state = 0; 11941 } 11942 } else { 11943 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 11944 if (!i->mwisendactive && energy > dtmfcid_level) { 11945 pthread_t threadid; 11946 struct ast_channel *chan; 11947 ast_mutex_unlock(&iflock); 11948 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11949 /* just in case this event changes or somehow destroys a channel, set doomed here too */ 11950 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); 11951 i->dtmfcid_holdoff_state = 1; 11952 } else { 11953 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11954 if (!chan) { 11955 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11956 } else { 11957 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11958 if (res) { 11959 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11960 ast_hangup(chan); 11961 } else { 11962 i->dtmfcid_holdoff_state = 1; 11963 } 11964 } 11965 } 11966 ast_mutex_lock(&iflock); 11967 } 11968 } 11969 } 11970 if (i->mwisendactive) { 11971 mwi_send_process_buffer(i, res); 11972 } 11973 } else { 11974 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 11975 } 11976 } 11977 if (pollres & POLLPRI) { 11978 if (i->owner || i->subs[SUB_REAL].owner) { 11979 #ifdef HAVE_PRI 11980 if (!i->pri) 11981 #endif 11982 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 11983 continue; 11984 } 11985 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11986 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 11987 /* Don't hold iflock while handling init events */ 11988 ast_mutex_unlock(&iflock); 11989 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 11990 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11991 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11992 else 11993 doomed = handle_init_event(i, res); 11994 } 11995 ast_mutex_lock(&iflock); 11996 } 11997 } 11998 } 11999 ast_mutex_unlock(&iflock); 12000 } 12001 /* Never reached */ 12002 return NULL; 12003 12004 }
static int drc_sample | ( | int | sample, | |
float | drc | |||
) | [static] |
Definition at line 5002 of file chan_dahdi.c.
Referenced by fill_rxgain(), and fill_txgain().
05003 { 05004 float neg; 05005 float shallow, steep; 05006 float max = SHRT_MAX; 05007 05008 neg = (sample < 0 ? -1 : 1); 05009 steep = drc*sample; 05010 shallow = neg*(max-max/drc)+(float)sample/drc; 05011 if (abs(steep) < abs(shallow)) { 05012 sample = steep; 05013 } 05014 else { 05015 sample = shallow; 05016 } 05017 05018 return sample; 05019 }
Definition at line 13464 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().
13465 { 13466 struct dahdi_pvt *p; 13467 struct dahdi_bufferinfo bi; 13468 int res; 13469 13470 p = ast_malloc(sizeof(*p)); 13471 if (!p) { 13472 return NULL; 13473 } 13474 *p = *src; 13475 13476 /* Must deep copy the cc_params. */ 13477 p->cc_params = ast_cc_config_params_init(); 13478 if (!p->cc_params) { 13479 ast_free(p); 13480 return NULL; 13481 } 13482 ast_cc_copy_config_params(p->cc_params, src->cc_params); 13483 13484 p->which_iflist = DAHDI_IFLIST_NONE; 13485 p->next = NULL; 13486 p->prev = NULL; 13487 ast_mutex_init(&p->lock); 13488 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13489 if (p->subs[SUB_REAL].dfd < 0) { 13490 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 13491 destroy_dahdi_pvt(p); 13492 return NULL; 13493 } 13494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13495 if (!res) { 13496 bi.txbufpolicy = src->buf_policy; 13497 bi.rxbufpolicy = src->buf_policy; 13498 bi.numbufs = src->buf_no; 13499 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13500 if (res < 0) { 13501 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 13502 } 13503 } else 13504 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 13505 p->destroy = 1; 13506 dahdi_iflist_insert(p); 13507 return p; 13508 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6674 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().
06675 { 06676 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06677 06678 if (p->channel == CHAN_PSEUDO) 06679 return; 06680 06681 p->ignoredtmf = 0; 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 const char * event2str | ( | int | event | ) | [static] |
Definition at line 4654 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 5066 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_rxgain().
05067 { 05068 int j; 05069 int k; 05070 float linear_gain = pow(10.0, gain / 20.0); 05071 05072 switch (law) { 05073 case DAHDI_LAW_ALAW: 05074 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05075 if (gain || drc) { 05076 k = AST_ALAW(j); 05077 if (drc) { 05078 k = drc_sample(k, drc); 05079 } 05080 k = (float)k*linear_gain; 05081 if (k > 32767) k = 32767; 05082 if (k < -32767) k = -32767; 05083 g->rxgain[j] = AST_LIN2A(k); 05084 } else { 05085 g->rxgain[j] = j; 05086 } 05087 } 05088 break; 05089 case DAHDI_LAW_MULAW: 05090 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05091 if (gain || drc) { 05092 k = AST_MULAW(j); 05093 if (drc) { 05094 k = drc_sample(k, drc); 05095 } 05096 k = (float)k*linear_gain; 05097 if (k > 32767) k = 32767; 05098 if (k < -32767) k = -32767; 05099 g->rxgain[j] = AST_LIN2MU(k); 05100 } else { 05101 g->rxgain[j] = j; 05102 } 05103 } 05104 break; 05105 } 05106 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5022 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_txgain().
05023 { 05024 int j; 05025 int k; 05026 05027 float linear_gain = pow(10.0, gain / 20.0); 05028 05029 switch (law) { 05030 case DAHDI_LAW_ALAW: 05031 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05032 if (gain || drc) { 05033 k = AST_ALAW(j); 05034 if (drc) { 05035 k = drc_sample(k, drc); 05036 } 05037 k = (float)k*linear_gain; 05038 if (k > 32767) k = 32767; 05039 if (k < -32767) k = -32767; 05040 g->txgain[j] = AST_LIN2A(k); 05041 } else { 05042 g->txgain[j] = j; 05043 } 05044 } 05045 break; 05046 case DAHDI_LAW_MULAW: 05047 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 05048 if (gain || drc) { 05049 k = AST_MULAW(j); 05050 if (drc) { 05051 k = drc_sample(k, drc); 05052 } 05053 k = (float)k*linear_gain; 05054 if (k > 32767) k = 32767; 05055 if (k < -32767) k = -32767; 05056 g->txgain[j] = AST_LIN2MU(k); 05057 05058 } else { 05059 g->txgain[j] = j; 05060 } 05061 } 05062 break; 05063 } 05064 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 15937 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().
15938 { 15939 struct dahdi_pvt *p; 15940 15941 ast_mutex_lock(&iflock); 15942 for (p = iflist; p; p = p->next) { 15943 if (p->channel == channel) { 15944 break; 15945 } 15946 } 15947 ast_mutex_unlock(&iflock); 15948 return p; 15949 }
static struct dahdi_pvt* find_channel_from_str | ( | const char * | channel | ) | [static, read] |
Definition at line 15960 of file chan_dahdi.c.
References find_channel().
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
15961 { 15962 int chan_num; 15963 15964 if (sscanf(channel, "%30d", &chan_num) != 1) { 15965 /* Not numeric string. */ 15966 return NULL; 15967 } 15968 15969 return find_channel(chan_num); 15970 }
Definition at line 5750 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 7746 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().
07747 { 07748 int res; 07749 struct dahdi_spaninfo zi; 07750 struct dahdi_params params; 07751 07752 memset(&zi, 0, sizeof(zi)); 07753 zi.spanno = p->span; 07754 07755 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 07756 if (zi.alarms != DAHDI_ALARM_NONE) 07757 return zi.alarms; 07758 } else { 07759 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 07760 return 0; 07761 } 07762 07763 /* No alarms on the span. Check for channel alarms. */ 07764 memset(¶ms, 0, sizeof(params)); 07765 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 07766 return params.chan_alarms; 07767 07768 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 07769 07770 return DAHDI_ALARM_NONE; 07771 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 7871 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().
07872 { 07873 const char *alarm_str; 07874 07875 #if defined(HAVE_PRI) 07876 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 07877 return; 07878 } 07879 #endif /* defined(HAVE_PRI) */ 07880 07881 alarm_str = alarm2str(alms); 07882 if (report_alarms & REPORT_CHANNEL_ALARMS) { 07883 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 07884 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 07885 "Alarm: %s\r\n" 07886 "Channel: %d\r\n", 07887 alarm_str, p->channel); 07888 } 07889 07890 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 07891 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); 07892 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", 07893 "Alarm: %s\r\n" 07894 "Span: %d\r\n", 07895 alarm_str, p->span); 07896 } 07897 }
static void handle_clear_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3868 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().
03869 { 03870 #if defined(HAVE_PRI) 03871 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) { 03872 return; 03873 } 03874 #endif /* defined(HAVE_PRI) */ 03875 03876 if (report_alarms & REPORT_CHANNEL_ALARMS) { 03877 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 03878 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 03879 } 03880 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 03881 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); 03882 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); 03883 } 03884 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15555 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.
15556 { 15557 int i, j; 15558 switch (cmd) { 15559 case CLI_INIT: 15560 e->command = "dahdi show cadences"; 15561 e->usage = 15562 "Usage: dahdi show cadences\n" 15563 " Shows all cadences currently defined\n"; 15564 return NULL; 15565 case CLI_GENERATE: 15566 return NULL; 15567 } 15568 for (i = 0; i < num_cadence; i++) { 15569 char output[1024]; 15570 char tmp[16], tmp2[64]; 15571 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 15572 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 15573 15574 for (j = 0; j < 16; j++) { 15575 if (cadences[i].ringcadence[j] == 0) 15576 break; 15577 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 15578 if (cidrings[i] * 2 - 1 == j) 15579 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 15580 else 15581 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 15582 if (j != 0) 15583 strncat(output, ",", sizeof(output) - strlen(output) - 1); 15584 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 15585 } 15586 ast_cli(a->fd,"%s\n",output); 15587 } 15588 return CLI_SUCCESS; 15589 }
Definition at line 11476 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().
11477 { 11478 int res; 11479 pthread_t threadid; 11480 struct ast_channel *chan; 11481 11482 /* Handle an event on a given channel for the monitor thread. */ 11483 11484 switch (event) { 11485 case DAHDI_EVENT_NONE: 11486 case DAHDI_EVENT_BITSCHANGED: 11487 break; 11488 case DAHDI_EVENT_WINKFLASH: 11489 case DAHDI_EVENT_RINGOFFHOOK: 11490 if (i->inalarm) break; 11491 if (i->radio) break; 11492 /* Got a ring/answer. What kind of channel are we? */ 11493 switch (i->sig) { 11494 case SIG_FXOLS: 11495 case SIG_FXOGS: 11496 case SIG_FXOKS: 11497 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11498 if (res && (errno == EBUSY)) 11499 break; 11500 11501 /* Cancel VMWI spill */ 11502 ast_free(i->cidspill); 11503 i->cidspill = NULL; 11504 restore_conference(i); 11505 11506 if (i->immediate) { 11507 dahdi_enable_ec(i); 11508 /* The channel is immediately up. Start right away */ 11509 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 11510 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL); 11511 if (!chan) { 11512 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 11513 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11514 if (res < 0) 11515 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11516 } 11517 } else { 11518 /* Check for callerid, digits, etc */ 11519 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL); 11520 if (chan) { 11521 if (has_voicemail(i)) 11522 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 11523 else 11524 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 11525 if (res < 0) 11526 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 11527 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11528 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11529 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11530 if (res < 0) 11531 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11532 ast_hangup(chan); 11533 } 11534 } else 11535 ast_log(LOG_WARNING, "Unable to create channel\n"); 11536 } 11537 break; 11538 case SIG_FXSLS: 11539 case SIG_FXSGS: 11540 case SIG_FXSKS: 11541 i->ringt = i->ringt_base; 11542 /* Fall through */ 11543 case SIG_EMWINK: 11544 case SIG_FEATD: 11545 case SIG_FEATDMF: 11546 case SIG_FEATDMF_TA: 11547 case SIG_E911: 11548 case SIG_FGC_CAMA: 11549 case SIG_FGC_CAMAMF: 11550 case SIG_FEATB: 11551 case SIG_EM: 11552 case SIG_EM_E1: 11553 case SIG_SFWINK: 11554 case SIG_SF_FEATD: 11555 case SIG_SF_FEATDMF: 11556 case SIG_SF_FEATB: 11557 case SIG_SF: 11558 /* Check for callerid, digits, etc */ 11559 if (i->cid_start == CID_START_POLARITY_IN) { 11560 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11561 } else { 11562 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL); 11563 } 11564 11565 if (!chan) { 11566 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11567 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11568 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11569 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11570 if (res < 0) { 11571 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11572 } 11573 ast_hangup(chan); 11574 } 11575 break; 11576 default: 11577 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11578 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11579 if (res < 0) 11580 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11581 return NULL; 11582 } 11583 break; 11584 case DAHDI_EVENT_NOALARM: 11585 switch (i->sig) { 11586 #if defined(HAVE_PRI) 11587 case SIG_PRI_LIB_HANDLE_CASES: 11588 ast_mutex_lock(&i->lock); 11589 sig_pri_chan_alarm_notify(i->sig_pvt, 1); 11590 ast_mutex_unlock(&i->lock); 11591 break; 11592 #endif /* defined(HAVE_PRI) */ 11593 #if defined(HAVE_SS7) 11594 case SIG_SS7: 11595 sig_ss7_set_alarm(i->sig_pvt, 0); 11596 break; 11597 #endif /* defined(HAVE_SS7) */ 11598 default: 11599 i->inalarm = 0; 11600 break; 11601 } 11602 handle_clear_alarms(i); 11603 break; 11604 case DAHDI_EVENT_ALARM: 11605 switch (i->sig) { 11606 #if defined(HAVE_PRI) 11607 case SIG_PRI_LIB_HANDLE_CASES: 11608 ast_mutex_lock(&i->lock); 11609 sig_pri_chan_alarm_notify(i->sig_pvt, 0); 11610 ast_mutex_unlock(&i->lock); 11611 break; 11612 #endif /* defined(HAVE_PRI) */ 11613 #if defined(HAVE_SS7) 11614 case SIG_SS7: 11615 sig_ss7_set_alarm(i->sig_pvt, 1); 11616 break; 11617 #endif /* defined(HAVE_SS7) */ 11618 default: 11619 i->inalarm = 1; 11620 break; 11621 } 11622 res = get_alarms(i); 11623 handle_alarms(i, res); 11624 /* fall thru intentionally */ 11625 case DAHDI_EVENT_ONHOOK: 11626 if (i->radio) 11627 break; 11628 /* Back on hook. Hang up. */ 11629 switch (i->sig) { 11630 case SIG_FXOLS: 11631 case SIG_FXOGS: 11632 case SIG_FEATD: 11633 case SIG_FEATDMF: 11634 case SIG_FEATDMF_TA: 11635 case SIG_E911: 11636 case SIG_FGC_CAMA: 11637 case SIG_FGC_CAMAMF: 11638 case SIG_FEATB: 11639 case SIG_EM: 11640 case SIG_EM_E1: 11641 case SIG_EMWINK: 11642 case SIG_SF_FEATD: 11643 case SIG_SF_FEATDMF: 11644 case SIG_SF_FEATB: 11645 case SIG_SF: 11646 case SIG_SFWINK: 11647 case SIG_FXSLS: 11648 case SIG_FXSGS: 11649 case SIG_FXSKS: 11650 case SIG_FXOKS: 11651 dahdi_disable_ec(i); 11652 /* Diddle the battery for the zhone */ 11653 #ifdef ZHONE_HACK 11654 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11655 usleep(1); 11656 #endif 11657 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11658 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 11659 break; 11660 case SIG_SS7: 11661 case SIG_PRI_LIB_HANDLE_CASES: 11662 dahdi_disable_ec(i); 11663 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11664 break; 11665 default: 11666 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11667 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11668 return NULL; 11669 } 11670 break; 11671 case DAHDI_EVENT_POLARITY: 11672 switch (i->sig) { 11673 case SIG_FXSLS: 11674 case SIG_FXSKS: 11675 case SIG_FXSGS: 11676 /* We have already got a PR before the channel was 11677 created, but it wasn't handled. We need polarity 11678 to be REV for remote hangup detection to work. 11679 At least in Spain */ 11680 if (i->hanguponpolarityswitch) 11681 i->polarity = POLARITY_REV; 11682 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 11683 i->polarity = POLARITY_REV; 11684 ast_verb(2, "Starting post polarity " 11685 "CID detection on channel %d\n", 11686 i->channel); 11687 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11688 if (!chan) { 11689 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11690 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11691 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11692 ast_hangup(chan); 11693 } 11694 } 11695 break; 11696 default: 11697 ast_log(LOG_WARNING, "handle_init_event detected " 11698 "polarity reversal on non-FXO (SIG_FXS) " 11699 "interface %d\n", i->channel); 11700 } 11701 break; 11702 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 11703 ast_log(LOG_NOTICE, 11704 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 11705 i->channel); 11706 return i; 11707 case DAHDI_EVENT_NEONMWI_ACTIVE: 11708 if (i->mwimonitor_neon) { 11709 notify_message(i->mailbox, 1); 11710 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 11711 } 11712 break; 11713 case DAHDI_EVENT_NEONMWI_INACTIVE: 11714 if (i->mwimonitor_neon) { 11715 notify_message(i->mailbox, 0); 11716 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 11717 } 11718 break; 11719 } 11720 return NULL; 11721 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5285 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().
05286 { 05287 int new_msgs; 05288 struct ast_event *event; 05289 char *mailbox, *context; 05290 05291 mailbox = context = ast_strdupa(p->mailbox); 05292 strsep(&context, "@"); 05293 if (ast_strlen_zero(context)) 05294 context = "default"; 05295 05296 event = ast_event_get_cached(AST_EVENT_MWI, 05297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 05298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 05299 AST_EVENT_IE_END); 05300 05301 if (event) { 05302 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 05303 ast_event_destroy(event); 05304 } else 05305 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 05306 05307 return new_msgs; 05308 }
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 13223 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::group, and dahdi_pvt::span.
Referenced by dahdi_cc_callback(), and dahdi_request().
13224 { 13225 #if defined(HAVE_PRI) 13226 if (0 < span) { 13227 /* The channel must be on the specified PRI span. */ 13228 if (!p->pri || p->pri->span != span) { 13229 return 0; 13230 } 13231 if (!groupmatch && channelmatch == -1) { 13232 /* Match any group since it only needs to be on the PRI span. */ 13233 *groupmatched = 1; 13234 return 1; 13235 } 13236 } 13237 #endif /* defined(HAVE_PRI) */ 13238 /* check group matching */ 13239 if (groupmatch) { 13240 if ((p->group & groupmatch) != groupmatch) 13241 /* Doesn't match the specified group, try the next one */ 13242 return 0; 13243 *groupmatched = 1; 13244 } 13245 /* Check to see if we have a channel match */ 13246 if (channelmatch != -1) { 13247 if (p->channel != channelmatch) 13248 /* Doesn't match the specified channel, try the next one */ 13249 return 0; 13250 *channelmatched = 1; 13251 } 13252 13253 return 1; 13254 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 4767 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
04768 { 04769 /* If they're listening to our channel, they're ours */ 04770 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 04771 return 1; 04772 /* If they're a talker on our (allocated) conference, they're ours */ 04773 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 04774 return 1; 04775 return 0; 04776 }
Definition at line 4797 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().
04798 { 04799 int x; 04800 int useslavenative; 04801 struct dahdi_pvt *slave = NULL; 04802 /* Start out optimistic */ 04803 useslavenative = 1; 04804 /* Update conference state in a stateless fashion */ 04805 for (x = 0; x < 3; x++) { 04806 /* Any three-way calling makes slave native mode *definitely* out 04807 of the question */ 04808 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 04809 useslavenative = 0; 04810 } 04811 /* If we don't have any 3-way calls, check to see if we have 04812 precisely one slave */ 04813 if (useslavenative) { 04814 for (x = 0; x < MAX_SLAVES; x++) { 04815 if (p->slaves[x]) { 04816 if (slave) { 04817 /* Whoops already have a slave! No 04818 slave native and stop right away */ 04819 slave = NULL; 04820 useslavenative = 0; 04821 break; 04822 } else { 04823 /* We have one slave so far */ 04824 slave = p->slaves[x]; 04825 } 04826 } 04827 } 04828 } 04829 /* If no slave, slave native definitely out */ 04830 if (!slave) 04831 useslavenative = 0; 04832 else if (slave->law != p->law) { 04833 useslavenative = 0; 04834 slave = NULL; 04835 } 04836 if (out) 04837 *out = slave; 04838 return useslavenative; 04839 }
static int load_module | ( | void | ) | [static] |
Definition at line 18609 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().
18610 { 18611 int res; 18612 #if defined(HAVE_PRI) || defined(HAVE_SS7) 18613 int y; 18614 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 18615 18616 #ifdef HAVE_PRI 18617 memset(pris, 0, sizeof(pris)); 18618 for (y = 0; y < NUM_SPANS; y++) { 18619 sig_pri_init_pri(&pris[y].pri); 18620 } 18621 pri_set_error(dahdi_pri_error); 18622 pri_set_message(dahdi_pri_message); 18623 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 18624 #ifdef HAVE_PRI_PROG_W_CAUSE 18625 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 18626 #endif 18627 #if defined(HAVE_PRI_CCSS) 18628 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks) 18629 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) { 18630 __unload_module(); 18631 return AST_MODULE_LOAD_FAILURE; 18632 } 18633 #endif /* defined(HAVE_PRI_CCSS) */ 18634 if (sig_pri_load( 18635 #if defined(HAVE_PRI_CCSS) 18636 dahdi_pri_cc_type 18637 #else 18638 NULL 18639 #endif /* defined(HAVE_PRI_CCSS) */ 18640 )) { 18641 __unload_module(); 18642 return AST_MODULE_LOAD_FAILURE; 18643 } 18644 #endif 18645 #if defined(HAVE_SS7) 18646 memset(linksets, 0, sizeof(linksets)); 18647 for (y = 0; y < NUM_SPANS; y++) { 18648 sig_ss7_init_linkset(&linksets[y].ss7); 18649 } 18650 ss7_set_error(dahdi_ss7_error); 18651 ss7_set_message(dahdi_ss7_message); 18652 #endif /* defined(HAVE_SS7) */ 18653 res = setup_dahdi(0); 18654 /* Make sure we can register our DAHDI channel type */ 18655 if (res) 18656 return AST_MODULE_LOAD_DECLINE; 18657 if (ast_channel_register(&dahdi_tech)) { 18658 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 18659 __unload_module(); 18660 return AST_MODULE_LOAD_FAILURE; 18661 } 18662 #ifdef HAVE_PRI 18663 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 18664 #endif 18665 #if defined(HAVE_SS7) 18666 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 18667 #endif /* defined(HAVE_SS7) */ 18668 #ifdef HAVE_OPENR2 18669 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 18670 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 18671 #endif 18672 18673 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 18674 /* register all the data providers */ 18675 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers)); 18676 memset(round_robin, 0, sizeof(round_robin)); 18677 ast_manager_register_xml("DAHDITransfer", 0, action_transfer); 18678 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup); 18679 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook); 18680 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon); 18681 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff); 18682 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels); 18683 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart); 18684 18685 ast_cond_init(&ss_thread_complete, NULL); 18686 18687 return res; 18688 }
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 12333 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().
12334 { 12335 /* Make a dahdi_pvt structure for this interface */ 12336 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */ 12337 char fn[80]; 12338 struct dahdi_bufferinfo bi; 12339 12340 int res; 12341 #if defined(HAVE_PRI) 12342 int span = 0; 12343 #endif /* defined(HAVE_PRI) */ 12344 int here = 0;/*!< TRUE if the channel interface already exists. */ 12345 int x; 12346 struct analog_pvt *analog_p = NULL; 12347 struct dahdi_params p; 12348 #if defined(HAVE_PRI) 12349 struct dahdi_spaninfo si; 12350 struct sig_pri_chan *pri_chan = NULL; 12351 #endif /* defined(HAVE_PRI) */ 12352 #if defined(HAVE_SS7) 12353 struct sig_ss7_chan *ss7_chan = NULL; 12354 #endif /* defined(HAVE_SS7) */ 12355 12356 /* Search channel interface list to see if it already exists. */ 12357 for (tmp = iflist; tmp; tmp = tmp->next) { 12358 if (!tmp->destroy) { 12359 if (tmp->channel == channel) { 12360 /* The channel interface already exists. */ 12361 here = 1; 12362 break; 12363 } 12364 if (tmp->channel > channel) { 12365 /* No way it can be in the sorted list. */ 12366 tmp = NULL; 12367 break; 12368 } 12369 } 12370 } 12371 12372 if (!here && reloading != 1) { 12373 tmp = ast_calloc(1, sizeof(*tmp)); 12374 if (!tmp) { 12375 return NULL; 12376 } 12377 tmp->cc_params = ast_cc_config_params_init(); 12378 if (!tmp->cc_params) { 12379 ast_free(tmp); 12380 return NULL; 12381 } 12382 ast_mutex_init(&tmp->lock); 12383 ifcount++; 12384 for (x = 0; x < 3; x++) 12385 tmp->subs[x].dfd = -1; 12386 tmp->channel = channel; 12387 tmp->priindication_oob = conf->chan.priindication_oob; 12388 } 12389 12390 if (tmp) { 12391 int chan_sig = conf->chan.sig; 12392 12393 /* If there are variables in tmp before it is updated to match the new config, clear them */ 12394 if (reloading && tmp->vars) { 12395 ast_variables_destroy(tmp->vars); 12396 tmp->vars = NULL; 12397 } 12398 12399 12400 if (!here) { 12401 /* Can only get here if this is a new channel interface being created. */ 12402 if ((channel != CHAN_PSEUDO)) { 12403 int count = 0; 12404 12405 snprintf(fn, sizeof(fn), "%d", channel); 12406 /* Open non-blocking */ 12407 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12408 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 */ 12409 usleep(1); 12410 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12411 count++; 12412 } 12413 /* Allocate a DAHDI structure */ 12414 if (tmp->subs[SUB_REAL].dfd < 0) { 12415 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); 12416 destroy_dahdi_pvt(tmp); 12417 return NULL; 12418 } 12419 memset(&p, 0, sizeof(p)); 12420 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12421 if (res < 0) { 12422 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 12423 destroy_dahdi_pvt(tmp); 12424 return NULL; 12425 } 12426 if (conf->is_sig_auto) 12427 chan_sig = sigtype_to_signalling(p.sigtype); 12428 if (p.sigtype != (chan_sig & 0x3ffff)) { 12429 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)); 12430 destroy_dahdi_pvt(tmp); 12431 return NULL; 12432 } 12433 tmp->law_default = p.curlaw; 12434 tmp->law = p.curlaw; 12435 tmp->span = p.spanno; 12436 #if defined(HAVE_PRI) 12437 span = p.spanno - 1; 12438 #endif /* defined(HAVE_PRI) */ 12439 } else { 12440 chan_sig = 0; 12441 } 12442 tmp->sig = chan_sig; 12443 tmp->outsigmod = conf->chan.outsigmod; 12444 12445 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) { 12446 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp); 12447 if (!analog_p) { 12448 destroy_dahdi_pvt(tmp); 12449 return NULL; 12450 } 12451 tmp->sig_pvt = analog_p; 12452 } 12453 #if defined(HAVE_SS7) 12454 if (chan_sig == SIG_SS7) { 12455 struct dahdi_ss7 *ss7; 12456 int clear = 0; 12457 12458 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 12459 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12460 destroy_dahdi_pvt(tmp); 12461 return NULL; 12462 } 12463 12464 ss7 = ss7_resolve_linkset(cur_linkset); 12465 if (!ss7) { 12466 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 12467 destroy_dahdi_pvt(tmp); 12468 return NULL; 12469 } 12470 ss7->ss7.span = cur_linkset; 12471 if (cur_cicbeginswith < 0) { 12472 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 12473 destroy_dahdi_pvt(tmp); 12474 return NULL; 12475 } 12476 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7); 12477 if (!ss7_chan) { 12478 destroy_dahdi_pvt(tmp); 12479 return NULL; 12480 } 12481 tmp->sig_pvt = ss7_chan; 12482 tmp->ss7 = &ss7->ss7; 12483 12484 ss7_chan->channel = tmp->channel; 12485 ss7_chan->cic = cur_cicbeginswith++; 12486 12487 /* DB: Add CIC's DPC information */ 12488 ss7_chan->dpc = cur_defaultdpc; 12489 12490 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan; 12491 12492 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix)); 12493 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix)); 12494 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix)); 12495 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix)); 12496 12497 ss7->ss7.called_nai = conf->ss7.ss7.called_nai; 12498 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai; 12499 } 12500 #endif /* defined(HAVE_SS7) */ 12501 #ifdef HAVE_OPENR2 12502 if (chan_sig == SIG_MFCR2) { 12503 struct dahdi_mfcr2 *r2_link; 12504 r2_link = dahdi_r2_get_link(); 12505 if (!r2_link) { 12506 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 12507 destroy_dahdi_pvt(tmp); 12508 return NULL; 12509 } 12510 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 12511 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 12512 destroy_dahdi_pvt(tmp); 12513 return NULL; 12514 } 12515 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) { 12516 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 12517 destroy_dahdi_pvt(tmp); 12518 return NULL; 12519 } 12520 r2_link->pvts[r2_link->numchans++] = tmp; 12521 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 12522 tmp->subs[SUB_REAL].dfd, 12523 NULL, NULL); 12524 if (!tmp->r2chan) { 12525 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 12526 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 12527 destroy_dahdi_pvt(tmp); 12528 return NULL; 12529 } 12530 tmp->mfcr2 = r2_link; 12531 if (conf->mfcr2.call_files) { 12532 openr2_chan_enable_call_files(tmp->r2chan); 12533 } 12534 openr2_chan_set_client_data(tmp->r2chan, tmp); 12535 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 12536 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 12537 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 12538 tmp->mfcr2_category = conf->mfcr2.category; 12539 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 12540 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 12541 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 12542 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 12543 tmp->mfcr2call = 0; 12544 tmp->mfcr2_dnis_index = 0; 12545 tmp->mfcr2_ani_index = 0; 12546 r2_link->monitored_count++; 12547 } 12548 #endif 12549 #ifdef HAVE_PRI 12550 if (dahdi_sig_pri_lib_handles(chan_sig)) { 12551 int offset; 12552 int matchesdchan; 12553 int x,y; 12554 int myswitchtype = 0; 12555 12556 offset = 0; 12557 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 12558 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12559 destroy_dahdi_pvt(tmp); 12560 return NULL; 12561 } 12562 if (span >= NUM_SPANS) { 12563 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 12564 destroy_dahdi_pvt(tmp); 12565 return NULL; 12566 } else { 12567 si.spanno = 0; 12568 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12569 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12570 destroy_dahdi_pvt(tmp); 12571 return NULL; 12572 } 12573 /* Store the logical span first based upon the real span */ 12574 tmp->logicalspan = pris[span].prilogicalspan; 12575 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 12576 if (span < 0) { 12577 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 12578 destroy_dahdi_pvt(tmp); 12579 return NULL; 12580 } 12581 myswitchtype = conf->pri.pri.switchtype; 12582 /* Make sure this isn't a d-channel */ 12583 matchesdchan=0; 12584 for (x = 0; x < NUM_SPANS; x++) { 12585 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 12586 if (pris[x].dchannels[y] == tmp->channel) { 12587 matchesdchan = 1; 12588 break; 12589 } 12590 } 12591 } 12592 if (!matchesdchan) { 12593 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) { 12594 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype)); 12595 destroy_dahdi_pvt(tmp); 12596 return NULL; 12597 } 12598 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) { 12599 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype)); 12600 destroy_dahdi_pvt(tmp); 12601 return NULL; 12602 } 12603 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) { 12604 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)); 12605 destroy_dahdi_pvt(tmp); 12606 return NULL; 12607 } 12608 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) { 12609 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial); 12610 destroy_dahdi_pvt(tmp); 12611 return NULL; 12612 } 12613 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) { 12614 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext); 12615 destroy_dahdi_pvt(tmp); 12616 return NULL; 12617 } 12618 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) { 12619 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused); 12620 destroy_dahdi_pvt(tmp); 12621 return NULL; 12622 } 12623 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) { 12624 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle); 12625 destroy_dahdi_pvt(tmp); 12626 return NULL; 12627 } 12628 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) { 12629 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 12630 pris[span].pri.trunkgroup); 12631 destroy_dahdi_pvt(tmp); 12632 return NULL; 12633 } 12634 12635 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel); 12636 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup); 12637 if (!pri_chan) { 12638 destroy_dahdi_pvt(tmp); 12639 return NULL; 12640 } 12641 tmp->sig_pvt = pri_chan; 12642 tmp->pri = &pris[span].pri; 12643 12644 tmp->priexclusive = conf->chan.priexclusive; 12645 12646 if (!tmp->pri->cc_params) { 12647 tmp->pri->cc_params = ast_cc_config_params_init(); 12648 if (!tmp->pri->cc_params) { 12649 destroy_dahdi_pvt(tmp); 12650 return NULL; 12651 } 12652 } 12653 ast_cc_copy_config_params(tmp->pri->cc_params, 12654 conf->chan.cc_params); 12655 12656 pris[span].pri.sig = chan_sig; 12657 pris[span].pri.nodetype = conf->pri.pri.nodetype; 12658 pris[span].pri.switchtype = myswitchtype; 12659 pris[span].pri.nsf = conf->pri.pri.nsf; 12660 pris[span].pri.dialplan = conf->pri.pri.dialplan; 12661 pris[span].pri.localdialplan = conf->pri.pri.localdialplan; 12662 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt; 12663 pris[span].pri.minunused = conf->pri.pri.minunused; 12664 pris[span].pri.minidle = conf->pri.pri.minidle; 12665 pris[span].pri.overlapdial = conf->pri.pri.overlapdial; 12666 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping; 12667 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval; 12668 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12669 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support; 12670 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12671 #ifdef HAVE_PRI_INBANDDISCONNECT 12672 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect; 12673 #endif 12674 #if defined(HAVE_PRI_CALL_HOLD) 12675 pris[span].pri.hold_disconnect_transfer = 12676 conf->pri.pri.hold_disconnect_transfer; 12677 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 12678 #if defined(HAVE_PRI_CCSS) 12679 pris[span].pri.cc_ptmp_recall_mode = 12680 conf->pri.pri.cc_ptmp_recall_mode; 12681 pris[span].pri.cc_qsig_signaling_link_req = 12682 conf->pri.pri.cc_qsig_signaling_link_req; 12683 pris[span].pri.cc_qsig_signaling_link_rsp = 12684 conf->pri.pri.cc_qsig_signaling_link_rsp; 12685 #endif /* defined(HAVE_PRI_CCSS) */ 12686 #if defined(HAVE_PRI_CALL_WAITING) 12687 pris[span].pri.max_call_waiting_calls = 12688 conf->pri.pri.max_call_waiting_calls; 12689 pris[span].pri.allow_call_waiting_calls = 12690 conf->pri.pri.allow_call_waiting_calls; 12691 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12692 pris[span].pri.transfer = conf->chan.transfer; 12693 pris[span].pri.facilityenable = conf->pri.pri.facilityenable; 12694 #if defined(HAVE_PRI_L2_PERSISTENCE) 12695 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence; 12696 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 12697 #if defined(HAVE_PRI_AOC_EVENTS) 12698 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag; 12699 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup; 12700 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 12701 if (chan_sig == SIG_BRI_PTMP) { 12702 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored; 12703 } else { 12704 /* Option does not apply to this line type. */ 12705 pris[span].pri.layer1_ignored = 0; 12706 } 12707 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag; 12708 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag)); 12709 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list)); 12710 #if defined(HAVE_PRI_MWI) 12711 ast_copy_string(pris[span].pri.mwi_mailboxes, 12712 conf->pri.pri.mwi_mailboxes, 12713 sizeof(pris[span].pri.mwi_mailboxes)); 12714 #endif /* defined(HAVE_PRI_MWI) */ 12715 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial)); 12716 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext)); 12717 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix)); 12718 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix)); 12719 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix)); 12720 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix)); 12721 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix)); 12722 pris[span].pri.resetinterval = conf->pri.pri.resetinterval; 12723 12724 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12725 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x]; 12726 } 12727 12728 #if defined(HAVE_PRI_CALL_WAITING) 12729 /* Channel initial config parameters. */ 12730 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd; 12731 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid; 12732 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname; 12733 pris[span].pri.ch_cfg.immediate = conf->chan.immediate; 12734 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive; 12735 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob; 12736 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid; 12737 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres; 12738 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context)); 12739 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret)); 12740 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12741 } else { 12742 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos); 12743 destroy_dahdi_pvt(tmp); 12744 return NULL; 12745 } 12746 } 12747 } 12748 #endif 12749 } else { 12750 /* already exists in interface list */ 12751 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)); 12752 chan_sig = tmp->sig; 12753 if (tmp->subs[SUB_REAL].dfd > -1) { 12754 memset(&p, 0, sizeof(p)); 12755 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12756 } 12757 } 12758 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 12759 switch (chan_sig) { 12760 case SIG_FXSKS: 12761 case SIG_FXSLS: 12762 case SIG_EM: 12763 case SIG_EM_E1: 12764 case SIG_EMWINK: 12765 case SIG_FEATD: 12766 case SIG_FEATDMF: 12767 case SIG_FEATDMF_TA: 12768 case SIG_FEATB: 12769 case SIG_E911: 12770 case SIG_SF: 12771 case SIG_SFWINK: 12772 case SIG_FGC_CAMA: 12773 case SIG_FGC_CAMAMF: 12774 case SIG_SF_FEATD: 12775 case SIG_SF_FEATDMF: 12776 case SIG_SF_FEATB: 12777 p.starttime = 250; 12778 break; 12779 } 12780 12781 if (tmp->radio) { 12782 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 12783 p.channo = channel; 12784 p.rxwinktime = 1; 12785 p.rxflashtime = 1; 12786 p.starttime = 1; 12787 p.debouncetime = 5; 12788 } else { 12789 p.channo = channel; 12790 /* Override timing settings based on config file */ 12791 if (conf->timing.prewinktime >= 0) 12792 p.prewinktime = conf->timing.prewinktime; 12793 if (conf->timing.preflashtime >= 0) 12794 p.preflashtime = conf->timing.preflashtime; 12795 if (conf->timing.winktime >= 0) 12796 p.winktime = conf->timing.winktime; 12797 if (conf->timing.flashtime >= 0) 12798 p.flashtime = conf->timing.flashtime; 12799 if (conf->timing.starttime >= 0) 12800 p.starttime = conf->timing.starttime; 12801 if (conf->timing.rxwinktime >= 0) 12802 p.rxwinktime = conf->timing.rxwinktime; 12803 if (conf->timing.rxflashtime >= 0) 12804 p.rxflashtime = conf->timing.rxflashtime; 12805 if (conf->timing.debouncetime >= 0) 12806 p.debouncetime = conf->timing.debouncetime; 12807 } 12808 12809 /* don't set parms on a pseudo-channel */ 12810 if (tmp->subs[SUB_REAL].dfd >= 0) 12811 { 12812 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 12813 if (res < 0) { 12814 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 12815 destroy_dahdi_pvt(tmp); 12816 return NULL; 12817 } 12818 } 12819 #if 1 12820 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 12821 memset(&bi, 0, sizeof(bi)); 12822 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 12823 if (!res) { 12824 bi.txbufpolicy = conf->chan.buf_policy; 12825 bi.rxbufpolicy = conf->chan.buf_policy; 12826 bi.numbufs = conf->chan.buf_no; 12827 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 12828 if (res < 0) { 12829 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 12830 } 12831 } else { 12832 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 12833 } 12834 tmp->buf_policy = conf->chan.buf_policy; 12835 tmp->buf_no = conf->chan.buf_no; 12836 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 12837 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 12838 tmp->faxbuf_no = conf->chan.faxbuf_no; 12839 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 12840 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 12841 * The reason the ioctl call above failed should to be determined before worrying about the 12842 * faxbuffer-related ioctl calls */ 12843 tmp->bufsize = bi.bufsize; 12844 } 12845 #endif 12846 tmp->immediate = conf->chan.immediate; 12847 tmp->transfertobusy = conf->chan.transfertobusy; 12848 if (chan_sig & __DAHDI_SIG_FXS) { 12849 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 12850 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 12851 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 12852 } 12853 tmp->ringt_base = ringt_base; 12854 tmp->firstradio = 0; 12855 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 12856 tmp->permcallwaiting = conf->chan.callwaiting; 12857 else 12858 tmp->permcallwaiting = 0; 12859 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 12860 tmp->destroy = 0; 12861 tmp->drings = conf->chan.drings; 12862 12863 /* 10 is a nice default. */ 12864 if (tmp->drings.ringnum[0].range == 0) 12865 tmp->drings.ringnum[0].range = 10; 12866 if (tmp->drings.ringnum[1].range == 0) 12867 tmp->drings.ringnum[1].range = 10; 12868 if (tmp->drings.ringnum[2].range == 0) 12869 tmp->drings.ringnum[2].range = 10; 12870 12871 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 12872 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 12873 tmp->threewaycalling = conf->chan.threewaycalling; 12874 tmp->adsi = conf->chan.adsi; 12875 tmp->use_smdi = conf->chan.use_smdi; 12876 tmp->permhidecallerid = conf->chan.hidecallerid; 12877 tmp->hidecalleridname = conf->chan.hidecalleridname; 12878 tmp->callreturn = conf->chan.callreturn; 12879 tmp->echocancel = conf->chan.echocancel; 12880 tmp->echotraining = conf->chan.echotraining; 12881 tmp->pulse = conf->chan.pulse; 12882 if (tmp->echocancel.head.tap_length) { 12883 tmp->echocanbridged = conf->chan.echocanbridged; 12884 } else { 12885 if (conf->chan.echocanbridged) 12886 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 12887 tmp->echocanbridged = 0; 12888 } 12889 tmp->busydetect = conf->chan.busydetect; 12890 tmp->busycount = conf->chan.busycount; 12891 tmp->busycompare = conf->chan.busycompare; 12892 tmp->busytonelength = conf->chan.busytonelength; 12893 tmp->busyquietlength = conf->chan.busyquietlength; 12894 tmp->busyfuzziness = conf->chan.busyfuzziness; 12895 tmp->silencethreshold = conf->chan.silencethreshold; 12896 tmp->callprogress = conf->chan.callprogress; 12897 tmp->waitfordialtone = conf->chan.waitfordialtone; 12898 tmp->cancallforward = conf->chan.cancallforward; 12899 tmp->dtmfrelax = conf->chan.dtmfrelax; 12900 tmp->callwaiting = tmp->permcallwaiting; 12901 tmp->hidecallerid = tmp->permhidecallerid; 12902 tmp->channel = channel; 12903 tmp->stripmsd = conf->chan.stripmsd; 12904 tmp->use_callerid = conf->chan.use_callerid; 12905 tmp->cid_signalling = conf->chan.cid_signalling; 12906 tmp->cid_start = conf->chan.cid_start; 12907 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 12908 tmp->restrictcid = conf->chan.restrictcid; 12909 tmp->use_callingpres = conf->chan.use_callingpres; 12910 if (tmp->usedistinctiveringdetection) { 12911 if (!tmp->use_callerid) { 12912 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 12913 tmp->use_callerid = 1; 12914 } 12915 } 12916 12917 if (tmp->cid_signalling == CID_SIG_SMDI) { 12918 if (!tmp->use_smdi) { 12919 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 12920 tmp->use_smdi = 1; 12921 } 12922 } 12923 if (tmp->use_smdi) { 12924 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 12925 if (!(tmp->smdi_iface)) { 12926 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 12927 tmp->use_smdi = 0; 12928 } 12929 } 12930 12931 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 12932 tmp->amaflags = conf->chan.amaflags; 12933 if (!here) { 12934 tmp->confno = -1; 12935 tmp->propconfno = -1; 12936 } 12937 tmp->canpark = conf->chan.canpark; 12938 tmp->transfer = conf->chan.transfer; 12939 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 12940 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 12941 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 12942 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 12943 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 12944 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 12945 tmp->cid_ton = 0; 12946 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) { 12947 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 12948 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 12949 } else { 12950 tmp->cid_num[0] = '\0'; 12951 tmp->cid_name[0] = '\0'; 12952 } 12953 #if defined(HAVE_PRI) 12954 if (dahdi_sig_pri_lib_handles(tmp->sig)) { 12955 tmp->cid_tag[0] = '\0'; 12956 } else 12957 #endif /* defined(HAVE_PRI) */ 12958 { 12959 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); 12960 } 12961 tmp->cid_subaddr[0] = '\0'; 12962 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 12963 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 12964 char *mailbox, *context; 12965 mailbox = context = ast_strdupa(tmp->mailbox); 12966 strsep(&context, "@"); 12967 if (ast_strlen_zero(context)) 12968 context = "default"; 12969 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL, 12970 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 12971 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 12972 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 12973 AST_EVENT_IE_END); 12974 } 12975 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 12976 tmp->mwisend_setting = conf->chan.mwisend_setting; 12977 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 12978 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 12979 #endif 12980 12981 tmp->group = conf->chan.group; 12982 tmp->callgroup = conf->chan.callgroup; 12983 tmp->pickupgroup= conf->chan.pickupgroup; 12984 if (conf->chan.vars) { 12985 struct ast_variable *v, *tmpvar; 12986 for (v = conf->chan.vars ; v ; v = v->next) { 12987 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 12988 tmpvar->next = tmp->vars; 12989 tmp->vars = tmpvar; 12990 } 12991 } 12992 } 12993 tmp->cid_rxgain = conf->chan.cid_rxgain; 12994 tmp->rxgain = conf->chan.rxgain; 12995 tmp->txgain = conf->chan.txgain; 12996 tmp->txdrc = conf->chan.txdrc; 12997 tmp->rxdrc = conf->chan.rxdrc; 12998 tmp->tonezone = conf->chan.tonezone; 12999 if (tmp->subs[SUB_REAL].dfd > -1) { 13000 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law); 13001 if (tmp->dsp) 13002 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 13003 update_conf(tmp); 13004 if (!here) { 13005 switch (chan_sig) { 13006 case SIG_PRI_LIB_HANDLE_CASES: 13007 case SIG_SS7: 13008 case SIG_MFCR2: 13009 break; 13010 default: 13011 /* Hang it up to be sure it's good */ 13012 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 13013 break; 13014 } 13015 } 13016 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 13017 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 13018 /* the dchannel is down so put the channel in alarm */ 13019 switch (tmp->sig) { 13020 #ifdef HAVE_PRI 13021 case SIG_PRI_LIB_HANDLE_CASES: 13022 sig_pri_set_alarm(tmp->sig_pvt, 1); 13023 break; 13024 #endif 13025 #if defined(HAVE_SS7) 13026 case SIG_SS7: 13027 sig_ss7_set_alarm(tmp->sig_pvt, 1); 13028 break; 13029 #endif /* defined(HAVE_SS7) */ 13030 default: 13031 /* The only sig submodule left should be sig_analog. */ 13032 analog_p = tmp->sig_pvt; 13033 if (analog_p) { 13034 analog_p->inalarm = 1; 13035 } 13036 tmp->inalarm = 1; 13037 break; 13038 } 13039 handle_alarms(tmp, res); 13040 } 13041 } 13042 13043 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13044 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13045 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13046 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 13047 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); 13048 13049 if (!here) { 13050 tmp->locallyblocked = 0; 13051 tmp->remotelyblocked = 0; 13052 switch (tmp->sig) { 13053 #if defined(HAVE_PRI) 13054 case SIG_PRI_LIB_HANDLE_CASES: 13055 tmp->inservice = 1;/* Inservice until actually implemented. */ 13056 #if defined(HAVE_PRI_SERVICE_MESSAGES) 13057 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0; 13058 if (chan_sig == SIG_PRI) { 13059 char db_chan_name[20]; 13060 char db_answer[5]; 13061 13062 /* 13063 * Initialize the active out-of-service status 13064 * and delete any record if the feature is not enabled. 13065 */ 13066 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); 13067 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 13068 unsigned *why; 13069 13070 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 13071 if (tmp->pri->enable_service_message_support) { 13072 char state; 13073 13074 sscanf(db_answer, "%1c:%30u", &state, why); 13075 13076 /* Ensure that only the implemented bits could be set.*/ 13077 *why &= (SRVST_NEAREND | SRVST_FAREND); 13078 } 13079 if (!*why) { 13080 ast_db_del(db_chan_name, SRVST_DBKEY); 13081 } 13082 } 13083 } 13084 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 13085 break; 13086 #endif /* defined(HAVE_PRI) */ 13087 #if defined(HAVE_SS7) 13088 case SIG_SS7: 13089 tmp->inservice = 0; 13090 break; 13091 #endif /* defined(HAVE_SS7) */ 13092 default: 13093 /* We default to in service on protocols that don't have a reset */ 13094 tmp->inservice = 1; 13095 break; 13096 } 13097 } 13098 13099 switch (tmp->sig) { 13100 #if defined(HAVE_PRI) 13101 case SIG_PRI_LIB_HANDLE_CASES: 13102 if (pri_chan) { 13103 pri_chan->channel = tmp->channel; 13104 pri_chan->hidecallerid = tmp->hidecallerid; 13105 pri_chan->hidecalleridname = tmp->hidecalleridname; 13106 pri_chan->immediate = tmp->immediate; 13107 pri_chan->inalarm = tmp->inalarm; 13108 pri_chan->priexclusive = tmp->priexclusive; 13109 pri_chan->priindication_oob = tmp->priindication_oob; 13110 pri_chan->use_callerid = tmp->use_callerid; 13111 pri_chan->use_callingpres = tmp->use_callingpres; 13112 ast_copy_string(pri_chan->context, tmp->context, 13113 sizeof(pri_chan->context)); 13114 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret, 13115 sizeof(pri_chan->mohinterpret)); 13116 pri_chan->stripmsd = tmp->stripmsd; 13117 } 13118 break; 13119 #endif /* defined(HAVE_PRI) */ 13120 #if defined(HAVE_SS7) 13121 case SIG_SS7: 13122 if (ss7_chan) { 13123 ss7_chan->inalarm = tmp->inalarm; 13124 13125 ss7_chan->stripmsd = tmp->stripmsd; 13126 ss7_chan->hidecallerid = tmp->hidecallerid; 13127 ss7_chan->use_callerid = tmp->use_callerid; 13128 ss7_chan->use_callingpres = tmp->use_callingpres; 13129 ss7_chan->immediate = tmp->immediate; 13130 ss7_chan->locallyblocked = tmp->locallyblocked; 13131 ss7_chan->remotelyblocked = tmp->remotelyblocked; 13132 ast_copy_string(ss7_chan->context, tmp->context, 13133 sizeof(ss7_chan->context)); 13134 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret, 13135 sizeof(ss7_chan->mohinterpret)); 13136 } 13137 break; 13138 #endif /* defined(HAVE_SS7) */ 13139 default: 13140 /* The only sig submodule left should be sig_analog. */ 13141 analog_p = tmp->sig_pvt; 13142 if (analog_p) { 13143 analog_p->channel = tmp->channel; 13144 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 13145 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 13146 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 13147 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ 13148 analog_p->callreturn = conf->chan.callreturn; 13149 analog_p->cancallforward = conf->chan.cancallforward; 13150 analog_p->canpark = conf->chan.canpark; 13151 analog_p->dahditrcallerid = conf->chan.dahditrcallerid; 13152 analog_p->immediate = conf->chan.immediate; 13153 analog_p->permhidecallerid = conf->chan.permhidecallerid; 13154 analog_p->pulse = conf->chan.pulse; 13155 analog_p->threewaycalling = conf->chan.threewaycalling; 13156 analog_p->transfer = conf->chan.transfer; 13157 analog_p->transfertobusy = conf->chan.transfertobusy; 13158 analog_p->use_callerid = tmp->use_callerid; 13159 analog_p->use_smdi = tmp->use_smdi; 13160 analog_p->smdi_iface = tmp->smdi_iface; 13161 analog_p->outsigmod = ANALOG_SIG_NONE; 13162 analog_p->echotraining = conf->chan.echotraining; 13163 analog_p->cid_signalling = conf->chan.cid_signalling; 13164 analog_p->stripmsd = conf->chan.stripmsd; 13165 switch (conf->chan.cid_start) { 13166 case CID_START_POLARITY: 13167 analog_p->cid_start = ANALOG_CID_START_POLARITY; 13168 break; 13169 case CID_START_POLARITY_IN: 13170 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; 13171 break; 13172 case CID_START_DTMF_NOALERT: 13173 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; 13174 break; 13175 default: 13176 analog_p->cid_start = ANALOG_CID_START_RING; 13177 break; 13178 } 13179 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; 13180 analog_p->ringt = conf->chan.ringt; 13181 analog_p->ringt_base = ringt_base; 13182 analog_p->onhooktime = time(NULL); 13183 if (chan_sig & __DAHDI_SIG_FXO) { 13184 memset(&p, 0, sizeof(p)); 13185 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 13186 if (!res) { 13187 analog_p->fxsoffhookstate = p.rxisoffhook; 13188 } 13189 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 13190 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 13191 #endif 13192 } 13193 analog_p->msgstate = -1; 13194 13195 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); 13196 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); 13197 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); 13198 13199 analog_config_complete(analog_p); 13200 } 13201 break; 13202 } 13203 #if defined(HAVE_PRI) 13204 if (tmp->channel == CHAN_PSEUDO) { 13205 /* 13206 * Save off pseudo channel buffer policy values for dynamic creation of 13207 * no B channel interfaces. 13208 */ 13209 dahdi_pseudo_parms.buf_no = tmp->buf_no; 13210 dahdi_pseudo_parms.buf_policy = tmp->buf_policy; 13211 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no; 13212 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy; 13213 } 13214 #endif /* defined(HAVE_PRI) */ 13215 } 13216 if (tmp && !here) { 13217 /* Add the new channel interface to the sorted channel interface list. */ 13218 dahdi_iflist_insert(tmp); 13219 } 13220 return tmp; 13221 }
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 11270 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().
11271 { 11272 int x; 11273 11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11275 /* Determine how this spill is to be sent */ 11276 if (pvt->mwisend_rpas) { 11277 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11278 pvt->mwisendactive = 1; 11279 } else if (pvt->mwisend_fsk) { 11280 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11281 pvt->mwisendactive = 1; 11282 } else { 11283 pvt->mwisendactive = 0; 11284 return 0; 11285 } 11286 #else 11287 if (mwisend_rpas) { 11288 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11289 } else { 11290 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11291 } 11292 pvt->mwisendactive = 1; 11293 #endif 11294 11295 if (pvt->cidspill) { 11296 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 11297 ast_free(pvt->cidspill); 11298 pvt->cidspill = NULL; 11299 pvt->cidpos = 0; 11300 pvt->cidlen = 0; 11301 } 11302 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 11303 if (!pvt->cidspill) { 11304 pvt->mwisendactive = 0; 11305 return -1; 11306 } 11307 x = DAHDI_FLUSH_BOTH; 11308 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 11309 x = 3000; 11310 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 11311 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11312 if (pvt->mwisend_fsk) { 11313 #endif 11314 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 11315 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 11316 pvt->cidpos = 0; 11317 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11318 } 11319 #endif 11320 return 0; 11321 }
static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
int | num_read | |||
) | [static] |
Definition at line 11323 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().
11324 { 11325 struct timeval now; 11326 int res; 11327 11328 /* sanity check to catch if this had been interrupted previously 11329 * i.e. state says there is more to do but there is no spill allocated 11330 */ 11331 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 11332 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11333 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11334 /* Normal processing -- Perform mwi send action */ 11335 switch ( pvt->mwisend_data.mwisend_current) { 11336 case MWI_SEND_SA: 11337 /* Send the Ring Pulse Signal Alert */ 11338 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 11339 if (res) { 11340 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 11341 goto quit; 11342 } 11343 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 11344 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 11345 break; 11346 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 11347 break; 11348 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 11349 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11350 if (pvt->mwisend_fsk) { 11351 #endif 11352 gettimeofday(&now, NULL); 11353 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 11354 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11355 } 11356 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11357 } else { /* support for mwisendtype=nofsk */ 11358 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11359 } 11360 #endif 11361 break; 11362 case MWI_SEND_SPILL: 11363 /* We read some number of bytes. Write an equal amount of data */ 11364 if(0 < num_read) { 11365 if (num_read > pvt->cidlen - pvt->cidpos) 11366 num_read = pvt->cidlen - pvt->cidpos; 11367 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 11368 if (res > 0) { 11369 pvt->cidpos += res; 11370 if (pvt->cidpos >= pvt->cidlen) { 11371 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11372 } 11373 } else { 11374 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 11375 goto quit; 11376 } 11377 } 11378 break; 11379 case MWI_SEND_CLEANUP: 11380 /* For now, do nothing */ 11381 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11382 break; 11383 default: 11384 /* Should not get here, punt*/ 11385 goto quit; 11386 } 11387 } 11388 11389 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 11390 if (pvt->cidspill) { 11391 ast_free(pvt->cidspill); 11392 pvt->cidspill = NULL; 11393 pvt->cidpos = 0; 11394 pvt->cidlen = 0; 11395 } 11396 pvt->mwisendactive = 0; 11397 } 11398 return 0; 11399 quit: 11400 if (pvt->cidspill) { 11401 ast_free(pvt->cidspill); 11402 pvt->cidspill = NULL; 11403 pvt->cidpos = 0; 11404 pvt->cidlen = 0; 11405 } 11406 pvt->mwisendactive = 0; 11407 return -1; 11408 }
static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
int | event | |||
) | [static] |
Definition at line 11410 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().
11411 { 11412 int handled = 0; 11413 11414 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11415 switch (event) { 11416 case DAHDI_EVENT_RINGEROFF: 11417 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 11418 handled = 1; 11419 11420 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 11421 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno)); 11422 ast_free(pvt->cidspill); 11423 pvt->cidspill = NULL; 11424 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11425 pvt->mwisendactive = 0; 11426 } else { 11427 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 11428 gettimeofday(&pvt->mwisend_data.pause, NULL); 11429 } 11430 } 11431 break; 11432 /* Going off hook, I need to punt this spill */ 11433 case DAHDI_EVENT_RINGOFFHOOK: 11434 if (pvt->cidspill) { 11435 ast_free(pvt->cidspill); 11436 pvt->cidspill = NULL; 11437 pvt->cidpos = 0; 11438 pvt->cidlen = 0; 11439 } 11440 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11441 pvt->mwisendactive = 0; 11442 break; 11443 case DAHDI_EVENT_RINGERON: 11444 case DAHDI_EVENT_HOOKCOMPLETE: 11445 break; 11446 default: 11447 break; 11448 } 11449 } 11450 return handled; 11451 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 11118 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().
11119 { 11120 struct mwi_thread_data *mtd = data; 11121 struct callerid_state *cs; 11122 pthread_t threadid; 11123 int samples = 0; 11124 char *name, *number; 11125 int flags; 11126 int i, res; 11127 unsigned int spill_done = 0; 11128 int spill_result = -1; 11129 11130 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 11131 goto quit_no_clean; 11132 } 11133 11134 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 11135 11136 bump_gains(mtd->pvt); 11137 11138 for (;;) { 11139 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 11140 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 11141 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 11142 goto quit; 11143 } 11144 11145 if (i & DAHDI_IOMUX_SIGEVENT) { 11146 struct ast_channel *chan; 11147 11148 /* If we get an event, screen out events that we do not act on. 11149 * Otherwise, cancel and go to the simple switch to let it deal with it. 11150 */ 11151 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 11152 11153 switch (res) { 11154 case DAHDI_EVENT_NEONMWI_ACTIVE: 11155 case DAHDI_EVENT_NEONMWI_INACTIVE: 11156 case DAHDI_EVENT_NONE: 11157 case DAHDI_EVENT_BITSCHANGED: 11158 break; 11159 case DAHDI_EVENT_NOALARM: 11160 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11161 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11162 11163 analog_p->inalarm = 0; 11164 } 11165 mtd->pvt->inalarm = 0; 11166 handle_clear_alarms(mtd->pvt); 11167 break; 11168 case DAHDI_EVENT_ALARM: 11169 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11170 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11171 11172 analog_p->inalarm = 1; 11173 } 11174 mtd->pvt->inalarm = 1; 11175 res = get_alarms(mtd->pvt); 11176 handle_alarms(mtd->pvt, res); 11177 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 11178 default: 11179 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res)); 11180 callerid_free(cs); 11181 11182 restore_gains(mtd->pvt); 11183 mtd->pvt->ringt = mtd->pvt->ringt_base; 11184 11185 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) { 11186 int result; 11187 11188 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11189 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan); 11190 } else { 11191 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11192 } 11193 if (result) { 11194 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 11195 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11196 if (res < 0) 11197 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 11198 ast_hangup(chan); 11199 } 11200 } else { 11201 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 11202 } 11203 goto quit_no_clean; 11204 } 11205 } else if (i & DAHDI_IOMUX_READ) { 11206 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 11207 if (errno != ELAST) { 11208 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 11209 goto quit; 11210 } 11211 break; 11212 } 11213 samples += res; 11214 if (!spill_done) { 11215 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 11216 /* 11217 * The previous diagnostic message output likely 11218 * explains why it failed. 11219 */ 11220 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 11221 break; 11222 } else if (spill_result) { 11223 spill_done = 1; 11224 } 11225 } else { 11226 /* keep reading data until the energy level drops below the threshold 11227 so we don't get another 'trigger' on the remaining carrier signal 11228 */ 11229 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 11230 break; 11231 } 11232 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 11233 break; 11234 } 11235 } 11236 11237 if (spill_result == 1) { 11238 callerid_get(cs, &name, &number, &flags); 11239 if (flags & CID_MSGWAITING) { 11240 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 11241 notify_message(mtd->pvt->mailbox, 1); 11242 } else if (flags & CID_NOMSGWAITING) { 11243 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 11244 notify_message(mtd->pvt->mailbox, 0); 11245 } else { 11246 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 11247 } 11248 } 11249 11250 11251 quit: 11252 callerid_free(cs); 11253 11254 restore_gains(mtd->pvt); 11255 11256 quit_no_clean: 11257 mtd->pvt->mwimonitoractive = 0; 11258 ast_free(mtd); 11259 11260 return NULL; 11261 }
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_usec) { 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 9375 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().
09376 { 09377 int sent=0; 09378 int size; 09379 int res; 09380 int fd; 09381 fd = p->subs[idx].dfd; 09382 while (len) { 09383 size = len; 09384 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 09385 size = (linear ? READ_SIZE * 2 : READ_SIZE); 09386 res = write(fd, buf, size); 09387 if (res != size) { 09388 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 09389 return sent; 09390 } 09391 len -= size; 09392 buf += size; 09393 } 09394 return sent; 09395 }
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 %d\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 1738 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_free(), 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.
01739 { 01740 struct dahdi_pvt *p = pvt; 01741 struct analog_pvt *analog_p = p->sig_pvt; 01742 struct pollfd poller; 01743 char *name, *num; 01744 int index = SUB_REAL; 01745 int res; 01746 unsigned char buf[256]; 01747 int flags; 01748 01749 poller.fd = p->subs[SUB_REAL].dfd; 01750 poller.events = POLLPRI | POLLIN; 01751 poller.revents = 0; 01752 01753 res = poll(&poller, 1, timeout); 01754 01755 if (poller.revents & POLLPRI) { 01756 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd)); 01757 return 1; 01758 } 01759 01760 if (poller.revents & POLLIN) { 01761 /*** NOTES ***/ 01762 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function 01763 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until 01764 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be 01765 * a failure and die, and returning 2 means no event was received. */ 01766 res = read(p->subs[index].dfd, buf, sizeof(buf)); 01767 if (res < 0) { 01768 if (errno != ELAST) { 01769 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01770 callerid_free(p->cs); 01771 return -1; 01772 } 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 9857 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by analog_ss_thread().
09858 { 09859 char c; 09860 09861 *str = 0; /* start with empty output buffer */ 09862 for (;;) 09863 { 09864 /* Wait for the first digit (up to specified ms). */ 09865 c = ast_waitfordigit(chan, ms); 09866 /* if timeout, hangup or error, return as such */ 09867 if (c < 1) 09868 return c; 09869 *str++ = c; 09870 *str = 0; 09871 if (strchr(term, c)) 09872 return 1; 09873 } 09874 }
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 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 3684 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().
03685 { 03686 struct dahdi_pvt *p = pvt; 03687 03688 if (neon_mwievent > -1 && !p->mwimonitor_neon) 03689 return; 03690 03691 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) { 03692 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox); 03693 notify_message(p->mailbox, 1); 03694 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) { 03695 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox); 03696 notify_message(p->mailbox, 0); 03697 } 03698 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 03699 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 03700 if (neon_mwievent == -1 && p->mwimonitor_rpas) { 03701 ast_hangup(chan); 03702 return; 03703 } 03704 }
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 3706 of file chan_dahdi.c.
References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.
03707 { 03708 struct dahdi_pvt *p = pvt; 03709 03710 if ((p->callprogress & CALLPROGRESS_PROGRESS) 03711 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03712 return 1; 03713 } else { 03714 /* Don't have progress detection. */ 03715 return 0; 03716 } 03717 }
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 1713 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.
01714 { 01715 struct dahdi_pvt *p = pvt; 01716 int index = SUB_REAL; 01717 p->cs = callerid_new(cid_signalling); 01718 if (!p->cs) { 01719 ast_log(LOG_ERROR, "Unable to alloc callerid\n"); 01720 return -1; 01721 } 01722 bump_gains(p); 01723 dahdi_setlinear(p->subs[index].dfd, 0); 01724 01725 return 0; 01726 }
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 1728 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.
01729 { 01730 struct dahdi_pvt *p = pvt; 01731 int index = SUB_REAL; 01732 if (p->cs) 01733 callerid_free(p->cs); 01734 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 01735 return 0; 01736 }
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 3655 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().
03656 { 03657 char s[sizeof(mwimonitornotify) + 80]; 03658 struct ast_event *event; 03659 char *mailbox, *context; 03660 03661 /* Strip off @default */ 03662 context = mailbox = ast_strdupa(mailbox_full); 03663 strsep(&context, "@"); 03664 if (ast_strlen_zero(context)) 03665 context = "default"; 03666 03667 if (!(event = ast_event_new(AST_EVENT_MWI, 03668 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03669 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03670 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03671 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03672 AST_EVENT_IE_END))) { 03673 return; 03674 } 03675 03676 ast_event_queue_and_cache(event); 03677 03678 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 03679 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 03680 ast_safe_system(s); 03681 } 03682 }
static int parse_buffers_policy | ( | const char * | parse, | |
int * | num_buffers, | |||
int * | policy | |||
) | [static] |
Definition at line 7061 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write(), and process_dahdi().
07062 { 07063 int res; 07064 char policy_str[21] = ""; 07065 07066 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) { 07067 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 07068 return 1; 07069 } 07070 if (*num_buffers < 0) { 07071 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 07072 return -1; 07073 } 07074 if (!strcasecmp(policy_str, "full")) { 07075 *policy = DAHDI_POLICY_WHEN_FULL; 07076 } else if (!strcasecmp(policy_str, "immediate")) { 07077 *policy = DAHDI_POLICY_IMMEDIATE; 07078 #if defined(HAVE_DAHDI_HALF_FULL) 07079 } else if (!strcasecmp(policy_str, "half")) { 07080 *policy = DAHDI_POLICY_HALF_FULL; 07081 #endif 07082 } else { 07083 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 07084 return -1; 07085 } 07086 07087 return 0; 07088 }
static char* parse_spanchan | ( | char * | chanstr, | |
char ** | subdir | |||
) | [static] |
Definition at line 16856 of file chan_dahdi.c.
References string_replace().
Referenced by build_channels().
16857 { 16858 char *p; 16859 16860 if ((p = strrchr(chanstr, '!')) == NULL) { 16861 *subdir = NULL; 16862 return chanstr; 16863 } 16864 *p++ = '\0'; 16865 string_replace(chanstr, '!', '/'); 16866 *subdir = chanstr; 16867 return p; 16868 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 16999 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().
17000 { 17001 struct dahdi_pvt *tmp; 17002 int y; 17003 int found_pseudo = 0; 17004 struct ast_variable *dahdichan = NULL; 17005 17006 for (; v; v = v->next) { 17007 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 17008 continue; 17009 17010 /* Create the interface list */ 17011 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) { 17012 if (options & PROC_DAHDI_OPT_NOCHAN) { 17013 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 17014 continue; 17015 } 17016 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) { 17017 if (confp->ignore_failed_channels) { 17018 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value); 17019 continue; 17020 } else { 17021 return -1; 17022 } 17023 } 17024 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 17025 } else if (!strcasecmp(v->name, "ignore_failed_channels")) { 17026 confp->ignore_failed_channels = ast_true(v->value); 17027 } else if (!strcasecmp(v->name, "buffers")) { 17028 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 17029 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 17030 confp->chan.buf_no = numbufs; 17031 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 17032 } 17033 } else if (!strcasecmp(v->name, "faxbuffers")) { 17034 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) { 17035 confp->chan.usefaxbuffers = 1; 17036 } 17037 } else if (!strcasecmp(v->name, "dahdichan")) { 17038 /* Only process the last dahdichan value. */ 17039 dahdichan = v; 17040 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 17041 usedistinctiveringdetection = ast_true(v->value); 17042 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 17043 distinctiveringaftercid = ast_true(v->value); 17044 } else if (!strcasecmp(v->name, "dring1context")) { 17045 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 17046 } else if (!strcasecmp(v->name, "dring2context")) { 17047 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 17048 } else if (!strcasecmp(v->name, "dring3context")) { 17049 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 17050 } else if (!strcasecmp(v->name, "dring1range")) { 17051 confp->chan.drings.ringnum[0].range = atoi(v->value); 17052 } else if (!strcasecmp(v->name, "dring2range")) { 17053 confp->chan.drings.ringnum[1].range = atoi(v->value); 17054 } else if (!strcasecmp(v->name, "dring3range")) { 17055 confp->chan.drings.ringnum[2].range = atoi(v->value); 17056 } else if (!strcasecmp(v->name, "dring1")) { 17057 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]); 17058 } else if (!strcasecmp(v->name, "dring2")) { 17059 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]); 17060 } else if (!strcasecmp(v->name, "dring3")) { 17061 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]); 17062 } else if (!strcasecmp(v->name, "usecallerid")) { 17063 confp->chan.use_callerid = ast_true(v->value); 17064 } else if (!strcasecmp(v->name, "cidsignalling")) { 17065 if (!strcasecmp(v->value, "bell")) 17066 confp->chan.cid_signalling = CID_SIG_BELL; 17067 else if (!strcasecmp(v->value, "v23")) 17068 confp->chan.cid_signalling = CID_SIG_V23; 17069 else if (!strcasecmp(v->value, "dtmf")) 17070 confp->chan.cid_signalling = CID_SIG_DTMF; 17071 else if (!strcasecmp(v->value, "smdi")) 17072 confp->chan.cid_signalling = CID_SIG_SMDI; 17073 else if (!strcasecmp(v->value, "v23_jp")) 17074 confp->chan.cid_signalling = CID_SIG_V23_JP; 17075 else if (ast_true(v->value)) 17076 confp->chan.cid_signalling = CID_SIG_BELL; 17077 } else if (!strcasecmp(v->name, "cidstart")) { 17078 if (!strcasecmp(v->value, "ring")) 17079 confp->chan.cid_start = CID_START_RING; 17080 else if (!strcasecmp(v->value, "polarity_in")) 17081 confp->chan.cid_start = CID_START_POLARITY_IN; 17082 else if (!strcasecmp(v->value, "polarity")) 17083 confp->chan.cid_start = CID_START_POLARITY; 17084 else if (!strcasecmp(v->value, "dtmf")) 17085 confp->chan.cid_start = CID_START_DTMF_NOALERT; 17086 else if (ast_true(v->value)) 17087 confp->chan.cid_start = CID_START_RING; 17088 } else if (!strcasecmp(v->name, "threewaycalling")) { 17089 confp->chan.threewaycalling = ast_true(v->value); 17090 } else if (!strcasecmp(v->name, "cancallforward")) { 17091 confp->chan.cancallforward = ast_true(v->value); 17092 } else if (!strcasecmp(v->name, "relaxdtmf")) { 17093 if (ast_true(v->value)) 17094 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 17095 else 17096 confp->chan.dtmfrelax = 0; 17097 } else if (!strcasecmp(v->name, "mailbox")) { 17098 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 17099 } else if (!strcasecmp(v->name, "hasvoicemail")) { 17100 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 17101 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 17102 } 17103 } else if (!strcasecmp(v->name, "adsi")) { 17104 confp->chan.adsi = ast_true(v->value); 17105 } else if (!strcasecmp(v->name, "usesmdi")) { 17106 confp->chan.use_smdi = ast_true(v->value); 17107 } else if (!strcasecmp(v->name, "smdiport")) { 17108 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 17109 } else if (!strcasecmp(v->name, "transfer")) { 17110 confp->chan.transfer = ast_true(v->value); 17111 } else if (!strcasecmp(v->name, "canpark")) { 17112 confp->chan.canpark = ast_true(v->value); 17113 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 17114 confp->chan.echocanbridged = ast_true(v->value); 17115 } else if (!strcasecmp(v->name, "busydetect")) { 17116 confp->chan.busydetect = ast_true(v->value); 17117 } else if (!strcasecmp(v->name, "busycount")) { 17118 confp->chan.busycount = atoi(v->value); 17119 } else if (!strcasecmp(v->name, "silencethreshold")) { 17120 confp->chan.silencethreshold = atoi(v->value); 17121 } else if (!strcasecmp(v->name, "busycompare")) { 17122 confp->chan.busycompare = ast_true(v->value); 17123 } else if (!strcasecmp(v->name, "busypattern")) { 17124 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 17125 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 17126 } 17127 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 17128 if (count == 1) 17129 confp->chan.busyquietlength = 0; 17130 else if (count < 1) 17131 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 17132 } else if (!strcasecmp(v->name, "busyfuzziness")) { 17133 confp->chan.busyfuzziness = atoi(v->value); 17134 } else if (!strcasecmp(v->name, "callprogress")) { 17135 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 17136 if (ast_true(v->value)) 17137 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 17138 } else if (!strcasecmp(v->name, "waitfordialtone")) { 17139 confp->chan.waitfordialtone = atoi(v->value); 17140 } else if (!strcasecmp(v->name, "faxdetect")) { 17141 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 17142 if (!strcasecmp(v->value, "incoming")) { 17143 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 17144 } else if (!strcasecmp(v->value, "outgoing")) { 17145 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 17146 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 17147 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 17148 } else if (!strcasecmp(v->name, "echocancel")) { 17149 process_echocancel(confp, v->value, v->lineno); 17150 } else if (!strcasecmp(v->name, "echotraining")) { 17151 if (sscanf(v->value, "%30d", &y) == 1) { 17152 if ((y < 10) || (y > 4000)) { 17153 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 17154 } else { 17155 confp->chan.echotraining = y; 17156 } 17157 } else if (ast_true(v->value)) { 17158 confp->chan.echotraining = 400; 17159 } else 17160 confp->chan.echotraining = 0; 17161 } else if (!strcasecmp(v->name, "hidecallerid")) { 17162 confp->chan.hidecallerid = ast_true(v->value); 17163 } else if (!strcasecmp(v->name, "hidecalleridname")) { 17164 confp->chan.hidecalleridname = ast_true(v->value); 17165 } else if (!strcasecmp(v->name, "pulsedial")) { 17166 confp->chan.pulse = ast_true(v->value); 17167 } else if (!strcasecmp(v->name, "callreturn")) { 17168 confp->chan.callreturn = ast_true(v->value); 17169 } else if (!strcasecmp(v->name, "callwaiting")) { 17170 confp->chan.callwaiting = ast_true(v->value); 17171 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 17172 confp->chan.callwaitingcallerid = ast_true(v->value); 17173 } else if (!strcasecmp(v->name, "context")) { 17174 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 17175 } else if (!strcasecmp(v->name, "language")) { 17176 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 17177 } else if (!strcasecmp(v->name, "progzone")) { 17178 ast_copy_string(progzone, v->value, sizeof(progzone)); 17179 } else if (!strcasecmp(v->name, "mohinterpret") 17180 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 17181 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 17182 } else if (!strcasecmp(v->name, "mohsuggest")) { 17183 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 17184 } else if (!strcasecmp(v->name, "parkinglot")) { 17185 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 17186 } else if (!strcasecmp(v->name, "stripmsd")) { 17187 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 17188 confp->chan.stripmsd = atoi(v->value); 17189 } else if (!strcasecmp(v->name, "jitterbuffers")) { 17190 numbufs = atoi(v->value); 17191 } else if (!strcasecmp(v->name, "group")) { 17192 confp->chan.group = ast_get_group(v->value); 17193 } else if (!strcasecmp(v->name, "callgroup")) { 17194 if (!strcasecmp(v->value, "none")) 17195 confp->chan.callgroup = 0; 17196 else 17197 confp->chan.callgroup = ast_get_group(v->value); 17198 } else if (!strcasecmp(v->name, "pickupgroup")) { 17199 if (!strcasecmp(v->value, "none")) 17200 confp->chan.pickupgroup = 0; 17201 else 17202 confp->chan.pickupgroup = ast_get_group(v->value); 17203 } else if (!strcasecmp(v->name, "setvar")) { 17204 char *varname = ast_strdupa(v->value), *varval = NULL; 17205 struct ast_variable *tmpvar; 17206 if (varname && (varval = strchr(varname, '='))) { 17207 *varval++ = '\0'; 17208 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 17209 tmpvar->next = confp->chan.vars; 17210 confp->chan.vars = tmpvar; 17211 } 17212 } 17213 } else if (!strcasecmp(v->name, "immediate")) { 17214 confp->chan.immediate = ast_true(v->value); 17215 } else if (!strcasecmp(v->name, "transfertobusy")) { 17216 confp->chan.transfertobusy = ast_true(v->value); 17217 } else if (!strcasecmp(v->name, "mwimonitor")) { 17218 confp->chan.mwimonitor_neon = 0; 17219 confp->chan.mwimonitor_fsk = 0; 17220 confp->chan.mwimonitor_rpas = 0; 17221 if (strcasestr(v->value, "fsk")) { 17222 confp->chan.mwimonitor_fsk = 1; 17223 } 17224 if (strcasestr(v->value, "rpas")) { 17225 confp->chan.mwimonitor_rpas = 1; 17226 } 17227 if (strcasestr(v->value, "neon")) { 17228 confp->chan.mwimonitor_neon = 1; 17229 } 17230 /* If set to true or yes, assume that simple fsk is desired */ 17231 if (ast_true(v->value)) { 17232 confp->chan.mwimonitor_fsk = 1; 17233 } 17234 } else if (!strcasecmp(v->name, "cid_rxgain")) { 17235 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 17236 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 17237 } 17238 } else if (!strcasecmp(v->name, "rxgain")) { 17239 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 17240 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 17241 } 17242 } else if (!strcasecmp(v->name, "txgain")) { 17243 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 17244 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 17245 } 17246 } else if (!strcasecmp(v->name, "txdrc")) { 17247 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) { 17248 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value); 17249 } 17250 } else if (!strcasecmp(v->name, "rxdrc")) { 17251 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) { 17252 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value); 17253 } 17254 } else if (!strcasecmp(v->name, "tonezone")) { 17255 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 17256 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 17257 } 17258 } else if (!strcasecmp(v->name, "callerid")) { 17259 if (!strcasecmp(v->value, "asreceived")) { 17260 confp->chan.cid_num[0] = '\0'; 17261 confp->chan.cid_name[0] = '\0'; 17262 } else { 17263 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 17264 } 17265 } else if (!strcasecmp(v->name, "fullname")) { 17266 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 17267 } else if (!strcasecmp(v->name, "cid_number")) { 17268 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 17269 } else if (!strcasecmp(v->name, "cid_tag")) { 17270 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); 17271 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 17272 confp->chan.dahditrcallerid = ast_true(v->value); 17273 } else if (!strcasecmp(v->name, "restrictcid")) { 17274 confp->chan.restrictcid = ast_true(v->value); 17275 } else if (!strcasecmp(v->name, "usecallingpres")) { 17276 confp->chan.use_callingpres = ast_true(v->value); 17277 } else if (!strcasecmp(v->name, "accountcode")) { 17278 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 17279 } else if (!strcasecmp(v->name, "amaflags")) { 17280 y = ast_cdr_amaflags2int(v->value); 17281 if (y < 0) 17282 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 17283 else 17284 confp->chan.amaflags = y; 17285 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 17286 confp->chan.polarityonanswerdelay = atoi(v->value); 17287 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 17288 confp->chan.answeronpolarityswitch = ast_true(v->value); 17289 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 17290 confp->chan.hanguponpolarityswitch = ast_true(v->value); 17291 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 17292 confp->chan.sendcalleridafter = atoi(v->value); 17293 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 17294 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 17295 } else if (ast_cc_is_config_param(v->name)) { 17296 ast_cc_set_param(confp->chan.cc_params, v->name, v->value); 17297 } else if (!strcasecmp(v->name, "mwisendtype")) { 17298 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 17299 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 17300 mwisend_rpas = 1; 17301 } else { 17302 mwisend_rpas = 0; 17303 } 17304 #else 17305 /* Default is fsk, to turn it off you must specify nofsk */ 17306 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 17307 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 17308 confp->chan.mwisend_fsk = 0; 17309 } else { /* Default FSK */ 17310 confp->chan.mwisend_fsk = 1; 17311 } 17312 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 17313 confp->chan.mwisend_rpas = 1; 17314 } else { 17315 confp->chan.mwisend_rpas = 0; 17316 } 17317 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 17318 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 17319 } 17320 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 17321 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 17322 } 17323 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 17324 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 17325 } 17326 #endif 17327 } else if (reload != 1) { 17328 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 17329 int orig_radio = confp->chan.radio; 17330 int orig_outsigmod = confp->chan.outsigmod; 17331 int orig_auto = confp->is_sig_auto; 17332 17333 confp->chan.radio = 0; 17334 confp->chan.outsigmod = -1; 17335 confp->is_sig_auto = 0; 17336 if (!strcasecmp(v->value, "em")) { 17337 confp->chan.sig = SIG_EM; 17338 } else if (!strcasecmp(v->value, "em_e1")) { 17339 confp->chan.sig = SIG_EM_E1; 17340 } else if (!strcasecmp(v->value, "em_w")) { 17341 confp->chan.sig = SIG_EMWINK; 17342 } else if (!strcasecmp(v->value, "fxs_ls")) { 17343 confp->chan.sig = SIG_FXSLS; 17344 } else if (!strcasecmp(v->value, "fxs_gs")) { 17345 confp->chan.sig = SIG_FXSGS; 17346 } else if (!strcasecmp(v->value, "fxs_ks")) { 17347 confp->chan.sig = SIG_FXSKS; 17348 } else if (!strcasecmp(v->value, "fxo_ls")) { 17349 confp->chan.sig = SIG_FXOLS; 17350 } else if (!strcasecmp(v->value, "fxo_gs")) { 17351 confp->chan.sig = SIG_FXOGS; 17352 } else if (!strcasecmp(v->value, "fxo_ks")) { 17353 confp->chan.sig = SIG_FXOKS; 17354 } else if (!strcasecmp(v->value, "fxs_rx")) { 17355 confp->chan.sig = SIG_FXSKS; 17356 confp->chan.radio = 1; 17357 } else if (!strcasecmp(v->value, "fxo_rx")) { 17358 confp->chan.sig = SIG_FXOLS; 17359 confp->chan.radio = 1; 17360 } else if (!strcasecmp(v->value, "fxs_tx")) { 17361 confp->chan.sig = SIG_FXSLS; 17362 confp->chan.radio = 1; 17363 } else if (!strcasecmp(v->value, "fxo_tx")) { 17364 confp->chan.sig = SIG_FXOGS; 17365 confp->chan.radio = 1; 17366 } else if (!strcasecmp(v->value, "em_rx")) { 17367 confp->chan.sig = SIG_EM; 17368 confp->chan.radio = 1; 17369 } else if (!strcasecmp(v->value, "em_tx")) { 17370 confp->chan.sig = SIG_EM; 17371 confp->chan.radio = 1; 17372 } else if (!strcasecmp(v->value, "em_rxtx")) { 17373 confp->chan.sig = SIG_EM; 17374 confp->chan.radio = 2; 17375 } else if (!strcasecmp(v->value, "em_txrx")) { 17376 confp->chan.sig = SIG_EM; 17377 confp->chan.radio = 2; 17378 } else if (!strcasecmp(v->value, "sf")) { 17379 confp->chan.sig = SIG_SF; 17380 } else if (!strcasecmp(v->value, "sf_w")) { 17381 confp->chan.sig = SIG_SFWINK; 17382 } else if (!strcasecmp(v->value, "sf_featd")) { 17383 confp->chan.sig = SIG_FEATD; 17384 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17385 confp->chan.sig = SIG_FEATDMF; 17386 } else if (!strcasecmp(v->value, "sf_featb")) { 17387 confp->chan.sig = SIG_SF_FEATB; 17388 } else if (!strcasecmp(v->value, "sf")) { 17389 confp->chan.sig = SIG_SF; 17390 } else if (!strcasecmp(v->value, "sf_rx")) { 17391 confp->chan.sig = SIG_SF; 17392 confp->chan.radio = 1; 17393 } else if (!strcasecmp(v->value, "sf_tx")) { 17394 confp->chan.sig = SIG_SF; 17395 confp->chan.radio = 1; 17396 } else if (!strcasecmp(v->value, "sf_rxtx")) { 17397 confp->chan.sig = SIG_SF; 17398 confp->chan.radio = 2; 17399 } else if (!strcasecmp(v->value, "sf_txrx")) { 17400 confp->chan.sig = SIG_SF; 17401 confp->chan.radio = 2; 17402 } else if (!strcasecmp(v->value, "featd")) { 17403 confp->chan.sig = SIG_FEATD; 17404 } else if (!strcasecmp(v->value, "featdmf")) { 17405 confp->chan.sig = SIG_FEATDMF; 17406 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17407 confp->chan.sig = SIG_FEATDMF_TA; 17408 } else if (!strcasecmp(v->value, "e911")) { 17409 confp->chan.sig = SIG_E911; 17410 } else if (!strcasecmp(v->value, "fgccama")) { 17411 confp->chan.sig = SIG_FGC_CAMA; 17412 } else if (!strcasecmp(v->value, "fgccamamf")) { 17413 confp->chan.sig = SIG_FGC_CAMAMF; 17414 } else if (!strcasecmp(v->value, "featb")) { 17415 confp->chan.sig = SIG_FEATB; 17416 #ifdef HAVE_PRI 17417 } else if (!strcasecmp(v->value, "pri_net")) { 17418 confp->chan.sig = SIG_PRI; 17419 confp->pri.pri.nodetype = PRI_NETWORK; 17420 } else if (!strcasecmp(v->value, "pri_cpe")) { 17421 confp->chan.sig = SIG_PRI; 17422 confp->pri.pri.nodetype = PRI_CPE; 17423 } else if (!strcasecmp(v->value, "bri_cpe")) { 17424 confp->chan.sig = SIG_BRI; 17425 confp->pri.pri.nodetype = PRI_CPE; 17426 } else if (!strcasecmp(v->value, "bri_net")) { 17427 confp->chan.sig = SIG_BRI; 17428 confp->pri.pri.nodetype = PRI_NETWORK; 17429 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 17430 confp->chan.sig = SIG_BRI_PTMP; 17431 confp->pri.pri.nodetype = PRI_CPE; 17432 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 17433 #if defined(HAVE_PRI_CALL_HOLD) 17434 confp->chan.sig = SIG_BRI_PTMP; 17435 confp->pri.pri.nodetype = PRI_NETWORK; 17436 #else 17437 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 17438 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 17439 #endif 17440 #if defined(HAVE_SS7) 17441 } else if (!strcasecmp(v->value, "ss7")) { 17442 confp->chan.sig = SIG_SS7; 17443 #endif /* defined(HAVE_SS7) */ 17444 #ifdef HAVE_OPENR2 17445 } else if (!strcasecmp(v->value, "mfcr2")) { 17446 confp->chan.sig = SIG_MFCR2; 17447 #endif 17448 } else if (!strcasecmp(v->value, "auto")) { 17449 confp->is_sig_auto = 1; 17450 } else { 17451 confp->chan.outsigmod = orig_outsigmod; 17452 confp->chan.radio = orig_radio; 17453 confp->is_sig_auto = orig_auto; 17454 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17455 } 17456 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 17457 if (!strcasecmp(v->value, "em")) { 17458 confp->chan.outsigmod = SIG_EM; 17459 } else if (!strcasecmp(v->value, "em_e1")) { 17460 confp->chan.outsigmod = SIG_EM_E1; 17461 } else if (!strcasecmp(v->value, "em_w")) { 17462 confp->chan.outsigmod = SIG_EMWINK; 17463 } else if (!strcasecmp(v->value, "sf")) { 17464 confp->chan.outsigmod = SIG_SF; 17465 } else if (!strcasecmp(v->value, "sf_w")) { 17466 confp->chan.outsigmod = SIG_SFWINK; 17467 } else if (!strcasecmp(v->value, "sf_featd")) { 17468 confp->chan.outsigmod = SIG_FEATD; 17469 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17470 confp->chan.outsigmod = SIG_FEATDMF; 17471 } else if (!strcasecmp(v->value, "sf_featb")) { 17472 confp->chan.outsigmod = SIG_SF_FEATB; 17473 } else if (!strcasecmp(v->value, "sf")) { 17474 confp->chan.outsigmod = SIG_SF; 17475 } else if (!strcasecmp(v->value, "featd")) { 17476 confp->chan.outsigmod = SIG_FEATD; 17477 } else if (!strcasecmp(v->value, "featdmf")) { 17478 confp->chan.outsigmod = SIG_FEATDMF; 17479 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17480 confp->chan.outsigmod = SIG_FEATDMF_TA; 17481 } else if (!strcasecmp(v->value, "e911")) { 17482 confp->chan.outsigmod = SIG_E911; 17483 } else if (!strcasecmp(v->value, "fgccama")) { 17484 confp->chan.outsigmod = SIG_FGC_CAMA; 17485 } else if (!strcasecmp(v->value, "fgccamamf")) { 17486 confp->chan.outsigmod = SIG_FGC_CAMAMF; 17487 } else if (!strcasecmp(v->value, "featb")) { 17488 confp->chan.outsigmod = SIG_FEATB; 17489 } else { 17490 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17491 } 17492 #ifdef HAVE_PRI 17493 } else if (!strcasecmp(v->name, "pridialplan")) { 17494 if (!strcasecmp(v->value, "national")) { 17495 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1; 17496 } else if (!strcasecmp(v->value, "unknown")) { 17497 confp->pri.pri.dialplan = PRI_UNKNOWN + 1; 17498 } else if (!strcasecmp(v->value, "private")) { 17499 confp->pri.pri.dialplan = PRI_PRIVATE + 1; 17500 } else if (!strcasecmp(v->value, "international")) { 17501 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 17502 } else if (!strcasecmp(v->value, "local")) { 17503 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1; 17504 } else if (!strcasecmp(v->value, "dynamic")) { 17505 confp->pri.pri.dialplan = -1; 17506 } else if (!strcasecmp(v->value, "redundant")) { 17507 confp->pri.pri.dialplan = -2; 17508 } else { 17509 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 17510 } 17511 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 17512 if (!strcasecmp(v->value, "national")) { 17513 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1; 17514 } else if (!strcasecmp(v->value, "unknown")) { 17515 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1; 17516 } else if (!strcasecmp(v->value, "private")) { 17517 confp->pri.pri.localdialplan = PRI_PRIVATE + 1; 17518 } else if (!strcasecmp(v->value, "international")) { 17519 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 17520 } else if (!strcasecmp(v->value, "local")) { 17521 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1; 17522 } else if (!strcasecmp(v->value, "dynamic")) { 17523 confp->pri.pri.localdialplan = -1; 17524 } else if (!strcasecmp(v->value, "redundant")) { 17525 confp->pri.pri.localdialplan = -2; 17526 } else { 17527 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 17528 } 17529 } else if (!strcasecmp(v->name, "switchtype")) { 17530 if (!strcasecmp(v->value, "national")) 17531 confp->pri.pri.switchtype = PRI_SWITCH_NI2; 17532 else if (!strcasecmp(v->value, "ni1")) 17533 confp->pri.pri.switchtype = PRI_SWITCH_NI1; 17534 else if (!strcasecmp(v->value, "dms100")) 17535 confp->pri.pri.switchtype = PRI_SWITCH_DMS100; 17536 else if (!strcasecmp(v->value, "4ess")) 17537 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS; 17538 else if (!strcasecmp(v->value, "5ess")) 17539 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E; 17540 else if (!strcasecmp(v->value, "euroisdn")) 17541 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1; 17542 else if (!strcasecmp(v->value, "qsig")) 17543 confp->pri.pri.switchtype = PRI_SWITCH_QSIG; 17544 else { 17545 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 17546 return -1; 17547 } 17548 } else if (!strcasecmp(v->name, "msn")) { 17549 ast_copy_string(confp->pri.pri.msn_list, v->value, 17550 sizeof(confp->pri.pri.msn_list)); 17551 } else if (!strcasecmp(v->name, "nsf")) { 17552 if (!strcasecmp(v->value, "sdn")) 17553 confp->pri.pri.nsf = PRI_NSF_SDN; 17554 else if (!strcasecmp(v->value, "megacom")) 17555 confp->pri.pri.nsf = PRI_NSF_MEGACOM; 17556 else if (!strcasecmp(v->value, "tollfreemegacom")) 17557 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 17558 else if (!strcasecmp(v->value, "accunet")) 17559 confp->pri.pri.nsf = PRI_NSF_ACCUNET; 17560 else if (!strcasecmp(v->value, "none")) 17561 confp->pri.pri.nsf = PRI_NSF_NONE; 17562 else { 17563 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 17564 confp->pri.pri.nsf = PRI_NSF_NONE; 17565 } 17566 } else if (!strcasecmp(v->name, "priindication")) { 17567 if (!strcasecmp(v->value, "outofband")) 17568 confp->chan.priindication_oob = 1; 17569 else if (!strcasecmp(v->value, "inband")) 17570 confp->chan.priindication_oob = 0; 17571 else 17572 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 17573 v->value, v->lineno); 17574 } else if (!strcasecmp(v->name, "priexclusive")) { 17575 confp->chan.priexclusive = ast_true(v->value); 17576 } else if (!strcasecmp(v->name, "internationalprefix")) { 17577 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix)); 17578 } else if (!strcasecmp(v->name, "nationalprefix")) { 17579 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix)); 17580 } else if (!strcasecmp(v->name, "localprefix")) { 17581 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix)); 17582 } else if (!strcasecmp(v->name, "privateprefix")) { 17583 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix)); 17584 } else if (!strcasecmp(v->name, "unknownprefix")) { 17585 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix)); 17586 } else if (!strcasecmp(v->name, "resetinterval")) { 17587 if (!strcasecmp(v->value, "never")) 17588 confp->pri.pri.resetinterval = -1; 17589 else if (atoi(v->value) >= 60) 17590 confp->pri.pri.resetinterval = atoi(v->value); 17591 else 17592 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 17593 v->value, v->lineno); 17594 } else if (!strcasecmp(v->name, "minunused")) { 17595 confp->pri.pri.minunused = atoi(v->value); 17596 } else if (!strcasecmp(v->name, "minidle")) { 17597 confp->pri.pri.minidle = atoi(v->value); 17598 } else if (!strcasecmp(v->name, "idleext")) { 17599 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext)); 17600 } else if (!strcasecmp(v->name, "idledial")) { 17601 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial)); 17602 } else if (!strcasecmp(v->name, "overlapdial")) { 17603 if (ast_true(v->value)) { 17604 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17605 } else if (!strcasecmp(v->value, "incoming")) { 17606 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 17607 } else if (!strcasecmp(v->value, "outgoing")) { 17608 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 17609 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 17610 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17611 } else { 17612 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 17613 } 17614 #ifdef HAVE_PRI_PROG_W_CAUSE 17615 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 17616 if (!strcasecmp(v->value, "logical")) { 17617 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 17618 } else if (!strcasecmp(v->value, "physical")) { 17619 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17620 } else { 17621 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17622 } 17623 #endif 17624 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 17625 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value); 17626 #if defined(HAVE_PRI_SERVICE_MESSAGES) 17627 } else if (!strcasecmp(v->name, "service_message_support")) { 17628 /* assuming switchtype for this channel group has been configured already */ 17629 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 17630 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E 17631 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) { 17632 confp->pri.pri.enable_service_message_support = 1; 17633 } else { 17634 confp->pri.pri.enable_service_message_support = 0; 17635 } 17636 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 17637 #ifdef HAVE_PRI_INBANDDISCONNECT 17638 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 17639 confp->pri.pri.inbanddisconnect = ast_true(v->value); 17640 #endif 17641 } else if (!strcasecmp(v->name, "pritimer")) { 17642 #ifdef PRI_GETSET_TIMERS 17643 char tmp[20]; 17644 char *timerc; 17645 char *c; 17646 int timer; 17647 int timeridx; 17648 17649 ast_copy_string(tmp, v->value, sizeof(tmp)); 17650 c = tmp; 17651 timerc = strsep(&c, ","); 17652 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 17653 timeridx = pri_timer2idx(timerc); 17654 timer = atoi(c); 17655 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 17656 ast_log(LOG_WARNING, 17657 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 17658 v->lineno); 17659 } else if (!timer) { 17660 ast_log(LOG_WARNING, 17661 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 17662 c, timerc, v->lineno); 17663 } else { 17664 confp->pri.pri.pritimers[timeridx] = timer; 17665 } 17666 } else { 17667 ast_log(LOG_WARNING, 17668 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 17669 v->value, v->lineno); 17670 } 17671 #endif /* PRI_GETSET_TIMERS */ 17672 } else if (!strcasecmp(v->name, "facilityenable")) { 17673 confp->pri.pri.facilityenable = ast_true(v->value); 17674 #if defined(HAVE_PRI_AOC_EVENTS) 17675 } else if (!strcasecmp(v->name, "aoc_enable")) { 17676 confp->pri.pri.aoc_passthrough_flag = 0; 17677 if (strchr(v->value, 's') || strchr(v->value, 'S')) { 17678 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S; 17679 } 17680 if (strchr(v->value, 'd') || strchr(v->value, 'D')) { 17681 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D; 17682 } 17683 if (strchr(v->value, 'e') || strchr(v->value, 'E')) { 17684 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E; 17685 } 17686 } else if (!strcasecmp(v->name, "aoce_delayhangup")) { 17687 confp->pri.pri.aoce_delayhangup = ast_true(v->value); 17688 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 17689 #if defined(HAVE_PRI_CALL_HOLD) 17690 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) { 17691 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value); 17692 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 17693 #if defined(HAVE_PRI_CCSS) 17694 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) { 17695 if (!strcasecmp(v->value, "global")) { 17696 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */ 17697 } else if (!strcasecmp(v->value, "specific")) { 17698 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17699 } else { 17700 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17701 } 17702 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) { 17703 if (!strcasecmp(v->value, "release")) { 17704 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */ 17705 } else if (!strcasecmp(v->value, "retain")) { 17706 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17707 } else if (!strcasecmp(v->value, "do_not_care")) { 17708 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */ 17709 } else { 17710 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17711 } 17712 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) { 17713 if (!strcasecmp(v->value, "release")) { 17714 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */ 17715 } else if (!strcasecmp(v->value, "retain")) { 17716 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17717 } else { 17718 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17719 } 17720 #endif /* defined(HAVE_PRI_CCSS) */ 17721 #if defined(HAVE_PRI_CALL_WAITING) 17722 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) { 17723 confp->pri.pri.max_call_waiting_calls = atoi(v->value); 17724 if (confp->pri.pri.max_call_waiting_calls < 0) { 17725 /* Negative values are not allowed. */ 17726 confp->pri.pri.max_call_waiting_calls = 0; 17727 } 17728 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) { 17729 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value); 17730 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 17731 #if defined(HAVE_PRI_MWI) 17732 } else if (!strcasecmp(v->name, "mwi_mailboxes")) { 17733 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value, 17734 sizeof(confp->pri.pri.mwi_mailboxes)); 17735 #endif /* defined(HAVE_PRI_MWI) */ 17736 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) { 17737 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value); 17738 } else if (!strcasecmp(v->name, "layer1_presence")) { 17739 if (!strcasecmp(v->value, "required")) { 17740 confp->pri.pri.layer1_ignored = 0; 17741 } else if (!strcasecmp(v->value, "ignore")) { 17742 confp->pri.pri.layer1_ignored = 1; 17743 } else { 17744 /* Default */ 17745 confp->pri.pri.layer1_ignored = 0; 17746 } 17747 #if defined(HAVE_PRI_L2_PERSISTENCE) 17748 } else if (!strcasecmp(v->name, "layer2_persistence")) { 17749 if (!strcasecmp(v->value, "keep_up")) { 17750 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP; 17751 } else if (!strcasecmp(v->value, "leave_down")) { 17752 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN; 17753 } else { 17754 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT; 17755 } 17756 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 17757 #endif /* HAVE_PRI */ 17758 #if defined(HAVE_SS7) 17759 } else if (!strcasecmp(v->name, "ss7type")) { 17760 if (!strcasecmp(v->value, "itu")) { 17761 cur_ss7type = SS7_ITU; 17762 } else if (!strcasecmp(v->value, "ansi")) { 17763 cur_ss7type = SS7_ANSI; 17764 } else 17765 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 17766 } else if (!strcasecmp(v->name, "linkset")) { 17767 cur_linkset = atoi(v->value); 17768 } else if (!strcasecmp(v->name, "pointcode")) { 17769 cur_pointcode = parse_pointcode(v->value); 17770 } else if (!strcasecmp(v->name, "adjpointcode")) { 17771 cur_adjpointcode = parse_pointcode(v->value); 17772 } else if (!strcasecmp(v->name, "defaultdpc")) { 17773 cur_defaultdpc = parse_pointcode(v->value); 17774 } else if (!strcasecmp(v->name, "cicbeginswith")) { 17775 cur_cicbeginswith = atoi(v->value); 17776 } else if (!strcasecmp(v->name, "networkindicator")) { 17777 if (!strcasecmp(v->value, "national")) 17778 cur_networkindicator = SS7_NI_NAT; 17779 else if (!strcasecmp(v->value, "national_spare")) 17780 cur_networkindicator = SS7_NI_NAT_SPARE; 17781 else if (!strcasecmp(v->value, "international")) 17782 cur_networkindicator = SS7_NI_INT; 17783 else if (!strcasecmp(v->value, "international_spare")) 17784 cur_networkindicator = SS7_NI_INT_SPARE; 17785 else 17786 cur_networkindicator = -1; 17787 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 17788 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix)); 17789 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 17790 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix)); 17791 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 17792 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix)); 17793 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 17794 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix)); 17795 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 17796 if (!strcasecmp(v->value, "national")) { 17797 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL; 17798 } else if (!strcasecmp(v->value, "international")) { 17799 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL; 17800 } else if (!strcasecmp(v->value, "subscriber")) { 17801 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER; 17802 } else if (!strcasecmp(v->value, "unknown")) { 17803 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN; 17804 } else if (!strcasecmp(v->value, "dynamic")) { 17805 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC; 17806 } else { 17807 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 17808 } 17809 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 17810 if (!strcasecmp(v->value, "national")) { 17811 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL; 17812 } else if (!strcasecmp(v->value, "international")) { 17813 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL; 17814 } else if (!strcasecmp(v->value, "subscriber")) { 17815 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER; 17816 } else if (!strcasecmp(v->value, "unknown")) { 17817 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN; 17818 } else if (!strcasecmp(v->value, "dynamic")) { 17819 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC; 17820 } else { 17821 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 17822 } 17823 } else if (!strcasecmp(v->name, "sigchan")) { 17824 int sigchan, res; 17825 sigchan = atoi(v->value); 17826 res = linkset_addsigchan(sigchan); 17827 if (res < 0) 17828 return -1; 17829 17830 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 17831 struct dahdi_ss7 *link; 17832 link = ss7_resolve_linkset(cur_linkset); 17833 if (!link) { 17834 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 17835 return -1; 17836 } 17837 if (ast_true(v->value)) 17838 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM; 17839 #endif /* defined(HAVE_SS7) */ 17840 #ifdef HAVE_OPENR2 17841 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 17842 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 17843 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); 17844 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 17845 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 17846 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 17847 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 17848 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 17849 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 17850 confp->mfcr2.variant = OR2_VAR_ITU; 17851 } 17852 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 17853 confp->mfcr2.mfback_timeout = atoi(v->value); 17854 if (!confp->mfcr2.mfback_timeout) { 17855 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 17856 confp->mfcr2.mfback_timeout = -1; 17857 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 17858 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 17859 } 17860 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 17861 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 17862 if (confp->mfcr2.metering_pulse_timeout > 500) { 17863 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 17864 } 17865 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 17866 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 17867 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 17868 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 17869 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 17870 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 17871 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 17872 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 17873 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 17874 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 17875 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 17876 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 17877 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 17878 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 17879 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 17880 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 17881 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0; 17882 #endif 17883 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 17884 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 17885 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 17886 confp->mfcr2.max_ani = atoi(v->value); 17887 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 17888 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 17889 } 17890 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 17891 confp->mfcr2.max_dnis = atoi(v->value); 17892 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 17893 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 17894 } 17895 } else if (!strcasecmp(v->name, "mfcr2_category")) { 17896 confp->mfcr2.category = openr2_proto_get_category(v->value); 17897 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 17898 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 17899 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 17900 v->value, v->lineno); 17901 } 17902 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 17903 openr2_log_level_t tmplevel; 17904 char *clevel; 17905 char *logval = ast_strdupa(v->value); 17906 while (logval) { 17907 clevel = strsep(&logval,","); 17908 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 17909 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 17910 continue; 17911 } 17912 confp->mfcr2.loglevel |= tmplevel; 17913 } 17914 #endif /* HAVE_OPENR2 */ 17915 } else if (!strcasecmp(v->name, "cadence")) { 17916 /* setup to scan our argument */ 17917 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 17918 int i; 17919 struct dahdi_ring_cadence new_cadence; 17920 int cid_location = -1; 17921 int firstcadencepos = 0; 17922 char original_args[80]; 17923 int cadence_is_ok = 1; 17924 17925 ast_copy_string(original_args, v->value, sizeof(original_args)); 17926 /* 16 cadences allowed (8 pairs) */ 17927 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]); 17928 17929 /* Cadence must be even (on/off) */ 17930 if (element_count % 2 == 1) { 17931 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 17932 cadence_is_ok = 0; 17933 } 17934 17935 /* Ring cadences cannot be negative */ 17936 for (i = 0; i < element_count; i++) { 17937 if (c[i] == 0) { 17938 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 17939 cadence_is_ok = 0; 17940 break; 17941 } else if (c[i] < 0) { 17942 if (i % 2 == 1) { 17943 /* Silence duration, negative possibly okay */ 17944 if (cid_location == -1) { 17945 cid_location = i; 17946 c[i] *= -1; 17947 } else { 17948 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 17949 cadence_is_ok = 0; 17950 break; 17951 } 17952 } else { 17953 if (firstcadencepos == 0) { 17954 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 17955 /* duration will be passed negative to the DAHDI driver */ 17956 } else { 17957 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 17958 cadence_is_ok = 0; 17959 break; 17960 } 17961 } 17962 } 17963 } 17964 17965 /* Substitute our scanned cadence */ 17966 for (i = 0; i < 16; i++) { 17967 new_cadence.ringcadence[i] = c[i]; 17968 } 17969 17970 if (cadence_is_ok) { 17971 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 17972 if (element_count < 2) { 17973 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 17974 } else { 17975 if (cid_location == -1) { 17976 /* user didn't say; default to first pause */ 17977 cid_location = 1; 17978 } else { 17979 /* convert element_index to cidrings value */ 17980 cid_location = (cid_location + 1) / 2; 17981 } 17982 /* ---we like their cadence; try to install it--- */ 17983 if (!user_has_defined_cadences++) 17984 /* this is the first user-defined cadence; clear the default user cadences */ 17985 num_cadence = 0; 17986 if ((num_cadence+1) >= NUM_CADENCE_MAX) 17987 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 17988 else { 17989 cadences[num_cadence] = new_cadence; 17990 cidrings[num_cadence++] = cid_location; 17991 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 17992 } 17993 } 17994 } 17995 } else if (!strcasecmp(v->name, "ringtimeout")) { 17996 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 17997 } else if (!strcasecmp(v->name, "prewink")) { 17998 confp->timing.prewinktime = atoi(v->value); 17999 } else if (!strcasecmp(v->name, "preflash")) { 18000 confp->timing.preflashtime = atoi(v->value); 18001 } else if (!strcasecmp(v->name, "wink")) { 18002 confp->timing.winktime = atoi(v->value); 18003 } else if (!strcasecmp(v->name, "flash")) { 18004 confp->timing.flashtime = atoi(v->value); 18005 } else if (!strcasecmp(v->name, "start")) { 18006 confp->timing.starttime = atoi(v->value); 18007 } else if (!strcasecmp(v->name, "rxwink")) { 18008 confp->timing.rxwinktime = atoi(v->value); 18009 } else if (!strcasecmp(v->name, "rxflash")) { 18010 confp->timing.rxflashtime = atoi(v->value); 18011 } else if (!strcasecmp(v->name, "debounce")) { 18012 confp->timing.debouncetime = atoi(v->value); 18013 } else if (!strcasecmp(v->name, "toneduration")) { 18014 int toneduration; 18015 int ctlfd; 18016 int res; 18017 struct dahdi_dialparams dps; 18018 18019 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 18020 if (ctlfd == -1) { 18021 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 18022 return -1; 18023 } 18024 18025 toneduration = atoi(v->value); 18026 if (toneduration > -1) { 18027 memset(&dps, 0, sizeof(dps)); 18028 18029 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 18030 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 18031 if (res < 0) { 18032 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 18033 close(ctlfd); 18034 return -1; 18035 } 18036 } 18037 close(ctlfd); 18038 } else if (!strcasecmp(v->name, "defaultcic")) { 18039 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 18040 } else if (!strcasecmp(v->name, "defaultozz")) { 18041 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 18042 } else if (!strcasecmp(v->name, "mwilevel")) { 18043 mwilevel = atoi(v->value); 18044 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 18045 dtmfcid_level = atoi(v->value); 18046 } else if (!strcasecmp(v->name, "reportalarms")) { 18047 if (!strcasecmp(v->value, "all")) 18048 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; 18049 if (!strcasecmp(v->value, "none")) 18050 report_alarms = 0; 18051 else if (!strcasecmp(v->value, "channels")) 18052 report_alarms = REPORT_CHANNEL_ALARMS; 18053 else if (!strcasecmp(v->value, "spans")) 18054 report_alarms = REPORT_SPAN_ALARMS; 18055 } 18056 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 18057 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 18058 } 18059 18060 /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */ 18061 if (confp->chan.vars) { 18062 ast_variables_destroy(confp->chan.vars); 18063 confp->chan.vars = NULL; 18064 } 18065 18066 if (dahdichan) { 18067 /* Process the deferred dahdichan value. */ 18068 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno, 18069 &found_pseudo)) { 18070 if (confp->ignore_failed_channels) { 18071 ast_log(LOG_WARNING, 18072 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n", 18073 dahdichan->value); 18074 } else { 18075 return -1; 18076 } 18077 } 18078 } 18079 18080 /* mark the first channels of each DAHDI span to watch for their span alarms */ 18081 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { 18082 if (!tmp->destroy && tmp->span != y) { 18083 tmp->manages_span_alarms = 1; 18084 y = tmp->span; 18085 } else { 18086 tmp->manages_span_alarms = 0; 18087 } 18088 } 18089 18090 /*< \todo why check for the pseudo in the per-channel section. 18091 * Any actual use for manual setup of the pseudo channel? */ 18092 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) { 18093 /* use the default configuration for a channel, so 18094 that any settings from real configured channels 18095 don't "leak" into the pseudo channel config 18096 */ 18097 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18098 18099 if (conf.chan.cc_params) { 18100 tmp = mkintf(CHAN_PSEUDO, &conf, reload); 18101 } else { 18102 tmp = NULL; 18103 } 18104 if (tmp) { 18105 ast_verb(3, "Automatically generated pseudo channel\n"); 18106 } else { 18107 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 18108 } 18109 ast_cc_config_params_destroy(conf.chan.cc_params); 18110 } 18111 return 0; 18112 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 16943 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().
16944 { 16945 char *parse = ast_strdupa(data); 16946 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 16947 unsigned int param_count; 16948 unsigned int x; 16949 16950 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 16951 return; 16952 16953 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 16954 16955 /* first parameter is tap length, process it here */ 16956 16957 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 16958 16959 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 16960 confp->chan.echocancel.head.tap_length = x; 16961 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 16962 confp->chan.echocancel.head.tap_length = 128; 16963 16964 /* now process any remaining parameters */ 16965 16966 for (x = 1; x < param_count; x++) { 16967 struct { 16968 char *name; 16969 char *value; 16970 } param; 16971 16972 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 16973 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 16974 continue; 16975 } 16976 16977 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 16978 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 16979 continue; 16980 } 16981 16982 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 16983 16984 if (param.value) { 16985 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 16986 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 16987 continue; 16988 } 16989 } 16990 confp->chan.echocancel.head.param_count++; 16991 } 16992 }
static int reload | ( | void | ) | [static] |
Definition at line 18790 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
18791 { 18792 int res = 0; 18793 18794 res = setup_dahdi(1); 18795 if (res) { 18796 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 18797 return -1; 18798 } 18799 return 0; 18800 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4841 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().
04842 { 04843 p->confno = -1; 04844 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 04845 if (p->subs[SUB_REAL].dfd > -1) { 04846 struct dahdi_confinfo zi; 04847 04848 memset(&zi, 0, sizeof(zi)); 04849 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 04850 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 04851 } 04852 return 0; 04853 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 12006 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().
12007 { 12008 /* If we're supposed to be stopped -- stay stopped */ 12009 if (monitor_thread == AST_PTHREADT_STOP) 12010 return 0; 12011 ast_mutex_lock(&monlock); 12012 if (monitor_thread == pthread_self()) { 12013 ast_mutex_unlock(&monlock); 12014 ast_log(LOG_WARNING, "Cannot kill myself\n"); 12015 return -1; 12016 } 12017 if (monitor_thread != AST_PTHREADT_NULL) { 12018 /* Wake up the thread */ 12019 pthread_kill(monitor_thread, SIGURG); 12020 } else { 12021 /* Start a new monitor */ 12022 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 12023 ast_mutex_unlock(&monlock); 12024 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 12025 return -1; 12026 } 12027 } 12028 ast_mutex_unlock(&monlock); 12029 return 0; 12030 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5254 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().
05255 { 05256 int res; 05257 if (p->saveconf.confmode) { 05258 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 05259 p->saveconf.confmode = 0; 05260 if (res) { 05261 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 05262 return -1; 05263 } 05264 ast_debug(1, "Restored conferencing\n"); 05265 } 05266 return 0; 05267 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5161 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 6152 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().
06153 { 06154 if (p->bufferoverrideinuse) { 06155 /* faxbuffers are in use, revert them */ 06156 struct dahdi_bufferinfo bi = { 06157 .txbufpolicy = p->buf_policy, 06158 .rxbufpolicy = p->buf_policy, 06159 .bufsize = p->bufsize, 06160 .numbufs = p->buf_no 06161 }; 06162 int bpres; 06163 06164 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06165 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno)); 06166 } 06167 p->bufferoverrideinuse = 0; 06168 return bpres; 06169 } 06170 06171 return -1; 06172 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5228 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().
05229 { 05230 struct dahdi_confinfo c; 05231 int res; 05232 if (p->saveconf.confmode) { 05233 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 05234 return -1; 05235 } 05236 p->saveconf.chan = 0; 05237 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 05238 if (res) { 05239 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 05240 p->saveconf.confmode = 0; 05241 return -1; 05242 } 05243 memset(&c, 0, sizeof(c)); 05244 c.confmode = DAHDI_CONF_NORMAL; 05245 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 05246 if (res) { 05247 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 05248 return -1; 05249 } 05250 ast_debug(1, "Disabled conferencing\n"); 05251 return 0; 05252 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5312 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().
05313 { 05314 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 05315 int res; 05316 /* Take out of linear mode if necessary */ 05317 if (p->subs[SUB_REAL].linear) { 05318 p->subs[SUB_REAL].linear = 0; 05319 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 05320 } 05321 while (p->cidpos < p->cidlen) { 05322 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 05323 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res); 05324 if (res < 0) { 05325 if (errno == EAGAIN) 05326 return 0; 05327 else { 05328 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05329 return -1; 05330 } 05331 } 05332 if (!res) 05333 return 0; 05334 p->cidpos += res; 05335 } 05336 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 05337 ast_free(p->cidspill); 05338 p->cidspill = NULL; 05339 if (p->callwaitcas) { 05340 /* Wait for CID/CW to expire */ 05341 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 05342 p->cid_suppress_expire = p->cidcwexpire; 05343 } else 05344 restore_conference(p); 05345 return 0; 05346 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5269 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().
05270 { 05271 p->callwaitcas = 0; 05272 p->cidcwexpire = 0; 05273 p->cid_suppress_expire = 0; 05274 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 05275 return -1; 05276 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 05277 /* Make sure we account for the end */ 05278 p->cidlen += READ_SIZE * 4; 05279 p->cidpos = 0; 05280 send_callerid(p); 05281 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 05282 return 0; 05283 }
static int set_actual_gain | ( | int | fd, | |
float | rxgain, | |||
float | txgain, | |||
float | rxdrc, | |||
float | txdrc, | |||
int | law | |||
) | [static] |
Definition at line 5142 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), and restore_gains().
05143 { 05144 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law); 05145 }
static int set_actual_rxgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5125 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
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_rxgain(&g, gain, drc, law); 05138 05139 return ioctl(fd, DAHDI_SETGAINS, &g); 05140 }
static int set_actual_txgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5108 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05109 { 05110 struct dahdi_gains g; 05111 int res; 05112 05113 memset(&g, 0, sizeof(g)); 05114 res = ioctl(fd, DAHDI_GETGAINS, &g); 05115 if (res) { 05116 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05117 return res; 05118 } 05119 05120 fill_txgain(&g, gain, drc, law); 05121 05122 return ioctl(fd, DAHDI_SETGAINS, &g); 05123 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 18433 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().
18434 { 18435 int res; 18436 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default(); 18437 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 18438 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18439 18440 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) { 18441 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf); 18442 } else { 18443 res = -1; 18444 } 18445 ast_cc_config_params_destroy(default_conf.chan.cc_params); 18446 ast_cc_config_params_destroy(base_conf.chan.cc_params); 18447 ast_cc_config_params_destroy(conf.chan.cc_params); 18448 18449 return res; 18450 }
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 18146 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(), restart_monitor(), sig_pri_start_pri(), sig_ss7_linkset::ss7, ss7_linkset(), and ast_variable::value.
Referenced by setup_dahdi().
18147 { 18148 struct ast_config *cfg; 18149 struct ast_config *ucfg; 18150 struct ast_variable *v; 18151 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 18152 const char *chans; 18153 const char *cat; 18154 int res; 18155 18156 #ifdef HAVE_PRI 18157 char *c; 18158 int spanno; 18159 int i; 18160 int logicalspan; 18161 int trunkgroup; 18162 int dchannels[SIG_PRI_NUM_DCHANS]; 18163 #endif 18164 int have_cfg_now; 18165 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */ 18166 18167 cfg = ast_config_load(config, config_flags); 18168 have_cfg_now = !!cfg; 18169 if (!cfg) { 18170 /* Error if we have no config file */ 18171 if (had_cfg_before) { 18172 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 18173 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18174 } 18175 cfg = ast_config_new();/* Dummy config */ 18176 if (!cfg) { 18177 return 0; 18178 } 18179 ucfg = ast_config_load("users.conf", config_flags); 18180 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18181 ast_config_destroy(cfg); 18182 return 0; 18183 } 18184 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18185 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18186 ast_config_destroy(cfg); 18187 return 0; 18188 } 18189 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 18190 ucfg = ast_config_load("users.conf", config_flags); 18191 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18192 return 0; 18193 } 18194 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18195 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18196 return 0; 18197 } 18198 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18199 cfg = ast_config_load(config, config_flags); 18200 have_cfg_now = !!cfg; 18201 if (!cfg) { 18202 if (had_cfg_before) { 18203 /* We should have been able to load the config. */ 18204 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config); 18205 ast_config_destroy(ucfg); 18206 return 0; 18207 } 18208 cfg = ast_config_new();/* Dummy config */ 18209 if (!cfg) { 18210 ast_config_destroy(ucfg); 18211 return 0; 18212 } 18213 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18214 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18215 ast_config_destroy(ucfg); 18216 return 0; 18217 } 18218 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18219 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18220 return 0; 18221 } else { 18222 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18223 ucfg = ast_config_load("users.conf", config_flags); 18224 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18225 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18226 ast_config_destroy(cfg); 18227 return 0; 18228 } 18229 } 18230 had_cfg_before = have_cfg_now; 18231 18232 /* It's a little silly to lock it, but we might as well just to be sure */ 18233 ast_mutex_lock(&iflock); 18234 #ifdef HAVE_PRI 18235 if (reload != 1) { 18236 /* Process trunkgroups first */ 18237 v = ast_variable_browse(cfg, "trunkgroups"); 18238 while (v) { 18239 if (!strcasecmp(v->name, "trunkgroup")) { 18240 trunkgroup = atoi(v->value); 18241 if (trunkgroup > 0) { 18242 if ((c = strchr(v->value, ','))) { 18243 i = 0; 18244 memset(dchannels, 0, sizeof(dchannels)); 18245 while (c && (i < SIG_PRI_NUM_DCHANS)) { 18246 dchannels[i] = atoi(c + 1); 18247 if (dchannels[i] < 0) { 18248 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); 18249 } else 18250 i++; 18251 c = strchr(c + 1, ','); 18252 } 18253 if (i) { 18254 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 18255 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); 18256 } else 18257 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"); 18258 } else 18259 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18260 } else 18261 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18262 } else 18263 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 18264 } else if (!strcasecmp(v->name, "spanmap")) { 18265 spanno = atoi(v->value); 18266 if (spanno > 0) { 18267 if ((c = strchr(v->value, ','))) { 18268 trunkgroup = atoi(c + 1); 18269 if (trunkgroup > 0) { 18270 if ((c = strchr(c + 1, ','))) 18271 logicalspan = atoi(c + 1); 18272 else 18273 logicalspan = 0; 18274 if (logicalspan >= 0) { 18275 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 18276 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18277 } else 18278 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18279 } else 18280 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); 18281 } else 18282 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 18283 } else 18284 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 18285 } else 18286 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 18287 } else { 18288 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 18289 } 18290 v = v->next; 18291 } 18292 } 18293 #endif 18294 18295 /* Copy the default jb config over global_jbconf */ 18296 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 18297 18298 mwimonitornotify[0] = '\0'; 18299 18300 v = ast_variable_browse(cfg, "channels"); 18301 if ((res = process_dahdi(base_conf, 18302 "" /* Must be empty for the channels category. Silly voicemail mailbox. */, 18303 v, reload, 0))) { 18304 ast_mutex_unlock(&iflock); 18305 ast_config_destroy(cfg); 18306 if (ucfg) { 18307 ast_config_destroy(ucfg); 18308 } 18309 return res; 18310 } 18311 18312 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 18313 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 18314 /* [channels] and [trunkgroups] are used. Let's also reserve 18315 * [globals] and [general] for future use 18316 */ 18317 if (!strcasecmp(cat, "general") || 18318 !strcasecmp(cat, "trunkgroups") || 18319 !strcasecmp(cat, "globals") || 18320 !strcasecmp(cat, "channels")) { 18321 continue; 18322 } 18323 18324 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 18325 if (ast_strlen_zero(chans)) { 18326 /* Section is useless without a dahdichan value present. */ 18327 continue; 18328 } 18329 18330 /* Copy base_conf to conf. */ 18331 deep_copy_dahdi_chan_conf(conf, base_conf); 18332 18333 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 18334 ast_mutex_unlock(&iflock); 18335 ast_config_destroy(cfg); 18336 if (ucfg) { 18337 ast_config_destroy(ucfg); 18338 } 18339 return res; 18340 } 18341 } 18342 18343 ast_config_destroy(cfg); 18344 18345 if (ucfg) { 18346 /* Reset base_conf, so things don't leak from chan_dahdi.conf */ 18347 deep_copy_dahdi_chan_conf(base_conf, default_conf); 18348 process_dahdi(base_conf, 18349 "" /* Must be empty for the general category. Silly voicemail mailbox. */, 18350 ast_variable_browse(ucfg, "general"), 1, 0); 18351 18352 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 18353 if (!strcasecmp(cat, "general")) { 18354 continue; 18355 } 18356 18357 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 18358 if (ast_strlen_zero(chans)) { 18359 /* Section is useless without a dahdichan value present. */ 18360 continue; 18361 } 18362 18363 /* Copy base_conf to conf. */ 18364 deep_copy_dahdi_chan_conf(conf, base_conf); 18365 18366 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 18367 ast_config_destroy(ucfg); 18368 ast_mutex_unlock(&iflock); 18369 return res; 18370 } 18371 } 18372 ast_config_destroy(ucfg); 18373 } 18374 ast_mutex_unlock(&iflock); 18375 18376 #ifdef HAVE_PRI 18377 if (reload != 1) { 18378 int x; 18379 for (x = 0; x < NUM_SPANS; x++) { 18380 if (pris[x].pri.pvts[0]) { 18381 prepare_pri(pris + x); 18382 if (sig_pri_start_pri(&pris[x].pri)) { 18383 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 18384 return -1; 18385 } else 18386 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 18387 } 18388 } 18389 } 18390 #endif 18391 #if defined(HAVE_SS7) 18392 if (reload != 1) { 18393 int x; 18394 for (x = 0; x < NUM_SPANS; x++) { 18395 if (linksets[x].ss7.ss7) { 18396 linksets[x].ss7.calls = &dahdi_ss7_callbacks; 18397 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) { 18398 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 18399 return -1; 18400 } else 18401 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 18402 } 18403 } 18404 } 18405 #endif /* defined(HAVE_SS7) */ 18406 #ifdef HAVE_OPENR2 18407 if (reload != 1) { 18408 int x; 18409 for (x = 0; x < r2links_count; x++) { 18410 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 18411 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 18412 return -1; 18413 } else { 18414 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 18415 } 18416 } 18417 } 18418 #endif 18419 /* And start the monitor for the first time */ 18420 restart_monitor(); 18421 return 0; 18422 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 12282 of file chan_dahdi.c.
Referenced by mkintf().
12283 { 12284 return sigtype; 12285 }
static void string_replace | ( | char * | str, | |
int | char1, | |||
int | char2 | |||
) | [static] |
Definition at line 16847 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 4336 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().
04337 { 04338 int tchan; 04339 int tinthreeway; 04340 struct ast_channel *towner; 04341 04342 ast_debug(1, "Swapping %d and %d\n", a, b); 04343 04344 tchan = p->subs[a].chan; 04345 towner = p->subs[a].owner; 04346 tinthreeway = p->subs[a].inthreeway; 04347 04348 p->subs[a].chan = p->subs[b].chan; 04349 p->subs[a].owner = p->subs[b].owner; 04350 p->subs[a].inthreeway = p->subs[b].inthreeway; 04351 04352 p->subs[b].chan = tchan; 04353 p->subs[b].owner = towner; 04354 p->subs[b].inthreeway = tinthreeway; 04355 04356 if (p->subs[a].owner) 04357 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 04358 if (p->subs[b].owner) 04359 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 04360 wakeup_sub(p, a); 04361 wakeup_sub(p, b); 04362 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4482 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().
04483 { 04484 if (!x) { 04485 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 04486 return -1; 04487 } 04488 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 04489 dahdi_close_sub(p, x); 04490 p->subs[x].linear = 0; 04491 p->subs[x].chan = 0; 04492 p->subs[x].owner = NULL; 04493 p->subs[x].inthreeway = 0; 04494 p->polarity = POLARITY_IDLE; 04495 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 04496 return 0; 04497 }
static int unload_module | ( | void | ) | [static] |
Definition at line 16831 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, and sig_ss7_linkset::lock.
16832 { 16833 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16834 int y; 16835 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16836 #ifdef HAVE_PRI 16837 for (y = 0; y < NUM_SPANS; y++) 16838 ast_mutex_destroy(&pris[y].pri.lock); 16839 #endif 16840 #if defined(HAVE_SS7) 16841 for (y = 0; y < NUM_SPANS; y++) 16842 ast_mutex_destroy(&linksets[y].ss7.lock); 16843 #endif /* defined(HAVE_SS7) */ 16844 return __unload_module(); 16845 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4855 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().
04856 { 04857 int needconf = 0; 04858 int x; 04859 int useslavenative; 04860 struct dahdi_pvt *slave = NULL; 04861 04862 useslavenative = isslavenative(p, &slave); 04863 /* Start with the obvious, general stuff */ 04864 for (x = 0; x < 3; x++) { 04865 /* Look for three way calls */ 04866 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 04867 conf_add(p, &p->subs[x], x, 0); 04868 needconf++; 04869 } else { 04870 conf_del(p, &p->subs[x], x); 04871 } 04872 } 04873 /* If we have a slave, add him to our conference now. or DAX 04874 if this is slave native */ 04875 for (x = 0; x < MAX_SLAVES; x++) { 04876 if (p->slaves[x]) { 04877 if (useslavenative) 04878 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 04879 else { 04880 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 04881 needconf++; 04882 } 04883 } 04884 } 04885 /* If we're supposed to be in there, do so now */ 04886 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 04887 if (useslavenative) 04888 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 04889 else { 04890 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 04891 needconf++; 04892 } 04893 } 04894 /* If we have a master, add ourselves to his conference */ 04895 if (p->master) { 04896 if (isslavenative(p->master, NULL)) { 04897 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 04898 } else { 04899 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 04900 } 04901 } 04902 if (!needconf) { 04903 /* Nobody is left (or should be left) in our conference. 04904 Kill it. */ 04905 p->confno = -1; 04906 } 04907 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 04908 return 0; 04909 }
static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
int | a | |||
) | [static] |
Definition at line 3843 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().
03844 { 03845 dahdi_lock_sub_owner(p, a); 03846 if (p->subs[a].owner) { 03847 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 03848 ast_channel_unlock(p->subs[a].owner); 03849 } 03850 }
int alarm |
Definition at line 4632 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 3719 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 18593 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 15905 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 18603 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 18588 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1518 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 18598 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 4609 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 1322 of file chan_dahdi.c.
Main interface list start
Definition at line 1321 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 4633 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 3790 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 634 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.