#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 "sig_pri.h"
#include <openr2.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_mfcr2 |
struct | dahdi_mfcr2_conf |
struct | dahdi_parms_pseudo |
struct | dahdi_pri |
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 | CHAN_TAG "Chan " |
#define | CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) |
#define | CONF_USER_REAL (1 << 0) |
#define | CONF_USER_THIRDCALL (1 << 1) |
#define | CONTEXT_TAG "Context - " |
#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 | FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" |
#define | FORMAT "%4s %40s\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 | R2_LINK_CAPACITY 10 |
#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_MFCR2_MAX_CHANNELS 672 |
#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, DAHDI_IFLIST_NO_B_CHAN } |
enum | mwisend_states { MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE } |
Functions | |
static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
static void | __reg_module (void) |
static int | __unload_module (void) |
static void | __unreg_module (void) |
static int | _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) | |
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 char * | complete_span_4 (const char *line, const char *word, int pos, int state) |
static char * | complete_span_helper (const char *line, const char *word, int pos, int state, int rpos) |
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, int is_outgoing, char *address) |
static int | dahdi_accept_r2_call_exec (struct ast_channel *chan, const char *data) |
static void | dahdi_ami_channel_event (struct dahdi_pvt *p, struct ast_channel *chan) |
static int | dahdi_answer (struct ast_channel *ast) |
static openr2_call_disconnect_cause_t | dahdi_ast_cause_to_r2_cause (int cause) |
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_pri_fd (struct dahdi_pri *pri, int fd_num) |
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_new_pri_nobch_channel (struct sig_pri_span *pri) |
static void | dahdi_nobch_extract (struct sig_pri_span *pri, struct dahdi_pvt *pvt) |
static void | dahdi_nobch_insert (struct sig_pri_span *pri, struct dahdi_pvt *pvt) |
static int | dahdi_open (char *fn) |
static void | dahdi_pri_cc_agent_destructor (struct ast_cc_agent *agent) |
static int | dahdi_pri_cc_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan) |
static void | dahdi_pri_error (struct pri *pri, char *s) |
static void | dahdi_pri_message (struct pri *pri, char *s) |
static void | dahdi_pri_update_span_devstate (struct sig_pri_span *pri) |
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 int16_t | dahdi_r2_alaw_to_linear (uint8_t sample) |
static int | dahdi_r2_answer (struct dahdi_pvt *p) |
static int | dahdi_r2_cause_to_ast_cause (openr2_call_disconnect_cause_t cause) |
static void | dahdi_r2_destroy_links (void) |
static void | dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause) |
static openr2_calling_party_category_t | dahdi_r2_get_channel_category (struct ast_channel *c) |
static struct dahdi_mfcr2 * | dahdi_r2_get_link (void) |
static uint8_t | dahdi_r2_linear_to_alaw (int sample) |
static void | dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit) |
static void | dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode) |
static void | dahdi_r2_on_call_answered (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause) |
static void | dahdi_r2_on_call_end (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_init (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category) |
static void | dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen) |
static void | dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap) |
static void | dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap) |
static int | dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit) |
static void | dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm) |
static void | dahdi_r2_on_line_blocked (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_line_idle (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode) |
static void | dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason) |
static int | dahdi_r2_set_context (struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf) |
static void | dahdi_r2_write_log (openr2_log_level_t level, char *logmessage) |
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_send_callrerouting_facility_exec (struct ast_channel *chan, const char *data) |
static int | dahdi_send_keypad_facility_exec (struct ast_channel *chan, const char *digits) |
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_setlaw (int dfd, int law) |
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 void | dahdi_unlink_pri_pvt (struct dahdi_pvt *pvt) |
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 char * | handle_mfcr2_call_files (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_set_blocked (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_set_idle (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_show_variants (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mfcr2_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_service_disable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_service_enable_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_service_generic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus) |
static char * | handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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 void * | mfcr2_monitor (void *data) |
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_ami_channel_event (void *pvt, struct ast_channel *chan) |
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_dchan_exception (struct sig_pri_span *pri, int index) |
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 void | my_module_ref (void) |
static void | my_module_unref (void) |
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 struct ast_channel * | my_new_pri_ast_channel (void *pvt, int state, enum sig_pri_law law, char *exten, 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 void | my_pri_fixup_chans (void *chan_old, void *chan_new) |
static void | my_pri_init_config (void *priv, struct sig_pri_span *pri) |
static void | my_pri_make_cc_dialstring (void *priv, char *buf, size_t buf_size) |
static void | my_pri_open_media (void *p) |
static int | my_pri_play_tone (void *pvt, enum sig_pri_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 *cidrings, struct ast_channel *ast) |
static void | my_set_callerid (void *pvt, const struct ast_party_caller *caller) |
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 void | my_set_digital (void *pvt, int is_digital) |
static void | my_set_dnid (void *pvt, const char *dnid) |
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_polarity (void *pvt, int value) |
static void | my_set_pulsedial (void *pvt, int flag) |
static void | my_set_rdnis (void *pvt, const char *rdnis) |
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 | prepare_pri (struct dahdi_pri *pri) |
static int | pri_create_spanmap (int span, int trunkgroup, int logicalspan) |
static int | pri_create_trunkgroup (int trunkgroup, int *channels) |
static int | pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si) |
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 | sig_pri_tone_to_dahditone (enum sig_pri_tone tone) |
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 | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
static int | cidrings [NUM_CADENCE_MAX] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
static const char | config [] = "chan_dahdi.conf" |
static const char *const | dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" |
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_cli_entry | dahdi_mfcr2_cli [] |
static struct sig_pri_callback | dahdi_pri_callbacks |
static struct ast_cc_agent_callbacks | dahdi_pri_cc_agent_callbacks |
static struct ast_cc_monitor_callbacks | dahdi_pri_cc_monitor_callbacks |
static const char | dahdi_pri_cc_type [] = "DAHDI/PRI" |
static struct ast_cli_entry | dahdi_pri_cli [] |
static struct dahdi_parms_pseudo | dahdi_pseudo_parms |
static openr2_event_interface_t | dahdi_r2_event_iface |
static openr2_transcoder_interface_t | dahdi_r2_transcode_iface |
static char * | dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" |
static char * | dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" |
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 ast_mutex_t | iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Protect the interface list (of dahdi_pvt's). | |
static const char *const | lbostr [] |
static int | matchdigittimeout = 3000 |
How long to wait for an extra digit, if there is an ambiguous match. | |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
static ast_mutex_t | monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
static int | mwilevel = 512 |
static char | mwimonitornotify [PATH_MAX] = "" |
static int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static int | pridebugfd = -1 |
static ast_mutex_t | pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static char | pridebugfilename [1024] = "" |
static struct dahdi_pri | pris [NUM_SPANS] |
static char | progzone [10] = "" |
static struct dahdi_mfcr2 ** | r2links |
static int | r2links_count = 0 |
static int | report_alarms = REPORT_CHANNEL_ALARMS |
static ast_mutex_t | restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static int | ringt_base = DEFAULT_RINGT |
Configured ring timeout base. | |
static struct dahdi_pvt * | round_robin [32] |
static ast_cond_t | ss_thread_complete |
static int | ss_thread_count = 0 |
static ast_mutex_t | ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | subnames [] |
static const char | tdesc [] |
static int | usedistinctiveringdetection = 0 |
static int | user_has_defined_cadences = 0 |
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 314 of file chan_dahdi.c.
Referenced by analog_ss_thread(), dahdi_callwait(), dahdi_sendtext(), 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 381 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmf(), and my_handle_dtmf().
#define CALLPROGRESS_FAX_INCOMING 4 |
#define CALLPROGRESS_FAX_OUTGOING 2 |
#define CALLPROGRESS_PROGRESS 1 |
Definition at line 378 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and my_have_progressdetect().
#define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) |
10,000 ms
Definition at line 516 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 515 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) */) |
#define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 412 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 376 of file chan_dahdi.c.
Referenced by build_channels(), create_channel_name(), dahdi_ami_channel_event(), dahdi_new(), dahdi_new_pri_nobch_channel(), dahdi_request(), determine_starting_point(), enable_dtmf_detect(), my_dsp_set_digitmode(), and my_set_polarity().
#define CHAN_TAG "Chan " |
Referenced by dahdi_r2_on_chan_log().
#define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 652 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 653 of file chan_dahdi.c.
#define CONTEXT_TAG "Context - " |
Referenced by dahdi_r2_on_context_log().
#define dahdi_get_index | ( | ast, | |||
p, | |||||
nullok | ) | _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
Definition at line 3684 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 1244 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 312 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 520 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" |
#define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" |
#define FORMAT "%4s %40s\n" |
Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), 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_mfcr2_show_channels(), handle_mfcr2_show_variants(), 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) |
#define HANGUP 1 |
Definition at line 15749 of file chan_dahdi.c.
Referenced by action_transferhangup(), and dahdi_fake_event().
#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), and parse_setup_acknowledge().
#define HEADER_MS 50 |
Referenced by dahdi_sendtext().
#define ISTRUNK | ( | p | ) |
Value:
Definition at line 408 of file chan_dahdi.c.
Referenced by __analog_ss_thread(), analog_ss_thread(), and dahdi_indicate().
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 512 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 513 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 16771 of file chan_dahdi.c.
#define MAX_SLAVES 4 |
Definition at line 655 of file chan_dahdi.c.
Referenced by isslavenative(), and my_complete_conference_update().
#define MIN_MS_SINCE_FLASH ((2000) ) |
2000 ms
Definition at line 519 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 318 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and dahdi_new().
#define NUM_CADENCE_MAX 25 |
Definition at line 383 of file chan_dahdi.c.
#define NUM_SPANS 32 |
Definition at line 373 of file chan_dahdi.c.
Referenced by destroy_all_channels(), pri_create_trunkgroup(), and pri_resolve_span().
#define POLARITY_IDLE 0 |
Definition at line 612 of file chan_dahdi.c.
Referenced by __analog_handle_event(), __analog_ss_thread(), analog_hangup(), dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 613 of file chan_dahdi.c.
Referenced by __analog_handle_event(), __analog_ss_thread(), analog_handle_init_event(), dahdi_handle_event(), and handle_init_event().
#define PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 16825 of file chan_dahdi.c.
Referenced by process_dahdi().
#define PROC_DAHDI_OPT_NOWARN (1 << 1) |
process_dahdi() - No warnings on non-existing cofiguration keywords
Definition at line 16827 of file chan_dahdi.c.
Referenced by setup_dahdi_int().
#define R2_LINK_CAPACITY 10 |
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 510 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(), and send_cwcidspill().
#define REPORT_CHANNEL_ALARMS 1 |
Definition at line 433 of file chan_dahdi.c.
Referenced by handle_alarms(), and handle_clear_alarms().
#define REPORT_SPAN_ALARMS 2 |
Definition at line 434 of file chan_dahdi.c.
Referenced by handle_alarms(), and handle_clear_alarms().
#define sig2str dahdi_sig2str |
Definition at line 4610 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), and handle_init_event().
#define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 359 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), and sig_pri_start_pri().
#define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 360 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), pri_dchannel(), sig_pri_cc_generic_check(), and sig_pri_start_pri().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 348 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 343 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 368 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 344 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 347 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 345 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 346 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_FEATDMF_TA (0x2000000 | 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(), and handle_init_event().
#define SIG_FGC_CAMA (0x4000000 | 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(), and handle_init_event().
#define SIG_FGC_CAMAMF (0x8000000 | 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(), and handle_init_event().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 356 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(), and handle_init_event().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 357 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(), and handle_init_event().
#define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 355 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(), and handle_init_event().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 353 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(), and my_is_off_hook().
#define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 354 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(), and my_is_off_hook().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 352 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(), and handle_init_event().
#define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 362 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), and handle_mfcr2_show_channels().
#define SIG_MFCR2_MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 84 of file chan_dahdi.c.
#define SIG_PRI DAHDI_SIG_CLEAR |
#define SIG_PRI_LIB_HANDLE_CASES |
Value:
SIG_PRI: \ case SIG_BRI: \ case SIG_BRI_PTMP
Definition at line 1539 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_send_callrerouting_facility_exec(), dahdi_sig_pri_lib_handles(), destroy_dahdi_pvt(), handle_init_event(), and my_new_pri_ast_channel().
#define SIG_SF DAHDI_SIG_SF |
Definition at line 363 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 367 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 365 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 366 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 364 of file chan_dahdi.c.
Referenced by analog_lib_handles(), analog_ss_thread(), dahdi_handle_event(), dahdi_sig2str(), dahdisig_to_analogsig(), and handle_init_event().
#define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 361 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_func_read(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), destroy_dahdi_pvt(), and handle_init_event().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 608 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 607 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_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), dahdi_read(), dahdi_request(), 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(), mfcr2_monitor(), 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_new_pri_ast_channel(), my_off_hook(), my_pri_fixup_chans(), my_pri_open_media(), my_pri_play_tone(), 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(), and unistim_senddigit_end().
#define SUB_THREEWAY 2 |
Three-way call
Definition at line 609 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 15748 of file chan_dahdi.c.
Referenced by action_transfer(), and dahdi_fake_event().
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 |
DAHDI_IFLIST_NO_B_CHAN | The dahdi_pvt is in a no B channel interface list |
Definition at line 676 of file chan_dahdi.c.
00676 { 00677 DAHDI_IFLIST_NONE, /*!< The dahdi_pvt is not in any list. */ 00678 DAHDI_IFLIST_MAIN, /*!< The dahdi_pvt is in the main interface list */ 00679 #if defined(HAVE_PRI) 00680 DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */ 00681 #endif /* defined(HAVE_PRI) */ 00682 };
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 660 of file chan_dahdi.c.
00660 { 00661 MWI_SEND_NULL = 0, 00662 MWI_SEND_SA, 00663 MWI_SEND_SA_WAIT, 00664 MWI_SEND_PAUSE, 00665 MWI_SEND_SPILL, 00666 MWI_SEND_CLEANUP, 00667 MWI_SEND_DONE, 00668 } mwisend_states;
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8672 of file chan_dahdi.c.
References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, dahdi_pvt::channel, 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, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_channel::name, 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().
08673 { 08674 int res; 08675 int idx; 08676 struct ast_frame *f; 08677 int usedindex = -1; 08678 struct dahdi_pvt *p = ast->tech_pvt; 08679 08680 idx = dahdi_get_index(ast, p, 1); 08681 08682 p->subs[idx].f.frametype = AST_FRAME_NULL; 08683 p->subs[idx].f.datalen = 0; 08684 p->subs[idx].f.samples = 0; 08685 p->subs[idx].f.mallocd = 0; 08686 p->subs[idx].f.offset = 0; 08687 p->subs[idx].f.subclass.integer = 0; 08688 p->subs[idx].f.delivery = ast_tv(0,0); 08689 p->subs[idx].f.src = "dahdi_exception"; 08690 p->subs[idx].f.data.ptr = NULL; 08691 08692 08693 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 08694 /* If nobody owns us, absorb the event appropriately, otherwise 08695 we loop indefinitely. This occurs when, during call waiting, the 08696 other end hangs up our channel so that it no longer exists, but we 08697 have neither FLASH'd nor ONHOOK'd to signify our desire to 08698 change to the other channel. */ 08699 if (p->fake_event) { 08700 res = p->fake_event; 08701 p->fake_event = 0; 08702 } else 08703 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 08704 /* Switch to real if there is one and this isn't something really silly... */ 08705 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 08706 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 08707 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 08708 p->owner = p->subs[SUB_REAL].owner; 08709 if (p->owner && ast_bridged_channel(p->owner)) 08710 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08711 p->subs[SUB_REAL].needunhold = 1; 08712 } 08713 switch (res) { 08714 case DAHDI_EVENT_ONHOOK: 08715 dahdi_disable_ec(p); 08716 if (p->owner) { 08717 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 08718 dahdi_ring_phone(p); 08719 p->callwaitingrepeat = 0; 08720 p->cidcwexpire = 0; 08721 p->cid_suppress_expire = 0; 08722 } else 08723 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08724 update_conf(p); 08725 break; 08726 case DAHDI_EVENT_RINGOFFHOOK: 08727 dahdi_enable_ec(p); 08728 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08729 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 08730 p->subs[SUB_REAL].needanswer = 1; 08731 p->dialing = 0; 08732 } 08733 break; 08734 case DAHDI_EVENT_HOOKCOMPLETE: 08735 case DAHDI_EVENT_RINGERON: 08736 case DAHDI_EVENT_RINGEROFF: 08737 /* Do nothing */ 08738 break; 08739 case DAHDI_EVENT_WINKFLASH: 08740 p->flashtime = ast_tvnow(); 08741 if (p->owner) { 08742 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 08743 if (p->owner->_state != AST_STATE_UP) { 08744 /* Answer if necessary */ 08745 usedindex = dahdi_get_index(p->owner, p, 0); 08746 if (usedindex > -1) { 08747 p->subs[usedindex].needanswer = 1; 08748 } 08749 ast_setstate(p->owner, AST_STATE_UP); 08750 } 08751 p->callwaitingrepeat = 0; 08752 p->cidcwexpire = 0; 08753 p->cid_suppress_expire = 0; 08754 if (ast_bridged_channel(p->owner)) 08755 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08756 p->subs[SUB_REAL].needunhold = 1; 08757 } else 08758 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08759 update_conf(p); 08760 break; 08761 default: 08762 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 08763 } 08764 f = &p->subs[idx].f; 08765 return f; 08766 } 08767 if (!(p->radio || (p->oprmode < 0))) 08768 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 08769 /* If it's not us, return NULL immediately */ 08770 if (ast != p->owner) { 08771 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 08772 f = &p->subs[idx].f; 08773 return f; 08774 } 08775 f = dahdi_handle_event(ast); 08776 08777 /* tell the cdr this zap device hung up */ 08778 if (f == NULL) { 08779 ast_set_hangupsource(ast, ast->name, 0); 08780 } 08781 08782 return f; 08783 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 18633 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 16571 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(), dahdi_cli, dahdi_close_pri_fd(), dahdi_mfcr2_cli, dahdi_pri_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cli, dahdi_r2_destroy_links(), dahdi_tech, destroy_all_channels(), iflist, sig_ss7_linkset::master, sig_pri_span::master, monitor_thread, monlock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::pri, sig_pri_stop_pri(), sig_pri_unload(), and ss_thread_complete.
Referenced by load_module(), and unload_module().
16572 { 16573 struct dahdi_pvt *p; 16574 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16575 int i, j; 16576 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16577 16578 #ifdef HAVE_PRI 16579 for (i = 0; i < NUM_SPANS; i++) { 16580 if (pris[i].pri.master != AST_PTHREADT_NULL) 16581 pthread_cancel(pris[i].pri.master); 16582 } 16583 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 16584 ast_unregister_application(dahdi_send_keypad_facility_app); 16585 #ifdef HAVE_PRI_PROG_W_CAUSE 16586 ast_unregister_application(dahdi_send_callrerouting_facility_app); 16587 #endif 16588 #endif 16589 #if defined(HAVE_SS7) 16590 for (i = 0; i < NUM_SPANS; i++) { 16591 if (linksets[i].ss7.master != AST_PTHREADT_NULL) 16592 pthread_cancel(linksets[i].ss7.master); 16593 } 16594 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 16595 #endif /* defined(HAVE_SS7) */ 16596 #if defined(HAVE_OPENR2) 16597 dahdi_r2_destroy_links(); 16598 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 16599 ast_unregister_application(dahdi_accept_r2_call_app); 16600 #endif 16601 16602 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 16603 ast_manager_unregister("DAHDIDialOffhook"); 16604 ast_manager_unregister("DAHDIHangup"); 16605 ast_manager_unregister("DAHDITransfer"); 16606 ast_manager_unregister("DAHDIDNDoff"); 16607 ast_manager_unregister("DAHDIDNDon"); 16608 ast_manager_unregister("DAHDIShowChannels"); 16609 ast_manager_unregister("DAHDIRestart"); 16610 ast_data_unregister(NULL); 16611 ast_channel_unregister(&dahdi_tech); 16612 16613 /* Hangup all interfaces if they have an owner */ 16614 ast_mutex_lock(&iflock); 16615 for (p = iflist; p; p = p->next) { 16616 if (p->owner) 16617 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 16618 } 16619 ast_mutex_unlock(&iflock); 16620 16621 ast_mutex_lock(&monlock); 16622 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 16623 pthread_cancel(monitor_thread); 16624 pthread_kill(monitor_thread, SIGURG); 16625 pthread_join(monitor_thread, NULL); 16626 } 16627 monitor_thread = AST_PTHREADT_STOP; 16628 ast_mutex_unlock(&monlock); 16629 16630 destroy_all_channels(); 16631 16632 #if defined(HAVE_PRI) 16633 for (i = 0; i < NUM_SPANS; i++) { 16634 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) 16635 pthread_join(pris[i].pri.master, NULL); 16636 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) { 16637 dahdi_close_pri_fd(&(pris[i]), j); 16638 } 16639 sig_pri_stop_pri(&pris[i].pri); 16640 } 16641 #if defined(HAVE_PRI_CCSS) 16642 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks); 16643 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks); 16644 #endif /* defined(HAVE_PRI_CCSS) */ 16645 sig_pri_unload(); 16646 #endif 16647 16648 #if defined(HAVE_SS7) 16649 for (i = 0; i < NUM_SPANS; i++) { 16650 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) 16651 pthread_join(linksets[i].ss7.master, NULL); 16652 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) { 16653 dahdi_close_ss7_fd(&(linksets[i]), j); 16654 } 16655 } 16656 #endif /* defined(HAVE_SS7) */ 16657 ast_cond_destroy(&ss_thread_complete); 16658 return 0; 16659 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 18633 of file chan_dahdi.c.
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 3685 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, LOG_WARNING, ast_channel::name, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
03686 { 03687 int res; 03688 if (p->subs[SUB_REAL].owner == ast) 03689 res = 0; 03690 else if (p->subs[SUB_CALLWAIT].owner == ast) 03691 res = 1; 03692 else if (p->subs[SUB_THREEWAY].owner == ast) 03693 res = 2; 03694 else { 03695 res = -1; 03696 if (!nullok) 03697 ast_log(LOG_WARNING, 03698 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 03699 ast ? ast->name : "", p->channel, fname, line); 03700 } 03701 return res; 03702 }
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15886 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), f, find_channel_from_str(), and dahdi_pvt::owner.
Referenced by load_module().
15887 { 15888 struct dahdi_pvt *p; 15889 const char *channel = astman_get_header(m, "DAHDIChannel"); 15890 const char *number = astman_get_header(m, "Number"); 15891 int i; 15892 15893 if (ast_strlen_zero(channel)) { 15894 astman_send_error(s, m, "No channel specified"); 15895 return 0; 15896 } 15897 if (ast_strlen_zero(number)) { 15898 astman_send_error(s, m, "No number specified"); 15899 return 0; 15900 } 15901 p = find_channel_from_str(channel); 15902 if (!p) { 15903 astman_send_error(s, m, "No such channel"); 15904 return 0; 15905 } 15906 if (!p->owner) { 15907 astman_send_error(s, m, "Channel does not have it's owner"); 15908 return 0; 15909 } 15910 for (i = 0; i < strlen(number); i++) { 15911 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] }; 15912 dahdi_queue_frame(p, &f); 15913 } 15914 astman_send_ack(s, m, "DAHDIDialOffhook"); 15915 return 0; 15916 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15821 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel_from_str().
Referenced by load_module().
15822 { 15823 struct dahdi_pvt *p; 15824 const char *channel = astman_get_header(m, "DAHDIChannel"); 15825 15826 if (ast_strlen_zero(channel)) { 15827 astman_send_error(s, m, "No channel specified"); 15828 return 0; 15829 } 15830 p = find_channel_from_str(channel); 15831 if (!p) { 15832 astman_send_error(s, m, "No such channel"); 15833 return 0; 15834 } 15835 dahdi_dnd(p, 0); 15836 astman_send_ack(s, m, "DND Disabled"); 15837 return 0; 15838 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15802 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_dnd(), and find_channel_from_str().
Referenced by load_module().
15803 { 15804 struct dahdi_pvt *p; 15805 const char *channel = astman_get_header(m, "DAHDIChannel"); 15806 15807 if (ast_strlen_zero(channel)) { 15808 astman_send_error(s, m, "No channel specified"); 15809 return 0; 15810 } 15811 p = find_channel_from_str(channel); 15812 if (!p) { 15813 astman_send_error(s, m, "No such channel"); 15814 return 0; 15815 } 15816 dahdi_dnd(p, 1); 15817 astman_send_ack(s, m, "DND Enabled"); 15818 return 0; 15819 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15086 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
15087 { 15088 if (dahdi_restart() != 0) { 15089 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 15090 return 1; 15091 } 15092 astman_send_ack(s, m, "DAHDIRestart: Success"); 15093 return 0; 15094 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15918 of file chan_dahdi.c.
References ast_channel::accountcode, alarm2str(), ast_mutex_lock, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, channels, dahdi_pvt::context, dahdi_dnd(), get_alarms(), iflist, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.
Referenced by load_module().
15919 { 15920 struct dahdi_pvt *tmp = NULL; 15921 const char *id = astman_get_header(m, "ActionID"); 15922 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 15923 char idText[256] = ""; 15924 int channels = 0; 15925 int dahdichanquery; 15926 15927 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) { 15928 /* Not numeric string. */ 15929 dahdichanquery = -1; 15930 } 15931 15932 astman_send_ack(s, m, "DAHDI channel status will follow"); 15933 if (!ast_strlen_zero(id)) 15934 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 15935 15936 ast_mutex_lock(&iflock); 15937 15938 for (tmp = iflist; tmp; tmp = tmp->next) { 15939 if (tmp->channel > 0) { 15940 int alm; 15941 15942 /* If a specific channel is queried for, only deliver status for that channel */ 15943 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 15944 continue; 15945 15946 alm = get_alarms(tmp); 15947 channels++; 15948 if (tmp->owner) { 15949 /* Add data if we have a current call */ 15950 astman_append(s, 15951 "Event: DAHDIShowChannels\r\n" 15952 "DAHDIChannel: %d\r\n" 15953 "Channel: %s\r\n" 15954 "Uniqueid: %s\r\n" 15955 "AccountCode: %s\r\n" 15956 "Signalling: %s\r\n" 15957 "SignallingCode: %d\r\n" 15958 "Context: %s\r\n" 15959 "DND: %s\r\n" 15960 "Alarm: %s\r\n" 15961 "%s" 15962 "\r\n", 15963 tmp->channel, 15964 tmp->owner->name, 15965 tmp->owner->uniqueid, 15966 tmp->owner->accountcode, 15967 sig2str(tmp->sig), 15968 tmp->sig, 15969 tmp->context, 15970 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15971 alarm2str(alm), idText); 15972 } else { 15973 astman_append(s, 15974 "Event: DAHDIShowChannels\r\n" 15975 "DAHDIChannel: %d\r\n" 15976 "Signalling: %s\r\n" 15977 "SignallingCode: %d\r\n" 15978 "Context: %s\r\n" 15979 "DND: %s\r\n" 15980 "Alarm: %s\r\n" 15981 "%s" 15982 "\r\n", 15983 tmp->channel, sig2str(tmp->sig), tmp->sig, 15984 tmp->context, 15985 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15986 alarm2str(alm), idText); 15987 } 15988 } 15989 } 15990 15991 ast_mutex_unlock(&iflock); 15992 15993 astman_append(s, 15994 "Event: DAHDIShowChannelsComplete\r\n" 15995 "%s" 15996 "Items: %d\r\n" 15997 "\r\n", 15998 idText, 15999 channels); 16000 return 0; 16001 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15840 of file chan_dahdi.c.
References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), dahdi_pvt::sig, and TRANSFER.
Referenced by load_module().
15841 { 15842 struct dahdi_pvt *p; 15843 const char *channel = astman_get_header(m, "DAHDIChannel"); 15844 15845 if (ast_strlen_zero(channel)) { 15846 astman_send_error(s, m, "No channel specified"); 15847 return 0; 15848 } 15849 p = find_channel_from_str(channel); 15850 if (!p) { 15851 astman_send_error(s, m, "No such channel"); 15852 return 0; 15853 } 15854 if (!analog_lib_handles(p->sig, 0, 0)) { 15855 astman_send_error(s, m, "Channel signaling is not analog"); 15856 return 0; 15857 } 15858 dahdi_fake_event(p,TRANSFER); 15859 astman_send_ack(s, m, "DAHDITransfer"); 15860 return 0; 15861 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15863 of file chan_dahdi.c.
References analog_lib_handles(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel_from_str(), HANGUP, and dahdi_pvt::sig.
Referenced by load_module().
15864 { 15865 struct dahdi_pvt *p; 15866 const char *channel = astman_get_header(m, "DAHDIChannel"); 15867 15868 if (ast_strlen_zero(channel)) { 15869 astman_send_error(s, m, "No channel specified"); 15870 return 0; 15871 } 15872 p = find_channel_from_str(channel); 15873 if (!p) { 15874 astman_send_error(s, m, "No such channel"); 15875 return 0; 15876 } 15877 if (!analog_lib_handles(p->sig, 0, 0)) { 15878 astman_send_error(s, m, "Channel signaling is not analog"); 15879 return 0; 15880 } 15881 dahdi_fake_event(p,HANGUP); 15882 astman_send_ack(s, m, "DAHDIHangup"); 15883 return 0; 15884 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 4527 of file chan_dahdi.c.
References alarm, alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
04528 { 04529 int x; 04530 for (x = 0; x < ARRAY_LEN(alarms); x++) { 04531 if (alarms[x].alarm & alm) 04532 return alarms[x].name; 04533 } 04534 return alm ? "Unknown Alarm" : "No Alarm"; 04535 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4331 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, subnames, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), build_device(), dahdi_handle_event(), HandleCallOutgoing(), my_allocate_sub(), and rcv_mac_addr().
04332 { 04333 struct dahdi_bufferinfo bi; 04334 int res; 04335 if (p->subs[x].dfd >= 0) { 04336 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 04337 return -1; 04338 } 04339 04340 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 04341 if (p->subs[x].dfd <= -1) { 04342 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 04343 return -1; 04344 } 04345 04346 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 04347 if (!res) { 04348 bi.txbufpolicy = p->buf_policy; 04349 bi.rxbufpolicy = p->buf_policy; 04350 bi.numbufs = p->buf_no; 04351 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 04352 if (res < 0) { 04353 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 04354 } 04355 } else 04356 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 04357 04358 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 04359 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 04360 dahdi_close_sub(p, x); 04361 p->subs[x].dfd = -1; 04362 return -1; 04363 } 04364 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 04365 return 0; 04366 }
static int analog_lib_handles | ( | int | signalling, | |
int | radio, | |||
int | oprmode | |||
) | [static] |
Definition at line 4612 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_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), and mwi_thread().
04613 { 04614 switch (signalling) { 04615 case SIG_FXOLS: 04616 case SIG_FXOGS: 04617 case SIG_FXOKS: 04618 case SIG_FXSLS: 04619 case SIG_FXSGS: 04620 case SIG_FXSKS: 04621 case SIG_EMWINK: 04622 case SIG_EM: 04623 case SIG_EM_E1: 04624 case SIG_FEATD: 04625 case SIG_FEATDMF: 04626 case SIG_E911: 04627 case SIG_FGC_CAMA: 04628 case SIG_FGC_CAMAMF: 04629 case SIG_FEATB: 04630 case SIG_SFWINK: 04631 case SIG_SF: 04632 case SIG_SF_FEATD: 04633 case SIG_SF_FEATDMF: 04634 case SIG_FEATDMF_TA: 04635 case SIG_SF_FEATB: 04636 break; 04637 default: 04638 /* The rest of the function should cover the remainder of signalling types */ 04639 return 0; 04640 } 04641 04642 if (radio) 04643 return 0; 04644 04645 if (oprmode) 04646 return 0; 04647 04648 return 1; 04649 }
static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 9801 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), ast_clear_flag, 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_safe_sleep(), ast_set_callerid(), ast_set_flag, ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), 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, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_pvt::cs, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, 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, f, firstdigittimeout, ast_smdi_md_message::fwd_st, gendigittimeout, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, ast_party_caller::id, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, len(), dahdi_subchannel::linear, LOG_NOTICE, matchdigittimeout, my_getsigstr(), ast_party_id::name, ast_channel::name, name, NEED_MFDETECT, ast_party_id::number, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_COR, S_OR, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_count, ss_thread_lock, ast_party_number::str, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, 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(), handle_init_event(), and mwi_thread().
09802 { 09803 struct ast_channel *chan = data; 09804 struct dahdi_pvt *p = chan->tech_pvt; 09805 char exten[AST_MAX_EXTENSION] = ""; 09806 char exten2[AST_MAX_EXTENSION] = ""; 09807 unsigned char buf[256]; 09808 char dtmfcid[300]; 09809 char dtmfbuf[300]; 09810 struct callerid_state *cs = NULL; 09811 char *name = NULL, *number = NULL; 09812 int distMatches; 09813 int curRingData[3]; 09814 int receivedRingT; 09815 int counter1; 09816 int counter; 09817 int samples = 0; 09818 struct ast_smdi_md_message *smdi_msg = NULL; 09819 int flags = 0; 09820 int i; 09821 int timeout; 09822 int getforward = 0; 09823 char *s1, *s2; 09824 int len = 0; 09825 int res; 09826 int idx; 09827 09828 ast_mutex_lock(&ss_thread_lock); 09829 ss_thread_count++; 09830 ast_mutex_unlock(&ss_thread_lock); 09831 /* in the bizarre case where the channel has become a zombie before we 09832 even get started here, abort safely 09833 */ 09834 if (!p) { 09835 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 09836 ast_hangup(chan); 09837 goto quit; 09838 } 09839 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 09840 idx = dahdi_get_index(chan, p, 1); 09841 if (idx < 0) { 09842 ast_log(LOG_WARNING, "Huh?\n"); 09843 ast_hangup(chan); 09844 goto quit; 09845 } 09846 if (p->dsp) 09847 ast_dsp_digitreset(p->dsp); 09848 switch (p->sig) { 09849 case SIG_FEATD: 09850 case SIG_FEATDMF: 09851 case SIG_FEATDMF_TA: 09852 case SIG_E911: 09853 case SIG_FGC_CAMAMF: 09854 case SIG_FEATB: 09855 case SIG_EMWINK: 09856 case SIG_SF_FEATD: 09857 case SIG_SF_FEATDMF: 09858 case SIG_SF_FEATB: 09859 case SIG_SFWINK: 09860 if (dahdi_wink(p, idx)) 09861 goto quit; 09862 /* Fall through */ 09863 case SIG_EM: 09864 case SIG_EM_E1: 09865 case SIG_SF: 09866 case SIG_FGC_CAMA: 09867 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09868 if (p->dsp) 09869 ast_dsp_digitreset(p->dsp); 09870 /* set digit mode appropriately */ 09871 if (p->dsp) { 09872 if (NEED_MFDETECT(p)) 09873 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 09874 else 09875 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09876 } 09877 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 09878 /* Wait for the first digit only if immediate=no */ 09879 if (!p->immediate) 09880 /* Wait for the first digit (up to 5 seconds). */ 09881 res = ast_waitfordigit(chan, 5000); 09882 else 09883 res = 0; 09884 if (res > 0) { 09885 /* save first char */ 09886 dtmfbuf[0] = res; 09887 switch (p->sig) { 09888 case SIG_FEATD: 09889 case SIG_SF_FEATD: 09890 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 09891 if (res > 0) 09892 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 09893 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09894 break; 09895 case SIG_FEATDMF_TA: 09896 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09897 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09898 if (dahdi_wink(p, idx)) goto quit; 09899 dtmfbuf[0] = 0; 09900 /* Wait for the first digit (up to 5 seconds). */ 09901 res = ast_waitfordigit(chan, 5000); 09902 if (res <= 0) break; 09903 dtmfbuf[0] = res; 09904 /* fall through intentionally */ 09905 case SIG_FEATDMF: 09906 case SIG_E911: 09907 case SIG_FGC_CAMAMF: 09908 case SIG_SF_FEATDMF: 09909 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09910 /* if international caca, do it again to get real ANO */ 09911 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 09912 { 09913 if (dahdi_wink(p, idx)) goto quit; 09914 dtmfbuf[0] = 0; 09915 /* Wait for the first digit (up to 5 seconds). */ 09916 res = ast_waitfordigit(chan, 5000); 09917 if (res <= 0) break; 09918 dtmfbuf[0] = res; 09919 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09920 } 09921 if (res > 0) { 09922 /* if E911, take off hook */ 09923 if (p->sig == SIG_E911) 09924 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09925 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 09926 } 09927 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09928 break; 09929 case SIG_FEATB: 09930 case SIG_SF_FEATB: 09931 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09932 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09933 break; 09934 case SIG_EMWINK: 09935 /* if we received a '*', we are actually receiving Feature Group D 09936 dial syntax, so use that mode; otherwise, fall through to normal 09937 mode 09938 */ 09939 if (res == '*') { 09940 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 09941 if (res > 0) 09942 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 09943 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09944 break; 09945 } 09946 default: 09947 /* If we got the first digit, get the rest */ 09948 len = 1; 09949 dtmfbuf[len] = '\0'; 09950 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 09951 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 09952 timeout = matchdigittimeout; 09953 } else { 09954 timeout = gendigittimeout; 09955 } 09956 res = ast_waitfordigit(chan, timeout); 09957 if (res < 0) { 09958 ast_debug(1, "waitfordigit returned < 0...\n"); 09959 ast_hangup(chan); 09960 goto quit; 09961 } else if (res) { 09962 dtmfbuf[len++] = res; 09963 dtmfbuf[len] = '\0'; 09964 } else { 09965 break; 09966 } 09967 } 09968 break; 09969 } 09970 } 09971 if (res == -1) { 09972 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 09973 ast_hangup(chan); 09974 goto quit; 09975 } else if (res < 0) { 09976 ast_debug(1, "Got hung up before digits finished\n"); 09977 ast_hangup(chan); 09978 goto quit; 09979 } 09980 09981 if (p->sig == SIG_FGC_CAMA) { 09982 char anibuf[100]; 09983 09984 if (ast_safe_sleep(chan,1000) == -1) { 09985 ast_hangup(chan); 09986 goto quit; 09987 } 09988 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09989 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 09990 res = my_getsigstr(chan, anibuf, "#", 10000); 09991 if ((res > 0) && (strlen(anibuf) > 2)) { 09992 if (anibuf[strlen(anibuf) - 1] == '#') 09993 anibuf[strlen(anibuf) - 1] = 0; 09994 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 09995 } 09996 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09997 } 09998 09999 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 10000 if (ast_strlen_zero(exten)) 10001 ast_copy_string(exten, "s", sizeof(exten)); 10002 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 10003 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 10004 if (exten[0] == '*') { 10005 char *stringp=NULL; 10006 ast_copy_string(exten2, exten, sizeof(exten2)); 10007 /* Parse out extension and callerid */ 10008 stringp=exten2 +1; 10009 s1 = strsep(&stringp, "*"); 10010 s2 = strsep(&stringp, "*"); 10011 if (s2) { 10012 if (!ast_strlen_zero(p->cid_num)) 10013 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10014 else 10015 ast_set_callerid(chan, s1, NULL, s1); 10016 ast_copy_string(exten, s2, sizeof(exten)); 10017 } else 10018 ast_copy_string(exten, s1, sizeof(exten)); 10019 } else if (p->sig == SIG_FEATD) 10020 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10021 } 10022 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10023 if (exten[0] == '*') { 10024 char *stringp=NULL; 10025 ast_copy_string(exten2, exten, sizeof(exten2)); 10026 /* Parse out extension and callerid */ 10027 stringp=exten2 +1; 10028 s1 = strsep(&stringp, "#"); 10029 s2 = strsep(&stringp, "#"); 10030 if (s2) { 10031 if (!ast_strlen_zero(p->cid_num)) 10032 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10033 else 10034 if (*(s1 + 2)) 10035 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 10036 ast_copy_string(exten, s2 + 1, sizeof(exten)); 10037 } else 10038 ast_copy_string(exten, s1 + 2, sizeof(exten)); 10039 } else 10040 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 10041 } 10042 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 10043 if (exten[0] == '*') { 10044 char *stringp=NULL; 10045 ast_copy_string(exten2, exten, sizeof(exten2)); 10046 /* Parse out extension and callerid */ 10047 stringp=exten2 +1; 10048 s1 = strsep(&stringp, "#"); 10049 s2 = strsep(&stringp, "#"); 10050 if (s2 && (*(s2 + 1) == '0')) { 10051 if (*(s2 + 2)) 10052 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 10053 } 10054 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 10055 else ast_copy_string(exten, "911", sizeof(exten)); 10056 } else 10057 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 10058 } 10059 if (p->sig == SIG_FEATB) { 10060 if (exten[0] == '*') { 10061 char *stringp=NULL; 10062 ast_copy_string(exten2, exten, sizeof(exten2)); 10063 /* Parse out extension and callerid */ 10064 stringp=exten2 +1; 10065 s1 = strsep(&stringp, "#"); 10066 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 10067 } else 10068 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 10069 } 10070 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 10071 dahdi_wink(p, idx); 10072 /* some switches require a minimum guard time between 10073 the last FGD wink and something that answers 10074 immediately. This ensures it */ 10075 if (ast_safe_sleep(chan, 100)) { 10076 ast_hangup(chan); 10077 goto quit; 10078 } 10079 } 10080 dahdi_enable_ec(p); 10081 if (NEED_MFDETECT(p)) { 10082 if (p->dsp) { 10083 if (!p->hardwaredtmf) 10084 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 10085 else { 10086 ast_dsp_free(p->dsp); 10087 p->dsp = NULL; 10088 } 10089 } 10090 } 10091 10092 if (ast_exists_extension(chan, chan->context, exten, 1, 10093 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 10094 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10095 if (p->dsp) ast_dsp_digitreset(p->dsp); 10096 res = ast_pbx_run(chan); 10097 if (res) { 10098 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10100 } 10101 goto quit; 10102 } else { 10103 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 10104 sleep(2); 10105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 10106 if (res < 0) 10107 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 10108 else 10109 sleep(1); 10110 res = ast_streamfile(chan, "ss-noservice", chan->language); 10111 if (res >= 0) 10112 ast_waitstream(chan, ""); 10113 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10114 ast_hangup(chan); 10115 goto quit; 10116 } 10117 break; 10118 case SIG_FXOLS: 10119 case SIG_FXOGS: 10120 case SIG_FXOKS: 10121 /* Read the first digit */ 10122 timeout = firstdigittimeout; 10123 /* If starting a threeway call, never timeout on the first digit so someone 10124 can use flash-hook as a "hold" feature */ 10125 if (p->subs[SUB_THREEWAY].owner) 10126 timeout = 999999; 10127 while (len < AST_MAX_EXTENSION-1) { 10128 /* Read digit unless it's supposed to be immediate, in which case the 10129 only answer is 's' */ 10130 if (p->immediate) 10131 res = 's'; 10132 else 10133 res = ast_waitfordigit(chan, timeout); 10134 timeout = 0; 10135 if (res < 0) { 10136 ast_debug(1, "waitfordigit returned < 0...\n"); 10137 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10138 ast_hangup(chan); 10139 goto quit; 10140 } else if (res) { 10141 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 10142 exten[len++]=res; 10143 exten[len] = '\0'; 10144 } 10145 if (!ast_ignore_pattern(chan->context, exten)) 10146 tone_zone_play_tone(p->subs[idx].dfd, -1); 10147 else 10148 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10149 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) { 10150 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 10151 if (getforward) { 10152 /* Record this as the forwarding extension */ 10153 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 10154 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 10155 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10156 if (res) 10157 break; 10158 usleep(500000); 10159 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10160 sleep(1); 10161 memset(exten, 0, sizeof(exten)); 10162 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 10163 len = 0; 10164 getforward = 0; 10165 } else { 10166 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 10167 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 10168 if (!ast_strlen_zero(p->cid_num)) { 10169 if (!p->hidecallerid) 10170 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 10171 else 10172 ast_set_callerid(chan, NULL, NULL, p->cid_num); 10173 } 10174 if (!ast_strlen_zero(p->cid_name)) { 10175 if (!p->hidecallerid) 10176 ast_set_callerid(chan, NULL, p->cid_name, NULL); 10177 } 10178 ast_setstate(chan, AST_STATE_RING); 10179 dahdi_enable_ec(p); 10180 res = ast_pbx_run(chan); 10181 if (res) { 10182 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10183 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10184 } 10185 goto quit; 10186 } 10187 } else { 10188 /* It's a match, but they just typed a digit, and there is an ambiguous match, 10189 so just set the timeout to matchdigittimeout and wait some more */ 10190 timeout = matchdigittimeout; 10191 } 10192 } else if (res == 0) { 10193 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 10194 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10195 dahdi_wait_event(p->subs[idx].dfd); 10196 ast_hangup(chan); 10197 goto quit; 10198 } else if (p->callwaiting && !strcmp(exten, "*70")) { 10199 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 10200 /* Disable call waiting if enabled */ 10201 p->callwaiting = 0; 10202 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10203 if (res) { 10204 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10205 chan->name, strerror(errno)); 10206 } 10207 len = 0; 10208 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 10209 memset(exten, 0, sizeof(exten)); 10210 timeout = firstdigittimeout; 10211 10212 } else if (!strcmp(exten,ast_pickup_ext())) { 10213 /* Scan all channels and see if there are any 10214 * ringing channels that have call groups 10215 * that equal this channels pickup group 10216 */ 10217 if (idx == SUB_REAL) { 10218 /* Switch us from Third call to Call Wait */ 10219 if (p->subs[SUB_THREEWAY].owner) { 10220 /* If you make a threeway call and the *8# a call, it should actually 10221 look like a callwait */ 10222 alloc_sub(p, SUB_CALLWAIT); 10223 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 10224 unalloc_sub(p, SUB_THREEWAY); 10225 } 10226 dahdi_enable_ec(p); 10227 if (ast_pickup_call(chan)) { 10228 ast_debug(1, "No call pickup possible...\n"); 10229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10230 dahdi_wait_event(p->subs[idx].dfd); 10231 } 10232 ast_hangup(chan); 10233 goto quit; 10234 } else { 10235 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 10236 ast_hangup(chan); 10237 goto quit; 10238 } 10239 10240 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 10241 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 10242 /* Disable Caller*ID if enabled */ 10243 p->hidecallerid = 1; 10244 ast_party_number_free(&chan->caller.id.number); 10245 ast_party_number_init(&chan->caller.id.number); 10246 ast_party_name_free(&chan->caller.id.name); 10247 ast_party_name_init(&chan->caller.id.name); 10248 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10249 if (res) { 10250 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10251 chan->name, strerror(errno)); 10252 } 10253 len = 0; 10254 memset(exten, 0, sizeof(exten)); 10255 timeout = firstdigittimeout; 10256 } else if (p->callreturn && !strcmp(exten, "*69")) { 10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10258 break; 10259 } else if (!strcmp(exten, "*78")) { 10260 dahdi_dnd(p, 1); 10261 /* Do not disturb */ 10262 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10263 getforward = 0; 10264 memset(exten, 0, sizeof(exten)); 10265 len = 0; 10266 } else if (!strcmp(exten, "*79")) { 10267 dahdi_dnd(p, 0); 10268 /* Do not disturb */ 10269 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10270 getforward = 0; 10271 memset(exten, 0, sizeof(exten)); 10272 len = 0; 10273 } else if (p->cancallforward && !strcmp(exten, "*72")) { 10274 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10275 getforward = 1; 10276 memset(exten, 0, sizeof(exten)); 10277 len = 0; 10278 } else if (p->cancallforward && !strcmp(exten, "*73")) { 10279 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 10280 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10281 memset(p->call_forward, 0, sizeof(p->call_forward)); 10282 getforward = 0; 10283 memset(exten, 0, sizeof(exten)); 10284 len = 0; 10285 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) && 10286 p->subs[SUB_THREEWAY].owner && 10287 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 10288 /* This is a three way call, the main call being a real channel, 10289 and we're parking the first call. */ 10290 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), 10291 chan, exten, chan->context, 0, NULL); 10292 ast_verb(3, "Parking call to '%s'\n", chan->name); 10293 break; 10294 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 10295 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 10296 /* Enable Caller*ID if enabled */ 10297 p->hidecallerid = 0; 10298 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10300 if (res) { 10301 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10302 chan->name, strerror(errno)); 10303 } 10304 len = 0; 10305 memset(exten, 0, sizeof(exten)); 10306 timeout = firstdigittimeout; 10307 } else if (!strcmp(exten, "*0")) { 10308 struct ast_channel *nbridge = 10309 p->subs[SUB_THREEWAY].owner; 10310 struct dahdi_pvt *pbridge = NULL; 10311 /* set up the private struct of the bridged one, if any */ 10312 if (nbridge && ast_bridged_channel(nbridge)) 10313 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 10314 if (nbridge && pbridge && 10315 (nbridge->tech == &dahdi_tech) && 10316 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 10317 ISTRUNK(pbridge)) { 10318 int func = DAHDI_FLASH; 10319 /* Clear out the dial buffer */ 10320 p->dop.dialstr[0] = '\0'; 10321 /* flash hookswitch */ 10322 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 10323 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 10324 nbridge->name, strerror(errno)); 10325 } 10326 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10327 unalloc_sub(p, SUB_THREEWAY); 10328 p->owner = p->subs[SUB_REAL].owner; 10329 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 10330 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 10331 ast_hangup(chan); 10332 goto quit; 10333 } else { 10334 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10335 dahdi_wait_event(p->subs[idx].dfd); 10336 tone_zone_play_tone(p->subs[idx].dfd, -1); 10337 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10338 unalloc_sub(p, SUB_THREEWAY); 10339 p->owner = p->subs[SUB_REAL].owner; 10340 ast_hangup(chan); 10341 goto quit; 10342 } 10343 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, 10344 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 10345 && !canmatch_featurecode(exten)) { 10346 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, 10347 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 10348 chan->context); 10349 break; 10350 } 10351 if (!timeout) 10352 timeout = gendigittimeout; 10353 if (len && !ast_ignore_pattern(chan->context, exten)) 10354 tone_zone_play_tone(p->subs[idx].dfd, -1); 10355 } 10356 break; 10357 case SIG_FXSLS: 10358 case SIG_FXSGS: 10359 case SIG_FXSKS: 10360 /* check for SMDI messages */ 10361 if (p->use_smdi && p->smdi_iface) { 10362 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 10363 10364 if (smdi_msg != NULL) { 10365 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 10366 10367 if (smdi_msg->type == 'B') 10368 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 10369 else if (smdi_msg->type == 'N') 10370 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 10371 10372 ast_debug(1, "Received SMDI message on %s\n", chan->name); 10373 } else { 10374 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 10375 } 10376 } 10377 10378 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 10379 number = smdi_msg->calling_st; 10380 10381 /* If we want caller id, we're in a prering state due to a polarity reversal 10382 * and we're set to use a polarity reversal to trigger the start of caller id, 10383 * grab the caller id and wait for ringing to start... */ 10384 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 10385 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 10386 /* If set to use DTMF CID signalling, listen for DTMF */ 10387 if (p->cid_signalling == CID_SIG_DTMF) { 10388 int k = 0; 10389 cs = NULL; 10390 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 10391 dahdi_setlinear(p->subs[idx].dfd, 0); 10392 /* 10393 * We are the only party interested in the Rx stream since 10394 * we have not answered yet. We don't need or even want DTMF 10395 * emulation. The DTMF digits can come so fast that emulation 10396 * can drop some of them. 10397 */ 10398 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 10399 res = 4000;/* This is a typical OFF time between rings. */ 10400 for (;;) { 10401 struct ast_frame *f; 10402 res = ast_waitfor(chan, res); 10403 if (res <= 0) { 10404 /* 10405 * We do not need to restore the dahdi_setlinear() 10406 * or AST_FLAG_END_DTMF_ONLY flag settings since we 10407 * are hanging up the channel. 10408 */ 10409 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10410 "Exiting simple switch\n"); 10411 ast_hangup(chan); 10412 goto quit; 10413 } 10414 f = ast_read(chan); 10415 if (!f) 10416 break; 10417 if (f->frametype == AST_FRAME_DTMF) { 10418 if (k < ARRAY_LEN(dtmfbuf) - 1) { 10419 dtmfbuf[k++] = f->subclass.integer; 10420 } 10421 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer); 10422 res = 4000;/* This is a typical OFF time between rings. */ 10423 } 10424 ast_frfree(f); 10425 if (chan->_state == AST_STATE_RING || 10426 chan->_state == AST_STATE_RINGING) 10427 break; /* Got ring */ 10428 } 10429 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 10430 dtmfbuf[k] = '\0'; 10431 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10432 /* Got cid and ring. */ 10433 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 10434 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10435 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 10436 /* If first byte is NULL, we have no cid */ 10437 if (!ast_strlen_zero(dtmfcid)) 10438 number = dtmfcid; 10439 else 10440 number = NULL; 10441 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10442 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 10443 cs = callerid_new(p->cid_signalling); 10444 if (cs) { 10445 samples = 0; 10446 #if 1 10447 bump_gains(p); 10448 #endif 10449 /* Take out of linear mode for Caller*ID processing */ 10450 dahdi_setlinear(p->subs[idx].dfd, 0); 10451 10452 /* First we wait and listen for the Caller*ID */ 10453 for (;;) { 10454 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10455 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10456 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10457 callerid_free(cs); 10458 ast_hangup(chan); 10459 goto quit; 10460 } 10461 if (i & DAHDI_IOMUX_SIGEVENT) { 10462 res = dahdi_get_event(p->subs[idx].dfd); 10463 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10464 if (res == DAHDI_EVENT_NOALARM) { 10465 p->inalarm = 0; 10466 } 10467 10468 if (p->cid_signalling == CID_SIG_V23_JP) { 10469 if (res == DAHDI_EVENT_RINGBEGIN) { 10470 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10471 usleep(1); 10472 } 10473 } else { 10474 res = 0; 10475 break; 10476 } 10477 } else if (i & DAHDI_IOMUX_READ) { 10478 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10479 if (res < 0) { 10480 if (errno != ELAST) { 10481 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10482 callerid_free(cs); 10483 ast_hangup(chan); 10484 goto quit; 10485 } 10486 break; 10487 } 10488 samples += res; 10489 10490 if (p->cid_signalling == CID_SIG_V23_JP) { 10491 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 10492 } else { 10493 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10494 } 10495 if (res < 0) { 10496 /* 10497 * The previous diagnostic message output likely 10498 * explains why it failed. 10499 */ 10500 ast_log(LOG_WARNING, 10501 "Failed to decode CallerID on channel '%s'\n", 10502 chan->name); 10503 break; 10504 } else if (res) 10505 break; 10506 else if (samples > (8000 * 10)) 10507 break; 10508 } 10509 } 10510 if (res == 1) { 10511 callerid_get(cs, &name, &number, &flags); 10512 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10513 } 10514 10515 if (p->cid_signalling == CID_SIG_V23_JP) { 10516 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10517 usleep(1); 10518 } 10519 10520 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 10521 res = 4000;/* This is a typical OFF time between rings. */ 10522 for (;;) { 10523 struct ast_frame *f; 10524 res = ast_waitfor(chan, res); 10525 if (res <= 0) { 10526 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 10527 "Exiting simple switch\n"); 10528 ast_hangup(chan); 10529 goto quit; 10530 } 10531 if (!(f = ast_read(chan))) { 10532 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 10533 ast_hangup(chan); 10534 goto quit; 10535 } 10536 ast_frfree(f); 10537 if (chan->_state == AST_STATE_RING || 10538 chan->_state == AST_STATE_RINGING) 10539 break; /* Got ring */ 10540 } 10541 10542 /* We must have a ring by now, so, if configured, lets try to listen for 10543 * distinctive ringing */ 10544 if (p->usedistinctiveringdetection) { 10545 len = 0; 10546 distMatches = 0; 10547 /* Clear the current ring data array so we don't have old data in it. */ 10548 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10549 curRingData[receivedRingT] = 0; 10550 receivedRingT = 0; 10551 counter = 0; 10552 counter1 = 0; 10553 /* Check to see if context is what it should be, if not set to be. */ 10554 if (strcmp(p->context,p->defcontext) != 0) { 10555 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10556 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10557 } 10558 10559 for (;;) { 10560 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10561 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10562 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10563 callerid_free(cs); 10564 ast_hangup(chan); 10565 goto quit; 10566 } 10567 if (i & DAHDI_IOMUX_SIGEVENT) { 10568 res = dahdi_get_event(p->subs[idx].dfd); 10569 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10570 if (res == DAHDI_EVENT_NOALARM) { 10571 p->inalarm = 0; 10572 } 10573 res = 0; 10574 /* Let us detect distinctive ring */ 10575 10576 curRingData[receivedRingT] = p->ringt; 10577 10578 if (p->ringt < p->ringt_base/2) 10579 break; 10580 /* Increment the ringT counter so we can match it against 10581 values in chan_dahdi.conf for distinctive ring */ 10582 if (++receivedRingT == ARRAY_LEN(curRingData)) 10583 break; 10584 } else if (i & DAHDI_IOMUX_READ) { 10585 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10586 if (res < 0) { 10587 if (errno != ELAST) { 10588 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10589 callerid_free(cs); 10590 ast_hangup(chan); 10591 goto quit; 10592 } 10593 break; 10594 } 10595 if (p->ringt > 0) { 10596 if (!(--p->ringt)) { 10597 res = -1; 10598 break; 10599 } 10600 } 10601 } 10602 } 10603 /* this only shows up if you have n of the dring patterns filled in */ 10604 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10605 for (counter = 0; counter < 3; counter++) { 10606 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10607 channel */ 10608 distMatches = 0; 10609 for (counter1 = 0; counter1 < 3; counter1++) { 10610 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10611 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10612 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10613 curRingData[counter1]); 10614 distMatches++; 10615 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10616 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10617 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10618 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10619 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10620 distMatches++; 10621 } 10622 } 10623 10624 if (distMatches == 3) { 10625 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10626 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10627 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10628 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10629 break; 10630 } 10631 } 10632 } 10633 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10634 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10635 #if 1 10636 restore_gains(p); 10637 #endif 10638 } else 10639 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10640 } else { 10641 ast_log(LOG_WARNING, "Channel %s in prering " 10642 "state, but I have nothing to do. " 10643 "Terminating simple switch, should be " 10644 "restarted by the actual ring.\n", 10645 chan->name); 10646 ast_hangup(chan); 10647 goto quit; 10648 } 10649 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 10650 if (p->cid_signalling == CID_SIG_DTMF) { 10651 int k = 0; 10652 cs = NULL; 10653 dahdi_setlinear(p->subs[idx].dfd, 0); 10654 res = 2000; 10655 for (;;) { 10656 struct ast_frame *f; 10657 res = ast_waitfor(chan, res); 10658 if (res <= 0) { 10659 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10660 "Exiting simple switch\n"); 10661 ast_hangup(chan); 10662 goto quit; 10663 } 10664 f = ast_read(chan); 10665 if (!f) { 10666 /* Hangup received waiting for DTMFCID. Exiting simple switch. */ 10667 ast_hangup(chan); 10668 goto quit; 10669 } 10670 if (f->frametype == AST_FRAME_DTMF) { 10671 dtmfbuf[k++] = f->subclass.integer; 10672 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer); 10673 res = 2000; 10674 } 10675 ast_frfree(f); 10676 10677 if (p->ringt_base == p->ringt) 10678 break; 10679 } 10680 dtmfbuf[k] = '\0'; 10681 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10682 /* Got cid and ring. */ 10683 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10684 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 10685 dtmfcid, flags); 10686 /* If first byte is NULL, we have no cid */ 10687 if (!ast_strlen_zero(dtmfcid)) 10688 number = dtmfcid; 10689 else 10690 number = NULL; 10691 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10692 } else { 10693 /* FSK Bell202 callerID */ 10694 cs = callerid_new(p->cid_signalling); 10695 if (cs) { 10696 #if 1 10697 bump_gains(p); 10698 #endif 10699 samples = 0; 10700 len = 0; 10701 distMatches = 0; 10702 /* Clear the current ring data array so we don't have old data in it. */ 10703 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10704 curRingData[receivedRingT] = 0; 10705 receivedRingT = 0; 10706 counter = 0; 10707 counter1 = 0; 10708 /* Check to see if context is what it should be, if not set to be. */ 10709 if (strcmp(p->context,p->defcontext) != 0) { 10710 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10711 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10712 } 10713 10714 /* Take out of linear mode for Caller*ID processing */ 10715 dahdi_setlinear(p->subs[idx].dfd, 0); 10716 for (;;) { 10717 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10718 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10719 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10720 callerid_free(cs); 10721 ast_hangup(chan); 10722 goto quit; 10723 } 10724 if (i & DAHDI_IOMUX_SIGEVENT) { 10725 res = dahdi_get_event(p->subs[idx].dfd); 10726 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10727 if (res == DAHDI_EVENT_NOALARM) { 10728 p->inalarm = 0; 10729 } 10730 /* If we get a PR event, they hung up while processing calerid */ 10731 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 10732 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 10733 p->polarity = POLARITY_IDLE; 10734 callerid_free(cs); 10735 ast_hangup(chan); 10736 goto quit; 10737 } 10738 res = 0; 10739 /* Let us detect callerid when the telco uses distinctive ring */ 10740 10741 curRingData[receivedRingT] = p->ringt; 10742 10743 if (p->ringt < p->ringt_base/2) 10744 break; 10745 /* Increment the ringT counter so we can match it against 10746 values in chan_dahdi.conf for distinctive ring */ 10747 if (++receivedRingT == ARRAY_LEN(curRingData)) 10748 break; 10749 } else if (i & DAHDI_IOMUX_READ) { 10750 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10751 if (res < 0) { 10752 if (errno != ELAST) { 10753 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10754 callerid_free(cs); 10755 ast_hangup(chan); 10756 goto quit; 10757 } 10758 break; 10759 } 10760 if (p->ringt > 0) { 10761 if (!(--p->ringt)) { 10762 res = -1; 10763 break; 10764 } 10765 } 10766 samples += res; 10767 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10768 if (res < 0) { 10769 /* 10770 * The previous diagnostic message output likely 10771 * explains why it failed. 10772 */ 10773 ast_log(LOG_WARNING, 10774 "Failed to decode CallerID on channel '%s'\n", 10775 chan->name); 10776 break; 10777 } else if (res) 10778 break; 10779 else if (samples > (8000 * 10)) 10780 break; 10781 } 10782 } 10783 if (res == 1) { 10784 callerid_get(cs, &name, &number, &flags); 10785 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10786 } 10787 if (distinctiveringaftercid == 1) { 10788 /* Clear the current ring data array so we don't have old data in it. */ 10789 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 10790 curRingData[receivedRingT] = 0; 10791 } 10792 receivedRingT = 0; 10793 ast_verb(3, "Detecting post-CID distinctive ring\n"); 10794 for (;;) { 10795 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10796 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10797 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10798 callerid_free(cs); 10799 ast_hangup(chan); 10800 goto quit; 10801 } 10802 if (i & DAHDI_IOMUX_SIGEVENT) { 10803 res = dahdi_get_event(p->subs[idx].dfd); 10804 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10805 if (res == DAHDI_EVENT_NOALARM) { 10806 p->inalarm = 0; 10807 } 10808 res = 0; 10809 /* Let us detect callerid when the telco uses distinctive ring */ 10810 10811 curRingData[receivedRingT] = p->ringt; 10812 10813 if (p->ringt < p->ringt_base/2) 10814 break; 10815 /* Increment the ringT counter so we can match it against 10816 values in chan_dahdi.conf for distinctive ring */ 10817 if (++receivedRingT == ARRAY_LEN(curRingData)) 10818 break; 10819 } else if (i & DAHDI_IOMUX_READ) { 10820 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10821 if (res < 0) { 10822 if (errno != ELAST) { 10823 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10824 callerid_free(cs); 10825 ast_hangup(chan); 10826 goto quit; 10827 } 10828 break; 10829 } 10830 if (p->ringt > 0) { 10831 if (!(--p->ringt)) { 10832 res = -1; 10833 break; 10834 } 10835 } 10836 } 10837 } 10838 } 10839 if (p->usedistinctiveringdetection) { 10840 /* this only shows up if you have n of the dring patterns filled in */ 10841 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10842 10843 for (counter = 0; counter < 3; counter++) { 10844 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10845 channel */ 10846 /* this only shows up if you have n of the dring patterns filled in */ 10847 ast_verb(3, "Checking %d,%d,%d\n", 10848 p->drings.ringnum[counter].ring[0], 10849 p->drings.ringnum[counter].ring[1], 10850 p->drings.ringnum[counter].ring[2]); 10851 distMatches = 0; 10852 for (counter1 = 0; counter1 < 3; counter1++) { 10853 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10854 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10855 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10856 curRingData[counter1]); 10857 distMatches++; 10858 } 10859 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10860 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10861 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10862 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10863 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10864 distMatches++; 10865 } 10866 } 10867 if (distMatches == 3) { 10868 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10869 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10870 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10871 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10872 break; 10873 } 10874 } 10875 } 10876 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10877 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10878 #if 1 10879 restore_gains(p); 10880 #endif 10881 if (res < 0) { 10882 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 10883 } 10884 } else 10885 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10886 } 10887 } else 10888 cs = NULL; 10889 10890 if (number) 10891 ast_shrink_phone_number(number); 10892 ast_set_callerid(chan, number, name, number); 10893 10894 if (smdi_msg) 10895 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 10896 10897 if (cs) 10898 callerid_free(cs); 10899 10900 my_handle_notify_message(chan, p, flags, -1); 10901 10902 ast_setstate(chan, AST_STATE_RING); 10903 chan->rings = 1; 10904 p->ringt = p->ringt_base; 10905 res = ast_pbx_run(chan); 10906 if (res) { 10907 ast_hangup(chan); 10908 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10909 } 10910 goto quit; 10911 default: 10912 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 10913 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10914 if (res < 0) 10915 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 10916 } 10917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10918 if (res < 0) 10919 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 10920 ast_hangup(chan); 10921 quit: 10922 ast_mutex_lock(&ss_thread_lock); 10923 ss_thread_count--; 10924 ast_cond_signal(&ss_thread_complete); 10925 ast_mutex_unlock(&ss_thread_lock); 10926 return NULL; 10927 }
static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1620 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().
01621 { 01622 switch (tone) { 01623 case ANALOG_TONE_RINGTONE: 01624 return DAHDI_TONE_RINGTONE; 01625 case ANALOG_TONE_STUTTER: 01626 return DAHDI_TONE_STUTTER; 01627 case ANALOG_TONE_CONGESTION: 01628 return DAHDI_TONE_CONGESTION; 01629 case ANALOG_TONE_DIALTONE: 01630 return DAHDI_TONE_DIALTONE; 01631 case ANALOG_TONE_DIALRECALL: 01632 return DAHDI_TONE_DIALRECALL; 01633 case ANALOG_TONE_INFO: 01634 return DAHDI_TONE_INFO; 01635 default: 01636 return -1; 01637 } 01638 }
static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1640 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().
01641 { 01642 int index; 01643 01644 switch (analogsub) { 01645 case ANALOG_SUB_REAL: 01646 index = SUB_REAL; 01647 break; 01648 case ANALOG_SUB_CALLWAIT: 01649 index = SUB_CALLWAIT; 01650 break; 01651 case ANALOG_SUB_THREEWAY: 01652 index = SUB_THREEWAY; 01653 break; 01654 default: 01655 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01656 index = SUB_REAL; 01657 } 01658 01659 return index; 01660 }
AST_DATA_STRUCTURE | ( | dahdi_pvt | , | |
DATA_EXPORT_DAHDI_PVT | ||||
) |
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7580 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, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().
07581 { 07582 /* In order to transfer, we need at least one of the channels to 07583 actually be in a call bridge. We can't conference two applications 07584 together (but then, why would we want to?) */ 07585 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07586 /* The three-way person we're about to transfer to could still be in MOH, so 07587 stop if now if appropriate */ 07588 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 07589 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 07590 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 07591 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 07592 } 07593 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 07594 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07595 } 07596 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 07597 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07598 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 07599 return -1; 07600 } 07601 /* Orphan the channel after releasing the lock */ 07602 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07603 unalloc_sub(p, SUB_THREEWAY); 07604 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07605 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07606 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 07607 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 07608 } 07609 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 07610 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07611 } 07612 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 07613 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07614 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 07615 return -1; 07616 } 07617 /* Three-way is now the REAL */ 07618 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07619 ast_channel_unlock(p->subs[SUB_REAL].owner); 07620 unalloc_sub(p, SUB_THREEWAY); 07621 /* Tell the caller not to hangup */ 07622 return 1; 07623 } else { 07624 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 07625 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 07626 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07627 return -1; 07628 } 07629 return 0; 07630 }
static int available | ( | struct dahdi_pvt ** | pvt, | |
int | is_specific_channel | |||
) | [static] |
Definition at line 13084 of file chan_dahdi.c.
References analog_available(), analog_lib_handles(), sig_pri_chan::chan_pvt, dahdi_pvt::inalarm, dahdi_pvt::locallyblocked, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, 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().
13085 { 13086 struct dahdi_pvt *p = *pvt; 13087 13088 if (p->inalarm) 13089 return 0; 13090 13091 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 13092 return analog_available(p->sig_pvt); 13093 13094 switch (p->sig) { 13095 #if defined(HAVE_PRI) 13096 case SIG_PRI_LIB_HANDLE_CASES: 13097 { 13098 struct sig_pri_chan *pvt_chan; 13099 int res; 13100 13101 pvt_chan = p->sig_pvt; 13102 res = sig_pri_available(&pvt_chan, is_specific_channel); 13103 *pvt = pvt_chan->chan_pvt; 13104 return res; 13105 } 13106 #endif /* defined(HAVE_PRI) */ 13107 #if defined(HAVE_SS7) 13108 case SIG_SS7: 13109 return sig_ss7_available(p->sig_pvt); 13110 #endif /* defined(HAVE_SS7) */ 13111 default: 13112 break; 13113 } 13114 13115 if (p->locallyblocked || p->remotelyblocked) { 13116 return 0; 13117 } 13118 13119 /* If no owner definitely available */ 13120 if (!p->owner) { 13121 #ifdef HAVE_OPENR2 13122 /* Trust MFC/R2 */ 13123 if (p->mfcr2) { 13124 if (p->mfcr2call) { 13125 return 0; 13126 } else { 13127 return 1; 13128 } 13129 } 13130 #endif 13131 return 1; 13132 } 13133 13134 return 0; 13135 }
static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
const char * | value, | |||
int | reload, | |||
int | lineno, | |||
int * | found_pseudo | |||
) | [static] |
Definition at line 16700 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, mkintf(), parse_spanchan(), dahdi_pvt::sig, sig2str, and strsep().
Referenced by process_dahdi().
16701 { 16702 char *c, *chan; 16703 char *subdir; 16704 int x, start, finish; 16705 struct dahdi_pvt *tmp; 16706 16707 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 16708 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 16709 return -1; 16710 } 16711 16712 c = ast_strdupa(value); 16713 c = parse_spanchan(c, &subdir); 16714 16715 while ((chan = strsep(&c, ","))) { 16716 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 16717 /* Range */ 16718 } else if (sscanf(chan, "%30d", &start)) { 16719 /* Just one */ 16720 finish = start; 16721 } else if (!strcasecmp(chan, "pseudo")) { 16722 finish = start = CHAN_PSEUDO; 16723 if (found_pseudo) 16724 *found_pseudo = 1; 16725 } else { 16726 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 16727 return -1; 16728 } 16729 if (finish < start) { 16730 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 16731 x = finish; 16732 finish = start; 16733 start = x; 16734 } 16735 16736 for (x = start; x <= finish; x++) { 16737 char fn[PATH_MAX]; 16738 int real_channel = x; 16739 16740 if (!ast_strlen_zero(subdir)) { 16741 real_channel = device2chan(subdir, x, fn, sizeof(fn)); 16742 if (real_channel < 0) { 16743 if (conf->ignore_failed_channels) { 16744 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n", 16745 subdir, x, real_channel); 16746 continue; 16747 } else { 16748 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n", 16749 subdir, x, real_channel); 16750 return -1; 16751 } 16752 } 16753 } 16754 tmp = mkintf(real_channel, conf, reload); 16755 16756 if (tmp) { 16757 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig)); 16758 } else { 16759 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 16760 (reload == 1) ? "reconfigure" : "register", value); 16761 return -1; 16762 } 16763 } 16764 } 16765 16766 return 0; 16767 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5069 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, 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().
05070 { 05071 int res; 05072 05073 /* Bump receive gain by value stored in cid_rxgain */ 05074 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05075 if (res) { 05076 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 05077 return -1; 05078 } 05079 05080 return 0; 05081 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
format_t | law | |||
) | [static] |
Definition at line 10935 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by mwi_thread().
10936 { 10937 int x; 10938 int sum = 0; 10939 10940 if (!len) 10941 return 0; 10942 10943 for (x = 0; x < len; x++) 10944 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 10945 10946 return sum / len; 10947 }
static int canmatch_featurecode | ( | const char * | exten | ) | [static] |
Definition at line 9774 of file chan_dahdi.c.
References ast_pickup_ext(), and pickup_ext.
Referenced by analog_ss_thread().
09775 { 09776 int extlen = strlen(exten); 09777 const char *pickup_ext; 09778 if (!extlen) { 09779 return 1; 09780 } 09781 pickup_ext = ast_pickup_ext(); 09782 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) { 09783 return 1; 09784 } 09785 /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */ 09786 if (exten[0] == '*' && extlen < 3) { 09787 if (extlen == 1) { 09788 return 1; 09789 } 09790 /* "*0" should be processed before it gets here */ 09791 switch (exten[1]) { 09792 case '6': 09793 case '7': 09794 case '8': 09795 return 1; 09796 } 09797 } 09798 return 0; 09799 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7632 of file chan_dahdi.c.
References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), and my_check_for_conference().
07633 { 07634 struct dahdi_confinfo ci; 07635 /* Fine if we already have a master, etc */ 07636 if (p->master || (p->confno > -1)) 07637 return 0; 07638 memset(&ci, 0, sizeof(ci)); 07639 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 07640 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 07641 return 0; 07642 } 07643 /* If we have no master and don't have a confno, then 07644 if we're in a conference, it's probably a MeetMe room or 07645 some such, so don't let us 3-way out! */ 07646 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 07647 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 07648 return 1; 07649 } 07650 return 0; 07651 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 14136 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
14137 { 14138 return complete_span_helper(line,word,pos,state,3); 14139 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 14115 of file chan_dahdi.c.
References asprintf, ast_log(), errno, dahdi_pri::pri, and pris.
Referenced by complete_span_4().
14116 { 14117 int which, span; 14118 char *ret = NULL; 14119 14120 if (pos != rpos) 14121 return ret; 14122 14123 for (which = span = 0; span < NUM_SPANS; span++) { 14124 if (pris[span].pri.pri && ++which > state) { 14125 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 14126 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 14127 } 14128 break; 14129 } 14130 } 14131 return ret; 14132 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 4651 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().
04652 { 04653 /* If the conference already exists, and we're already in it 04654 don't bother doing anything */ 04655 struct dahdi_confinfo zi; 04656 04657 memset(&zi, 0, sizeof(zi)); 04658 zi.chan = 0; 04659 04660 if (slavechannel > 0) { 04661 /* If we have only one slave, do a digital mon */ 04662 zi.confmode = DAHDI_CONF_DIGITALMON; 04663 zi.confno = slavechannel; 04664 } else { 04665 if (!idx) { 04666 /* Real-side and pseudo-side both participate in conference */ 04667 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 04668 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 04669 } else 04670 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 04671 zi.confno = p->confno; 04672 } 04673 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 04674 return 0; 04675 if (c->dfd < 0) 04676 return 0; 04677 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04678 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 04679 return -1; 04680 } 04681 if (slavechannel < 1) { 04682 p->confno = zi.confno; 04683 } 04684 c->curconf = zi; 04685 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04686 return 0; 04687 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 4700 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().
04701 { 04702 struct dahdi_confinfo zi; 04703 if (/* Can't delete if there's no dfd */ 04704 (c->dfd < 0) || 04705 /* Don't delete from the conference if it's not our conference */ 04706 !isourconf(p, c) 04707 /* Don't delete if we don't think it's conferenced at all (implied) */ 04708 ) return 0; 04709 memset(&zi, 0, sizeof(zi)); 04710 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04711 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 04712 return -1; 04713 } 04714 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04715 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 04716 return 0; 04717 }
static struct ast_str* create_channel_name | ( | struct dahdi_pvt * | i, | |
int | is_outgoing, | |||
char * | address | |||
) | [static] |
Definition at line 9433 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(), and CHAN_PSEUDO.
Referenced by dahdi_cc_callback(), and dahdi_new().
09437 { 09438 struct ast_str *chan_name; 09439 int x, y; 09440 09441 /* Create the new channel name tail. */ 09442 if (!(chan_name = ast_str_create(32))) { 09443 return NULL; 09444 } 09445 if (i->channel == CHAN_PSEUDO) { 09446 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 09447 #if defined(HAVE_PRI) 09448 } else if (i->pri) { 09449 ast_mutex_lock(&i->pri->lock); 09450 y = ++i->pri->new_chan_seq; 09451 if (is_outgoing) { 09452 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y); 09453 address[0] = '\0'; 09454 } else if (ast_strlen_zero(i->cid_subaddr)) { 09455 /* Put in caller-id number only since there is no subaddress. */ 09456 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y); 09457 } else { 09458 /* Put in caller-id number and subaddress. */ 09459 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num, 09460 i->cid_subaddr, y); 09461 } 09462 ast_mutex_unlock(&i->pri->lock); 09463 #endif /* defined(HAVE_PRI) */ 09464 } else { 09465 y = 1; 09466 do { 09467 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 09468 for (x = 0; x < 3; ++x) { 09469 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), 09470 i->subs[x].owner->name + 6)) { 09471 break; 09472 } 09473 } 09474 ++y; 09475 } while (x < 3); 09476 } 09477 return chan_name; 09478 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 5926 of file chan_dahdi.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_strlen_zero(), dahdi_tech, f, LOG_DEBUG, parse(), and ast_channel::tech.
Referenced by load_module().
05927 { 05928 /* data is whether to accept with charge or no charge */ 05929 openr2_call_mode_t accept_mode; 05930 int res, timeout, maxloops; 05931 struct ast_frame *f; 05932 struct dahdi_pvt *p; 05933 char *parse; 05934 AST_DECLARE_APP_ARGS(args, 05935 AST_APP_ARG(charge); 05936 ); 05937 05938 if (ast_strlen_zero(data)) { 05939 ast_log(LOG_DEBUG, "No data sent to application!\n"); 05940 return -1; 05941 } 05942 05943 if (chan->tech != &dahdi_tech) { 05944 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 05945 return -1; 05946 } 05947 05948 p = (struct dahdi_pvt *)chan->tech_pvt; 05949 if (!p) { 05950 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 05951 return -1; 05952 } 05953 05954 parse = ast_strdupa(data); 05955 AST_STANDARD_APP_ARGS(args, parse); 05956 05957 if (ast_strlen_zero(args.charge)) { 05958 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 05959 return -1; 05960 } 05961 05962 ast_mutex_lock(&p->lock); 05963 if (!p->mfcr2 || !p->mfcr2call) { 05964 ast_mutex_unlock(&p->lock); 05965 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 05966 return -1; 05967 } 05968 05969 if (p->mfcr2_call_accepted) { 05970 ast_mutex_unlock(&p->lock); 05971 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 05972 return 0; 05973 } 05974 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 05975 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 05976 ast_mutex_unlock(&p->lock); 05977 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 05978 return -1; 05979 } 05980 ast_mutex_unlock(&p->lock); 05981 05982 res = 0; 05983 timeout = 100; 05984 maxloops = 50; /* wait up to 5 seconds */ 05985 /* we need to read() until the call is accepted */ 05986 while (maxloops > 0) { 05987 maxloops--; 05988 if (ast_check_hangup(chan)) { 05989 break; 05990 } 05991 res = ast_waitfor(chan, timeout); 05992 if (res < 0) { 05993 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 05994 res = -1; 05995 break; 05996 } 05997 if (res == 0) { 05998 continue; 05999 } 06000 f = ast_read(chan); 06001 if (!f) { 06002 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 06003 res = -1; 06004 break; 06005 } 06006 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) { 06007 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 06008 ast_frfree(f); 06009 res = -1; 06010 break; 06011 } 06012 ast_frfree(f); 06013 ast_mutex_lock(&p->lock); 06014 if (p->mfcr2_call_accepted) { 06015 ast_mutex_unlock(&p->lock); 06016 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 06017 break; 06018 } 06019 ast_mutex_unlock(&p->lock); 06020 } 06021 if (res == -1) { 06022 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 06023 } 06024 return res; 06025 }
static void dahdi_ami_channel_event | ( | struct dahdi_pvt * | p, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2139 of file chan_dahdi.c.
References ast_manager_event, CHAN_PSEUDO, dahdi_pvt::channel, EVENT_FLAG_CALL, ast_channel::name, dahdi_pvt::span, and ast_channel::uniqueid.
Referenced by dahdi_new(), and my_ami_channel_event().
02140 { 02141 char ch_name[20]; 02142 02143 if (p->channel < CHAN_PSEUDO) { 02144 /* No B channel */ 02145 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel); 02146 } else if (p->channel == CHAN_PSEUDO) { 02147 /* Pseudo channel */ 02148 strcpy(ch_name, "pseudo"); 02149 } else { 02150 /* Real channel */ 02151 snprintf(ch_name, sizeof(ch_name), "%d", p->channel); 02152 } 02153 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel", 02154 "Channel: %s\r\n" 02155 "Uniqueid: %s\r\n" 02156 "DAHDISpan: %d\r\n" 02157 "DAHDIChannel: %s\r\n", 02158 chan->name, 02159 chan->uniqueid, 02160 p->span, 02161 ch_name); 02162 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6510 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_r2_answer(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::oprmode, dahdi_pvt::r2chan, 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.
06511 { 06512 struct dahdi_pvt *p = ast->tech_pvt; 06513 int res = 0; 06514 int idx; 06515 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */ 06516 ast_mutex_lock(&p->lock); 06517 idx = dahdi_get_index(ast, p, 0); 06518 if (idx < 0) 06519 idx = SUB_REAL; 06520 /* nothing to do if a radio channel */ 06521 if ((p->radio || (p->oprmode < 0))) { 06522 ast_mutex_unlock(&p->lock); 06523 return 0; 06524 } 06525 06526 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06527 res = analog_answer(p->sig_pvt, ast); 06528 ast_mutex_unlock(&p->lock); 06529 return res; 06530 } 06531 06532 switch (p->sig) { 06533 #if defined(HAVE_PRI) 06534 case SIG_PRI_LIB_HANDLE_CASES: 06535 res = sig_pri_answer(p->sig_pvt, ast); 06536 break; 06537 #endif /* defined(HAVE_PRI) */ 06538 #if defined(HAVE_SS7) 06539 case SIG_SS7: 06540 res = sig_ss7_answer(p->sig_pvt, ast); 06541 break; 06542 #endif /* defined(HAVE_SS7) */ 06543 #ifdef HAVE_OPENR2 06544 case SIG_MFCR2: 06545 if (!p->mfcr2_call_accepted) { 06546 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 06547 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 06548 p->mfcr2_answer_pending = 1; 06549 if (p->mfcr2_charge_calls) { 06550 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 06551 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 06552 } else { 06553 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 06554 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 06555 } 06556 } else { 06557 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 06558 dahdi_r2_answer(p); 06559 } 06560 break; 06561 #endif 06562 case 0: 06563 ast_mutex_unlock(&p->lock); 06564 return 0; 06565 default: 06566 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 06567 res = -1; 06568 break; 06569 } 06570 ast_mutex_unlock(&p->lock); 06571 return res; 06572 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 6027 of file chan_dahdi.c.
References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INTERWORKING, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), and LOG_DEBUG.
Referenced by dahdi_hangup().
06028 { 06029 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 06030 switch (cause) { 06031 case AST_CAUSE_USER_BUSY: 06032 case AST_CAUSE_CALL_REJECTED: 06033 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 06034 r2cause = OR2_CAUSE_BUSY_NUMBER; 06035 break; 06036 06037 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 06038 case AST_CAUSE_SWITCH_CONGESTION: 06039 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 06040 break; 06041 06042 case AST_CAUSE_UNALLOCATED: 06043 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 06044 break; 06045 06046 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 06047 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 06048 r2cause = OR2_CAUSE_OUT_OF_ORDER; 06049 break; 06050 06051 case AST_CAUSE_NO_ANSWER: 06052 case AST_CAUSE_NO_USER_RESPONSE: 06053 r2cause = OR2_CAUSE_NO_ANSWER; 06054 break; 06055 06056 default: 06057 r2cause = OR2_CAUSE_NORMAL_CLEARING; 06058 break; 06059 } 06060 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n", 06061 cause, r2cause, openr2_proto_get_disconnect_string(r2cause)); 06062 return r2cause; 06063 }
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 7157 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_STATE_RINGING, 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(), f, ast_channel::fds, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, sig_pri_span::lock, dahdi_pvt::lock, LOG_NOTICE, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, subnames, dahdi_pvt::subs, t1, ast_channel::tech_pvt, sig_pri_span::transfer, and update_conf().
07158 { 07159 struct ast_channel *who; 07160 struct dahdi_pvt *p0, *p1, *op0, *op1; 07161 struct dahdi_pvt *master = NULL, *slave = NULL; 07162 struct ast_frame *f; 07163 int inconf = 0; 07164 int nothingok = 1; 07165 int ofd0, ofd1; 07166 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 07167 int os0 = -1, os1 = -1; 07168 int priority = 0; 07169 struct ast_channel *oc0, *oc1; 07170 enum ast_bridge_result res; 07171 #ifdef PRI_2BCT 07172 int triedtopribridge = 0; 07173 q931_call *q931c0; 07174 q931_call *q931c1; 07175 #endif 07176 07177 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 07178 There is code below to handle it properly until DTMF is actually seen, 07179 but due to currently unresolved issues it's ignored... 07180 */ 07181 07182 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 07183 return AST_BRIDGE_FAILED_NOWARN; 07184 07185 ast_channel_lock(c0); 07186 while (ast_channel_trylock(c1)) { 07187 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07188 } 07189 07190 p0 = c0->tech_pvt; 07191 p1 = c1->tech_pvt; 07192 /* cant do pseudo-channels here */ 07193 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 07194 ast_channel_unlock(c0); 07195 ast_channel_unlock(c1); 07196 return AST_BRIDGE_FAILED_NOWARN; 07197 } 07198 07199 oi0 = dahdi_get_index(c0, p0, 0); 07200 oi1 = dahdi_get_index(c1, p1, 0); 07201 if ((oi0 < 0) || (oi1 < 0)) { 07202 ast_channel_unlock(c0); 07203 ast_channel_unlock(c1); 07204 return AST_BRIDGE_FAILED; 07205 } 07206 07207 op0 = p0 = c0->tech_pvt; 07208 op1 = p1 = c1->tech_pvt; 07209 ofd0 = c0->fds[0]; 07210 ofd1 = c1->fds[0]; 07211 oc0 = p0->owner; 07212 oc1 = p1->owner; 07213 07214 if (ast_mutex_trylock(&p0->lock)) { 07215 /* Don't block, due to potential for deadlock */ 07216 ast_channel_unlock(c0); 07217 ast_channel_unlock(c1); 07218 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07219 return AST_BRIDGE_RETRY; 07220 } 07221 if (ast_mutex_trylock(&p1->lock)) { 07222 /* Don't block, due to potential for deadlock */ 07223 ast_mutex_unlock(&p0->lock); 07224 ast_channel_unlock(c0); 07225 ast_channel_unlock(c1); 07226 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07227 return AST_BRIDGE_RETRY; 07228 } 07229 07230 if ((p0->callwaiting && p0->callwaitingcallerid) 07231 || (p1->callwaiting && p1->callwaitingcallerid)) { 07232 /* 07233 * Call Waiting Caller ID requires DTMF detection to know if it 07234 * can send the CID spill. 07235 * 07236 * For now, don't attempt to native bridge if either channel 07237 * needs DTMF detection. There is code below to handle it 07238 * properly until DTMF is actually seen, but due to currently 07239 * unresolved issues it's ignored... 07240 */ 07241 ast_mutex_unlock(&p0->lock); 07242 ast_mutex_unlock(&p1->lock); 07243 ast_channel_unlock(c0); 07244 ast_channel_unlock(c1); 07245 return AST_BRIDGE_FAILED_NOWARN; 07246 } 07247 07248 #if defined(HAVE_PRI) 07249 if ((dahdi_sig_pri_lib_handles(p0->sig) 07250 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 07251 || (dahdi_sig_pri_lib_handles(p1->sig) 07252 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 07253 /* 07254 * PRI nobch channels (hold and call waiting) are equivalent to 07255 * pseudo channels and cannot be done here. 07256 */ 07257 ast_mutex_unlock(&p0->lock); 07258 ast_mutex_unlock(&p1->lock); 07259 ast_channel_unlock(c0); 07260 ast_channel_unlock(c1); 07261 return AST_BRIDGE_FAILED_NOWARN; 07262 } 07263 #endif /* defined(HAVE_PRI) */ 07264 07265 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07266 if (p0->owner && p1->owner) { 07267 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 07268 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 07269 master = p0; 07270 slave = p1; 07271 inconf = 1; 07272 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 07273 master = p1; 07274 slave = p0; 07275 inconf = 1; 07276 } else { 07277 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 07278 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 07279 p0->channel, 07280 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07281 p0->subs[SUB_REAL].inthreeway, p0->channel, 07282 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07283 p1->subs[SUB_REAL].inthreeway); 07284 } 07285 nothingok = 0; 07286 } 07287 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 07288 if (p1->subs[SUB_THREEWAY].inthreeway) { 07289 master = p1; 07290 slave = p0; 07291 nothingok = 0; 07292 } 07293 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 07294 if (p0->subs[SUB_THREEWAY].inthreeway) { 07295 master = p0; 07296 slave = p1; 07297 nothingok = 0; 07298 } 07299 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 07300 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 07301 don't put us in anything */ 07302 if (p1->subs[SUB_CALLWAIT].inthreeway) { 07303 master = p1; 07304 slave = p0; 07305 nothingok = 0; 07306 } 07307 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 07308 /* Same as previous */ 07309 if (p0->subs[SUB_CALLWAIT].inthreeway) { 07310 master = p0; 07311 slave = p1; 07312 nothingok = 0; 07313 } 07314 } 07315 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 07316 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 07317 if (master && slave) { 07318 /* Stop any tones, or play ringtone as appropriate. If they're bridged 07319 in an active threeway call with a channel that is ringing, we should 07320 indicate ringing. */ 07321 if ((oi1 == SUB_THREEWAY) && 07322 p1->subs[SUB_THREEWAY].inthreeway && 07323 p1->subs[SUB_REAL].owner && 07324 p1->subs[SUB_REAL].inthreeway && 07325 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07326 ast_debug(1, 07327 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07328 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07329 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 07330 os1 = p1->subs[SUB_REAL].owner->_state; 07331 } else { 07332 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07333 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07334 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 07335 } 07336 if ((oi0 == SUB_THREEWAY) && 07337 p0->subs[SUB_THREEWAY].inthreeway && 07338 p0->subs[SUB_REAL].owner && 07339 p0->subs[SUB_REAL].inthreeway && 07340 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07341 ast_debug(1, 07342 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07343 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07344 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 07345 os0 = p0->subs[SUB_REAL].owner->_state; 07346 } else { 07347 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07348 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07349 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 07350 } 07351 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07352 if (!p0->echocanbridged || !p1->echocanbridged) { 07353 /* Disable echo cancellation if appropriate */ 07354 dahdi_disable_ec(p0); 07355 dahdi_disable_ec(p1); 07356 } 07357 } 07358 dahdi_link(slave, master); 07359 master->inconference = inconf; 07360 } else if (!nothingok) 07361 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 07362 07363 update_conf(p0); 07364 update_conf(p1); 07365 t0 = p0->subs[SUB_REAL].inthreeway; 07366 t1 = p1->subs[SUB_REAL].inthreeway; 07367 07368 ast_mutex_unlock(&p0->lock); 07369 ast_mutex_unlock(&p1->lock); 07370 07371 ast_channel_unlock(c0); 07372 ast_channel_unlock(c1); 07373 07374 /* Native bridge failed */ 07375 if ((!master || !slave) && !nothingok) { 07376 dahdi_enable_ec(p0); 07377 dahdi_enable_ec(p1); 07378 return AST_BRIDGE_FAILED; 07379 } 07380 07381 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 07382 07383 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07384 disable_dtmf_detect(op0); 07385 07386 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07387 disable_dtmf_detect(op1); 07388 07389 for (;;) { 07390 struct ast_channel *c0_priority[2] = {c0, c1}; 07391 struct ast_channel *c1_priority[2] = {c1, c0}; 07392 07393 /* Here's our main loop... Start by locking things, looking for private parts, 07394 and then balking if anything is wrong */ 07395 07396 ast_channel_lock(c0); 07397 while (ast_channel_trylock(c1)) { 07398 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07399 } 07400 07401 p0 = c0->tech_pvt; 07402 p1 = c1->tech_pvt; 07403 07404 if (op0 == p0) 07405 i0 = dahdi_get_index(c0, p0, 1); 07406 if (op1 == p1) 07407 i1 = dahdi_get_index(c1, p1, 1); 07408 07409 ast_channel_unlock(c0); 07410 ast_channel_unlock(c1); 07411 07412 if (!timeoutms || 07413 (op0 != p0) || 07414 (op1 != p1) || 07415 (ofd0 != c0->fds[0]) || 07416 (ofd1 != c1->fds[0]) || 07417 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 07418 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 07419 (oc0 != p0->owner) || 07420 (oc1 != p1->owner) || 07421 (t0 != p0->subs[SUB_REAL].inthreeway) || 07422 (t1 != p1->subs[SUB_REAL].inthreeway) || 07423 (oi0 != i0) || 07424 (oi1 != i1)) { 07425 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 07426 op0->channel, oi0, op1->channel, oi1); 07427 res = AST_BRIDGE_RETRY; 07428 goto return_from_bridge; 07429 } 07430 07431 #ifdef PRI_2BCT 07432 if (!triedtopribridge) { 07433 triedtopribridge = 1; 07434 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) { 07435 ast_mutex_lock(&p0->pri->lock); 07436 switch (p0->sig) { 07437 case SIG_PRI_LIB_HANDLE_CASES: 07438 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 07439 break; 07440 default: 07441 q931c0 = NULL; 07442 break; 07443 } 07444 switch (p1->sig) { 07445 case SIG_PRI_LIB_HANDLE_CASES: 07446 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 07447 break; 07448 default: 07449 q931c1 = NULL; 07450 break; 07451 } 07452 if (q931c0 && q931c1) { 07453 pri_channel_bridge(q931c0, q931c1); 07454 } 07455 ast_mutex_unlock(&p0->pri->lock); 07456 } 07457 } 07458 #endif 07459 07460 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 07461 if (!who) { 07462 ast_debug(1, "Ooh, empty read...\n"); 07463 continue; 07464 } 07465 f = ast_read(who); 07466 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 07467 *fo = f; 07468 *rc = who; 07469 res = AST_BRIDGE_COMPLETE; 07470 goto return_from_bridge; 07471 } 07472 if (f->frametype == AST_FRAME_DTMF) { 07473 if ((who == c0) && p0->pulsedial) { 07474 ast_write(c1, f); 07475 } else if ((who == c1) && p1->pulsedial) { 07476 ast_write(c0, f); 07477 } else { 07478 *fo = f; 07479 *rc = who; 07480 res = AST_BRIDGE_COMPLETE; 07481 goto return_from_bridge; 07482 } 07483 } 07484 ast_frfree(f); 07485 07486 /* Swap who gets priority */ 07487 priority = !priority; 07488 } 07489 07490 return_from_bridge: 07491 if (op0 == p0) 07492 dahdi_enable_ec(p0); 07493 07494 if (op1 == p1) 07495 dahdi_enable_ec(p1); 07496 07497 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07498 enable_dtmf_detect(op0); 07499 07500 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07501 enable_dtmf_detect(op1); 07502 07503 dahdi_unlink(slave, master, 1); 07504 07505 return res; 07506 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 5303 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_r2_get_channel_category(), dahdi_sig_pri_lib_handles(), 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_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, ast_channel::name, dahdi_subchannel::needbusy, ast_party_id::number, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::r2chan, 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.
05304 { 05305 struct dahdi_pvt *p = ast->tech_pvt; 05306 int x, res, mysig; 05307 char dest[256]; /* must be same length as p->dialdest */ 05308 05309 ast_mutex_lock(&p->lock); 05310 ast_copy_string(dest, rdest, sizeof(dest)); 05311 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 05312 if ((ast->_state == AST_STATE_BUSY)) { 05313 p->subs[SUB_REAL].needbusy = 1; 05314 ast_mutex_unlock(&p->lock); 05315 return 0; 05316 } 05317 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05318 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 05319 ast_mutex_unlock(&p->lock); 05320 return -1; 05321 } 05322 p->waitingfordt.tv_sec = 0; 05323 p->dialednone = 0; 05324 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 05325 { 05326 /* Special pseudo -- automatically up */ 05327 ast_setstate(ast, AST_STATE_UP); 05328 ast_mutex_unlock(&p->lock); 05329 return 0; 05330 } 05331 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 05332 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 05333 if (res) 05334 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 05335 p->outgoing = 1; 05336 05337 if (IS_DIGITAL(ast->transfercapability)){ 05338 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law); 05339 } else { 05340 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05341 } 05342 05343 #ifdef HAVE_PRI 05344 if (dahdi_sig_pri_lib_handles(p->sig)) { 05345 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, 05346 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW); 05347 ast_mutex_unlock(&p->lock); 05348 return res; 05349 } 05350 #endif 05351 05352 #if defined(HAVE_SS7) 05353 if (p->sig == SIG_SS7) { 05354 res = sig_ss7_call(p->sig_pvt, ast, rdest); 05355 ast_mutex_unlock(&p->lock); 05356 return res; 05357 } 05358 #endif /* defined(HAVE_SS7) */ 05359 05360 /* If this is analog signalling we can exit here */ 05361 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05362 p->callwaitrings = 0; 05363 res = analog_call(p->sig_pvt, ast, rdest, timeout); 05364 ast_mutex_unlock(&p->lock); 05365 return res; 05366 } 05367 05368 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 05369 switch (mysig) { 05370 case 0: 05371 /* Special pseudo -- automatically up*/ 05372 ast_setstate(ast, AST_STATE_UP); 05373 break; 05374 case SIG_MFCR2: 05375 break; 05376 default: 05377 ast_debug(1, "not yet implemented\n"); 05378 ast_mutex_unlock(&p->lock); 05379 return -1; 05380 } 05381 05382 #ifdef HAVE_OPENR2 05383 if (p->mfcr2) { 05384 openr2_calling_party_category_t chancat; 05385 int callres = 0; 05386 char *c, *l; 05387 05388 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 05389 p->dialdest[0] = '\0'; 05390 05391 c = strchr(dest, '/'); 05392 if (c) { 05393 c++; 05394 } else { 05395 c = ""; 05396 } 05397 if (!p->hidecallerid) { 05398 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL; 05399 } else { 05400 l = NULL; 05401 } 05402 if (strlen(c) < p->stripmsd) { 05403 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 05404 ast_mutex_unlock(&p->lock); 05405 return -1; 05406 } 05407 p->dialing = 1; 05408 chancat = dahdi_r2_get_channel_category(ast); 05409 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 05410 if (-1 == callres) { 05411 ast_mutex_unlock(&p->lock); 05412 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 05413 return -1; 05414 } 05415 p->mfcr2_call_accepted = 0; 05416 p->mfcr2_progress = 0; 05417 ast_setstate(ast, AST_STATE_DIALING); 05418 } 05419 #endif /* HAVE_OPENR2 */ 05420 ast_mutex_unlock(&p->lock); 05421 return 0; 05422 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5270 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().
05271 { 05272 struct dahdi_pvt *p = ast->tech_pvt; 05273 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 05274 if (p->cidspill) { 05275 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 05276 ast_free(p->cidspill); 05277 } 05278 05279 /* 05280 * SAS: Subscriber Alert Signal, 440Hz for 300ms 05281 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 05282 */ 05283 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 05284 return -1; 05285 save_conference(p); 05286 /* Silence */ 05287 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 05288 if (!p->callwaitrings && p->callwaitingcallerid) { 05289 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 05290 p->callwaitcas = 1; 05291 p->cidlen = 2400 + 680 + READ_SIZE * 4; 05292 } else { 05293 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 05294 p->callwaitcas = 0; 05295 p->cidlen = 2400 + READ_SIZE * 4; 05296 } 05297 p->cidpos = 0; 05298 send_callerid(p); 05299 05300 return 0; 05301 }
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. |
0 | on success. | |
-1 | on error. |
Definition at line 13749 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_pvt::cc_params, sig_pri_span::cc_params, dahdi_starting_point::channelmatch, create_channel_name(), dahdi_sig_pri_lib_handles(), determine_starting_point(), dahdi_starting_point::groupmatch, iflock, is_group_or_channel_match(), dahdi_pvt::pri, and dahdi_starting_point::span.
13750 { 13751 struct dahdi_pvt *p; 13752 struct dahdi_pvt *exitpvt; 13753 struct dahdi_starting_point start; 13754 int groupmatched = 0; 13755 int channelmatched = 0; 13756 13757 ast_mutex_lock(&iflock); 13758 p = determine_starting_point(dest, &start); 13759 if (!p) { 13760 ast_mutex_unlock(&iflock); 13761 return -1; 13762 } 13763 exitpvt = p; 13764 for (;;) { 13765 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) { 13766 /* We found a potential match. call the callback */ 13767 struct ast_str *device_name; 13768 char *dash; 13769 const char *monitor_type; 13770 char dialstring[AST_CHANNEL_NAME]; 13771 char full_device_name[AST_CHANNEL_NAME]; 13772 13773 switch (ast_get_cc_monitor_policy(p->cc_params)) { 13774 case AST_CC_MONITOR_NEVER: 13775 break; 13776 case AST_CC_MONITOR_NATIVE: 13777 case AST_CC_MONITOR_ALWAYS: 13778 case AST_CC_MONITOR_GENERIC: 13779 #if defined(HAVE_PRI) 13780 if (dahdi_sig_pri_lib_handles(p->sig)) { 13781 /* 13782 * ISDN is in a trunk busy condition so we need to monitor 13783 * the span congestion device state. 13784 */ 13785 snprintf(full_device_name, sizeof(full_device_name), 13786 "DAHDI/I%d/congestion", p->pri->span); 13787 } else 13788 #endif /* defined(HAVE_PRI) */ 13789 { 13790 #if defined(HAVE_PRI) 13791 device_name = create_channel_name(p, 1, ""); 13792 #else 13793 device_name = create_channel_name(p); 13794 #endif /* defined(HAVE_PRI) */ 13795 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", 13796 device_name ? ast_str_buffer(device_name) : ""); 13797 ast_free(device_name); 13798 /* 13799 * The portion after the '-' in the channel name is either a random 13800 * number, a sequence number, or a subchannel number. None are 13801 * necessary so strip them off. 13802 */ 13803 dash = strrchr(full_device_name, '-'); 13804 if (dash) { 13805 *dash = '\0'; 13806 } 13807 } 13808 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest); 13809 13810 /* 13811 * Analog can only do generic monitoring. 13812 * ISDN is in a trunk busy condition and any "device" is going 13813 * to be busy until a B channel becomes available. The generic 13814 * monitor can do this task. 13815 */ 13816 monitor_type = AST_CC_GENERIC_MONITOR_TYPE; 13817 callback(inbound, 13818 #if defined(HAVE_PRI) 13819 p->pri ? p->pri->cc_params : p->cc_params, 13820 #else 13821 p->cc_params, 13822 #endif /* defined(HAVE_PRI) */ 13823 monitor_type, full_device_name, dialstring, NULL); 13824 break; 13825 } 13826 } 13827 p = start.backwards ? p->prev : p->next; 13828 if (!p) { 13829 p = start.backwards ? ifend : iflist; 13830 } 13831 if (p == exitpvt) { 13832 break; 13833 } 13834 } 13835 ast_mutex_unlock(&iflock); 13836 return 0; 13837 }
static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 1363 of file chan_dahdi.c.
References ast_cc_config_params_init, CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, DEFAULT_CIDRINGS, sig_pri_span::nsf, dahdi_pri::pri, and dahdi_chan_conf::pri.
Referenced by setup_dahdi().
01364 { 01365 /* recall that if a field is not included here it is initialized 01366 * to 0 or equivalent 01367 */ 01368 struct dahdi_chan_conf conf = { 01369 #ifdef HAVE_PRI 01370 .pri.pri = { 01371 .nsf = PRI_NSF_NONE, 01372 .switchtype = PRI_SWITCH_NI2, 01373 .dialplan = PRI_UNKNOWN + 1, 01374 .localdialplan = PRI_NATIONAL_ISDN + 1, 01375 .nodetype = PRI_CPE, 01376 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01377 01378 #if defined(HAVE_PRI_CCSS) 01379 .cc_ptmp_recall_mode = 1,/* specificRecall */ 01380 .cc_qsig_signaling_link_req = 1,/* retain */ 01381 .cc_qsig_signaling_link_rsp = 1,/* retain */ 01382 #endif /* defined(HAVE_PRI_CCSS) */ 01383 01384 .minunused = 2, 01385 .idleext = "", 01386 .idledial = "", 01387 .internationalprefix = "", 01388 .nationalprefix = "", 01389 .localprefix = "", 01390 .privateprefix = "", 01391 .unknownprefix = "", 01392 .resetinterval = -1, 01393 }, 01394 #endif 01395 #if defined(HAVE_SS7) 01396 .ss7.ss7 = { 01397 .called_nai = SS7_NAI_NATIONAL, 01398 .calling_nai = SS7_NAI_NATIONAL, 01399 .internationalprefix = "", 01400 .nationalprefix = "", 01401 .subscriberprefix = "", 01402 .unknownprefix = "" 01403 }, 01404 #endif /* defined(HAVE_SS7) */ 01405 #ifdef HAVE_OPENR2 01406 .mfcr2 = { 01407 .variant = OR2_VAR_ITU, 01408 .mfback_timeout = -1, 01409 .metering_pulse_timeout = -1, 01410 .max_ani = 10, 01411 .max_dnis = 4, 01412 .get_ani_first = -1, 01413 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01414 .skip_category_request = -1, 01415 #endif 01416 .call_files = 0, 01417 .allow_collect_calls = 0, 01418 .charge_calls = 1, 01419 .accept_on_offer = 1, 01420 .forced_release = 0, 01421 .double_answer = 0, 01422 .immediate_accept = -1, 01423 .logdir = "", 01424 .r2proto_file = "", 01425 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01426 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01427 }, 01428 #endif 01429 .chan = { 01430 .context = "default", 01431 .cid_num = "", 01432 .cid_name = "", 01433 .cid_tag = "", 01434 .mohinterpret = "default", 01435 .mohsuggest = "", 01436 .parkinglot = "", 01437 .transfertobusy = 1, 01438 01439 .cid_signalling = CID_SIG_BELL, 01440 .cid_start = CID_START_RING, 01441 .dahditrcallerid = 0, 01442 .use_callerid = 1, 01443 .sig = -1, 01444 .outsigmod = -1, 01445 01446 .cid_rxgain = +5.0, 01447 01448 .tonezone = -1, 01449 01450 .echocancel.head.tap_length = 1, 01451 01452 .busycount = 3, 01453 .busycompare = 0, 01454 .busytonelength = 0, 01455 .busyquietlength = 0, 01456 .busyfuzziness = 0, 01457 .silencethreshold = 0, 01458 01459 .accountcode = "", 01460 01461 .mailbox = "", 01462 01463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01464 .mwisend_fsk = 1, 01465 #endif 01466 .polarityonanswerdelay = 600, 01467 01468 .sendcalleridafter = DEFAULT_CIDRINGS, 01469 01470 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01471 .buf_no = numbufs, 01472 .usefaxbuffers = 0, 01473 .cc_params = ast_cc_config_params_init(), 01474 }, 01475 .timing = { 01476 .prewinktime = -1, 01477 .preflashtime = -1, 01478 .winktime = -1, 01479 .flashtime = -1, 01480 .starttime = -1, 01481 .rxwinktime = -1, 01482 .rxflashtime = -1, 01483 .debouncetime = -1 01484 }, 01485 .is_sig_auto = 1, 01486 .smdi_port = "/dev/ttyS0", 01487 }; 01488 01489 return conf; 01490 }
static int dahdi_channels_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18351 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, iflist, and dahdi_pvt::next.
18353 { 18354 struct dahdi_pvt *tmp; 18355 struct ast_data *data_channel; 18356 18357 ast_mutex_lock(&iflock); 18358 for (tmp = iflist; tmp; tmp = tmp->next) { 18359 data_channel = ast_data_add_node(data_root, "channel"); 18360 if (!data_channel) { 18361 continue; 18362 } 18363 18364 ast_data_add_structure(dahdi_pvt, data_channel, tmp); 18365 18366 /* if this channel doesn't match remove it. */ 18367 if (!ast_data_search_match(search, data_channel)) { 18368 ast_data_remove_node(data_root, data_channel); 18369 } 18370 } 18371 ast_mutex_unlock(&iflock); 18372 18373 return 0; 18374 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 4297 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().
static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
int | fd_num | |||
) | [static] |
Definition at line 4310 of file chan_dahdi.c.
References dahdi_close(), sig_pri_span::fds, and dahdi_pri::pri.
Referenced by __unload_module(), and prepare_pri().
04311 { 04312 dahdi_close(pri->pri.fds[fd_num]); 04313 pri->pri.fds[fd_num] = -1; 04314 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 4303 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().
04304 { 04305 dahdi_close(chan_pvt->subs[sub_num].dfd); 04306 chan_pvt->subs[sub_num].dfd = -1; 04307 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 5113 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, 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().
05114 { 05115 int x, res; 05116 05117 x = muted; 05118 #if defined(HAVE_PRI) || defined(HAVE_SS7) 05119 switch (p->sig) { 05120 #if defined(HAVE_PRI) 05121 case SIG_PRI_LIB_HANDLE_CASES: 05122 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 05123 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 05124 break; 05125 } 05126 /* Fall through */ 05127 #endif /* defined(HAVE_PRI) */ 05128 #if defined(HAVE_SS7) 05129 case SIG_SS7: 05130 #endif /* defined(HAVE_SS7) */ 05131 { 05132 int y = 1; 05133 05134 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 05135 if (res) 05136 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 05137 p->channel, strerror(errno)); 05138 } 05139 break; 05140 default: 05141 break; 05142 } 05143 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 05144 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 05145 if (res < 0) 05146 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 05147 return res; 05148 }
static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14901 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.
14902 { 14903 int channel; 14904 int ret; 14905 switch (cmd) { 14906 case CLI_INIT: 14907 e->command = "dahdi destroy channel"; 14908 e->usage = 14909 "Usage: dahdi destroy channel <chan num>\n" 14910 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 14911 return NULL; 14912 case CLI_GENERATE: 14913 return NULL; 14914 } 14915 if (a->argc != 4) 14916 return CLI_SHOWUSAGE; 14917 14918 channel = atoi(a->argv[3]); 14919 ret = dahdi_destroy_channel_bynum(channel); 14920 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 14921 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 11289 of file chan_dahdi.c.
References ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, destroy_channel(), iflist, iflock, dahdi_pvt::next, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel().
11290 { 11291 struct dahdi_pvt *cur; 11292 11293 ast_mutex_lock(&iflock); 11294 for (cur = iflist; cur; cur = cur->next) { 11295 if (cur->channel == channel) { 11296 int x = DAHDI_FLASH; 11297 11298 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 11299 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11300 11301 destroy_channel(cur, 1); 11302 ast_mutex_unlock(&iflock); 11303 ast_module_unref(ast_module_info->self); 11304 return RESULT_SUCCESS; 11305 } 11306 } 11307 ast_mutex_unlock(&iflock); 11308 return RESULT_FAILURE; 11309 }
static int dahdi_devicestate | ( | void * | data | ) | [static] |
Definition at line 13687 of file chan_dahdi.c.
References AST_DEVICE_UNKNOWN, sig_pri_span::congestion_devstate, dahdi_pri::pri, and pris.
13688 { 13689 #if defined(HAVE_PRI) 13690 char *device; 13691 unsigned span; 13692 int res; 13693 13694 device = data; 13695 13696 if (*device != 'I') { 13697 /* The request is not for an ISDN span device. */ 13698 return AST_DEVICE_UNKNOWN; 13699 } 13700 res = sscanf(device, "I%30u", &span); 13701 if (res != 1 || !span || NUM_SPANS < span) { 13702 /* Bad format for ISDN span device name. */ 13703 return AST_DEVICE_UNKNOWN; 13704 } 13705 device = strchr(device, '/'); 13706 if (!device) { 13707 /* Bad format for ISDN span device name. */ 13708 return AST_DEVICE_UNKNOWN; 13709 } 13710 13711 /* 13712 * Since there are currently no other span devstate's defined, 13713 * it must be congestion. 13714 */ 13715 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13716 ++device; 13717 if (!strcmp(device, "congestion")) 13718 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13719 { 13720 return pris[span - 1].pri.congestion_devstate; 13721 } 13722 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13723 else if (!strcmp(device, "threshold")) { 13724 return pris[span - 1].pri.threshold_devstate; 13725 } 13726 return AST_DEVICE_UNKNOWN; 13727 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13728 #else 13729 return AST_DEVICE_UNKNOWN; 13730 #endif /* defined(HAVE_PRI) */ 13731 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 4401 of file chan_dahdi.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index, 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.
04402 { 04403 struct dahdi_pvt *pvt; 04404 int idx; 04405 int dtmf = -1; 04406 int res; 04407 04408 pvt = chan->tech_pvt; 04409 04410 ast_mutex_lock(&pvt->lock); 04411 04412 idx = dahdi_get_index(chan, pvt, 0); 04413 04414 if ((idx != SUB_REAL) || !pvt->owner) 04415 goto out; 04416 04417 #ifdef HAVE_PRI 04418 switch (pvt->sig) { 04419 case SIG_PRI_LIB_HANDLE_CASES: 04420 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 04421 if (!res) 04422 goto out; 04423 break; 04424 default: 04425 break; 04426 } 04427 #endif 04428 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 04429 goto out; 04430 04431 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 04432 struct dahdi_dialoperation zo = { 04433 .op = DAHDI_DIAL_OP_APPEND, 04434 }; 04435 04436 zo.dialstr[0] = 'T'; 04437 zo.dialstr[1] = digit; 04438 zo.dialstr[2] = '\0'; 04439 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 04440 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 04441 else 04442 pvt->dialing = 1; 04443 } else { 04444 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 04445 pvt->dialing = 1; 04446 pvt->begindigit = digit; 04447 } 04448 04449 out: 04450 ast_mutex_unlock(&pvt->lock); 04451 04452 return 0; 04453 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 4455 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_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
04456 { 04457 struct dahdi_pvt *pvt; 04458 int res = 0; 04459 int idx; 04460 int x; 04461 04462 pvt = chan->tech_pvt; 04463 04464 ast_mutex_lock(&pvt->lock); 04465 04466 idx = dahdi_get_index(chan, pvt, 0); 04467 04468 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 04469 goto out; 04470 04471 #ifdef HAVE_PRI 04472 /* This means that the digit was already sent via PRI signalling */ 04473 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 04474 goto out; 04475 } 04476 #endif 04477 04478 if (pvt->begindigit) { 04479 x = -1; 04480 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 04481 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 04482 pvt->dialing = 0; 04483 pvt->begindigit = 0; 04484 } 04485 04486 out: 04487 ast_mutex_unlock(&pvt->lock); 04488 04489 return res; 04490 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4905 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, 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().
04906 { 04907 int res; 04908 04909 if (p->echocanon) { 04910 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04911 04912 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04913 04914 if (res) 04915 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04916 else 04917 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 04918 } 04919 04920 p->echocanon = 0; 04921 }
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 |
Definition at line 9751 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().
09752 { 09753 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 09754 return analog_dnd(dahdichan->sig_pvt, flag); 09755 } 09756 09757 if (flag == -1) { 09758 return dahdichan->dnd; 09759 } 09760 09761 /* Do not disturb */ 09762 dahdichan->dnd = flag; 09763 ast_verb(3, "%s DND on channel %d\n", 09764 flag? "Enabled" : "Disabled", 09765 dahdichan->channel); 09766 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 09767 "Channel: DAHDI/%d\r\n" 09768 "Status: %s\r\n", dahdichan->channel, 09769 flag? "enabled" : "disabled"); 09770 09771 return 0; 09772 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4833 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, 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_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and my_set_echocanceller().
04834 { 04835 int res; 04836 if (!p) 04837 return; 04838 if (p->echocanon) { 04839 ast_debug(1, "Echo cancellation already on\n"); 04840 return; 04841 } 04842 if (p->digital) { 04843 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04844 return; 04845 } 04846 if (p->echocancel.head.tap_length) { 04847 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04848 switch (p->sig) { 04849 #if defined(HAVE_PRI) 04850 case SIG_PRI_LIB_HANDLE_CASES: 04851 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04852 /* 04853 * PRI nobch pseudo channel. Does not need ec anyway. 04854 * Does not handle ioctl(DAHDI_AUDIOMODE) 04855 */ 04856 return; 04857 } 04858 /* Fall through */ 04859 #endif /* defined(HAVE_PRI) */ 04860 #if defined(HAVE_SS7) 04861 case SIG_SS7: 04862 #endif /* defined(HAVE_SS7) */ 04863 { 04864 int x = 1; 04865 04866 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04867 if (res) 04868 ast_log(LOG_WARNING, 04869 "Unable to enable audio mode on channel %d (%s)\n", 04870 p->channel, strerror(errno)); 04871 } 04872 break; 04873 default: 04874 break; 04875 } 04876 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04877 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04878 if (res) { 04879 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04880 } else { 04881 p->echocanon = 1; 04882 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04883 } 04884 } else 04885 ast_debug(1, "No echo cancellation requested\n"); 04886 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8785 of file chan_dahdi.c.
References __dahdi_exception(), analog_exception(), analog_lib_handles(), ast_mutex_lock, ast_mutex_unlock, f, dahdi_pvt::lock, dahdi_pvt::oprmode, dahdi_pvt::radio, dahdi_pvt::sig, dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.
08786 { 08787 struct dahdi_pvt *p = ast->tech_pvt; 08788 struct ast_frame *f; 08789 ast_mutex_lock(&p->lock); 08790 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08791 struct analog_pvt *analog_p = p->sig_pvt; 08792 f = analog_exception(analog_p, ast); 08793 } else { 08794 f = __dahdi_exception(ast); 08795 } 08796 ast_mutex_unlock(&p->lock); 08797 return f; 08798 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 15751 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, ast_channel::name, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
15752 { 15753 if (p) { 15754 switch (mode) { 15755 case TRANSFER: 15756 p->fake_event = DAHDI_EVENT_WINKFLASH; 15757 break; 15758 case HANGUP: 15759 p->fake_event = DAHDI_EVENT_ONHOOK; 15760 break; 15761 default: 15762 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 15763 } 15764 } 15765 return 0; 15766 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 7508 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock, dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.
07509 { 07510 struct dahdi_pvt *p = newchan->tech_pvt; 07511 int x; 07512 07513 ast_mutex_lock(&p->lock); 07514 07515 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 07516 if (p->owner == oldchan) { 07517 p->owner = newchan; 07518 } 07519 for (x = 0; x < 3; x++) { 07520 if (p->subs[x].owner == oldchan) { 07521 if (!x) { 07522 dahdi_unlink(NULL, p, 0); 07523 } 07524 p->subs[x].owner = newchan; 07525 } 07526 } 07527 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07528 analog_fixup(oldchan, newchan, p->sig_pvt); 07529 #if defined(HAVE_PRI) 07530 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 07531 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 07532 #endif /* defined(HAVE_PRI) */ 07533 #if defined(HAVE_SS7) 07534 } else if (p->sig == SIG_SS7) { 07535 sig_ss7_fixup(oldchan, newchan, p->sig_pvt); 07536 #endif /* defined(HAVE_SS7) */ 07537 } 07538 update_conf(p); 07539 07540 ast_mutex_unlock(&p->lock); 07541 07542 if (newchan->_state == AST_STATE_RINGING) { 07543 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 07544 } 07545 return 0; 07546 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 6865 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.
06866 { 06867 struct dahdi_pvt *p = chan->tech_pvt; 06868 int res = 0; 06869 06870 if (!p) { 06871 /* No private structure! */ 06872 *buf = '\0'; 06873 return -1; 06874 } 06875 06876 if (!strcasecmp(data, "rxgain")) { 06877 ast_mutex_lock(&p->lock); 06878 snprintf(buf, len, "%f", p->rxgain); 06879 ast_mutex_unlock(&p->lock); 06880 } else if (!strcasecmp(data, "txgain")) { 06881 ast_mutex_lock(&p->lock); 06882 snprintf(buf, len, "%f", p->txgain); 06883 ast_mutex_unlock(&p->lock); 06884 } else if (!strcasecmp(data, "dahdi_channel")) { 06885 ast_mutex_lock(&p->lock); 06886 snprintf(buf, len, "%d", p->channel); 06887 ast_mutex_unlock(&p->lock); 06888 } else if (!strcasecmp(data, "dahdi_span")) { 06889 ast_mutex_lock(&p->lock); 06890 snprintf(buf, len, "%d", p->span); 06891 ast_mutex_unlock(&p->lock); 06892 } else if (!strcasecmp(data, "dahdi_type")) { 06893 ast_mutex_lock(&p->lock); 06894 switch (p->sig) { 06895 #if defined(HAVE_OPENR2) 06896 case SIG_MFCR2: 06897 ast_copy_string(buf, "mfc/r2", len); 06898 break; 06899 #endif /* defined(HAVE_OPENR2) */ 06900 #if defined(HAVE_PRI) 06901 case SIG_PRI_LIB_HANDLE_CASES: 06902 ast_copy_string(buf, "pri", len); 06903 break; 06904 #endif /* defined(HAVE_PRI) */ 06905 case 0: 06906 ast_copy_string(buf, "pseudo", len); 06907 break; 06908 #if defined(HAVE_SS7) 06909 case SIG_SS7: 06910 ast_copy_string(buf, "ss7", len); 06911 break; 06912 #endif /* defined(HAVE_SS7) */ 06913 default: 06914 /* The only thing left is analog ports. */ 06915 ast_copy_string(buf, "analog", len); 06916 break; 06917 } 06918 ast_mutex_unlock(&p->lock); 06919 #if defined(HAVE_PRI) 06920 #if defined(HAVE_PRI_REVERSE_CHARGE) 06921 } else if (!strcasecmp(data, "reversecharge")) { 06922 ast_mutex_lock(&p->lock); 06923 switch (p->sig) { 06924 case SIG_PRI_LIB_HANDLE_CASES: 06925 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 06926 break; 06927 default: 06928 *buf = '\0'; 06929 res = -1; 06930 break; 06931 } 06932 ast_mutex_unlock(&p->lock); 06933 #endif 06934 #if defined(HAVE_PRI_SETUP_KEYPAD) 06935 } else if (!strcasecmp(data, "keypad_digits")) { 06936 ast_mutex_lock(&p->lock); 06937 switch (p->sig) { 06938 case SIG_PRI_LIB_HANDLE_CASES: 06939 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 06940 len); 06941 break; 06942 default: 06943 *buf = '\0'; 06944 res = -1; 06945 break; 06946 } 06947 ast_mutex_unlock(&p->lock); 06948 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 06949 } else if (!strcasecmp(data, "no_media_path")) { 06950 ast_mutex_lock(&p->lock); 06951 switch (p->sig) { 06952 case SIG_PRI_LIB_HANDLE_CASES: 06953 /* 06954 * TRUE if the call is on hold or is call waiting because 06955 * there is no media path available. 06956 */ 06957 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel); 06958 break; 06959 default: 06960 *buf = '\0'; 06961 res = -1; 06962 break; 06963 } 06964 ast_mutex_unlock(&p->lock); 06965 #endif /* defined(HAVE_PRI) */ 06966 } else { 06967 *buf = '\0'; 06968 res = -1; 06969 } 06970 06971 return res; 06972 }
static int dahdi_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 7004 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_pvt::echocanon, errno, dahdi_pvt::lock, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
07005 { 07006 struct dahdi_pvt *p = chan->tech_pvt; 07007 int res = 0; 07008 07009 if (!p) { 07010 /* No private structure! */ 07011 return -1; 07012 } 07013 07014 if (!strcasecmp(data, "buffers")) { 07015 int num_bufs, policy; 07016 07017 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 07018 struct dahdi_bufferinfo bi = { 07019 .txbufpolicy = policy, 07020 .rxbufpolicy = policy, 07021 .bufsize = p->bufsize, 07022 .numbufs = num_bufs, 07023 }; 07024 int bpres; 07025 07026 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07027 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 07028 } else { 07029 p->bufferoverrideinuse = 1; 07030 } 07031 } else { 07032 res = -1; 07033 } 07034 } else if (!strcasecmp(data, "echocan_mode")) { 07035 if (!strcasecmp(value, "on")) { 07036 ast_mutex_lock(&p->lock); 07037 dahdi_enable_ec(p); 07038 ast_mutex_unlock(&p->lock); 07039 } else if (!strcasecmp(value, "off")) { 07040 ast_mutex_lock(&p->lock); 07041 dahdi_disable_ec(p); 07042 ast_mutex_unlock(&p->lock); 07043 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07044 } else if (!strcasecmp(value, "fax")) { 07045 int blah = 1; 07046 07047 ast_mutex_lock(&p->lock); 07048 if (!p->echocanon) { 07049 dahdi_enable_ec(p); 07050 } 07051 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07052 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 07053 } 07054 ast_mutex_unlock(&p->lock); 07055 } else if (!strcasecmp(value, "voice")) { 07056 int blah = 0; 07057 07058 ast_mutex_lock(&p->lock); 07059 if (!p->echocanon) { 07060 dahdi_enable_ec(p); 07061 } 07062 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 07063 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 07064 } 07065 ast_mutex_unlock(&p->lock); 07066 #endif 07067 } else { 07068 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 07069 res = -1; 07070 } 07071 } else { 07072 res = -1; 07073 } 07074 07075 return res; 07076 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 489 of file chan_dahdi.c.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), my_get_callerid(), and my_get_event().
00490 { 00491 int j; 00492 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00493 return -1; 00494 return j; 00495 }
static void dahdi_handle_dtmf | ( | struct ast_channel * | ast, | |
int | idx, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 7685 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, 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, ast_channel::macrocontext, ast_channel::name, 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().
07686 { 07687 struct dahdi_pvt *p = ast->tech_pvt; 07688 struct ast_frame *f = *dest; 07689 07690 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 07691 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 07692 f->subclass.integer, f->subclass.integer, ast->name); 07693 07694 if (p->confirmanswer) { 07695 if (f->frametype == AST_FRAME_DTMF_END) { 07696 ast_debug(1, "Confirm answer on %s!\n", ast->name); 07697 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 07698 of a DTMF digit */ 07699 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07700 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07701 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 07702 p->confirmanswer = 0; 07703 } else { 07704 p->subs[idx].f.frametype = AST_FRAME_NULL; 07705 p->subs[idx].f.subclass.integer = 0; 07706 } 07707 *dest = &p->subs[idx].f; 07708 } else if (p->callwaitcas) { 07709 if (f->frametype == AST_FRAME_DTMF_END) { 07710 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) { 07711 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 07712 ast_free(p->cidspill); 07713 p->cidspill = NULL; 07714 send_cwcidspill(p); 07715 } 07716 p->callwaitcas = 0; 07717 } 07718 p->subs[idx].f.frametype = AST_FRAME_NULL; 07719 p->subs[idx].f.subclass.integer = 0; 07720 *dest = &p->subs[idx].f; 07721 } else if (f->subclass.integer == 'f') { 07722 if (f->frametype == AST_FRAME_DTMF_END) { 07723 /* Fax tone -- Handle and return NULL */ 07724 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 07725 /* If faxbuffers are configured, use them for the fax transmission */ 07726 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 07727 struct dahdi_bufferinfo bi = { 07728 .txbufpolicy = p->faxbuf_policy, 07729 .bufsize = p->bufsize, 07730 .numbufs = p->faxbuf_no 07731 }; 07732 int res; 07733 07734 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07735 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 07736 } else { 07737 p->bufferoverrideinuse = 1; 07738 } 07739 } 07740 p->faxhandled = 1; 07741 if (p->dsp) { 07742 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 07743 ast_dsp_set_features(p->dsp, p->dsp_features); 07744 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 07745 } 07746 if (strcmp(ast->exten, "fax")) { 07747 const char *target_context = S_OR(ast->macrocontext, ast->context); 07748 07749 /* We need to unlock 'ast' here because ast_exists_extension has the 07750 * potential to start autoservice on the channel. Such action is prone 07751 * to deadlock. 07752 */ 07753 ast_mutex_unlock(&p->lock); 07754 ast_channel_unlock(ast); 07755 if (ast_exists_extension(ast, target_context, "fax", 1, 07756 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 07757 ast_channel_lock(ast); 07758 ast_mutex_lock(&p->lock); 07759 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 07760 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 07761 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 07762 if (ast_async_goto(ast, target_context, "fax", 1)) 07763 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 07764 } else { 07765 ast_channel_lock(ast); 07766 ast_mutex_lock(&p->lock); 07767 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 07768 } 07769 } else { 07770 ast_debug(1, "Already in a fax extension, not redirecting\n"); 07771 } 07772 } else { 07773 ast_debug(1, "Fax already handled\n"); 07774 } 07775 dahdi_confmute(p, 0); 07776 } 07777 p->subs[idx].f.frametype = AST_FRAME_NULL; 07778 p->subs[idx].f.subclass.integer = 0; 07779 *dest = &p->subs[idx].f; 07780 } 07781 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 7804 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_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), ast_channel::caller, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), dahdi_pvt::cid_name, cid_name, dahdi_pvt::cid_num, cid_num, 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::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), dahdi_subchannel::f, 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, ast_frame::mallocd, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, ast_party_id::name, ast_channel::name, 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, sig_pri_span::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, sig_pri_span::pri, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, 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_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().
07805 { 07806 int res, x; 07807 int idx, mysig; 07808 char *c; 07809 struct dahdi_pvt *p = ast->tech_pvt; 07810 pthread_t threadid; 07811 struct ast_channel *chan; 07812 struct ast_frame *f; 07813 07814 idx = dahdi_get_index(ast, p, 0); 07815 mysig = p->sig; 07816 if (p->outsigmod > -1) 07817 mysig = p->outsigmod; 07818 p->subs[idx].f.frametype = AST_FRAME_NULL; 07819 p->subs[idx].f.subclass.integer = 0; 07820 p->subs[idx].f.datalen = 0; 07821 p->subs[idx].f.samples = 0; 07822 p->subs[idx].f.mallocd = 0; 07823 p->subs[idx].f.offset = 0; 07824 p->subs[idx].f.src = "dahdi_handle_event"; 07825 p->subs[idx].f.data.ptr = NULL; 07826 f = &p->subs[idx].f; 07827 07828 if (idx < 0) 07829 return &p->subs[idx].f; 07830 if (p->fake_event) { 07831 res = p->fake_event; 07832 p->fake_event = 0; 07833 } else 07834 res = dahdi_get_event(p->subs[idx].dfd); 07835 07836 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 07837 07838 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 07839 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 07840 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 07841 #if defined(HAVE_PRI) 07842 if (dahdi_sig_pri_lib_handles(p->sig) 07843 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07844 && p->pri 07845 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07846 /* absorb event */ 07847 } else 07848 #endif /* defined(HAVE_PRI) */ 07849 { 07850 /* Unmute conference */ 07851 dahdi_confmute(p, 0); 07852 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 07853 p->subs[idx].f.subclass.integer = res & 0xff; 07854 dahdi_handle_dtmf(ast, idx, &f); 07855 } 07856 return f; 07857 } 07858 07859 if (res & DAHDI_EVENT_DTMFDOWN) { 07860 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07861 #if defined(HAVE_PRI) 07862 if (dahdi_sig_pri_lib_handles(p->sig) 07863 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07864 && p->pri 07865 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07866 /* absorb event */ 07867 } else 07868 #endif /* defined(HAVE_PRI) */ 07869 { 07870 /* Mute conference */ 07871 dahdi_confmute(p, 1); 07872 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07873 p->subs[idx].f.subclass.integer = res & 0xff; 07874 dahdi_handle_dtmf(ast, idx, &f); 07875 } 07876 return &p->subs[idx].f; 07877 } 07878 07879 switch (res) { 07880 case DAHDI_EVENT_EC_DISABLED: 07881 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07882 p->echocanon = 0; 07883 break; 07884 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07885 case DAHDI_EVENT_TX_CED_DETECTED: 07886 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 07887 break; 07888 case DAHDI_EVENT_RX_CED_DETECTED: 07889 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 07890 break; 07891 case DAHDI_EVENT_EC_NLP_DISABLED: 07892 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 07893 break; 07894 case DAHDI_EVENT_EC_NLP_ENABLED: 07895 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 07896 break; 07897 #endif 07898 case DAHDI_EVENT_BITSCHANGED: 07899 #ifdef HAVE_OPENR2 07900 if (p->sig != SIG_MFCR2) { 07901 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07902 } else { 07903 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 07904 openr2_chan_handle_cas(p->r2chan); 07905 } 07906 #else 07907 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07908 #endif 07909 case DAHDI_EVENT_PULSE_START: 07910 /* Stop tone if there's a pulse start and the PBX isn't started */ 07911 if (!ast->pbx) 07912 tone_zone_play_tone(p->subs[idx].dfd, -1); 07913 break; 07914 case DAHDI_EVENT_DIALCOMPLETE: 07915 #ifdef HAVE_OPENR2 07916 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 07917 /* we don't need to do anything for this event for R2 signaling 07918 if the call is being setup */ 07919 break; 07920 } 07921 #endif 07922 if (p->inalarm) break; 07923 if ((p->radio || (p->oprmode < 0))) break; 07924 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 07925 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 07926 return NULL; 07927 } 07928 if (!x) { /* if not still dialing in driver */ 07929 dahdi_enable_ec(p); 07930 if (p->echobreak) { 07931 dahdi_train_ec(p); 07932 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 07933 p->dop.op = DAHDI_DIAL_OP_REPLACE; 07934 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07935 p->echobreak = 0; 07936 } else { 07937 p->dialing = 0; 07938 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 07939 /* if thru with dialing after offhook */ 07940 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 07941 ast_setstate(ast, AST_STATE_UP); 07942 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07943 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07944 break; 07945 } else { /* if to state wait for offhook to dial rest */ 07946 /* we now wait for off hook */ 07947 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 07948 } 07949 } 07950 if (ast->_state == AST_STATE_DIALING) { 07951 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 07952 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 07953 } else if (p->confirmanswer || (!p->dialednone 07954 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 07955 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 07956 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 07957 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 07958 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 07959 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 07960 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 07961 || (mysig == SIG_SF_FEATB)))) { 07962 ast_setstate(ast, AST_STATE_RINGING); 07963 } else if (!p->answeronpolarityswitch) { 07964 ast_setstate(ast, AST_STATE_UP); 07965 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07966 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07967 /* If aops=0 and hops=1, this is necessary */ 07968 p->polarity = POLARITY_REV; 07969 } else { 07970 /* Start clean, so we can catch the change to REV polarity when party answers */ 07971 p->polarity = POLARITY_IDLE; 07972 } 07973 } 07974 } 07975 } 07976 break; 07977 case DAHDI_EVENT_ALARM: 07978 switch (p->sig) { 07979 #if defined(HAVE_PRI) 07980 case SIG_PRI_LIB_HANDLE_CASES: 07981 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 07982 break; 07983 #endif /* defined(HAVE_PRI) */ 07984 #if defined(HAVE_SS7) 07985 case SIG_SS7: 07986 sig_ss7_set_alarm(p->sig_pvt, 1); 07987 break; 07988 #endif /* defined(HAVE_SS7) */ 07989 default: 07990 p->inalarm = 1; 07991 break; 07992 } 07993 res = get_alarms(p); 07994 handle_alarms(p, res); 07995 #ifdef HAVE_PRI 07996 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 07997 /* fall through intentionally */ 07998 } else { 07999 break; 08000 } 08001 #endif 08002 #if defined(HAVE_SS7) 08003 if (p->sig == SIG_SS7) 08004 break; 08005 #endif /* defined(HAVE_SS7) */ 08006 #ifdef HAVE_OPENR2 08007 if (p->sig == SIG_MFCR2) 08008 break; 08009 #endif 08010 case DAHDI_EVENT_ONHOOK: 08011 if (p->radio) { 08012 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08013 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08014 break; 08015 } 08016 if (p->oprmode < 0) 08017 { 08018 if (p->oprmode != -1) break; 08019 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08020 { 08021 /* Make sure it starts ringing */ 08022 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08023 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 08024 save_conference(p->oprpeer); 08025 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08026 } 08027 break; 08028 } 08029 switch (p->sig) { 08030 case SIG_FXOLS: 08031 case SIG_FXOGS: 08032 case SIG_FXOKS: 08033 /* Check for some special conditions regarding call waiting */ 08034 if (idx == SUB_REAL) { 08035 /* The normal line was hung up */ 08036 if (p->subs[SUB_CALLWAIT].owner) { 08037 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 08038 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 08039 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 08040 unalloc_sub(p, SUB_CALLWAIT); 08041 #if 0 08042 p->subs[idx].needanswer = 0; 08043 p->subs[idx].needringing = 0; 08044 #endif 08045 p->callwaitingrepeat = 0; 08046 p->cidcwexpire = 0; 08047 p->cid_suppress_expire = 0; 08048 p->owner = NULL; 08049 /* Don't start streaming audio yet if the incoming call isn't up yet */ 08050 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 08051 p->dialing = 1; 08052 dahdi_ring_phone(p); 08053 } else if (p->subs[SUB_THREEWAY].owner) { 08054 unsigned int mssinceflash; 08055 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 08056 the private structure -- not especially easy or clean */ 08057 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 08058 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 08059 DLA_UNLOCK(&p->lock); 08060 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08061 /* We can grab ast and p in that order, without worry. We should make sure 08062 nothing seriously bad has happened though like some sort of bizarre double 08063 masquerade! */ 08064 DLA_LOCK(&p->lock); 08065 if (p->owner != ast) { 08066 ast_log(LOG_WARNING, "This isn't good...\n"); 08067 return NULL; 08068 } 08069 } 08070 if (!p->subs[SUB_THREEWAY].owner) { 08071 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 08072 return NULL; 08073 } 08074 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 08075 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 08076 if (mssinceflash < MIN_MS_SINCE_FLASH) { 08077 /* It hasn't been long enough since the last flashook. This is probably a bounce on 08078 hanging up. Hangup both channels now */ 08079 if (p->subs[SUB_THREEWAY].owner) 08080 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 08081 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08082 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 08083 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08084 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 08085 if (p->transfer) { 08086 /* In any case this isn't a threeway call anymore */ 08087 p->subs[SUB_REAL].inthreeway = 0; 08088 p->subs[SUB_THREEWAY].inthreeway = 0; 08089 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 08090 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 08091 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08092 /* Swap subs and dis-own channel */ 08093 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08094 p->owner = NULL; 08095 /* Ring the phone */ 08096 dahdi_ring_phone(p); 08097 } else { 08098 if ((res = attempt_transfer(p)) < 0) { 08099 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08100 if (p->subs[SUB_THREEWAY].owner) 08101 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08102 } else if (res) { 08103 /* Don't actually hang up at this point */ 08104 if (p->subs[SUB_THREEWAY].owner) 08105 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08106 break; 08107 } 08108 } 08109 } else { 08110 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08111 if (p->subs[SUB_THREEWAY].owner) 08112 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08113 } 08114 } else { 08115 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 08116 /* Swap subs and dis-own channel */ 08117 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08118 p->owner = NULL; 08119 /* Ring the phone */ 08120 dahdi_ring_phone(p); 08121 } 08122 } 08123 } else { 08124 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 08125 } 08126 /* Fall through */ 08127 default: 08128 dahdi_disable_ec(p); 08129 return NULL; 08130 } 08131 break; 08132 case DAHDI_EVENT_RINGOFFHOOK: 08133 if (p->inalarm) break; 08134 if (p->oprmode < 0) 08135 { 08136 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 08137 { 08138 /* Make sure it stops ringing */ 08139 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08140 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 08141 restore_conference(p->oprpeer); 08142 } 08143 break; 08144 } 08145 if (p->radio) 08146 { 08147 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08148 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08149 break; 08150 } 08151 /* for E911, its supposed to wait for offhook then dial 08152 the second half of the dial string */ 08153 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 08154 c = strchr(p->dialdest, '/'); 08155 if (c) 08156 c++; 08157 else 08158 c = p->dialdest; 08159 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 08160 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 08161 if (strlen(p->dop.dialstr) > 4) { 08162 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 08163 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 08164 p->echorest[sizeof(p->echorest) - 1] = '\0'; 08165 p->echobreak = 1; 08166 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 08167 } else 08168 p->echobreak = 0; 08169 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 08170 int saveerr = errno; 08171 08172 x = DAHDI_ONHOOK; 08173 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 08174 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 08175 return NULL; 08176 } 08177 p->dialing = 1; 08178 return &p->subs[idx].f; 08179 } 08180 switch (p->sig) { 08181 case SIG_FXOLS: 08182 case SIG_FXOGS: 08183 case SIG_FXOKS: 08184 switch (ast->_state) { 08185 case AST_STATE_RINGING: 08186 dahdi_enable_ec(p); 08187 dahdi_train_ec(p); 08188 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08189 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08190 /* Make sure it stops ringing */ 08191 p->subs[SUB_REAL].needringing = 0; 08192 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08193 ast_debug(1, "channel %d answered\n", p->channel); 08194 08195 /* Cancel any running CallerID spill */ 08196 ast_free(p->cidspill); 08197 p->cidspill = NULL; 08198 restore_conference(p); 08199 08200 p->dialing = 0; 08201 p->callwaitcas = 0; 08202 if (p->confirmanswer) { 08203 /* Ignore answer if "confirm answer" is enabled */ 08204 p->subs[idx].f.frametype = AST_FRAME_NULL; 08205 p->subs[idx].f.subclass.integer = 0; 08206 } else if (!ast_strlen_zero(p->dop.dialstr)) { 08207 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 08208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08209 if (res < 0) { 08210 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08211 p->dop.dialstr[0] = '\0'; 08212 return NULL; 08213 } else { 08214 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 08215 p->subs[idx].f.frametype = AST_FRAME_NULL; 08216 p->subs[idx].f.subclass.integer = 0; 08217 p->dialing = 1; 08218 } 08219 p->dop.dialstr[0] = '\0'; 08220 ast_setstate(ast, AST_STATE_DIALING); 08221 } else 08222 ast_setstate(ast, AST_STATE_UP); 08223 return &p->subs[idx].f; 08224 case AST_STATE_DOWN: 08225 ast_setstate(ast, AST_STATE_RING); 08226 ast->rings = 1; 08227 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08228 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK; 08229 ast_debug(1, "channel %d picked up\n", p->channel); 08230 return &p->subs[idx].f; 08231 case AST_STATE_UP: 08232 /* Make sure it stops ringing */ 08233 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08234 /* Okay -- probably call waiting*/ 08235 if (ast_bridged_channel(p->owner)) 08236 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08237 p->subs[idx].needunhold = 1; 08238 break; 08239 case AST_STATE_RESERVED: 08240 /* Start up dialtone */ 08241 if (has_voicemail(p)) 08242 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08243 else 08244 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08245 break; 08246 default: 08247 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 08248 } 08249 break; 08250 case SIG_FXSLS: 08251 case SIG_FXSGS: 08252 case SIG_FXSKS: 08253 if (ast->_state == AST_STATE_RING) { 08254 p->ringt = p->ringt_base; 08255 } 08256 08257 /* If we get a ring then we cannot be in 08258 * reversed polarity. So we reset to idle */ 08259 ast_debug(1, "Setting IDLE polarity due " 08260 "to ring. Old polarity was %d\n", 08261 p->polarity); 08262 p->polarity = POLARITY_IDLE; 08263 08264 /* Fall through */ 08265 case SIG_EM: 08266 case SIG_EM_E1: 08267 case SIG_EMWINK: 08268 case SIG_FEATD: 08269 case SIG_FEATDMF: 08270 case SIG_FEATDMF_TA: 08271 case SIG_E911: 08272 case SIG_FGC_CAMA: 08273 case SIG_FGC_CAMAMF: 08274 case SIG_FEATB: 08275 case SIG_SF: 08276 case SIG_SFWINK: 08277 case SIG_SF_FEATD: 08278 case SIG_SF_FEATDMF: 08279 case SIG_SF_FEATB: 08280 if (ast->_state == AST_STATE_PRERING) 08281 ast_setstate(ast, AST_STATE_RING); 08282 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 08283 ast_debug(1, "Ring detected\n"); 08284 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08285 p->subs[idx].f.subclass.integer = AST_CONTROL_RING; 08286 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 08287 ast_debug(1, "Line answered\n"); 08288 if (p->confirmanswer) { 08289 p->subs[idx].f.frametype = AST_FRAME_NULL; 08290 p->subs[idx].f.subclass.integer = 0; 08291 } else { 08292 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08293 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08294 ast_setstate(ast, AST_STATE_UP); 08295 } 08296 } else if (ast->_state != AST_STATE_RING) 08297 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 08298 break; 08299 default: 08300 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08301 } 08302 break; 08303 case DAHDI_EVENT_RINGBEGIN: 08304 switch (p->sig) { 08305 case SIG_FXSLS: 08306 case SIG_FXSGS: 08307 case SIG_FXSKS: 08308 if (ast->_state == AST_STATE_RING) { 08309 p->ringt = p->ringt_base; 08310 } 08311 break; 08312 } 08313 break; 08314 case DAHDI_EVENT_RINGERON: 08315 break; 08316 case DAHDI_EVENT_NOALARM: 08317 switch (p->sig) { 08318 #if defined(HAVE_PRI) 08319 case SIG_PRI_LIB_HANDLE_CASES: 08320 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 08321 break; 08322 #endif /* defined(HAVE_PRI) */ 08323 #if defined(HAVE_SS7) 08324 case SIG_SS7: 08325 sig_ss7_set_alarm(p->sig_pvt, 0); 08326 break; 08327 #endif /* defined(HAVE_SS7) */ 08328 default: 08329 p->inalarm = 0; 08330 break; 08331 } 08332 handle_clear_alarms(p); 08333 break; 08334 case DAHDI_EVENT_WINKFLASH: 08335 if (p->inalarm) break; 08336 if (p->radio) break; 08337 if (p->oprmode < 0) break; 08338 if (p->oprmode > 1) 08339 { 08340 struct dahdi_params par; 08341 08342 memset(&par, 0, sizeof(par)); 08343 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 08344 { 08345 if (!par.rxisoffhook) 08346 { 08347 /* Make sure it stops ringing */ 08348 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08349 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 08350 save_conference(p); 08351 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08352 } 08353 } 08354 break; 08355 } 08356 /* Remember last time we got a flash-hook */ 08357 p->flashtime = ast_tvnow(); 08358 switch (mysig) { 08359 case SIG_FXOLS: 08360 case SIG_FXOGS: 08361 case SIG_FXOKS: 08362 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 08363 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 08364 08365 /* Cancel any running CallerID spill */ 08366 ast_free(p->cidspill); 08367 p->cidspill = NULL; 08368 restore_conference(p); 08369 p->callwaitcas = 0; 08370 08371 if (idx != SUB_REAL) { 08372 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 08373 goto winkflashdone; 08374 } 08375 08376 if (p->subs[SUB_CALLWAIT].owner) { 08377 /* Swap to call-wait */ 08378 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 08379 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 08380 p->owner = p->subs[SUB_REAL].owner; 08381 ast_debug(1, "Making %s the new owner\n", p->owner->name); 08382 if (p->owner->_state == AST_STATE_RINGING) { 08383 ast_setstate(p->owner, AST_STATE_UP); 08384 p->subs[SUB_REAL].needanswer = 1; 08385 } 08386 p->callwaitingrepeat = 0; 08387 p->cidcwexpire = 0; 08388 p->cid_suppress_expire = 0; 08389 /* Start music on hold if appropriate */ 08390 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 08391 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 08392 S_OR(p->mohsuggest, NULL), 08393 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08394 } 08395 p->subs[SUB_CALLWAIT].needhold = 1; 08396 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 08397 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 08398 S_OR(p->mohsuggest, NULL), 08399 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08400 } 08401 p->subs[SUB_REAL].needunhold = 1; 08402 } else if (!p->subs[SUB_THREEWAY].owner) { 08403 if (!p->threewaycalling) { 08404 /* Just send a flash if no 3-way calling */ 08405 p->subs[SUB_REAL].needflash = 1; 08406 goto winkflashdone; 08407 } else if (!check_for_conference(p)) { 08408 char cid_num[256]; 08409 char cid_name[256]; 08410 08411 cid_num[0] = 0; 08412 cid_name[0] = 0; 08413 if (p->dahditrcallerid && p->owner) { 08414 if (p->owner->caller.id.number.valid 08415 && p->owner->caller.id.number.str) { 08416 ast_copy_string(cid_num, p->owner->caller.id.number.str, 08417 sizeof(cid_num)); 08418 } 08419 if (p->owner->caller.id.name.valid 08420 && p->owner->caller.id.name.str) { 08421 ast_copy_string(cid_name, p->owner->caller.id.name.str, 08422 sizeof(cid_name)); 08423 } 08424 } 08425 /* XXX This section needs much more error checking!!! XXX */ 08426 /* Start a 3-way call if feasible */ 08427 if (!((ast->pbx) || 08428 (ast->_state == AST_STATE_UP) || 08429 (ast->_state == AST_STATE_RING))) { 08430 ast_debug(1, "Flash when call not up or ringing\n"); 08431 goto winkflashdone; 08432 } 08433 if (alloc_sub(p, SUB_THREEWAY)) { 08434 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 08435 goto winkflashdone; 08436 } 08437 /* Make new channel */ 08438 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL); 08439 if (p->dahditrcallerid) { 08440 if (!p->origcid_num) 08441 p->origcid_num = ast_strdup(p->cid_num); 08442 if (!p->origcid_name) 08443 p->origcid_name = ast_strdup(p->cid_name); 08444 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 08445 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 08446 } 08447 /* Swap things around between the three-way and real call */ 08448 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08449 /* Disable echo canceller for better dialing */ 08450 dahdi_disable_ec(p); 08451 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 08452 if (res) 08453 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 08454 p->owner = chan; 08455 if (!chan) { 08456 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 08457 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 08458 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 08459 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08460 dahdi_enable_ec(p); 08461 ast_hangup(chan); 08462 } else { 08463 ast_verb(3, "Started three way call on channel %d\n", p->channel); 08464 08465 /* Start music on hold if appropriate */ 08466 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08467 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 08468 S_OR(p->mohsuggest, NULL), 08469 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08470 } 08471 p->subs[SUB_THREEWAY].needhold = 1; 08472 } 08473 } 08474 } else { 08475 /* Already have a 3 way call */ 08476 if (p->subs[SUB_THREEWAY].inthreeway) { 08477 /* Call is already up, drop the last person */ 08478 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 08479 /* If the primary call isn't answered yet, use it */ 08480 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 08481 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 08482 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08483 p->owner = p->subs[SUB_REAL].owner; 08484 } 08485 /* Drop the last call and stop the conference */ 08486 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 08487 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08488 p->subs[SUB_REAL].inthreeway = 0; 08489 p->subs[SUB_THREEWAY].inthreeway = 0; 08490 } else { 08491 /* Lets see what we're up to */ 08492 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 08493 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 08494 int otherindex = SUB_THREEWAY; 08495 08496 ast_verb(3, "Building conference call with %s and %s\n", 08497 p->subs[SUB_THREEWAY].owner->name, 08498 p->subs[SUB_REAL].owner->name); 08499 /* Put them in the threeway, and flip */ 08500 p->subs[SUB_THREEWAY].inthreeway = 1; 08501 p->subs[SUB_REAL].inthreeway = 1; 08502 if (ast->_state == AST_STATE_UP) { 08503 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08504 otherindex = SUB_REAL; 08505 } 08506 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 08507 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 08508 p->subs[otherindex].needunhold = 1; 08509 p->owner = p->subs[SUB_REAL].owner; 08510 } else { 08511 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 08512 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08513 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08514 p->owner = p->subs[SUB_REAL].owner; 08515 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 08516 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08517 p->subs[SUB_REAL].needunhold = 1; 08518 dahdi_enable_ec(p); 08519 } 08520 } 08521 } 08522 winkflashdone: 08523 update_conf(p); 08524 break; 08525 case SIG_EM: 08526 case SIG_EM_E1: 08527 case SIG_FEATD: 08528 case SIG_SF: 08529 case SIG_SFWINK: 08530 case SIG_SF_FEATD: 08531 case SIG_FXSLS: 08532 case SIG_FXSGS: 08533 if (p->dialing) 08534 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 08535 else 08536 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 08537 break; 08538 case SIG_FEATDMF_TA: 08539 switch (p->whichwink) { 08540 case 0: 08541 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2, 08542 S_COR(p->owner->caller.ani.number.valid, 08543 p->owner->caller.ani.number.str, "")); 08544 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", 08545 p->owner->caller.ani2, 08546 S_COR(p->owner->caller.ani.number.valid, 08547 p->owner->caller.ani.number.str, "")); 08548 break; 08549 case 1: 08550 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 08551 break; 08552 case 2: 08553 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 08554 return NULL; 08555 } 08556 p->whichwink++; 08557 /* Fall through */ 08558 case SIG_FEATDMF: 08559 case SIG_E911: 08560 case SIG_FGC_CAMAMF: 08561 case SIG_FGC_CAMA: 08562 case SIG_FEATB: 08563 case SIG_SF_FEATDMF: 08564 case SIG_SF_FEATB: 08565 case SIG_EMWINK: 08566 /* FGD MF and EMWINK *Must* wait for wink */ 08567 if (!ast_strlen_zero(p->dop.dialstr)) { 08568 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08569 if (res < 0) { 08570 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08571 p->dop.dialstr[0] = '\0'; 08572 return NULL; 08573 } else 08574 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08575 } 08576 p->dop.dialstr[0] = '\0'; 08577 break; 08578 default: 08579 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08580 } 08581 break; 08582 case DAHDI_EVENT_HOOKCOMPLETE: 08583 if (p->inalarm) break; 08584 if ((p->radio || (p->oprmode < 0))) break; 08585 if (p->waitingfordt.tv_sec) break; 08586 switch (mysig) { 08587 case SIG_FXSLS: /* only interesting for FXS */ 08588 case SIG_FXSGS: 08589 case SIG_FXSKS: 08590 case SIG_EM: 08591 case SIG_EM_E1: 08592 case SIG_EMWINK: 08593 case SIG_FEATD: 08594 case SIG_SF: 08595 case SIG_SFWINK: 08596 case SIG_SF_FEATD: 08597 if (!ast_strlen_zero(p->dop.dialstr)) { 08598 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08599 if (res < 0) { 08600 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08601 p->dop.dialstr[0] = '\0'; 08602 return NULL; 08603 } else 08604 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08605 } 08606 p->dop.dialstr[0] = '\0'; 08607 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08608 break; 08609 case SIG_FEATDMF: 08610 case SIG_FEATDMF_TA: 08611 case SIG_E911: 08612 case SIG_FGC_CAMA: 08613 case SIG_FGC_CAMAMF: 08614 case SIG_FEATB: 08615 case SIG_SF_FEATDMF: 08616 case SIG_SF_FEATB: 08617 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 08618 break; 08619 default: 08620 break; 08621 } 08622 break; 08623 case DAHDI_EVENT_POLARITY: 08624 /* 08625 * If we get a Polarity Switch event, check to see 08626 * if we should change the polarity state and 08627 * mark the channel as UP or if this is an indication 08628 * of remote end disconnect. 08629 */ 08630 if (p->polarity == POLARITY_IDLE) { 08631 p->polarity = POLARITY_REV; 08632 if (p->answeronpolarityswitch && 08633 ((ast->_state == AST_STATE_DIALING) || 08634 (ast->_state == AST_STATE_RINGING))) { 08635 ast_debug(1, "Answering on polarity switch!\n"); 08636 ast_setstate(p->owner, AST_STATE_UP); 08637 if (p->hanguponpolarityswitch) { 08638 p->polaritydelaytv = ast_tvnow(); 08639 } 08640 } else 08641 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 08642 } 08643 /* Removed else statement from here as it was preventing hangups from ever happening*/ 08644 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 08645 if (p->hanguponpolarityswitch && 08646 (p->polarityonanswerdelay > 0) && 08647 (p->polarity == POLARITY_REV) && 08648 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 08649 /* Added log_debug information below to provide a better indication of what is going on */ 08650 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) ); 08651 08652 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 08653 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 08654 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 08655 p->polarity = POLARITY_IDLE; 08656 } else 08657 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); 08658 08659 } else { 08660 p->polarity = POLARITY_IDLE; 08661 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 08662 } 08663 /* Added more log_debug information below to provide a better indication of what is going on */ 08664 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) ); 08665 break; 08666 default: 08667 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 08668 } 08669 return &p->subs[idx].f; 08670 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6088 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_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_r2_disconnect_call(), 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, iflock, 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::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, num_restart_pending, 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::r2chan, 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.
06089 { 06090 int res = 0; 06091 int idx,x; 06092 int law; 06093 /*static int restore_gains(struct dahdi_pvt *p);*/ 06094 struct dahdi_pvt *p = ast->tech_pvt; 06095 struct dahdi_params par; 06096 06097 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 06098 if (!ast->tech_pvt) { 06099 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 06100 return 0; 06101 } 06102 06103 ast_mutex_lock(&p->lock); 06104 p->exten[0] = '\0'; 06105 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06106 dahdi_confmute(p, 0); 06107 restore_gains(p); 06108 p->ignoredtmf = 0; 06109 p->waitingfordt.tv_sec = 0; 06110 06111 res = analog_hangup(p->sig_pvt, ast); 06112 revert_fax_buffers(p, ast); 06113 06114 goto hangup_out; 06115 } else { 06116 p->cid_num[0] = '\0'; 06117 p->cid_name[0] = '\0'; 06118 p->cid_subaddr[0] = '\0'; 06119 } 06120 06121 #if defined(HAVE_PRI) 06122 if (dahdi_sig_pri_lib_handles(p->sig)) { 06123 x = 1; 06124 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06125 06126 dahdi_confmute(p, 0); 06127 p->muting = 0; 06128 restore_gains(p); 06129 if (p->dsp) { 06130 ast_dsp_free(p->dsp); 06131 p->dsp = NULL; 06132 } 06133 p->ignoredtmf = 0; 06134 06135 /* Real channel, do some fixup */ 06136 p->subs[SUB_REAL].owner = NULL; 06137 p->subs[SUB_REAL].needbusy = 0; 06138 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06139 06140 p->owner = NULL; 06141 p->cid_tag[0] = '\0'; 06142 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06143 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06144 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06145 p->outgoing = 0; 06146 p->digital = 0; 06147 p->faxhandled = 0; 06148 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06149 06150 revert_fax_buffers(p, ast); 06151 06152 p->law = p->law_default; 06153 law = p->law_default; 06154 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06155 if (res < 0) { 06156 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06157 p->channel, strerror(errno)); 06158 } 06159 06160 sig_pri_hangup(p->sig_pvt, ast); 06161 06162 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06163 dahdi_disable_ec(p); 06164 06165 x = 0; 06166 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06167 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06168 06169 p->rdnis[0] = '\0'; 06170 update_conf(p); 06171 reset_conf(p); 06172 06173 /* Restore data mode */ 06174 x = 0; 06175 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06176 06177 if (num_restart_pending == 0) { 06178 restart_monitor(); 06179 } 06180 goto hangup_out; 06181 } 06182 #endif /* defined(HAVE_PRI) */ 06183 06184 #if defined(HAVE_SS7) 06185 if (p->sig == SIG_SS7) { 06186 x = 1; 06187 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06188 06189 dahdi_confmute(p, 0); 06190 p->muting = 0; 06191 restore_gains(p); 06192 if (p->dsp) { 06193 ast_dsp_free(p->dsp); 06194 p->dsp = NULL; 06195 } 06196 p->ignoredtmf = 0; 06197 06198 /* Real channel, do some fixup */ 06199 p->subs[SUB_REAL].owner = NULL; 06200 p->subs[SUB_REAL].needbusy = 0; 06201 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06202 06203 p->owner = NULL; 06204 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06205 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06206 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06207 p->outgoing = 0; 06208 p->digital = 0; 06209 p->faxhandled = 0; 06210 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06211 06212 revert_fax_buffers(p, ast); 06213 06214 p->law = p->law_default; 06215 law = p->law_default; 06216 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06217 if (res < 0) { 06218 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", 06219 p->channel, strerror(errno)); 06220 } 06221 06222 sig_ss7_hangup(p->sig_pvt, ast); 06223 06224 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06225 dahdi_disable_ec(p); 06226 06227 x = 0; 06228 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0); 06229 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06230 06231 update_conf(p); 06232 reset_conf(p); 06233 06234 /* Restore data mode */ 06235 x = 0; 06236 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0); 06237 06238 if (num_restart_pending == 0) { 06239 restart_monitor(); 06240 } 06241 goto hangup_out; 06242 } 06243 #endif /* defined(HAVE_SS7) */ 06244 06245 idx = dahdi_get_index(ast, p, 1); 06246 06247 dahdi_confmute(p, 0); 06248 p->muting = 0; 06249 restore_gains(p); 06250 if (p->origcid_num) { 06251 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 06252 ast_free(p->origcid_num); 06253 p->origcid_num = NULL; 06254 } 06255 if (p->origcid_name) { 06256 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 06257 ast_free(p->origcid_name); 06258 p->origcid_name = NULL; 06259 } 06260 if (p->dsp) 06261 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06262 06263 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 06264 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06265 p->ignoredtmf = 0; 06266 06267 if (idx > -1) { 06268 /* Real channel, do some fixup */ 06269 p->subs[idx].owner = NULL; 06270 p->subs[idx].needanswer = 0; 06271 p->subs[idx].needflash = 0; 06272 p->subs[idx].needringing = 0; 06273 p->subs[idx].needbusy = 0; 06274 p->subs[idx].needcongestion = 0; 06275 p->subs[idx].linear = 0; 06276 p->polarity = POLARITY_IDLE; 06277 dahdi_setlinear(p->subs[idx].dfd, 0); 06278 if (idx == SUB_REAL) { 06279 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 06280 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 06281 if (p->subs[SUB_CALLWAIT].inthreeway) { 06282 /* We had flipped over to answer a callwait and now it's gone */ 06283 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 06284 /* Move to the call-wait, but un-own us until they flip back. */ 06285 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06286 unalloc_sub(p, SUB_CALLWAIT); 06287 p->owner = NULL; 06288 } else { 06289 /* The three way hung up, but we still have a call wait */ 06290 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 06291 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06292 unalloc_sub(p, SUB_THREEWAY); 06293 if (p->subs[SUB_REAL].inthreeway) { 06294 /* This was part of a three way call. Immediately make way for 06295 another call */ 06296 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06297 p->owner = p->subs[SUB_REAL].owner; 06298 } else { 06299 /* This call hasn't been completed yet... Set owner to NULL */ 06300 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06301 p->owner = NULL; 06302 } 06303 p->subs[SUB_REAL].inthreeway = 0; 06304 } 06305 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 06306 /* Move to the call-wait and switch back to them. */ 06307 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06308 unalloc_sub(p, SUB_CALLWAIT); 06309 p->owner = p->subs[SUB_REAL].owner; 06310 if (p->owner->_state != AST_STATE_UP) 06311 p->subs[SUB_REAL].needanswer = 1; 06312 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06313 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06314 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 06315 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06316 unalloc_sub(p, SUB_THREEWAY); 06317 if (p->subs[SUB_REAL].inthreeway) { 06318 /* This was part of a three way call. Immediately make way for 06319 another call */ 06320 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06321 p->owner = p->subs[SUB_REAL].owner; 06322 } else { 06323 /* This call hasn't been completed yet... Set owner to NULL */ 06324 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06325 p->owner = NULL; 06326 } 06327 p->subs[SUB_REAL].inthreeway = 0; 06328 } 06329 } else if (idx == SUB_CALLWAIT) { 06330 /* Ditch the holding callwait call, and immediately make it availabe */ 06331 if (p->subs[SUB_CALLWAIT].inthreeway) { 06332 /* This is actually part of a three way, placed on hold. Place the third part 06333 on music on hold now */ 06334 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06335 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06336 S_OR(p->mohsuggest, NULL), 06337 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06338 } 06339 p->subs[SUB_THREEWAY].inthreeway = 0; 06340 /* Make it the call wait now */ 06341 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06342 unalloc_sub(p, SUB_THREEWAY); 06343 } else 06344 unalloc_sub(p, SUB_CALLWAIT); 06345 } else if (idx == SUB_THREEWAY) { 06346 if (p->subs[SUB_CALLWAIT].inthreeway) { 06347 /* The other party of the three way call is currently in a call-wait state. 06348 Start music on hold for them, and take the main guy out of the third call */ 06349 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06350 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06351 S_OR(p->mohsuggest, NULL), 06352 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06353 } 06354 p->subs[SUB_CALLWAIT].inthreeway = 0; 06355 } 06356 p->subs[SUB_REAL].inthreeway = 0; 06357 /* If this was part of a three way call index, let us make 06358 another three way call */ 06359 unalloc_sub(p, SUB_THREEWAY); 06360 } else { 06361 /* This wasn't any sort of call, but how are we an index? */ 06362 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 06363 } 06364 } 06365 06366 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 06367 p->owner = NULL; 06368 p->ringt = 0; 06369 p->distinctivering = 0; 06370 p->confirmanswer = 0; 06371 p->outgoing = 0; 06372 p->digital = 0; 06373 p->faxhandled = 0; 06374 p->pulsedial = 0; 06375 if (p->dsp) { 06376 ast_dsp_free(p->dsp); 06377 p->dsp = NULL; 06378 } 06379 06380 revert_fax_buffers(p, ast); 06381 06382 p->law = p->law_default; 06383 law = p->law_default; 06384 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06385 if (res < 0) 06386 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06387 /* Perform low level hangup if no owner left */ 06388 #ifdef HAVE_OPENR2 06389 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 06390 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 06391 /* If it's an incoming call, check the mfcr2_forced_release setting */ 06392 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 06393 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 06394 } else { 06395 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 06396 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 06397 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 06398 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 06399 dahdi_r2_disconnect_call(p, r2cause); 06400 } 06401 } else if (p->mfcr2call) { 06402 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 06403 /* since ast_request() was called but not ast_call() we have not yet dialed 06404 and the openr2 stack will not call on_call_end callback, we need to unset 06405 the mfcr2call flag and bump the monitor count so the monitor thread can take 06406 care of this channel events from now on */ 06407 p->mfcr2call = 0; 06408 } 06409 #endif 06410 switch (p->sig) { 06411 case SIG_SS7: 06412 case SIG_MFCR2: 06413 case SIG_PRI_LIB_HANDLE_CASES: 06414 case 0: 06415 break; 06416 default: 06417 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06418 break; 06419 } 06420 if (res < 0) { 06421 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 06422 } 06423 switch (p->sig) { 06424 case SIG_FXOGS: 06425 case SIG_FXOLS: 06426 case SIG_FXOKS: 06427 memset(&par, 0, sizeof(par)); 06428 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 06429 if (!res) { 06430 struct analog_pvt *analog_p = p->sig_pvt; 06431 #if 0 06432 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 06433 #endif 06434 /* If they're off hook, try playing congestion */ 06435 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 06436 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06437 else 06438 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06439 analog_p->fxsoffhookstate = par.rxisoffhook; 06440 } 06441 break; 06442 case SIG_FXSGS: 06443 case SIG_FXSLS: 06444 case SIG_FXSKS: 06445 /* Make sure we're not made available for at least two seconds assuming 06446 we were actually used for an inbound or outbound call. */ 06447 if (ast->_state != AST_STATE_RESERVED) { 06448 time(&p->guardtime); 06449 p->guardtime += 2; 06450 } 06451 break; 06452 default: 06453 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06454 break; 06455 } 06456 if (p->sig) 06457 dahdi_disable_ec(p); 06458 x = 0; 06459 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06460 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06461 p->didtdd = 0; 06462 p->callwaitcas = 0; 06463 p->callwaiting = p->permcallwaiting; 06464 p->hidecallerid = p->permhidecallerid; 06465 p->waitingfordt.tv_sec = 0; 06466 p->dialing = 0; 06467 p->rdnis[0] = '\0'; 06468 update_conf(p); 06469 reset_conf(p); 06470 /* Restore data mode */ 06471 switch (p->sig) { 06472 case SIG_PRI_LIB_HANDLE_CASES: 06473 case SIG_SS7: 06474 x = 0; 06475 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06476 break; 06477 default: 06478 break; 06479 } 06480 if (num_restart_pending == 0) 06481 restart_monitor(); 06482 } 06483 06484 p->callwaitingrepeat = 0; 06485 p->cidcwexpire = 0; 06486 p->cid_suppress_expire = 0; 06487 p->oprmode = 0; 06488 hangup_out: 06489 ast->tech_pvt = NULL; 06490 ast_free(p->cidspill); 06491 p->cidspill = NULL; 06492 06493 ast_mutex_unlock(&p->lock); 06494 ast_verb(3, "Hungup '%s'\n", ast->name); 06495 06496 ast_mutex_lock(&iflock); 06497 if (p->restartpending) { 06498 num_restart_pending--; 06499 } 06500 06501 if (p->destroy) { 06502 destroy_channel(p, 0); 06503 } 06504 ast_mutex_unlock(&iflock); 06505 06506 ast_module_unref(ast_module_info->self); 06507 return 0; 06508 }
static void dahdi_iflist_extract | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5489 of file chan_dahdi.c.
References DAHDI_IFLIST_NONE, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.
Referenced by destroy_dahdi_pvt().
05490 { 05491 /* Extract from the forward chain. */ 05492 if (pvt->prev) { 05493 pvt->prev->next = pvt->next; 05494 } else if (iflist == pvt) { 05495 /* Node is at the head of the list. */ 05496 iflist = pvt->next; 05497 } 05498 05499 /* Extract from the reverse chain. */ 05500 if (pvt->next) { 05501 pvt->next->prev = pvt->prev; 05502 } else if (ifend == pvt) { 05503 /* Node is at the end of the list. */ 05504 ifend = pvt->prev; 05505 } 05506 05507 /* Node is no longer in the list. */ 05508 pvt->which_iflist = DAHDI_IFLIST_NONE; 05509 pvt->prev = NULL; 05510 pvt->next = NULL; 05511 }
static void dahdi_iflist_insert | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5439 of file chan_dahdi.c.
References dahdi_pvt::channel, DAHDI_IFLIST_MAIN, iflist, dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::which_iflist.
Referenced by duplicate_pseudo().
05440 { 05441 struct dahdi_pvt *cur; 05442 05443 pvt->which_iflist = DAHDI_IFLIST_MAIN; 05444 05445 /* Find place in middle of list for the new interface. */ 05446 for (cur = iflist; cur; cur = cur->next) { 05447 if (pvt->channel < cur->channel) { 05448 /* New interface goes before the current interface. */ 05449 pvt->prev = cur->prev; 05450 pvt->next = cur; 05451 if (cur->prev) { 05452 /* Insert into the middle of the list. */ 05453 cur->prev->next = pvt; 05454 } else { 05455 /* Insert at head of list. */ 05456 iflist = pvt; 05457 } 05458 cur->prev = pvt; 05459 return; 05460 } 05461 } 05462 05463 /* New interface goes onto the end of the list */ 05464 pvt->prev = ifend; 05465 pvt->next = NULL; 05466 if (ifend) { 05467 ifend->next = pvt; 05468 } 05469 ifend = pvt; 05470 if (!iflist) { 05471 /* List was empty */ 05472 iflist = pvt; 05473 } 05474 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 9311 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, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, ast_channel::name, 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.
09312 { 09313 struct dahdi_pvt *p = chan->tech_pvt; 09314 int res=-1; 09315 int idx; 09316 int func = DAHDI_FLASH; 09317 09318 ast_mutex_lock(&p->lock); 09319 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 09320 switch (p->sig) { 09321 #if defined(HAVE_PRI) 09322 case SIG_PRI_LIB_HANDLE_CASES: 09323 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen); 09324 ast_mutex_unlock(&p->lock); 09325 return res; 09326 #endif /* defined(HAVE_PRI) */ 09327 #if defined(HAVE_SS7) 09328 case SIG_SS7: 09329 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen); 09330 ast_mutex_unlock(&p->lock); 09331 return res; 09332 #endif /* defined(HAVE_SS7) */ 09333 default: 09334 break; 09335 } 09336 #ifdef HAVE_OPENR2 09337 if (p->mfcr2 && !p->mfcr2_call_accepted) { 09338 ast_mutex_unlock(&p->lock); 09339 /* if this is an R2 call and the call is not yet accepted, we don't want the 09340 tone indications to mess up with the MF tones */ 09341 return 0; 09342 } 09343 #endif 09344 idx = dahdi_get_index(chan, p, 0); 09345 if (idx == SUB_REAL) { 09346 switch (condition) { 09347 case AST_CONTROL_BUSY: 09348 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 09349 break; 09350 case AST_CONTROL_RINGING: 09351 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 09352 09353 if (chan->_state != AST_STATE_UP) { 09354 if ((chan->_state != AST_STATE_RING) || 09355 ((p->sig != SIG_FXSKS) && 09356 (p->sig != SIG_FXSLS) && 09357 (p->sig != SIG_FXSGS))) 09358 ast_setstate(chan, AST_STATE_RINGING); 09359 } 09360 break; 09361 case AST_CONTROL_INCOMPLETE: 09362 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name); 09363 /* act as a progress or proceeding, allowing the caller to enter additional numbers */ 09364 res = 0; 09365 break; 09366 case AST_CONTROL_PROCEEDING: 09367 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name); 09368 /* don't continue in ast_indicate */ 09369 res = 0; 09370 break; 09371 case AST_CONTROL_PROGRESS: 09372 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name); 09373 /* don't continue in ast_indicate */ 09374 res = 0; 09375 break; 09376 case AST_CONTROL_CONGESTION: 09377 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 09378 switch (chan->hangupcause) { 09379 case AST_CAUSE_USER_BUSY: 09380 case AST_CAUSE_NORMAL_CLEARING: 09381 case 0:/* Cause has not been set. */ 09382 /* Supply a more appropriate cause. */ 09383 chan->hangupcause = AST_CAUSE_CONGESTION; 09384 break; 09385 default: 09386 break; 09387 } 09388 break; 09389 case AST_CONTROL_HOLD: 09390 ast_moh_start(chan, data, p->mohinterpret); 09391 break; 09392 case AST_CONTROL_UNHOLD: 09393 ast_moh_stop(chan); 09394 break; 09395 case AST_CONTROL_RADIO_KEY: 09396 if (p->radio) 09397 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 09398 res = 0; 09399 break; 09400 case AST_CONTROL_RADIO_UNKEY: 09401 if (p->radio) 09402 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 09403 res = 0; 09404 break; 09405 case AST_CONTROL_FLASH: 09406 /* flash hookswitch */ 09407 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 09408 /* Clear out the dial buffer */ 09409 p->dop.dialstr[0] = '\0'; 09410 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09411 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09412 chan->name, strerror(errno)); 09413 } else 09414 res = 0; 09415 } else 09416 res = 0; 09417 break; 09418 case AST_CONTROL_SRCUPDATE: 09419 res = 0; 09420 break; 09421 case -1: 09422 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09423 break; 09424 } 09425 } else { 09426 res = 0; 09427 } 09428 ast_mutex_unlock(&p->lock); 09429 return res; 09430 }
Definition at line 7134 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and dahdi_pvt::slaves.
Referenced by dahdi_bridge().
07134 { 07135 int x; 07136 if (!slave || !master) { 07137 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 07138 return; 07139 } 07140 for (x = 0; x < MAX_SLAVES; x++) { 07141 if (!master->slaves[x]) { 07142 master->slaves[x] = slave; 07143 break; 07144 } 07145 } 07146 if (x >= MAX_SLAVES) { 07147 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 07148 master->slaves[MAX_SLAVES - 1] = slave; 07149 } 07150 if (slave->master) 07151 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 07152 slave->master = master; 07153 07154 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 07155 }
static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
int | sub_idx | |||
) | [static] |
Definition at line 3719 of file chan_dahdi.c.
References ast_channel_trylock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by wakeup_sub().
03720 { 03721 for (;;) { 03722 if (!pvt->subs[sub_idx].owner) { 03723 /* No subchannel owner pointer */ 03724 break; 03725 } 03726 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) { 03727 /* Got subchannel owner lock */ 03728 break; 03729 } 03730 /* We must unlock the private to avoid the possibility of a deadlock */ 03731 DEADLOCK_AVOIDANCE(&pvt->lock); 03732 } 03733 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | idx, | |||
int | law, | |||
const char * | linkedid | |||
) | [static] |
Definition at line 9480 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_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_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, sig_pri_span::cc_params, dahdi_pvt::cc_params, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cid_ani, 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_tech, 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_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, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, dahdi_pvt::muting, ast_variable::name, ast_party_id::name, ast_channel::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::pri, progzone, 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, subnames, 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_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), handle_init_event(), mwi_thread(), my_new_analog_ast_channel(), my_new_pri_ast_channel(), and register_translator().
09481 { 09482 struct ast_channel *tmp; 09483 format_t deflaw; 09484 int x; 09485 int features; 09486 struct ast_str *chan_name; 09487 struct ast_variable *v; 09488 char *dashptr; 09489 char device_name[AST_CHANNEL_NAME]; 09490 09491 if (i->subs[idx].owner) { 09492 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 09493 return NULL; 09494 } 09495 09496 #if defined(HAVE_PRI) 09497 /* 09498 * The dnid has been stuffed with the called-number[:subaddress] 09499 * by dahdi_request() for outgoing calls. 09500 */ 09501 chan_name = create_channel_name(i, i->outgoing, i->dnid); 09502 #else 09503 chan_name = create_channel_name(i); 09504 #endif /* defined(HAVE_PRI) */ 09505 if (!chan_name) { 09506 return NULL; 09507 } 09508 09509 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)); 09510 ast_free(chan_name); 09511 if (!tmp) 09512 return NULL; 09513 tmp->tech = &dahdi_tech; 09514 #if defined(HAVE_PRI) 09515 if (i->pri) { 09516 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params); 09517 } 09518 #endif /* defined(HAVE_PRI) */ 09519 ast_channel_cc_params_init(tmp, i->cc_params); 09520 if (law) { 09521 i->law = law; 09522 if (law == DAHDI_LAW_ALAW) { 09523 deflaw = AST_FORMAT_ALAW; 09524 } else { 09525 deflaw = AST_FORMAT_ULAW; 09526 } 09527 } else { 09528 switch (i->sig) { 09529 case SIG_PRI_LIB_HANDLE_CASES: 09530 /* Make sure companding law is known. */ 09531 i->law = (i->law_default == DAHDI_LAW_ALAW) 09532 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW; 09533 break; 09534 default: 09535 i->law = i->law_default; 09536 break; 09537 } 09538 if (i->law_default == DAHDI_LAW_ALAW) { 09539 deflaw = AST_FORMAT_ALAW; 09540 } else { 09541 deflaw = AST_FORMAT_ULAW; 09542 } 09543 } 09544 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 09545 tmp->nativeformats = deflaw; 09546 /* Start out assuming ulaw since it's smaller :) */ 09547 tmp->rawreadformat = deflaw; 09548 tmp->readformat = deflaw; 09549 tmp->rawwriteformat = deflaw; 09550 tmp->writeformat = deflaw; 09551 i->subs[idx].linear = 0; 09552 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 09553 features = 0; 09554 if (idx == SUB_REAL) { 09555 if (i->busydetect && CANBUSYDETECT(i)) 09556 features |= DSP_FEATURE_BUSY_DETECT; 09557 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 09558 features |= DSP_FEATURE_CALL_PROGRESS; 09559 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 09560 features |= DSP_FEATURE_WAITDIALTONE; 09561 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 09562 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 09563 features |= DSP_FEATURE_FAX_DETECT; 09564 } 09565 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 09566 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 09567 i->hardwaredtmf = 0; 09568 features |= DSP_FEATURE_DIGIT_DETECT; 09569 } else if (NEED_MFDETECT(i)) { 09570 i->hardwaredtmf = 1; 09571 features |= DSP_FEATURE_DIGIT_DETECT; 09572 } 09573 } 09574 if (features) { 09575 if (i->dsp) { 09576 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 09577 } else { 09578 if (i->channel != CHAN_PSEUDO) 09579 i->dsp = ast_dsp_new(); 09580 else 09581 i->dsp = NULL; 09582 if (i->dsp) { 09583 i->dsp_features = features; 09584 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09585 /* We cannot do progress detection until receive PROGRESS message */ 09586 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) { 09587 /* Remember requested DSP features, don't treat 09588 talking as ANSWER */ 09589 i->dsp_features = features & ~DSP_PROGRESS_TALK; 09590 features = 0; 09591 } 09592 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09593 ast_dsp_set_features(i->dsp, features); 09594 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 09595 if (!ast_strlen_zero(progzone)) 09596 ast_dsp_set_call_progress_zone(i->dsp, progzone); 09597 if (i->busydetect && CANBUSYDETECT(i)) { 09598 if(i->silencethreshold > 0) 09599 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 09600 ast_dsp_set_busy_count(i->dsp, i->busycount); 09601 if(i->busytonelength > 0) 09602 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 09603 if((i->busytonelength == i->busyquietlength) && i->busycompare) 09604 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 09605 } 09606 } 09607 } 09608 } 09609 09610 if (state == AST_STATE_RING) 09611 tmp->rings = 1; 09612 tmp->tech_pvt = i; 09613 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 09614 /* Only FXO signalled stuff can be picked up */ 09615 tmp->callgroup = i->callgroup; 09616 tmp->pickupgroup = i->pickupgroup; 09617 } 09618 if (!ast_strlen_zero(i->parkinglot)) 09619 ast_string_field_set(tmp, parkinglot, i->parkinglot); 09620 if (!ast_strlen_zero(i->language)) 09621 ast_string_field_set(tmp, language, i->language); 09622 if (!i->owner) 09623 i->owner = tmp; 09624 if (!ast_strlen_zero(i->accountcode)) 09625 ast_string_field_set(tmp, accountcode, i->accountcode); 09626 if (i->amaflags) 09627 tmp->amaflags = i->amaflags; 09628 i->subs[idx].owner = tmp; 09629 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 09630 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) { 09631 ast_string_field_set(tmp, call_forward, i->call_forward); 09632 } 09633 /* If we've been told "no ADSI" then enforce it */ 09634 if (!i->adsi) 09635 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 09636 if (!ast_strlen_zero(i->exten)) 09637 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 09638 if (!ast_strlen_zero(i->rdnis)) { 09639 tmp->redirecting.from.number.valid = 1; 09640 tmp->redirecting.from.number.str = ast_strdup(i->rdnis); 09641 } 09642 if (!ast_strlen_zero(i->dnid)) { 09643 tmp->dialed.number.str = ast_strdup(i->dnid); 09644 } 09645 09646 /* Don't use ast_set_callerid() here because it will 09647 * generate a needless NewCallerID event */ 09648 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09649 if (!ast_strlen_zero(i->cid_ani)) { 09650 tmp->caller.ani.number.valid = 1; 09651 tmp->caller.ani.number.str = ast_strdup(i->cid_ani); 09652 } else if (!ast_strlen_zero(i->cid_num)) { 09653 tmp->caller.ani.number.valid = 1; 09654 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09655 } 09656 #else 09657 if (!ast_strlen_zero(i->cid_num)) { 09658 tmp->caller.ani.number.valid = 1; 09659 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09660 } 09661 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09662 tmp->caller.id.name.presentation = i->callingpres; 09663 tmp->caller.id.number.presentation = i->callingpres; 09664 tmp->caller.id.number.plan = i->cid_ton; 09665 tmp->caller.ani2 = i->cid_ani2; 09666 tmp->caller.id.tag = ast_strdup(i->cid_tag); 09667 /* clear the fake event in case we posted one before we had ast_channel */ 09668 i->fake_event = 0; 09669 /* Assure there is no confmute on this channel */ 09670 dahdi_confmute(i, 0); 09671 i->muting = 0; 09672 /* Configure the new channel jb */ 09673 ast_jb_configure(tmp, &global_jbconf); 09674 09675 /* Set initial device state */ 09676 ast_copy_string(device_name, tmp->name, sizeof(device_name)); 09677 dashptr = strrchr(device_name, '-'); 09678 if (dashptr) { 09679 *dashptr = '\0'; 09680 } 09681 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name); 09682 09683 for (v = i->vars ; v ; v = v->next) 09684 pbx_builtin_setvar_helper(tmp, v->name, v->value); 09685 09686 ast_module_ref(ast_module_info->self); 09687 09688 dahdi_ami_channel_event(i, tmp); 09689 if (startpbx) { 09690 #ifdef HAVE_OPENR2 09691 if (i->mfcr2call) { 09692 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 09693 } 09694 #endif 09695 if (ast_pbx_start(tmp)) { 09696 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 09697 ast_hangup(tmp); 09698 return NULL; 09699 } 09700 } 09701 return tmp; 09702 }
static int dahdi_new_pri_nobch_channel | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 13182 of file chan_dahdi.c.
References CHAN_PSEUDO, sig_pri_span::numchans, and sig_pri_span::pvts.
13183 { 13184 int pvt_idx; 13185 int res; 13186 unsigned idx; 13187 struct dahdi_pvt *pvt; 13188 struct sig_pri_chan *chan; 13189 struct dahdi_bufferinfo bi; 13190 13191 static int nobch_channel = CHAN_PSEUDO; 13192 13193 /* Find spot in the private pointer array for new interface. */ 13194 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) { 13195 if (!pri->pvts[pvt_idx]) { 13196 break; 13197 } 13198 } 13199 if (pri->numchans == pvt_idx) { 13200 if (ARRAY_LEN(pri->pvts) <= pvt_idx) { 13201 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n"); 13202 return -1; 13203 } 13204 13205 /* Add new spot to the private pointer array. */ 13206 pri->pvts[pvt_idx] = NULL; 13207 ++pri->numchans; 13208 } 13209 13210 pvt = ast_calloc(1, sizeof(*pvt)); 13211 if (!pvt) { 13212 return -1; 13213 } 13214 pvt->cc_params = ast_cc_config_params_init(); 13215 if (!pvt->cc_params) { 13216 ast_free(pvt); 13217 return -1; 13218 } 13219 ast_mutex_init(&pvt->lock); 13220 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) { 13221 pvt->subs[idx].dfd = -1; 13222 } 13223 pvt->buf_no = dahdi_pseudo_parms.buf_no; 13224 pvt->buf_policy = dahdi_pseudo_parms.buf_policy; 13225 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no; 13226 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy; 13227 13228 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0); 13229 if (!chan) { 13230 destroy_dahdi_pvt(pvt); 13231 return -1; 13232 } 13233 chan->no_b_channel = 1; 13234 13235 /* 13236 * Pseudo channel companding law. 13237 * Needed for outgoing call waiting calls. 13238 * XXX May need to make this determined by switchtype or user option. 13239 */ 13240 pvt->law_default = DAHDI_LAW_ALAW; 13241 13242 pvt->sig = pri->sig; 13243 pvt->outsigmod = -1; 13244 pvt->pri = pri; 13245 pvt->sig_pvt = chan; 13246 pri->pvts[pvt_idx] = chan; 13247 13248 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13249 if (pvt->subs[SUB_REAL].dfd < 0) { 13250 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n", 13251 strerror(errno)); 13252 destroy_dahdi_pvt(pvt); 13253 return -1; 13254 } 13255 memset(&bi, 0, sizeof(bi)); 13256 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13257 if (!res) { 13258 pvt->bufsize = bi.bufsize; 13259 bi.txbufpolicy = pvt->buf_policy; 13260 bi.rxbufpolicy = pvt->buf_policy; 13261 bi.numbufs = pvt->buf_no; 13262 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13263 if (res < 0) { 13264 ast_log(LOG_WARNING, 13265 "Unable to set buffer policy on no B channel interface: %s\n", 13266 strerror(errno)); 13267 } 13268 } else 13269 ast_log(LOG_WARNING, 13270 "Unable to check buffer policy on no B channel interface: %s\n", 13271 strerror(errno)); 13272 13273 --nobch_channel; 13274 if (CHAN_PSEUDO < nobch_channel) { 13275 nobch_channel = CHAN_PSEUDO - 1; 13276 } 13277 pvt->channel = nobch_channel; 13278 pvt->span = pri->span; 13279 chan->channel = pvt->channel; 13280 13281 dahdi_nobch_insert(pri, pvt); 13282 13283 return pvt_idx; 13284 }
static void dahdi_nobch_extract | ( | struct sig_pri_span * | pri, | |
struct dahdi_pvt * | pvt | |||
) | [static] |
Definition at line 5583 of file chan_dahdi.c.
References DAHDI_IFLIST_NONE, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.
Referenced by destroy_dahdi_pvt().
05584 { 05585 /* Extract from the forward chain. */ 05586 if (pvt->prev) { 05587 pvt->prev->next = pvt->next; 05588 } else if (pri->no_b_chan_iflist == pvt) { 05589 /* Node is at the head of the list. */ 05590 pri->no_b_chan_iflist = pvt->next; 05591 } 05592 05593 /* Extract from the reverse chain. */ 05594 if (pvt->next) { 05595 pvt->next->prev = pvt->prev; 05596 } else if (pri->no_b_chan_end == pvt) { 05597 /* Node is at the end of the list. */ 05598 pri->no_b_chan_end = pvt->prev; 05599 } 05600 05601 /* Node is no longer in the list. */ 05602 pvt->which_iflist = DAHDI_IFLIST_NONE; 05603 pvt->prev = NULL; 05604 pvt->next = NULL; 05605 }
static void dahdi_nobch_insert | ( | struct sig_pri_span * | pri, | |
struct dahdi_pvt * | pvt | |||
) | [static] |
Definition at line 5530 of file chan_dahdi.c.
References dahdi_pvt::channel, DAHDI_IFLIST_NO_B_CHAN, dahdi_pvt::next, sig_pri_span::no_b_chan_end, sig_pri_span::no_b_chan_iflist, dahdi_pvt::prev, dahdi_pvt::pri, and dahdi_pvt::which_iflist.
05531 { 05532 struct dahdi_pvt *cur; 05533 05534 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN; 05535 05536 /* Find place in middle of list for the new interface. */ 05537 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) { 05538 if (pvt->channel < cur->channel) { 05539 /* New interface goes before the current interface. */ 05540 pvt->prev = cur->prev; 05541 pvt->next = cur; 05542 if (cur->prev) { 05543 /* Insert into the middle of the list. */ 05544 cur->prev->next = pvt; 05545 } else { 05546 /* Insert at head of list. */ 05547 pri->no_b_chan_iflist = pvt; 05548 } 05549 cur->prev = pvt; 05550 return; 05551 } 05552 } 05553 05554 /* New interface goes onto the end of the list */ 05555 pvt->prev = pri->no_b_chan_end; 05556 pvt->next = NULL; 05557 if (pri->no_b_chan_end) { 05558 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt; 05559 } 05560 pri->no_b_chan_end = pvt; 05561 if (!pri->no_b_chan_iflist) { 05562 /* List was empty */ 05563 pri->no_b_chan_iflist = pvt; 05564 } 05565 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 4250 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), and duplicate_pseudo().
04251 { 04252 int fd; 04253 int isnum; 04254 int chan = 0; 04255 int bs; 04256 int x; 04257 isnum = 1; 04258 for (x = 0; x < strlen(fn); x++) { 04259 if (!isdigit(fn[x])) { 04260 isnum = 0; 04261 break; 04262 } 04263 } 04264 if (isnum) { 04265 chan = atoi(fn); 04266 if (chan < 1) { 04267 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 04268 return -1; 04269 } 04270 fn = "/dev/dahdi/channel"; 04271 } 04272 fd = open(fn, O_RDWR | O_NONBLOCK); 04273 if (fd < 0) { 04274 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 04275 return -1; 04276 } 04277 if (chan) { 04278 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 04279 x = errno; 04280 close(fd); 04281 errno = x; 04282 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 04283 return -1; 04284 } 04285 } 04286 bs = READ_SIZE; 04287 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 04288 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 04289 x = errno; 04290 close(fd); 04291 errno = x; 04292 return -1; 04293 } 04294 return fd; 04295 }
static void dahdi_pri_cc_agent_destructor | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 16530 of file chan_dahdi.c.
References ast_module_unref(), and sig_pri_cc_agent_destructor().
16531 { 16532 sig_pri_cc_agent_destructor(agent); 16533 16534 ast_module_unref(ast_module_info->self); 16535 }
static int dahdi_pri_cc_agent_init | ( | struct ast_cc_agent * | agent, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 16486 of file chan_dahdi.c.
References ast_assert, ast_module_ref(), ast_module_unref(), dahdi_sig_pri_lib_handles(), dahdi_pvt::sig, sig_pri_cc_agent_init(), dahdi_pvt::sig_pvt, ast_channel::tech, ast_channel::tech_pvt, and ast_channel_tech::type.
16487 { 16488 struct dahdi_pvt *pvt; 16489 struct sig_pri_chan *pvt_chan; 16490 int res; 16491 16492 ast_assert(!strcmp(chan->tech->type, "DAHDI")); 16493 16494 pvt = chan->tech_pvt; 16495 if (dahdi_sig_pri_lib_handles(pvt->sig)) { 16496 pvt_chan = pvt->sig_pvt; 16497 } else { 16498 pvt_chan = NULL; 16499 } 16500 if (!pvt_chan) { 16501 return -1; 16502 } 16503 16504 ast_module_ref(ast_module_info->self); 16505 16506 res = sig_pri_cc_agent_init(agent, pvt_chan); 16507 if (res) { 16508 ast_module_unref(ast_module_info->self); 16509 } 16510 return res; 16511 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 14006 of file chan_dahdi.c.
References pris.
Referenced by load_module().
14007 { 14008 int x; 14009 int y; 14010 int dchan = -1; 14011 int span = -1; 14012 int dchancount = 0; 14013 14014 if (pri) { 14015 for (x = 0; x < NUM_SPANS; x++) { 14016 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 14017 if (pris[x].pri.dchans[y]) { 14018 dchancount++; 14019 } 14020 14021 if (pris[x].pri.dchans[y] == pri) { 14022 dchan = y; 14023 } 14024 } 14025 if (dchan >= 0) { 14026 span = x; 14027 break; 14028 } 14029 dchancount = 0; 14030 } 14031 if (-1 < span) { 14032 if (1 < dchancount) { 14033 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s); 14034 } else { 14035 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s); 14036 } 14037 } else { 14038 ast_log(LOG_ERROR, "PRI Span: ? %s", s); 14039 } 14040 } else { 14041 ast_log(LOG_ERROR, "PRI Span: ? %s", s); 14042 } 14043 14044 ast_mutex_lock(&pridebugfdlock); 14045 14046 if (pridebugfd >= 0) { 14047 if (write(pridebugfd, s, strlen(s)) < 0) { 14048 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 14049 } 14050 } 14051 14052 ast_mutex_unlock(&pridebugfdlock); 14053 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 13955 of file chan_dahdi.c.
References pris.
Referenced by load_module().
13956 { 13957 int x; 13958 int y; 13959 int dchan = -1; 13960 int span = -1; 13961 int dchancount = 0; 13962 13963 if (pri) { 13964 for (x = 0; x < NUM_SPANS; x++) { 13965 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 13966 if (pris[x].pri.dchans[y]) { 13967 dchancount++; 13968 } 13969 13970 if (pris[x].pri.dchans[y] == pri) { 13971 dchan = y; 13972 } 13973 } 13974 if (dchan >= 0) { 13975 span = x; 13976 break; 13977 } 13978 dchancount = 0; 13979 } 13980 if (-1 < span) { 13981 if (1 < dchancount) { 13982 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s); 13983 } else { 13984 ast_verbose("PRI Span: %d %s", span + 1, s); 13985 } 13986 } else { 13987 ast_verbose("PRI Span: ? %s", s); 13988 } 13989 } else { 13990 ast_verbose("PRI Span: ? %s", s); 13991 } 13992 13993 ast_mutex_lock(&pridebugfdlock); 13994 13995 if (pridebugfd >= 0) { 13996 if (write(pridebugfd, s, strlen(s)) < 0) { 13997 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 13998 } 13999 } 14000 14001 ast_mutex_unlock(&pridebugfdlock); 14002 }
static void dahdi_pri_update_span_devstate | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 3250 of file chan_dahdi.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_changed(), sig_pri_span::congestion_devstate, sig_pri_chan::inalarm, sig_pri_chan::no_b_channel, sig_pri_span::numchans, dahdi_pvt::pri, sig_pri_span::pvts, sig_pri_is_chan_available(), and sig_pri_span::span.
03251 { 03252 unsigned idx; 03253 unsigned num_b_chans; /* Number of B channels provisioned on the span. */ 03254 unsigned in_use; /* Number of B channels in use on the span. */ 03255 unsigned in_alarm; /* TRUE if the span is in alarm condition. */ 03256 enum ast_device_state new_state; 03257 03258 /* Count the number of B channels and the number of B channels in use. */ 03259 num_b_chans = 0; 03260 in_use = 0; 03261 in_alarm = 1; 03262 for (idx = pri->numchans; idx--;) { 03263 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) { 03264 /* This is a B channel interface. */ 03265 ++num_b_chans; 03266 if (!sig_pri_is_chan_available(pri->pvts[idx])) { 03267 ++in_use; 03268 } 03269 if (!pri->pvts[idx]->inalarm) { 03270 /* There is a channel that is not in alarm. */ 03271 in_alarm = 0; 03272 } 03273 } 03274 } 03275 03276 /* Update the span congestion device state and report any change. */ 03277 if (in_alarm) { 03278 new_state = AST_DEVICE_UNAVAILABLE; 03279 } else { 03280 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE; 03281 } 03282 if (pri->congestion_devstate != new_state) { 03283 pri->congestion_devstate = new_state; 03284 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span); 03285 } 03286 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 03287 /* Update the span threshold device state and report any change. */ 03288 if (in_alarm) { 03289 new_state = AST_DEVICE_UNAVAILABLE; 03290 } else if (!in_use) { 03291 new_state = AST_DEVICE_NOT_INUSE; 03292 } else if (!pri->user_busy_threshold) { 03293 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY; 03294 } else { 03295 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE 03296 : AST_DEVICE_BUSY; 03297 } 03298 if (pri->threshold_devstate != new_state) { 03299 pri->threshold_devstate = new_state; 03300 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span); 03301 } 03302 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 03303 }
static int dahdi_queryoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int * | datalen | |||
) | [static] |
Definition at line 6605 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_pri_cc_type, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, ast_channel::name, dahdi_pvt::sig, and ast_channel::tech_pvt.
06606 { 06607 char *cp; 06608 struct dahdi_pvt *p = chan->tech_pvt; 06609 06610 /* all supported options require data */ 06611 if (!p || !data || (*datalen < 1)) { 06612 errno = EINVAL; 06613 return -1; 06614 } 06615 06616 switch (option) { 06617 case AST_OPTION_DIGIT_DETECT: 06618 cp = (char *) data; 06619 *cp = p->ignoredtmf ? 0 : 1; 06620 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06621 break; 06622 case AST_OPTION_FAX_DETECT: 06623 cp = (char *) data; 06624 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1; 06625 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06626 break; 06627 case AST_OPTION_CC_AGENT_TYPE: 06628 #if defined(HAVE_PRI) 06629 #if defined(HAVE_PRI_CCSS) 06630 if (dahdi_sig_pri_lib_handles(p->sig)) { 06631 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen); 06632 break; 06633 } 06634 #endif /* defined(HAVE_PRI_CCSS) */ 06635 #endif /* defined(HAVE_PRI) */ 06636 return -1; 06637 default: 06638 return -1; 06639 } 06640 06641 errno = 0; 06642 06643 return 0; 06644 }
Definition at line 3744 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, and dahdi_pvt::owner.
Referenced by action_dahdidialoffhook().
03745 { 03746 for (;;) { 03747 if (p->owner) { 03748 if (ast_channel_trylock(p->owner)) { 03749 DEADLOCK_AVOIDANCE(&p->lock); 03750 } else { 03751 ast_queue_frame(p->owner, f); 03752 ast_channel_unlock(p->owner); 03753 break; 03754 } 03755 } else 03756 break; 03757 } 03758 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 4205 of file chan_dahdi.c.
References AST_ALAW.
04206 { 04207 return AST_ALAW(sample); 04208 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3774 of file chan_dahdi.c.
References ast_true(), dahdi_pvt::owner, pbx_builtin_getvar_helper(), and dahdi_pvt::r2chan.
Referenced by dahdi_answer(), and dahdi_r2_on_call_accepted().
03775 { 03776 int res = 0; 03777 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 03778 * and does not has support for openr2_chan_answer_call_with_mode 03779 * */ 03780 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 03781 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 03782 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 03783 if (!double_answer) { 03784 /* this still can result in double answer if the channel context 03785 * was configured that way */ 03786 res = openr2_chan_answer_call(p->r2chan); 03787 } else if (wants_double_answer) { 03788 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 03789 } else { 03790 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 03791 } 03792 #else 03793 res = openr2_chan_answer_call(p->r2chan); 03794 #endif 03795 return res; 03796 }
static int dahdi_r2_cause_to_ast_cause | ( | openr2_call_disconnect_cause_t | cause | ) | [static] |
Definition at line 4015 of file chan_dahdi.c.
References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, and AST_CAUSE_UNREGISTERED.
Referenced by dahdi_r2_on_call_disconnect().
04016 { 04017 switch (cause) { 04018 case OR2_CAUSE_BUSY_NUMBER: 04019 return AST_CAUSE_BUSY; 04020 case OR2_CAUSE_NETWORK_CONGESTION: 04021 return AST_CAUSE_CONGESTION; 04022 case OR2_CAUSE_OUT_OF_ORDER: 04023 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 04024 case OR2_CAUSE_UNALLOCATED_NUMBER: 04025 return AST_CAUSE_UNREGISTERED; 04026 case OR2_CAUSE_NO_ANSWER: 04027 return AST_CAUSE_NO_ANSWER; 04028 case OR2_CAUSE_NORMAL_CLEARING: 04029 return AST_CAUSE_NORMAL_CLEARING; 04030 case OR2_CAUSE_UNSPECIFIED: 04031 default: 04032 return AST_CAUSE_NOTDEFINED; 04033 } 04034 }
static void dahdi_r2_destroy_links | ( | void | ) | [static] |
Definition at line 12014 of file chan_dahdi.c.
References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.
Referenced by __unload_module(), and dahdi_restart().
12015 { 12016 int i = 0; 12017 if (!r2links) { 12018 return; 12019 } 12020 for (; i < r2links_count; i++) { 12021 if (r2links[i]->r2master != AST_PTHREADT_NULL) { 12022 pthread_cancel(r2links[i]->r2master); 12023 pthread_join(r2links[i]->r2master, NULL); 12024 openr2_context_delete(r2links[i]->protocol_context); 12025 } 12026 ast_free(r2links[i]); 12027 } 12028 ast_free(r2links); 12029 r2links = NULL; 12030 r2links_count = 0; 12031 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 3883 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mfcr2call, and dahdi_pvt::r2chan.
Referenced by dahdi_hangup(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_disconnect(), and dahdi_r2_on_call_offered().
03884 { 03885 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 03886 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 03887 p->channel, openr2_proto_get_disconnect_string(cause)); 03888 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 03889 openr2_chan_set_idle(p->r2chan); 03890 ast_mutex_lock(&p->lock); 03891 p->mfcr2call = 0; 03892 ast_mutex_unlock(&p->lock); 03893 } 03894 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3801 of file chan_dahdi.c.
References ast_debug, ast_log(), ast_strlen_zero(), LOG_WARNING, dahdi_pvt::mfcr2_category, ast_channel::name, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.
Referenced by dahdi_call().
03802 { 03803 openr2_calling_party_category_t cat; 03804 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 03805 struct dahdi_pvt *p = c->tech_pvt; 03806 if (ast_strlen_zero(catstr)) { 03807 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n", 03808 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 03809 return p->mfcr2_category; 03810 } 03811 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 03812 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 03813 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 03814 return p->mfcr2_category; 03815 } 03816 ast_debug(1, "Using category %s\n", catstr); 03817 return cat; 03818 }
static struct dahdi_mfcr2* dahdi_r2_get_link | ( | void | ) | [static] |
Definition at line 12034 of file chan_dahdi.c.
References ast_calloc, ast_free, ast_log(), AST_PTHREADT_NULL, ast_realloc, LOG_DEBUG, LOG_ERROR, dahdi_mfcr2::monitored_count, R2_LINK_CAPACITY, r2links, r2links_count, and dahdi_mfcr2::r2master.
12035 { 12036 struct dahdi_mfcr2 *new_r2link = NULL; 12037 struct dahdi_mfcr2 **new_r2links = NULL; 12038 /* this function is called just when starting up and no monitor threads have been launched, 12039 no need to lock monitored_count member */ 12040 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) { 12041 new_r2link = ast_calloc(1, sizeof(**r2links)); 12042 if (!new_r2link) { 12043 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n"); 12044 return NULL; 12045 } 12046 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links))); 12047 if (!new_r2links) { 12048 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n"); 12049 ast_free(new_r2link); 12050 return NULL; 12051 } 12052 r2links = new_r2links; 12053 new_r2link->r2master = AST_PTHREADT_NULL; 12054 r2links[r2links_count] = new_r2link; 12055 r2links_count++; 12056 ast_log(LOG_DEBUG, "Created new R2 link!\n"); 12057 } 12058 return r2links[r2links_count - 1]; 12059 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 4210 of file chan_dahdi.c.
References AST_LIN2A.
04211 { 04212 return AST_LIN2A(sample); 04213 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 4169 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
04170 { 04171 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04172 p->cid_num[p->mfcr2_ani_index] = digit; 04173 p->cid_name[p->mfcr2_ani_index] = digit; 04174 p->mfcr2_ani_index++; 04175 p->cid_num[p->mfcr2_ani_index] = 0; 04176 p->cid_name[p->mfcr2_ani_index] = 0; 04177 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4179 of file chan_dahdi.c.
References ast_verbose.
04180 { 04181 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 04182 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 3961 of file chan_dahdi.c.
References ast_log(), AST_STATE_RING, ast_verbose, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_new(), dahdi_r2_answer(), dahdi_r2_disconnect_call(), dahdi_pvt::dialing, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
03962 { 03963 struct dahdi_pvt *p = NULL; 03964 struct ast_channel *c = NULL; 03965 p = openr2_chan_get_client_data(r2chan); 03966 dahdi_enable_ec(p); 03967 p->mfcr2_call_accepted = 1; 03968 /* if it's an incoming call ... */ 03969 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 03970 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 03971 /* If accept on offer is not set, it means at this point the PBX thread is already 03972 launched (was launched in the 'on call offered' handler) and therefore this callback 03973 is being executed already in the PBX thread rather than the monitor thread, don't launch 03974 any other thread, just disable the openr2 reading and answer the call if needed */ 03975 if (!p->mfcr2_accept_on_offer) { 03976 openr2_chan_disable_read(r2chan); 03977 if (p->mfcr2_answer_pending) { 03978 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 03979 dahdi_r2_answer(p); 03980 } 03981 return; 03982 } 03983 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL); 03984 if (c) { 03985 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the 03986 library to forget about it */ 03987 openr2_chan_disable_read(r2chan); 03988 return; 03989 } 03990 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel); 03991 /* failed to create the channel, bail out and report it as an out of order line */ 03992 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 03993 return; 03994 } 03995 /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */ 03996 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel); 03997 p->subs[SUB_REAL].needringing = 1; 03998 p->dialing = 0; 03999 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */ 04000 openr2_chan_disable_read(r2chan); 04001 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4003 of file chan_dahdi.c.
References ast_verbose, dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
04004 { 04005 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04006 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan)); 04007 p->subs[SUB_REAL].needanswer = 1; 04008 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 4036 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_mutex_lock, ast_mutex_unlock, ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose, dahdi_r2_cause_to_ast_cause(), dahdi_r2_disconnect_call(), dahdi_pvt::lock, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.
04037 { 04038 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04039 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan)); 04040 ast_mutex_lock(&p->lock); 04041 if (!p->owner) { 04042 ast_mutex_unlock(&p->lock); 04043 /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */ 04044 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 04045 return; 04046 } 04047 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will 04048 be done in dahdi_hangup */ 04049 if (p->owner->_state == AST_STATE_UP) { 04050 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04051 ast_mutex_unlock(&p->lock); 04052 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 04053 /* being the forward side we must report what happened to the call to whoever requested it */ 04054 switch (cause) { 04055 case OR2_CAUSE_BUSY_NUMBER: 04056 p->subs[SUB_REAL].needbusy = 1; 04057 break; 04058 case OR2_CAUSE_NETWORK_CONGESTION: 04059 case OR2_CAUSE_OUT_OF_ORDER: 04060 case OR2_CAUSE_UNALLOCATED_NUMBER: 04061 case OR2_CAUSE_NO_ANSWER: 04062 case OR2_CAUSE_UNSPECIFIED: 04063 case OR2_CAUSE_NORMAL_CLEARING: 04064 p->subs[SUB_REAL].needcongestion = 1; 04065 break; 04066 default: 04067 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04068 } 04069 ast_mutex_unlock(&p->lock); 04070 } else { 04071 ast_mutex_unlock(&p->lock); 04072 /* being the backward side and not UP yet, we only need to request hangup */ 04073 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 04074 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause)); 04075 } 04076 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 3951 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, ast_verbose, dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
03952 { 03953 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03954 ast_verbose("MFC/R2 call end on channel %d\n", p->channel); 03955 ast_mutex_lock(&p->lock); 03956 p->mfcr2call = 0; 03957 ast_mutex_unlock(&p->lock); 03958 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 3820 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_answer_pending, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.
03821 { 03822 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03823 ast_mutex_lock(&p->lock); 03824 if (p->mfcr2call) { 03825 ast_mutex_unlock(&p->lock); 03826 /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same 03827 interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line, 03828 can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since 03829 the other end will see our seize as a forced release and drop the call, we will see an invalid 03830 pattern that will be seen and treated as protocol error. */ 03831 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 03832 return; 03833 } 03834 p->mfcr2call = 1; 03835 /* better safe than sorry ... */ 03836 p->cid_name[0] = '\0'; 03837 p->cid_num[0] = '\0'; 03838 p->cid_subaddr[0] = '\0'; 03839 p->rdnis[0] = '\0'; 03840 p->exten[0] = '\0'; 03841 p->mfcr2_ani_index = '\0'; 03842 p->mfcr2_dnis_index = '\0'; 03843 p->mfcr2_dnis_matched = 0; 03844 p->mfcr2_answer_pending = 0; 03845 p->mfcr2_call_accepted = 0; 03846 ast_mutex_unlock(&p->lock); 03847 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 03848 }
static void dahdi_r2_on_call_offered | ( | openr2_chan_t * | r2chan, | |
const char * | ani, | |||
const char * | dnis, | |||
openr2_calling_party_category_t | category | |||
) | [static] |
Definition at line 3896 of file chan_dahdi.c.
References ast_exists_extension(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RING, ast_verbose, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_new(), dahdi_r2_disconnect_call(), dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_recvd_category, SUB_REAL, and dahdi_pvt::use_callerid.
03897 { 03898 struct dahdi_pvt *p; 03899 struct ast_channel *c; 03900 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 03901 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, 03902 openr2_proto_get_category_string(category)); 03903 p = openr2_chan_get_client_data(r2chan); 03904 /* if collect calls are not allowed and this is a collect call, reject it! */ 03905 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 03906 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n"); 03907 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 03908 return; 03909 } 03910 ast_mutex_lock(&p->lock); 03911 p->mfcr2_recvd_category = category; 03912 /* if we're not supposed to use CID, clear whatever we have */ 03913 if (!p->use_callerid) { 03914 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 03915 p->cid_num[0] = 0; 03916 p->cid_name[0] = 0; 03917 } 03918 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 03919 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 03920 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 03921 p->exten[0] = 's'; 03922 p->exten[1] = 0; 03923 } 03924 ast_mutex_unlock(&p->lock); 03925 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 03926 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 03927 p->channel, p->exten, p->context); 03928 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 03929 return; 03930 } 03931 if (!p->mfcr2_accept_on_offer) { 03932 /* The user wants us to start the PBX thread right away without accepting the call first */ 03933 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL); 03934 if (c) { 03935 /* Done here, don't disable reading now since we still need to generate MF tones to accept 03936 the call or reject it and detect the tone off condition of the other end, all of this 03937 will be done in the PBX thread now */ 03938 return; 03939 } 03940 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel); 03941 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 03942 } else if (p->mfcr2_charge_calls) { 03943 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel); 03944 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 03945 } else { 03946 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel); 03947 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 03948 } 03949 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 4010 of file chan_dahdi.c.
04011 { 04012 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 04013 }
static void dahdi_r2_on_chan_log | ( | openr2_chan_t * | r2chan, | |
openr2_log_level_t | level, | |||
const char * | fmt, | |||
va_list | ap | |||
) | [static] |
Definition at line 4137 of file chan_dahdi.c.
References CHAN_TAG, and dahdi_r2_write_log().
04138 { 04139 #define CHAN_TAG "Chan " 04140 char logmsg[256]; 04141 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1]; 04142 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 04143 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg); 04144 dahdi_r2_write_log(level, completemsg); 04145 }
static void dahdi_r2_on_context_log | ( | openr2_context_t * | r2context, | |
openr2_log_level_t | level, | |||
const char * | fmt, | |||
va_list | ap | |||
) | [static] |
Definition at line 4124 of file chan_dahdi.c.
References CONTEXT_TAG, and dahdi_r2_write_log().
04125 { 04126 #define CONTEXT_TAG "Context - " 04127 char logmsg[256]; 04128 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1]; 04129 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 04130 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg); 04131 dahdi_r2_write_log(level, completemsg); 04132 #undef CONTEXT_TAG 04133 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 4147 of file chan_dahdi.c.
References ast_exists_extension(), ast_matchmore_extension(), dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, and dahdi_pvt::rdnis.
04148 { 04149 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04150 /* if 'immediate' is set, let's stop requesting DNIS */ 04151 if (p->immediate) { 04152 return 0; 04153 } 04154 p->exten[p->mfcr2_dnis_index] = digit; 04155 p->rdnis[p->mfcr2_dnis_index] = digit; 04156 p->mfcr2_dnis_index++; 04157 p->exten[p->mfcr2_dnis_index] = 0; 04158 p->rdnis[p->mfcr2_dnis_index] = 0; 04159 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 04160 if ((p->mfcr2_dnis_matched || 04161 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 04162 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 04163 return 0; 04164 } 04165 /* otherwise keep going */ 04166 return 1; 04167 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 3850 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, and dahdi_pvt::lock.
03851 { 03852 int res; 03853 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03854 ast_mutex_lock(&p->lock); 03855 p->inalarm = alarm ? 1 : 0; 03856 if (p->inalarm) { 03857 res = get_alarms(p); 03858 handle_alarms(p, res); 03859 } else { 03860 handle_clear_alarms(p); 03861 } 03862 ast_mutex_unlock(&p->lock); 03863 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4104 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.
04105 { 04106 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04107 ast_mutex_lock(&p->lock); 04108 p->remotelyblocked = 1; 04109 ast_mutex_unlock(&p->lock); 04110 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan)); 04111 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4113 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.
04114 { 04115 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04116 ast_mutex_lock(&p->lock); 04117 p->remotelyblocked = 0; 04118 ast_mutex_unlock(&p->lock); 04119 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 04120 }
static void dahdi_r2_on_os_error | ( | openr2_chan_t * | r2chan, | |
int | errorcode | |||
) | [static] |
static void dahdi_r2_on_protocol_error | ( | openr2_chan_t * | r2chan, | |
openr2_protocol_error_t | reason | |||
) | [static] |
Definition at line 3870 of file chan_dahdi.c.
References ast_channel::_softhangup, AST_CAUSE_PROTOCOL_ERROR, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_DEV, ast_channel::hangupcause, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2call, and dahdi_pvt::owner.
03871 { 03872 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03873 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 03874 if (p->owner) { 03875 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 03876 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03877 } 03878 ast_mutex_lock(&p->lock); 03879 p->mfcr2call = 0; 03880 ast_mutex_unlock(&p->lock); 03881 }
static int dahdi_r2_set_context | ( | struct dahdi_mfcr2 * | r2_link, | |
const struct dahdi_chan_conf * | conf | |||
) | [static] |
Definition at line 12061 of file chan_dahdi.c.
References ast_config_AST_LOG_DIR, ast_log(), ast_strlen_zero(), dahdi_mfcr2_conf::double_answer, dahdi_mfcr2_conf::get_ani_first, dahdi_mfcr2_conf::immediate_accept, LOG_ERROR, dahdi_mfcr2_conf::logdir, dahdi_mfcr2_conf::loglevel, dahdi_mfcr2_conf::max_ani, dahdi_mfcr2_conf::max_dnis, dahdi_mfcr2_conf::metering_pulse_timeout, dahdi_mfcr2_conf::mfback_timeout, dahdi_chan_conf::mfcr2, dahdi_mfcr2::monitored_count, dahdi_mfcr2::protocol_context, dahdi_mfcr2_conf::r2proto_file, and dahdi_mfcr2_conf::variant.
12062 { 12063 char tmplogdir[] = "/tmp"; 12064 char logdir[OR2_MAX_PATH]; 12065 int threshold = 0; 12066 int snres = 0; 12067 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 12068 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani, 12069 conf->mfcr2.max_dnis); 12070 if (!r2_link->protocol_context) { 12071 return -1; 12072 } 12073 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel); 12074 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first); 12075 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 12076 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request); 12077 #endif 12078 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold); 12079 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout); 12080 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout); 12081 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer); 12082 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept); 12083 if (ast_strlen_zero(conf->mfcr2.logdir)) { 12084 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) { 12085 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 12086 } 12087 } else { 12088 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir); 12089 if (snres >= sizeof(logdir)) { 12090 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 12091 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) { 12092 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 12093 } 12094 } else { 12095 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) { 12096 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 12097 } 12098 } 12099 } 12100 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) { 12101 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) { 12102 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file); 12103 } 12104 } 12105 r2_link->monitored_count = 0; 12106 return 0; 12107 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 4078 of file chan_dahdi.c.
References ast_log(), ast_verbose, LOG_DEBUG, LOG_ERROR, and LOG_WARNING.
Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().
04079 { 04080 switch (level) { 04081 case OR2_LOG_NOTICE: 04082 ast_verbose("%s", logmessage); 04083 break; 04084 case OR2_LOG_WARNING: 04085 ast_log(LOG_WARNING, "%s", logmessage); 04086 break; 04087 case OR2_LOG_ERROR: 04088 ast_log(LOG_ERROR, "%s", logmessage); 04089 break; 04090 case OR2_LOG_STACK_TRACE: 04091 case OR2_LOG_MF_TRACE: 04092 case OR2_LOG_CAS_TRACE: 04093 case OR2_LOG_DEBUG: 04094 case OR2_LOG_EX_DEBUG: 04095 ast_log(LOG_DEBUG, "%s", logmessage); 04096 break; 04097 default: 04098 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 04099 ast_log(LOG_DEBUG, "%s", logmessage); 04100 break; 04101 } 04102 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8800 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_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, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, ast_frame_subclass::integer, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_progress, mute, dahdi_pvt::muting, ast_channel::name, 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, sig_pri_span::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, 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.
08801 { 08802 struct dahdi_pvt *p; 08803 int res; 08804 int idx; 08805 void *readbuf; 08806 struct ast_frame *f; 08807 08808 /* 08809 * For analog channels, we must do deadlock avoidance because 08810 * analog ports can have more than one Asterisk channel using 08811 * the same private structure. 08812 */ 08813 p = ast->tech_pvt; 08814 while (ast_mutex_trylock(&p->lock)) { 08815 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08816 08817 /* 08818 * For PRI channels, we must refresh the private pointer because 08819 * the call could move to another B channel while the Asterisk 08820 * channel is unlocked. 08821 */ 08822 p = ast->tech_pvt; 08823 } 08824 08825 idx = dahdi_get_index(ast, p, 0); 08826 08827 /* Hang up if we don't really exist */ 08828 if (idx < 0) { 08829 ast_log(LOG_WARNING, "We don't exist?\n"); 08830 ast_mutex_unlock(&p->lock); 08831 return NULL; 08832 } 08833 08834 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 08835 ast_mutex_unlock(&p->lock); 08836 return NULL; 08837 } 08838 08839 p->subs[idx].f.frametype = AST_FRAME_NULL; 08840 p->subs[idx].f.datalen = 0; 08841 p->subs[idx].f.samples = 0; 08842 p->subs[idx].f.mallocd = 0; 08843 p->subs[idx].f.offset = 0; 08844 p->subs[idx].f.subclass.integer = 0; 08845 p->subs[idx].f.delivery = ast_tv(0,0); 08846 p->subs[idx].f.src = "dahdi_read"; 08847 p->subs[idx].f.data.ptr = NULL; 08848 08849 /* make sure it sends initial key state as first frame */ 08850 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 08851 { 08852 struct dahdi_params ps; 08853 08854 memset(&ps, 0, sizeof(ps)); 08855 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 08856 ast_mutex_unlock(&p->lock); 08857 return NULL; 08858 } 08859 p->firstradio = 1; 08860 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08861 if (ps.rxisoffhook) 08862 { 08863 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08864 } 08865 else 08866 { 08867 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08868 } 08869 ast_mutex_unlock(&p->lock); 08870 return &p->subs[idx].f; 08871 } 08872 if (p->ringt > 0) { 08873 if (!(--p->ringt)) { 08874 ast_mutex_unlock(&p->lock); 08875 return NULL; 08876 } 08877 } 08878 08879 #ifdef HAVE_OPENR2 08880 if (p->mfcr2) { 08881 openr2_chan_process_event(p->r2chan); 08882 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) { 08883 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, }; 08884 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING 08885 * now enqueue a progress frame to bridge the media up */ 08886 if (p->mfcr2_call_accepted && 08887 !p->mfcr2_progress && 08888 ast->_state == AST_STATE_RINGING) { 08889 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel); 08890 ast_queue_frame(p->owner, &f); 08891 p->mfcr2_progress = 1; 08892 } 08893 } 08894 } 08895 #endif 08896 08897 if (p->subs[idx].needringing) { 08898 /* Send ringing frame if requested */ 08899 p->subs[idx].needringing = 0; 08900 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08901 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING; 08902 ast_setstate(ast, AST_STATE_RINGING); 08903 ast_mutex_unlock(&p->lock); 08904 return &p->subs[idx].f; 08905 } 08906 08907 if (p->subs[idx].needbusy) { 08908 /* Send busy frame if requested */ 08909 p->subs[idx].needbusy = 0; 08910 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08911 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY; 08912 ast_mutex_unlock(&p->lock); 08913 return &p->subs[idx].f; 08914 } 08915 08916 if (p->subs[idx].needcongestion) { 08917 /* Send congestion frame if requested */ 08918 p->subs[idx].needcongestion = 0; 08919 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08920 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION; 08921 ast_mutex_unlock(&p->lock); 08922 return &p->subs[idx].f; 08923 } 08924 08925 if (p->subs[idx].needanswer) { 08926 /* Send answer frame if requested */ 08927 p->subs[idx].needanswer = 0; 08928 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08929 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08930 ast_mutex_unlock(&p->lock); 08931 return &p->subs[idx].f; 08932 } 08933 #ifdef HAVE_OPENR2 08934 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 08935 /* openr2 took care of reading and handling any event 08936 (needanswer, needbusy etc), if we continue we will read() 08937 twice, lets just return a null frame. This should only 08938 happen when openr2 is dialing out */ 08939 ast_mutex_unlock(&p->lock); 08940 return &ast_null_frame; 08941 } 08942 #endif 08943 08944 if (p->subs[idx].needflash) { 08945 /* Send answer frame if requested */ 08946 p->subs[idx].needflash = 0; 08947 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08948 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH; 08949 ast_mutex_unlock(&p->lock); 08950 return &p->subs[idx].f; 08951 } 08952 08953 if (p->subs[idx].needhold) { 08954 /* Send answer frame if requested */ 08955 p->subs[idx].needhold = 0; 08956 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08957 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD; 08958 ast_mutex_unlock(&p->lock); 08959 ast_debug(1, "Sending hold on '%s'\n", ast->name); 08960 return &p->subs[idx].f; 08961 } 08962 08963 if (p->subs[idx].needunhold) { 08964 /* Send answer frame if requested */ 08965 p->subs[idx].needunhold = 0; 08966 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08967 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD; 08968 ast_mutex_unlock(&p->lock); 08969 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 08970 return &p->subs[idx].f; 08971 } 08972 08973 /* 08974 * If we have a fake_event, fake an exception to handle it only 08975 * if this channel owns the private. 08976 */ 08977 if (p->fake_event && p->owner == ast) { 08978 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08979 struct analog_pvt *analog_p = p->sig_pvt; 08980 08981 f = analog_exception(analog_p, ast); 08982 } else { 08983 f = __dahdi_exception(ast); 08984 } 08985 ast_mutex_unlock(&p->lock); 08986 return f; 08987 } 08988 08989 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 08990 if (!p->subs[idx].linear) { 08991 p->subs[idx].linear = 1; 08992 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08993 if (res) 08994 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 08995 } 08996 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 08997 (ast->rawreadformat == AST_FORMAT_ALAW)) { 08998 if (p->subs[idx].linear) { 08999 p->subs[idx].linear = 0; 09000 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09001 if (res) 09002 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 09003 } 09004 } else { 09005 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 09006 ast_mutex_unlock(&p->lock); 09007 return NULL; 09008 } 09009 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 09010 CHECK_BLOCKING(ast); 09011 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09012 ast_clear_flag(ast, AST_FLAG_BLOCKING); 09013 /* Check for hangup */ 09014 if (res < 0) { 09015 f = NULL; 09016 if (res == -1) { 09017 if (errno == EAGAIN) { 09018 /* Return "NULL" frame if there is nobody there */ 09019 ast_mutex_unlock(&p->lock); 09020 return &p->subs[idx].f; 09021 } else if (errno == ELAST) { 09022 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09023 struct analog_pvt *analog_p = p->sig_pvt; 09024 f = analog_exception(analog_p, ast); 09025 } else { 09026 f = __dahdi_exception(ast); 09027 } 09028 } else 09029 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 09030 } 09031 ast_mutex_unlock(&p->lock); 09032 return f; 09033 } 09034 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 09035 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 09036 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09037 struct analog_pvt *analog_p = p->sig_pvt; 09038 f = analog_exception(analog_p, ast); 09039 } else { 09040 f = __dahdi_exception(ast); 09041 } 09042 ast_mutex_unlock(&p->lock); 09043 return f; 09044 } 09045 if (p->tdd) { /* if in TDD mode, see if we receive that */ 09046 int c; 09047 09048 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 09049 if (c < 0) { 09050 ast_debug(1,"tdd_feed failed\n"); 09051 ast_mutex_unlock(&p->lock); 09052 return NULL; 09053 } 09054 if (c) { /* if a char to return */ 09055 p->subs[idx].f.subclass.integer = 0; 09056 p->subs[idx].f.frametype = AST_FRAME_TEXT; 09057 p->subs[idx].f.mallocd = 0; 09058 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09059 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 09060 p->subs[idx].f.datalen = 1; 09061 *((char *) p->subs[idx].f.data.ptr) = c; 09062 ast_mutex_unlock(&p->lock); 09063 return &p->subs[idx].f; 09064 } 09065 } 09066 if (idx == SUB_REAL) { 09067 /* Ensure the CW timers decrement only on a single subchannel */ 09068 if (p->cidcwexpire) { 09069 if (!--p->cidcwexpire) { 09070 /* Expired CID/CW */ 09071 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 09072 restore_conference(p); 09073 } 09074 } 09075 if (p->cid_suppress_expire) { 09076 --p->cid_suppress_expire; 09077 } 09078 if (p->callwaitingrepeat) { 09079 if (!--p->callwaitingrepeat) { 09080 /* Expired, Repeat callwaiting tone */ 09081 ++p->callwaitrings; 09082 dahdi_callwait(ast); 09083 } 09084 } 09085 } 09086 if (p->subs[idx].linear) { 09087 p->subs[idx].f.datalen = READ_SIZE * 2; 09088 } else 09089 p->subs[idx].f.datalen = READ_SIZE; 09090 09091 /* Handle CallerID Transmission */ 09092 if ((p->owner == ast) && p->cidspill) { 09093 send_callerid(p); 09094 } 09095 09096 p->subs[idx].f.frametype = AST_FRAME_VOICE; 09097 p->subs[idx].f.subclass.codec = ast->rawreadformat; 09098 p->subs[idx].f.samples = READ_SIZE; 09099 p->subs[idx].f.mallocd = 0; 09100 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 09101 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 09102 #if 0 09103 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 09104 #endif 09105 if (p->dialing || p->radio || /* Transmitting something */ 09106 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 09107 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 09108 ) { 09109 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 09110 don't send anything */ 09111 p->subs[idx].f.frametype = AST_FRAME_NULL; 09112 p->subs[idx].f.subclass.integer = 0; 09113 p->subs[idx].f.samples = 0; 09114 p->subs[idx].f.mallocd = 0; 09115 p->subs[idx].f.offset = 0; 09116 p->subs[idx].f.data.ptr = NULL; 09117 p->subs[idx].f.datalen= 0; 09118 } 09119 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 09120 /* Perform busy detection etc on the dahdi line */ 09121 int mute; 09122 09123 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 09124 09125 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 09126 mute = ast_dsp_was_muted(p->dsp); 09127 if (p->muting != mute) { 09128 p->muting = mute; 09129 dahdi_confmute(p, mute); 09130 } 09131 09132 if (f) { 09133 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { 09134 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 09135 /* Treat this as a "hangup" instead of a "busy" on the assumption that 09136 a busy */ 09137 f = NULL; 09138 } 09139 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 09140 || f->frametype == AST_FRAME_DTMF_END) { 09141 #ifdef HAVE_PRI 09142 if (dahdi_sig_pri_lib_handles(p->sig) 09143 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 09144 && p->pri 09145 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 09146 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 09147 /* Don't accept in-band DTMF when in overlap dial mode */ 09148 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 09149 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 09150 f->subclass.integer, f->subclass.integer, ast->name); 09151 09152 f->frametype = AST_FRAME_NULL; 09153 f->subclass.integer = 0; 09154 } 09155 #endif 09156 /* DSP clears us of being pulse */ 09157 p->pulsedial = 0; 09158 } else if (p->waitingfordt.tv_sec) { 09159 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 09160 p->waitingfordt.tv_sec = 0; 09161 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 09162 f=NULL; 09163 } else if (f->frametype == AST_FRAME_VOICE) { 09164 f->frametype = AST_FRAME_NULL; 09165 f->subclass.integer = 0; 09166 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) { 09167 p->waitingfordt.tv_sec = 0; 09168 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 09169 ast_dsp_set_features(p->dsp, p->dsp_features); 09170 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 09171 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 09172 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 09173 if (res < 0) { 09174 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 09175 p->dop.dialstr[0] = '\0'; 09176 ast_mutex_unlock(&p->lock); 09177 return NULL; 09178 } else { 09179 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 09180 p->dialing = 1; 09181 p->dop.dialstr[0] = '\0'; 09182 p->dop.op = DAHDI_DIAL_OP_REPLACE; 09183 ast_setstate(ast, AST_STATE_DIALING); 09184 } 09185 } 09186 } 09187 } 09188 } 09189 } 09190 } else 09191 f = &p->subs[idx].f; 09192 09193 if (f) { 09194 switch (f->frametype) { 09195 case AST_FRAME_DTMF_BEGIN: 09196 case AST_FRAME_DTMF_END: 09197 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09198 analog_handle_dtmf(p->sig_pvt, ast, idx, &f); 09199 } else { 09200 dahdi_handle_dtmf(ast, idx, &f); 09201 } 09202 break; 09203 case AST_FRAME_VOICE: 09204 if (p->cidspill || p->cid_suppress_expire) { 09205 /* We are/were sending a caller id spill. Suppress any echo. */ 09206 p->subs[idx].f.frametype = AST_FRAME_NULL; 09207 p->subs[idx].f.subclass.integer = 0; 09208 p->subs[idx].f.samples = 0; 09209 p->subs[idx].f.mallocd = 0; 09210 p->subs[idx].f.offset = 0; 09211 p->subs[idx].f.data.ptr = NULL; 09212 p->subs[idx].f.datalen= 0; 09213 } 09214 break; 09215 default: 09216 break; 09217 } 09218 } 09219 09220 ast_mutex_unlock(&p->lock); 09221 return f; 09222 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 13517 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, ifend, iflist, iflock, is_group_or_channel_match(), ast_channel::linkedid, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2call, dahdi_pvt::next, sig_pri_span::num_call_waiting_calls, dahdi_pvt::oprmode, dahdi_starting_point::opt, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pvt::radio, restart_monitor(), round_robin, 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.
13518 { 13519 int callwait = 0; 13520 struct dahdi_pvt *p; 13521 struct ast_channel *tmp = NULL; 13522 struct dahdi_pvt *exitpvt; 13523 int channelmatched = 0; 13524 int groupmatched = 0; 13525 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13526 int transcapdigital = 0; 13527 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13528 struct dahdi_starting_point start; 13529 13530 ast_mutex_lock(&iflock); 13531 p = determine_starting_point(data, &start); 13532 if (!p) { 13533 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */ 13534 ast_mutex_unlock(&iflock); 13535 return NULL; 13536 } 13537 13538 /* Search for an unowned channel */ 13539 exitpvt = p; 13540 while (p && !tmp) { 13541 if (start.roundrobin) 13542 round_robin[start.rr_starting_point] = p; 13543 13544 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched) 13545 && available(&p, channelmatched)) { 13546 ast_debug(1, "Using channel %d\n", p->channel); 13547 13548 callwait = (p->owner != NULL); 13549 #ifdef HAVE_OPENR2 13550 if (p->mfcr2) { 13551 ast_mutex_lock(&p->lock); 13552 if (p->mfcr2call) { 13553 ast_mutex_unlock(&p->lock); 13554 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 13555 goto next; 13556 } 13557 p->mfcr2call = 1; 13558 ast_mutex_unlock(&p->lock); 13559 } 13560 #endif 13561 if (p->channel == CHAN_PSEUDO) { 13562 p = duplicate_pseudo(p); 13563 if (!p) { 13564 break; 13565 } 13566 } 13567 13568 p->distinctivering = 0; 13569 /* Make special notes */ 13570 switch (start.opt) { 13571 case '\0': 13572 /* No option present. */ 13573 break; 13574 case 'c': 13575 /* Confirm answer */ 13576 p->confirmanswer = 1; 13577 break; 13578 case 'r': 13579 /* Distinctive ring */ 13580 p->distinctivering = start.cadance; 13581 break; 13582 case 'd': 13583 #if defined(HAVE_PRI) || defined(HAVE_SS7) 13584 /* If this is an ISDN call, make it digital */ 13585 transcapdigital = AST_TRANS_CAP_DIGITAL; 13586 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 13587 break; 13588 default: 13589 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data); 13590 break; 13591 } 13592 13593 p->outgoing = 1; 13594 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 13595 tmp = analog_request(p->sig_pvt, &callwait, requestor); 13596 #ifdef HAVE_PRI 13597 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 13598 /* 13599 * We already have the B channel reserved for this call. We 13600 * just need to make sure that dahdi_hangup() has completed 13601 * cleaning up before continuing. 13602 */ 13603 ast_mutex_lock(&p->lock); 13604 ast_mutex_unlock(&p->lock); 13605 13606 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid, 13607 sizeof(p->dnid)); 13608 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital); 13609 #endif 13610 #if defined(HAVE_SS7) 13611 } else if (p->sig == SIG_SS7) { 13612 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital); 13613 #endif /* defined(HAVE_SS7) */ 13614 } else { 13615 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : ""); 13616 } 13617 if (!tmp) { 13618 p->outgoing = 0; 13619 #if defined(HAVE_PRI) 13620 switch (p->sig) { 13621 case SIG_PRI_LIB_HANDLE_CASES: 13622 #if defined(HAVE_PRI_CALL_WAITING) 13623 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) { 13624 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0; 13625 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); 13626 } 13627 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 13628 /* 13629 * This should be the last thing to clear when we are done with 13630 * the channel. 13631 */ 13632 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0; 13633 break; 13634 default: 13635 break; 13636 } 13637 #endif /* defined(HAVE_PRI) */ 13638 } else { 13639 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data); 13640 } 13641 break; 13642 } 13643 #ifdef HAVE_OPENR2 13644 next: 13645 #endif 13646 if (start.backwards) { 13647 p = p->prev; 13648 if (!p) 13649 p = ifend; 13650 } else { 13651 p = p->next; 13652 if (!p) 13653 p = iflist; 13654 } 13655 /* stop when you roll to the one that we started from */ 13656 if (p == exitpvt) 13657 break; 13658 } 13659 ast_mutex_unlock(&iflock); 13660 restart_monitor(); 13661 if (cause && !tmp) { 13662 if (callwait || channelmatched) { 13663 *cause = AST_CAUSE_BUSY; 13664 } else if (groupmatched) { 13665 *cause = AST_CAUSE_CONGESTION; 13666 } else { 13667 /* 13668 * We did not match any channel requested. 13669 * Dialplan error requesting non-existant channel? 13670 */ 13671 } 13672 } 13673 13674 return tmp; 13675 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 14952 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock, AST_PTHREADT_NULL, ast_verb, dahdi_r2_destroy_links(), dahdi_softhangup_all(), sig_pri_span::master, dahdi_pri::pri, dahdi_pvt::pri, pris, and restart_lock.
Referenced by action_dahdirestart(), and dahdi_restart_cmd().
14953 { 14954 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14955 int i, j; 14956 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 14957 int cancel_code; 14958 struct dahdi_pvt *p; 14959 14960 ast_mutex_lock(&restart_lock); 14961 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 14962 dahdi_softhangup_all(); 14963 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 14964 #ifdef HAVE_OPENR2 14965 dahdi_r2_destroy_links(); 14966 #endif 14967 14968 #if defined(HAVE_PRI) 14969 for (i = 0; i < NUM_SPANS; i++) { 14970 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 14971 cancel_code = pthread_cancel(pris[i].pri.master); 14972 pthread_kill(pris[i].pri.master, SIGURG); 14973 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); 14974 pthread_join(pris[i].pri.master, NULL); 14975 ast_debug(4, "Joined thread of span %d\n", i); 14976 } 14977 } 14978 #endif 14979 14980 #if defined(HAVE_SS7) 14981 for (i = 0; i < NUM_SPANS; i++) { 14982 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 14983 cancel_code = pthread_cancel(linksets[i].ss7.master); 14984 pthread_kill(linksets[i].ss7.master, SIGURG); 14985 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); 14986 pthread_join(linksets[i].ss7.master, NULL); 14987 ast_debug(4, "Joined thread of span %d\n", i); 14988 } 14989 } 14990 #endif /* defined(HAVE_SS7) */ 14991 14992 ast_mutex_lock(&monlock); 14993 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14994 cancel_code = pthread_cancel(monitor_thread); 14995 pthread_kill(monitor_thread, SIGURG); 14996 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 14997 pthread_join(monitor_thread, NULL); 14998 ast_debug(4, "Joined monitor thread\n"); 14999 } 15000 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 15001 15002 ast_mutex_lock(&ss_thread_lock); 15003 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 15004 int x = DAHDI_FLASH; 15005 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count); 15006 15007 ast_mutex_lock(&iflock); 15008 for (p = iflist; p; p = p->next) { 15009 if (p->owner) { 15010 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 15011 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 15012 } 15013 } 15014 ast_mutex_unlock(&iflock); 15015 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 15016 } 15017 15018 /* ensure any created channels before monitor threads were stopped are hungup */ 15019 dahdi_softhangup_all(); 15020 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 15021 destroy_all_channels(); 15022 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 15023 15024 ast_mutex_unlock(&monlock); 15025 15026 #ifdef HAVE_PRI 15027 for (i = 0; i < NUM_SPANS; i++) { 15028 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) 15029 dahdi_close_pri_fd(&(pris[i]), j); 15030 } 15031 15032 memset(pris, 0, sizeof(pris)); 15033 for (i = 0; i < NUM_SPANS; i++) { 15034 sig_pri_init_pri(&pris[i].pri); 15035 } 15036 pri_set_error(dahdi_pri_error); 15037 pri_set_message(dahdi_pri_message); 15038 #endif 15039 #if defined(HAVE_SS7) 15040 for (i = 0; i < NUM_SPANS; i++) { 15041 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) 15042 dahdi_close_ss7_fd(&(linksets[i]), j); 15043 } 15044 15045 memset(linksets, 0, sizeof(linksets)); 15046 for (i = 0; i < NUM_SPANS; i++) { 15047 sig_ss7_init_linkset(&linksets[i].ss7); 15048 } 15049 ss7_set_error(dahdi_ss7_error); 15050 ss7_set_message(dahdi_ss7_message); 15051 #endif /* defined(HAVE_SS7) */ 15052 15053 if (setup_dahdi(2) != 0) { 15054 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 15055 ast_mutex_unlock(&ss_thread_lock); 15056 return 1; 15057 } 15058 ast_mutex_unlock(&ss_thread_lock); 15059 ast_mutex_unlock(&restart_lock); 15060 return 0; 15061 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15063 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.
15064 { 15065 switch (cmd) { 15066 case CLI_INIT: 15067 e->command = "dahdi restart"; 15068 e->usage = 15069 "Usage: dahdi restart\n" 15070 " Restarts the DAHDI channels: destroys them all and then\n" 15071 " re-reads them from chan_dahdi.conf.\n" 15072 " Note that this will STOP any running CALL on DAHDI channels.\n" 15073 ""; 15074 return NULL; 15075 case CLI_GENERATE: 15076 return NULL; 15077 } 15078 if (a->argc != 2) 15079 return CLI_SHOWUSAGE; 15080 15081 if (dahdi_restart() != 0) 15082 return CLI_FAILURE; 15083 return CLI_SUCCESS; 15084 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7548 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_handle_event(), and my_ring().
07549 { 07550 int x; 07551 int res; 07552 /* Make sure our transmit state is on hook */ 07553 x = 0; 07554 x = DAHDI_ONHOOK; 07555 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07556 do { 07557 x = DAHDI_RING; 07558 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07559 if (res) { 07560 switch (errno) { 07561 case EBUSY: 07562 case EINTR: 07563 /* Wait just in case */ 07564 usleep(10000); 07565 continue; 07566 case EINPROGRESS: 07567 res = 0; 07568 break; 07569 default: 07570 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 07571 res = 0; 07572 } 07573 } 07574 } while (res); 07575 return res; 07576 }
static int dahdi_send_callrerouting_facility_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 5863 of file chan_dahdi.c.
References ast_channel::_state, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dahdi_tech, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pri_send_callrerouting_facility_exec(), dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, ast_channel::tech, and ast_channel::tech_pvt.
Referenced by load_module().
05864 { 05865 /* Data will be our digit string */ 05866 struct dahdi_pvt *pvt; 05867 char *parse; 05868 int res = -1; 05869 AST_DECLARE_APP_ARGS(args, 05870 AST_APP_ARG(destination); 05871 AST_APP_ARG(original); 05872 AST_APP_ARG(reason); 05873 ); 05874 05875 if (ast_strlen_zero(data)) { 05876 ast_log(LOG_DEBUG, "No data sent to application!\n"); 05877 return -1; 05878 } 05879 if (chan->tech != &dahdi_tech) { 05880 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 05881 return -1; 05882 } 05883 pvt = (struct dahdi_pvt *) chan->tech_pvt; 05884 if (!pvt) { 05885 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 05886 return -1; 05887 } 05888 switch (pvt->sig) { 05889 case SIG_PRI_LIB_HANDLE_CASES: 05890 break; 05891 default: 05892 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n", 05893 chan->name); 05894 return -1; 05895 } 05896 05897 parse = ast_strdupa(data); 05898 AST_STANDARD_APP_ARGS(args, parse); 05899 05900 if (ast_strlen_zero(args.destination)) { 05901 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n"); 05902 return -1; 05903 } 05904 05905 if (ast_strlen_zero(args.original)) { 05906 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n"); 05907 args.original = NULL; 05908 } 05909 05910 if (ast_strlen_zero(args.reason)) { 05911 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n"); 05912 args.reason = NULL; 05913 } 05914 05915 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination, 05916 args.original, args.reason); 05917 05918 return res; 05919 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
const char * | digits | |||
) | [static] |
Definition at line 5836 of file chan_dahdi.c.
References ast_debug, ast_strlen_zero(), pri_send_keypad_facility_exec(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.
Referenced by load_module().
05837 { 05838 /* Data will be our digit string */ 05839 struct dahdi_pvt *p; 05840 05841 if (ast_strlen_zero(digits)) { 05842 ast_debug(1, "No digit string sent to application!\n"); 05843 return -1; 05844 } 05845 05846 p = (struct dahdi_pvt *)chan->tech_pvt; 05847 05848 if (!p) { 05849 ast_debug(1, "Unable to find technology private\n"); 05850 return -1; 05851 } 05852 05853 pri_send_keypad_facility_exec(p->sig_pvt, digits); 05854 05855 return 0; 05856 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 18511 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(), 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.
18512 { 18513 #define END_SILENCE_LEN 400 18514 #define HEADER_MS 50 18515 #define TRAILER_MS 5 18516 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 18517 #define ASCII_BYTES_PER_CHAR 80 18518 18519 unsigned char *buf,*mybuf; 18520 struct dahdi_pvt *p = c->tech_pvt; 18521 struct pollfd fds[1]; 18522 int size,res,fd,len,x; 18523 int bytes=0; 18524 /* Initial carrier (imaginary) */ 18525 float cr = 1.0; 18526 float ci = 0.0; 18527 float scont = 0.0; 18528 int idx; 18529 18530 idx = dahdi_get_index(c, p, 0); 18531 if (idx < 0) { 18532 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 18533 return -1; 18534 } 18535 if (!text[0]) return(0); /* if nothing to send, don't */ 18536 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 18537 if (p->mate) 18538 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 18539 else 18540 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 18541 if (!buf) 18542 return -1; 18543 mybuf = buf; 18544 if (p->mate) { 18545 int codec = AST_LAW(p); 18546 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 18547 PUT_CLID_MARKMS; 18548 } 18549 /* Put actual message */ 18550 for (x = 0; text[x]; x++) { 18551 PUT_CLID(text[x]); 18552 } 18553 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 18554 PUT_CLID_MARKMS; 18555 } 18556 len = bytes; 18557 buf = mybuf; 18558 } else { 18559 len = tdd_generate(p->tdd, buf, text); 18560 if (len < 1) { 18561 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 18562 ast_free(mybuf); 18563 return -1; 18564 } 18565 } 18566 memset(buf + len, 0x7f, END_SILENCE_LEN); 18567 len += END_SILENCE_LEN; 18568 fd = p->subs[idx].dfd; 18569 while (len) { 18570 if (ast_check_hangup(c)) { 18571 ast_free(mybuf); 18572 return -1; 18573 } 18574 size = len; 18575 if (size > READ_SIZE) 18576 size = READ_SIZE; 18577 fds[0].fd = fd; 18578 fds[0].events = POLLOUT | POLLPRI; 18579 fds[0].revents = 0; 18580 res = poll(fds, 1, -1); 18581 if (!res) { 18582 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 18583 continue; 18584 } 18585 /* if got exception */ 18586 if (fds[0].revents & POLLPRI) { 18587 ast_free(mybuf); 18588 return -1; 18589 } 18590 if (!(fds[0].revents & POLLOUT)) { 18591 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 18592 continue; 18593 } 18594 res = write(fd, buf, size); 18595 if (res != size) { 18596 if (res == -1) { 18597 ast_free(mybuf); 18598 return -1; 18599 } 18600 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 18601 break; 18602 } 18603 len -= size; 18604 buf += size; 18605 } 18606 ast_free(mybuf); 18607 return(0); 18608 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15678 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, iflist, dahdi_pvt::next, and ast_cli_entry::usage.
15679 { 15680 int channel; 15681 int on; 15682 struct dahdi_pvt *dahdi_chan = NULL; 15683 15684 switch (cmd) { 15685 case CLI_INIT: 15686 e->command = "dahdi set dnd"; 15687 e->usage = 15688 "Usage: dahdi set dnd <chan#> <on|off>\n" 15689 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15690 " Changes take effect immediately.\n" 15691 " <chan num> is the channel number\n" 15692 " <on|off> Enable or disable DND mode?\n" 15693 ; 15694 return NULL; 15695 case CLI_GENERATE: 15696 return NULL; 15697 } 15698 15699 if (a->argc != 5) 15700 return CLI_SHOWUSAGE; 15701 15702 if ((channel = atoi(a->argv[3])) <= 0) { 15703 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 15704 return CLI_SHOWUSAGE; 15705 } 15706 15707 if (ast_true(a->argv[4])) 15708 on = 1; 15709 else if (ast_false(a->argv[4])) 15710 on = 0; 15711 else { 15712 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 15713 return CLI_SHOWUSAGE; 15714 } 15715 15716 ast_mutex_lock(&iflock); 15717 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 15718 if (dahdi_chan->channel != channel) 15719 continue; 15720 15721 /* Found the channel. Actually set it */ 15722 dahdi_dnd(dahdi_chan, on); 15723 break; 15724 } 15725 ast_mutex_unlock(&iflock); 15726 15727 if (!dahdi_chan) { 15728 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15729 return CLI_FAILURE; 15730 } 15731 15732 return CLI_SUCCESS; 15733 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 5096 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(), mwi_send_process_buffer(), mwi_send_process_event(), my_off_hook(), and my_on_hook().
05097 { 05098 int x, res; 05099 05100 x = hs; 05101 res = ioctl(fd, DAHDI_HOOK, &x); 05102 05103 if (res < 0) { 05104 if (errno == EINPROGRESS) 05105 return 0; 05106 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 05107 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 05108 } 05109 05110 return res; 05111 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15538 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, ast_cli_entry::command, errno, ast_cli_args::fd, iflist, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.
15539 { 15540 int channel; 15541 int gain; 15542 int tx; 15543 struct dahdi_hwgain hwgain; 15544 struct dahdi_pvt *tmp = NULL; 15545 15546 switch (cmd) { 15547 case CLI_INIT: 15548 e->command = "dahdi set hwgain"; 15549 e->usage = 15550 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 15551 " Sets the hardware gain on a a given channel, overriding the\n" 15552 " value provided at module loadtime, whether the channel is in\n" 15553 " use or not. Changes take effect immediately.\n" 15554 " <rx|tx> which direction do you want to change (relative to our module)\n" 15555 " <chan num> is the channel number relative to the device\n" 15556 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15557 return NULL; 15558 case CLI_GENERATE: 15559 return NULL; 15560 } 15561 15562 if (a->argc != 6) 15563 return CLI_SHOWUSAGE; 15564 15565 if (!strcasecmp("rx", a->argv[3])) 15566 tx = 0; /* rx */ 15567 else if (!strcasecmp("tx", a->argv[3])) 15568 tx = 1; /* tx */ 15569 else 15570 return CLI_SHOWUSAGE; 15571 15572 channel = atoi(a->argv[4]); 15573 gain = atof(a->argv[5])*10.0; 15574 15575 ast_mutex_lock(&iflock); 15576 15577 for (tmp = iflist; tmp; tmp = tmp->next) { 15578 15579 if (tmp->channel != channel) 15580 continue; 15581 15582 if (tmp->subs[SUB_REAL].dfd == -1) 15583 break; 15584 15585 hwgain.newgain = gain; 15586 hwgain.tx = tx; 15587 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15588 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15589 ast_mutex_unlock(&iflock); 15590 return CLI_FAILURE; 15591 } 15592 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15593 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15594 break; 15595 } 15596 15597 ast_mutex_unlock(&iflock); 15598 15599 if (tmp) 15600 return CLI_SUCCESS; 15601 15602 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15603 return CLI_FAILURE; 15604 15605 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15607 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, ast_cli_args::fd, iflist, 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.
15608 { 15609 int channel; 15610 float gain; 15611 int tx; 15612 int res; 15613 struct dahdi_pvt *tmp = NULL; 15614 15615 switch (cmd) { 15616 case CLI_INIT: 15617 e->command = "dahdi set swgain"; 15618 e->usage = 15619 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15620 " Sets the software gain on a a given channel, overriding the\n" 15621 " value provided at module loadtime, whether the channel is in\n" 15622 " use or not. Changes take effect immediately.\n" 15623 " <rx|tx> which direction do you want to change (relative to our module)\n" 15624 " <chan num> is the channel number relative to the device\n" 15625 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15626 return NULL; 15627 case CLI_GENERATE: 15628 return NULL; 15629 } 15630 15631 if (a->argc != 6) 15632 return CLI_SHOWUSAGE; 15633 15634 if (!strcasecmp("rx", a->argv[3])) 15635 tx = 0; /* rx */ 15636 else if (!strcasecmp("tx", a->argv[3])) 15637 tx = 1; /* tx */ 15638 else 15639 return CLI_SHOWUSAGE; 15640 15641 channel = atoi(a->argv[4]); 15642 gain = atof(a->argv[5]); 15643 15644 ast_mutex_lock(&iflock); 15645 for (tmp = iflist; tmp; tmp = tmp->next) { 15646 15647 if (tmp->channel != channel) 15648 continue; 15649 15650 if (tmp->subs[SUB_REAL].dfd == -1) 15651 break; 15652 15653 if (tx) 15654 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law); 15655 else 15656 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law); 15657 15658 if (res) { 15659 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15660 ast_mutex_unlock(&iflock); 15661 return CLI_FAILURE; 15662 } 15663 15664 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15665 tx ? "tx" : "rx", gain, channel); 15666 break; 15667 } 15668 ast_mutex_unlock(&iflock); 15669 15670 if (tmp) 15671 return CLI_SUCCESS; 15672 15673 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15674 return CLI_FAILURE; 15675 15676 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 2559 of file chan_dahdi.c.
Referenced by my_new_pri_ast_channel(), and my_pri_open_media().
02560 { 02561 int res; 02562 res = ioctl(dfd, DAHDI_SETLAW, &law); 02563 if (res) 02564 return res; 02565 return 0; 02566 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 4325 of file chan_dahdi.c.
Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), my_all_subchannels_hungup(), 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 6646 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, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, 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.
06647 { 06648 char *cp; 06649 signed char *scp; 06650 int x; 06651 int idx; 06652 struct dahdi_pvt *p = chan->tech_pvt, *pp; 06653 struct oprmode *oprmode; 06654 06655 06656 /* all supported options require data */ 06657 if (!p || !data || (datalen < 1)) { 06658 errno = EINVAL; 06659 return -1; 06660 } 06661 06662 switch (option) { 06663 case AST_OPTION_TXGAIN: 06664 scp = (signed char *) data; 06665 idx = dahdi_get_index(chan, p, 0); 06666 if (idx < 0) { 06667 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 06668 return -1; 06669 } 06670 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 06671 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law); 06672 case AST_OPTION_RXGAIN: 06673 scp = (signed char *) data; 06674 idx = dahdi_get_index(chan, p, 0); 06675 if (idx < 0) { 06676 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 06677 return -1; 06678 } 06679 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 06680 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law); 06681 case AST_OPTION_TONE_VERIFY: 06682 if (!p->dsp) 06683 break; 06684 cp = (char *) data; 06685 switch (*cp) { 06686 case 1: 06687 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 06688 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 06689 break; 06690 case 2: 06691 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 06692 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 06693 break; 06694 default: 06695 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 06696 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 06697 break; 06698 } 06699 break; 06700 case AST_OPTION_TDD: 06701 /* turn on or off TDD */ 06702 cp = (char *) data; 06703 p->mate = 0; 06704 if (!*cp) { /* turn it off */ 06705 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 06706 if (p->tdd) 06707 tdd_free(p->tdd); 06708 p->tdd = 0; 06709 break; 06710 } 06711 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 06712 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 06713 dahdi_disable_ec(p); 06714 /* otherwise, turn it on */ 06715 if (!p->didtdd) { /* if havent done it yet */ 06716 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 06717 unsigned char *buf; 06718 int size, res, fd, len; 06719 struct pollfd fds[1]; 06720 06721 buf = mybuf; 06722 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 06723 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 06724 len = 40000; 06725 idx = dahdi_get_index(chan, p, 0); 06726 if (idx < 0) { 06727 ast_log(LOG_WARNING, "No index in TDD?\n"); 06728 return -1; 06729 } 06730 fd = p->subs[idx].dfd; 06731 while (len) { 06732 if (ast_check_hangup(chan)) 06733 return -1; 06734 size = len; 06735 if (size > READ_SIZE) 06736 size = READ_SIZE; 06737 fds[0].fd = fd; 06738 fds[0].events = POLLPRI | POLLOUT; 06739 fds[0].revents = 0; 06740 res = poll(fds, 1, -1); 06741 if (!res) { 06742 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 06743 continue; 06744 } 06745 /* if got exception */ 06746 if (fds[0].revents & POLLPRI) 06747 return -1; 06748 if (!(fds[0].revents & POLLOUT)) { 06749 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 06750 continue; 06751 } 06752 res = write(fd, buf, size); 06753 if (res != size) { 06754 if (res == -1) return -1; 06755 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06756 break; 06757 } 06758 len -= size; 06759 buf += size; 06760 } 06761 p->didtdd = 1; /* set to have done it now */ 06762 } 06763 if (*cp == 2) { /* Mate mode */ 06764 if (p->tdd) 06765 tdd_free(p->tdd); 06766 p->tdd = 0; 06767 p->mate = 1; 06768 break; 06769 } 06770 if (!p->tdd) { /* if we don't have one yet */ 06771 p->tdd = tdd_new(); /* allocate one */ 06772 } 06773 break; 06774 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 06775 if (!p->dsp) 06776 break; 06777 cp = (char *) data; 06778 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 06779 *cp ? "ON" : "OFF", (int) *cp, chan->name); 06780 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 06781 break; 06782 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 06783 #if defined(HAVE_PRI) 06784 if (dahdi_sig_pri_lib_handles(p->sig) 06785 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 06786 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 06787 break; 06788 } 06789 #endif /* defined(HAVE_PRI) */ 06790 06791 cp = (char *) data; 06792 if (!*cp) { 06793 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 06794 x = 0; 06795 dahdi_disable_ec(p); 06796 } else { 06797 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 06798 x = 1; 06799 } 06800 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 06801 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 06802 break; 06803 case AST_OPTION_OPRMODE: /* Operator services mode */ 06804 oprmode = (struct oprmode *) data; 06805 /* We don't support operator mode across technologies */ 06806 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 06807 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 06808 chan->tech->type, oprmode->peer->tech->type); 06809 errno = EINVAL; 06810 return -1; 06811 } 06812 pp = oprmode->peer->tech_pvt; 06813 p->oprmode = pp->oprmode = 0; 06814 /* setup peers */ 06815 p->oprpeer = pp; 06816 pp->oprpeer = p; 06817 /* setup modes, if any */ 06818 if (oprmode->mode) 06819 { 06820 pp->oprmode = oprmode->mode; 06821 p->oprmode = -oprmode->mode; 06822 } 06823 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 06824 oprmode->mode, chan->name,oprmode->peer->name); 06825 break; 06826 case AST_OPTION_ECHOCAN: 06827 cp = (char *) data; 06828 if (*cp) { 06829 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name); 06830 dahdi_enable_ec(p); 06831 } else { 06832 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name); 06833 dahdi_disable_ec(p); 06834 } 06835 break; 06836 case AST_OPTION_DIGIT_DETECT: 06837 cp = (char *) data; 06838 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); 06839 if (*cp) { 06840 enable_dtmf_detect(p); 06841 } else { 06842 disable_dtmf_detect(p); 06843 } 06844 break; 06845 case AST_OPTION_FAX_DETECT: 06846 cp = (char *) data; 06847 if (p->dsp) { 06848 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name); 06849 if (*cp) { 06850 p->dsp_features |= DSP_FEATURE_FAX_DETECT; 06851 } else { 06852 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06853 } 06854 ast_dsp_set_features(p->dsp, p->dsp_features); 06855 } 06856 break; 06857 default: 06858 return -1; 06859 } 06860 errno = 0; 06861 06862 return 0; 06863 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15182 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_ton, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_dnd(), dahdi_pvt::destroy, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, HAVE_PRI_SUBADDR, dahdi_pvt::head, iflist, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::law_default, dahdi_subchannel::linear, dahdi_pvt::mailbox, dahdi_pvt::master, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_forced_release, ast_channel::name, ast_variable::name, ast_variable::next, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxdrc, dahdi_pvt::rxgain, S_OR, dahdi_pvt::sig, sig2str, 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.
15183 { 15184 int channel; 15185 struct dahdi_pvt *tmp = NULL; 15186 struct dahdi_confinfo ci; 15187 struct dahdi_params ps; 15188 int x; 15189 15190 switch (cmd) { 15191 case CLI_INIT: 15192 e->command = "dahdi show channel"; 15193 e->usage = 15194 "Usage: dahdi show channel <chan num>\n" 15195 " Detailed information about a given channel\n"; 15196 return NULL; 15197 case CLI_GENERATE: 15198 return NULL; 15199 } 15200 15201 if (a->argc != 4) 15202 return CLI_SHOWUSAGE; 15203 15204 channel = atoi(a->argv[3]); 15205 15206 ast_mutex_lock(&iflock); 15207 for (tmp = iflist; tmp; tmp = tmp->next) { 15208 if (tmp->channel == channel) { 15209 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 15210 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 15211 ast_cli(a->fd, "Span: %d\n", tmp->span); 15212 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 15213 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 15214 ast_cli(a->fd, "Context: %s\n", tmp->context); 15215 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 15216 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 15217 #if defined(HAVE_PRI) 15218 #if defined(HAVE_PRI_SUBADDR) 15219 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr); 15220 #endif /* defined(HAVE_PRI_SUBADDR) */ 15221 #endif /* defined(HAVE_PRI) */ 15222 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 15223 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 15224 if (tmp->vars) { 15225 struct ast_variable *v; 15226 ast_cli(a->fd, "Variables:\n"); 15227 for (v = tmp->vars ; v ; v = v->next) 15228 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 15229 } 15230 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 15231 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 15232 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 15233 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 15234 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 15235 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)" : ""); 15236 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)" : ""); 15237 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)" : ""); 15238 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 15239 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 15240 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 15241 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 15242 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 15243 if (tmp->busydetect) { 15244 #if defined(BUSYDETECT_TONEONLY) 15245 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 15246 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 15247 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 15248 #endif 15249 #ifdef BUSYDETECT_DEBUG 15250 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 15251 #endif 15252 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 15253 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 15254 } 15255 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 15256 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 15257 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 15258 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 15259 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 15260 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 15261 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain); 15262 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc); 15263 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no"); 15264 ast_cli(a->fd, "Echo Cancellation:\n"); 15265 15266 if (tmp->echocancel.head.tap_length) { 15267 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 15268 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 15269 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 15270 } 15271 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 15272 } else { 15273 ast_cli(a->fd, "\tnone\n"); 15274 } 15275 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 15276 if (tmp->master) 15277 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 15278 for (x = 0; x < MAX_SLAVES; x++) { 15279 if (tmp->slaves[x]) 15280 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 15281 } 15282 #ifdef HAVE_OPENR2 15283 if (tmp->mfcr2) { 15284 char calldir[OR2_MAX_PATH]; 15285 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 15286 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 15287 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 15288 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 15289 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 15290 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 15291 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 15292 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 15293 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 15294 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 15295 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 15296 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 15297 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 15298 #endif 15299 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 15300 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 15301 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 15302 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 15303 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 15304 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 15305 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 15306 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 15307 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 15308 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 15309 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 15310 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 15311 } 15312 #endif 15313 #if defined(HAVE_SS7) 15314 if (tmp->ss7) { 15315 struct sig_ss7_chan *chan = tmp->sig_pvt; 15316 15317 ast_cli(a->fd, "CIC: %d\n", chan->cic); 15318 } 15319 #endif /* defined(HAVE_SS7) */ 15320 #ifdef HAVE_PRI 15321 if (tmp->pri) { 15322 struct sig_pri_chan *chan = tmp->sig_pvt; 15323 15324 ast_cli(a->fd, "PRI Flags: "); 15325 if (chan->resetting) 15326 ast_cli(a->fd, "Resetting "); 15327 if (chan->call) 15328 ast_cli(a->fd, "Call "); 15329 if (chan->allocated) { 15330 ast_cli(a->fd, "Allocated "); 15331 } 15332 ast_cli(a->fd, "\n"); 15333 if (tmp->logicalspan) 15334 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 15335 else 15336 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 15337 } 15338 #endif 15339 memset(&ci, 0, sizeof(ci)); 15340 ps.channo = tmp->channel; 15341 if (tmp->subs[SUB_REAL].dfd > -1) { 15342 memset(&ci, 0, sizeof(ci)); 15343 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 15344 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 15345 } 15346 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 15347 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 15348 } 15349 memset(&ps, 0, sizeof(ps)); 15350 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 15351 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 15352 } else { 15353 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 15354 } 15355 } 15356 if (ISTRUNK(tmp)) { 15357 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 15358 if (!ast_strlen_zero(progzone)) 15359 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 15360 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 15361 if(tmp->busydetect) { 15362 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 15363 if(tmp->busytonelength > 0) { 15364 ast_cli(a->fd, "Busy Pattern:\n"); 15365 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 15366 if (tmp->busyquietlength > 0) 15367 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 15368 else 15369 ast_cli(a->fd, " -- Detect Tone Only\n"); 15370 if(tmp->busyfuzziness > 0) 15371 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 15372 } 15373 } 15374 } 15375 ast_mutex_unlock(&iflock); 15376 return CLI_SUCCESS; 15377 } 15378 } 15379 ast_mutex_unlock(&iflock); 15380 15381 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15382 return CLI_FAILURE; 15383 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15096 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT2, dahdi_pvt::group, iflist, dahdi_pvt::next, and ast_cli_entry::usage.
15097 { 15098 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15099 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 15100 unsigned int targetnum = 0; 15101 int filtertype = 0; 15102 struct dahdi_pvt *tmp = NULL; 15103 char tmps[20] = ""; 15104 char statestr[20] = ""; 15105 char blockstr[20] = ""; 15106 15107 switch (cmd) { 15108 case CLI_INIT: 15109 e->command = "dahdi show channels [group|context]"; 15110 e->usage = 15111 "Usage: dahdi show channels [ group <group> | context <context> ]\n" 15112 " Shows a list of available channels with optional filtering\n" 15113 " <group> must be a number between 0 and 63\n"; 15114 return NULL; 15115 case CLI_GENERATE: 15116 return NULL; 15117 } 15118 15119 /* syntax: dahdi show channels [ group <group> | context <context> ] */ 15120 15121 if (!((a->argc == 3) || (a->argc == 5))) 15122 return CLI_SHOWUSAGE; 15123 15124 if (a->argc == 5) { 15125 if (!strcasecmp(a->argv[3], "group")) { 15126 targetnum = atoi(a->argv[4]); 15127 if ((targetnum < 0) || (targetnum > 63)) 15128 return CLI_SHOWUSAGE; 15129 targetnum = 1 << targetnum; 15130 filtertype = 1; 15131 } else if (!strcasecmp(a->argv[3], "context")) { 15132 filtertype = 2; 15133 } 15134 } 15135 15136 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 15137 ast_mutex_lock(&iflock); 15138 for (tmp = iflist; tmp; tmp = tmp->next) { 15139 if (filtertype) { 15140 switch(filtertype) { 15141 case 1: /* dahdi show channels group <group> */ 15142 if (!(tmp->group & targetnum)) { 15143 continue; 15144 } 15145 break; 15146 case 2: /* dahdi show channels context <context> */ 15147 if (strcasecmp(tmp->context, a->argv[4])) { 15148 continue; 15149 } 15150 break; 15151 default: 15152 break; 15153 } 15154 } 15155 if (tmp->channel > 0) { 15156 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 15157 } else 15158 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 15159 15160 if (tmp->locallyblocked) 15161 blockstr[0] = 'L'; 15162 else 15163 blockstr[0] = ' '; 15164 15165 if (tmp->remotelyblocked) 15166 blockstr[1] = 'R'; 15167 else 15168 blockstr[1] = ' '; 15169 15170 blockstr[2] = '\0'; 15171 15172 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 15173 15174 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 15175 } 15176 ast_mutex_unlock(&iflock); 15177 return CLI_SUCCESS; 15178 #undef FORMAT 15179 #undef FORMAT2 15180 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15422 of file chan_dahdi.c.
References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, lbostr, and ast_cli_entry::usage.
15423 { 15424 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 15425 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 15426 int span; 15427 int res; 15428 char alarmstr[50]; 15429 15430 int ctl; 15431 struct dahdi_spaninfo s; 15432 15433 switch (cmd) { 15434 case CLI_INIT: 15435 e->command = "dahdi show status"; 15436 e->usage = 15437 "Usage: dahdi show status\n" 15438 " Shows a list of DAHDI cards with status\n"; 15439 return NULL; 15440 case CLI_GENERATE: 15441 return NULL; 15442 } 15443 ctl = open("/dev/dahdi/ctl", O_RDWR); 15444 if (ctl < 0) { 15445 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 15446 return CLI_FAILURE; 15447 } 15448 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO"); 15449 15450 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 15451 s.spanno = span; 15452 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 15453 if (res) { 15454 continue; 15455 } 15456 alarmstr[0] = '\0'; 15457 if (s.alarms > 0) { 15458 if (s.alarms & DAHDI_ALARM_BLUE) 15459 strcat(alarmstr, "BLU/"); 15460 if (s.alarms & DAHDI_ALARM_YELLOW) 15461 strcat(alarmstr, "YEL/"); 15462 if (s.alarms & DAHDI_ALARM_RED) 15463 strcat(alarmstr, "RED/"); 15464 if (s.alarms & DAHDI_ALARM_LOOPBACK) 15465 strcat(alarmstr, "LB/"); 15466 if (s.alarms & DAHDI_ALARM_RECOVER) 15467 strcat(alarmstr, "REC/"); 15468 if (s.alarms & DAHDI_ALARM_NOTOPEN) 15469 strcat(alarmstr, "NOP/"); 15470 if (!strlen(alarmstr)) 15471 strcat(alarmstr, "UUU/"); 15472 if (strlen(alarmstr)) { 15473 /* Strip trailing / */ 15474 alarmstr[strlen(alarmstr) - 1] = '\0'; 15475 } 15476 } else { 15477 if (s.numchans) 15478 strcpy(alarmstr, "OK"); 15479 else 15480 strcpy(alarmstr, "UNCONFIGURED"); 15481 } 15482 15483 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 15484 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 15485 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 15486 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 15487 "CAS", 15488 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 15489 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 15490 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 15491 "Unk", 15492 s.lineconfig & DAHDI_CONFIG_CRC4 ? 15493 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 15494 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "", 15495 lbostr[s.lbo] 15496 ); 15497 } 15498 close(ctl); 15499 15500 return CLI_SUCCESS; 15501 #undef FORMAT 15502 #undef FORMAT2 15503 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15505 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.
15506 { 15507 int pseudo_fd = -1; 15508 struct dahdi_versioninfo vi; 15509 15510 switch (cmd) { 15511 case CLI_INIT: 15512 e->command = "dahdi show version"; 15513 e->usage = 15514 "Usage: dahdi show version\n" 15515 " Shows the DAHDI version in use\n"; 15516 return NULL; 15517 case CLI_GENERATE: 15518 return NULL; 15519 } 15520 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 15521 ast_cli(a->fd, "Failed to open control file to get version.\n"); 15522 return CLI_SUCCESS; 15523 } 15524 15525 strcpy(vi.version, "Unknown"); 15526 strcpy(vi.echo_canceller, "Unknown"); 15527 15528 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 15529 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 15530 else 15531 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 15532 15533 close(pseudo_fd); 15534 15535 return CLI_SUCCESS; 15536 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 4546 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.
04547 { 04548 static char buf[256]; 04549 switch (sig) { 04550 case SIG_EM: 04551 return "E & M Immediate"; 04552 case SIG_EMWINK: 04553 return "E & M Wink"; 04554 case SIG_EM_E1: 04555 return "E & M E1"; 04556 case SIG_FEATD: 04557 return "Feature Group D (DTMF)"; 04558 case SIG_FEATDMF: 04559 return "Feature Group D (MF)"; 04560 case SIG_FEATDMF_TA: 04561 return "Feature Groud D (MF) Tandem Access"; 04562 case SIG_FEATB: 04563 return "Feature Group B (MF)"; 04564 case SIG_E911: 04565 return "E911 (MF)"; 04566 case SIG_FGC_CAMA: 04567 return "FGC/CAMA (Dialpulse)"; 04568 case SIG_FGC_CAMAMF: 04569 return "FGC/CAMA (MF)"; 04570 case SIG_FXSLS: 04571 return "FXS Loopstart"; 04572 case SIG_FXSGS: 04573 return "FXS Groundstart"; 04574 case SIG_FXSKS: 04575 return "FXS Kewlstart"; 04576 case SIG_FXOLS: 04577 return "FXO Loopstart"; 04578 case SIG_FXOGS: 04579 return "FXO Groundstart"; 04580 case SIG_FXOKS: 04581 return "FXO Kewlstart"; 04582 case SIG_PRI: 04583 return "ISDN PRI"; 04584 case SIG_BRI: 04585 return "ISDN BRI Point to Point"; 04586 case SIG_BRI_PTMP: 04587 return "ISDN BRI Point to MultiPoint"; 04588 case SIG_SS7: 04589 return "SS7"; 04590 case SIG_MFCR2: 04591 return "MFC/R2"; 04592 case SIG_SF: 04593 return "SF (Tone) Immediate"; 04594 case SIG_SFWINK: 04595 return "SF (Tone) Wink"; 04596 case SIG_SF_FEATD: 04597 return "SF (Tone) with Feature Group D (DTMF)"; 04598 case SIG_SF_FEATDMF: 04599 return "SF (Tone) with Feature Group D (MF)"; 04600 case SIG_SF_FEATB: 04601 return "SF (Tone) with Feature Group B (MF)"; 04602 case 0: 04603 return "Pseudo"; 04604 default: 04605 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 04606 return buf; 04607 } 04608 }
static int dahdi_sig_pri_lib_handles | ( | int | signaling | ) | [inline, static] |
Definition at line 1553 of file chan_dahdi.c.
References SIG_PRI_LIB_HANDLE_CASES.
Referenced by dahdi_bridge(), dahdi_call(), dahdi_cc_callback(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_pri_cc_agent_init(), dahdi_queryoption(), dahdi_read(), dahdi_request(), and dahdi_setoption().
01554 { 01555 int handles; 01556 01557 switch (signaling) { 01558 case SIG_PRI_LIB_HANDLE_CASES: 01559 handles = 1; 01560 break; 01561 default: 01562 handles = 0; 01563 break; 01564 } 01565 01566 return handles; 01567 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 14923 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, iflist, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, num_restart_pending, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
14924 { 14925 struct dahdi_pvt *p; 14926 retry: 14927 ast_mutex_lock(&iflock); 14928 for (p = iflist; p; p = p->next) { 14929 ast_mutex_lock(&p->lock); 14930 if (p->owner && !p->restartpending) { 14931 if (ast_channel_trylock(p->owner)) { 14932 if (option_debug > 2) 14933 ast_verbose("Avoiding deadlock\n"); 14934 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 14935 ast_mutex_unlock(&p->lock); 14936 ast_mutex_unlock(&iflock); 14937 goto retry; 14938 } 14939 if (option_debug > 2) 14940 ast_verbose("Softhanging up on %s\n", p->owner->name); 14941 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 14942 p->restartpending = 1; 14943 num_restart_pending++; 14944 ast_channel_unlock(p->owner); 14945 } 14946 ast_mutex_unlock(&p->lock); 14947 } 14948 ast_mutex_unlock(&iflock); 14949 }
static int dahdi_status_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18280 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 lbostr.
18282 { 18283 int ctl, res, span; 18284 struct ast_data *data_span, *data_alarms; 18285 struct dahdi_spaninfo s; 18286 18287 ctl = open("/dev/dahdi/ctl", O_RDWR); 18288 if (ctl < 0) { 18289 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 18290 return -1; 18291 } 18292 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 18293 s.spanno = span; 18294 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 18295 if (res) { 18296 continue; 18297 } 18298 18299 data_span = ast_data_add_node(data_root, "span"); 18300 if (!data_span) { 18301 continue; 18302 } 18303 ast_data_add_str(data_span, "description", s.desc); 18304 18305 /* insert the alarms status */ 18306 data_alarms = ast_data_add_node(data_span, "alarms"); 18307 if (!data_alarms) { 18308 continue; 18309 } 18310 18311 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE); 18312 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW); 18313 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED); 18314 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK); 18315 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER); 18316 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN); 18317 18318 ast_data_add_int(data_span, "irqmisses", s.irqmisses); 18319 ast_data_add_int(data_span, "bpviol", s.bpvcount); 18320 ast_data_add_int(data_span, "crc4", s.crc4count); 18321 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 18322 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 18323 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 18324 "CAS"); 18325 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 18326 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 18327 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 18328 "Unknown"); 18329 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ? 18330 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 18331 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : ""); 18332 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]); 18333 18334 /* if this span doesn't match remove it. */ 18335 if (!ast_data_search_match(search, data_span)) { 18336 ast_data_remove_node(data_root, data_span); 18337 } 18338 } 18339 close(ctl); 18340 18341 return 0; 18342 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4888 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), and my_train_echocanceller().
04889 { 04890 int x; 04891 int res; 04892 04893 if (p && p->echocanon && p->echotraining) { 04894 x = p->echotraining; 04895 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 04896 if (res) 04897 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 04898 else 04899 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 04900 } else { 04901 ast_debug(1, "No echo training requested\n"); 04902 } 04903 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 7078 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock, ast_mutex_trylock, dahdi_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pvt::master, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge(), and dahdi_fixup().
07079 { 07080 /* Unlink a specific slave or all slaves/masters from a given master */ 07081 int x; 07082 int hasslaves; 07083 if (!master) 07084 return; 07085 if (needlock) { 07086 ast_mutex_lock(&master->lock); 07087 if (slave) { 07088 while (ast_mutex_trylock(&slave->lock)) { 07089 DEADLOCK_AVOIDANCE(&master->lock); 07090 } 07091 } 07092 } 07093 hasslaves = 0; 07094 for (x = 0; x < MAX_SLAVES; x++) { 07095 if (master->slaves[x]) { 07096 if (!slave || (master->slaves[x] == slave)) { 07097 /* Take slave out of the conference */ 07098 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 07099 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 07100 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 07101 master->slaves[x]->master = NULL; 07102 master->slaves[x] = NULL; 07103 } else 07104 hasslaves = 1; 07105 } 07106 if (!hasslaves) 07107 master->inconference = 0; 07108 } 07109 if (!slave) { 07110 if (master->master) { 07111 /* Take master out of the conference */ 07112 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 07113 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 07114 hasslaves = 0; 07115 for (x = 0; x < MAX_SLAVES; x++) { 07116 if (master->master->slaves[x] == master) 07117 master->master->slaves[x] = NULL; 07118 else if (master->master->slaves[x]) 07119 hasslaves = 1; 07120 } 07121 if (!hasslaves) 07122 master->master->inconference = 0; 07123 } 07124 master->master = NULL; 07125 } 07126 update_conf(master); 07127 if (needlock) { 07128 if (slave) 07129 ast_mutex_unlock(&slave->lock); 07130 ast_mutex_unlock(&master->lock); 07131 } 07132 }
static void dahdi_unlink_pri_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5618 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::pri, sig_pri_span::pri, and dahdi_pvt::sig_pvt.
Referenced by destroy_dahdi_pvt().
05619 { 05620 unsigned idx; 05621 struct sig_pri_span *pri; 05622 05623 pri = pvt->pri; 05624 if (!pri) { 05625 /* Not PRI signaling so cannot be in a PRI private pointer array. */ 05626 return; 05627 } 05628 ast_mutex_lock(&pri->lock); 05629 for (idx = 0; idx < pri->numchans; ++idx) { 05630 if (pri->pvts[idx] == pvt->sig_pvt) { 05631 pri->pvts[idx] = NULL; 05632 ast_mutex_unlock(&pri->lock); 05633 return; 05634 } 05635 } 05636 ast_mutex_unlock(&pri->lock); 05637 }
static int dahdi_version_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 18383 of file chan_dahdi.c.
References ast_data_add_str(), ast_log(), and errno.
18385 { 18386 int pseudo_fd = -1; 18387 struct dahdi_versioninfo vi = { 18388 .version = "Unknown", 18389 .echo_canceller = "Unknown" 18390 }; 18391 18392 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 18393 ast_log(LOG_ERROR, "Failed to open control file to get version.\n"); 18394 return -1; 18395 } 18396 18397 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) { 18398 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno)); 18399 } 18400 18401 close(pseudo_fd); 18402 18403 ast_data_add_str(data_root, "value", vi.version); 18404 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller); 18405 18406 return 0; 18407 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 498 of file chan_dahdi.c.
00499 { 00500 int i, j = 0; 00501 i = DAHDI_IOMUX_SIGEVENT; 00502 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00503 return -1; 00504 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00505 return -1; 00506 return j; 00507 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 9724 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), and my_wink().
09725 { 09726 int j; 09727 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 09728 for (;;) 09729 { 09730 /* set bits of interest */ 09731 j = DAHDI_IOMUX_SIGEVENT; 09732 /* wait for some happening */ 09733 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 09734 /* exit loop if we have it */ 09735 if (j & DAHDI_IOMUX_SIGEVENT) break; 09736 } 09737 /* get the event info */ 09738 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 09739 return 0; 09740 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 9246 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, my_dahdi_write(), ast_channel::name, dahdi_pvt::owner, ast_frame::ptr, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
09247 { 09248 struct dahdi_pvt *p = ast->tech_pvt; 09249 int res; 09250 int idx; 09251 idx = dahdi_get_index(ast, p, 0); 09252 if (idx < 0) { 09253 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 09254 return -1; 09255 } 09256 09257 /* Write a frame of (presumably voice) data */ 09258 if (frame->frametype != AST_FRAME_VOICE) { 09259 if (frame->frametype != AST_FRAME_IMAGE) 09260 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 09261 return 0; 09262 } 09263 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && 09264 (frame->subclass.codec != AST_FORMAT_ULAW) && 09265 (frame->subclass.codec != AST_FORMAT_ALAW)) { 09266 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 09267 return -1; 09268 } 09269 if (p->dialing) { 09270 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 09271 return 0; 09272 } 09273 if (!p->owner) { 09274 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 09275 return 0; 09276 } 09277 if (p->cidspill) { 09278 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n", 09279 ast->name); 09280 return 0; 09281 } 09282 /* Return if it's not valid data */ 09283 if (!frame->data.ptr || !frame->datalen) 09284 return 0; 09285 09286 if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 09287 if (!p->subs[idx].linear) { 09288 p->subs[idx].linear = 1; 09289 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09290 if (res) 09291 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 09292 } 09293 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 09294 } else { 09295 /* x-law already */ 09296 if (p->subs[idx].linear) { 09297 p->subs[idx].linear = 0; 09298 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09299 if (res) 09300 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 09301 } 09302 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 09303 } 09304 if (res < 0) { 09305 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 09306 return -1; 09307 } 09308 return 0; 09309 }
static enum analog_event dahdievent_to_analogevent | ( | int | event | ) | [static] |
Definition at line 2704 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 my_get_callerid(), and my_get_event().
02705 { 02706 enum analog_event res; 02707 02708 switch (event) { 02709 case DAHDI_EVENT_ONHOOK: 02710 res = ANALOG_EVENT_ONHOOK; 02711 break; 02712 case DAHDI_EVENT_RINGOFFHOOK: 02713 res = ANALOG_EVENT_RINGOFFHOOK; 02714 break; 02715 case DAHDI_EVENT_WINKFLASH: 02716 res = ANALOG_EVENT_WINKFLASH; 02717 break; 02718 case DAHDI_EVENT_ALARM: 02719 res = ANALOG_EVENT_ALARM; 02720 break; 02721 case DAHDI_EVENT_NOALARM: 02722 res = ANALOG_EVENT_NOALARM; 02723 break; 02724 case DAHDI_EVENT_DIALCOMPLETE: 02725 res = ANALOG_EVENT_DIALCOMPLETE; 02726 break; 02727 case DAHDI_EVENT_RINGERON: 02728 res = ANALOG_EVENT_RINGERON; 02729 break; 02730 case DAHDI_EVENT_RINGEROFF: 02731 res = ANALOG_EVENT_RINGEROFF; 02732 break; 02733 case DAHDI_EVENT_HOOKCOMPLETE: 02734 res = ANALOG_EVENT_HOOKCOMPLETE; 02735 break; 02736 case DAHDI_EVENT_PULSE_START: 02737 res = ANALOG_EVENT_PULSE_START; 02738 break; 02739 case DAHDI_EVENT_POLARITY: 02740 res = ANALOG_EVENT_POLARITY; 02741 break; 02742 case DAHDI_EVENT_RINGBEGIN: 02743 res = ANALOG_EVENT_RINGBEGIN; 02744 break; 02745 case DAHDI_EVENT_EC_DISABLED: 02746 res = ANALOG_EVENT_EC_DISABLED; 02747 break; 02748 case DAHDI_EVENT_REMOVED: 02749 res = ANALOG_EVENT_REMOVED; 02750 break; 02751 case DAHDI_EVENT_NEONMWI_ACTIVE: 02752 res = ANALOG_EVENT_NEONMWI_ACTIVE; 02753 break; 02754 case DAHDI_EVENT_NEONMWI_INACTIVE: 02755 res = ANALOG_EVENT_NEONMWI_INACTIVE; 02756 break; 02757 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 02758 case DAHDI_EVENT_TX_CED_DETECTED: 02759 res = ANALOG_EVENT_TX_CED_DETECTED; 02760 break; 02761 case DAHDI_EVENT_RX_CED_DETECTED: 02762 res = ANALOG_EVENT_RX_CED_DETECTED; 02763 break; 02764 case DAHDI_EVENT_EC_NLP_DISABLED: 02765 res = ANALOG_EVENT_EC_NLP_DISABLED; 02766 break; 02767 case DAHDI_EVENT_EC_NLP_ENABLED: 02768 res = ANALOG_EVENT_EC_NLP_ENABLED; 02769 break; 02770 #endif 02771 case DAHDI_EVENT_PULSEDIGIT: 02772 res = ANALOG_EVENT_PULSEDIGIT; 02773 break; 02774 case DAHDI_EVENT_DTMFDOWN: 02775 res = ANALOG_EVENT_DTMFDOWN; 02776 break; 02777 case DAHDI_EVENT_DTMFUP: 02778 res = ANALOG_EVENT_DTMFUP; 02779 break; 02780 default: 02781 switch(event & 0xFFFF0000) { 02782 case DAHDI_EVENT_PULSEDIGIT: 02783 case DAHDI_EVENT_DTMFDOWN: 02784 case DAHDI_EVENT_DTMFUP: 02785 /* The event includes a digit number in the low word. 02786 * Converting it to a 'enum analog_event' would remove 02787 * that information. Thus it is returned as-is. 02788 */ 02789 return event; 02790 } 02791 02792 res = ANALOG_EVENT_ERROR; 02793 break; 02794 } 02795 02796 return res; 02797 }
static enum analog_sigtype dahdisig_to_analogsig | ( | int | sig | ) | [static] |
Definition at line 1569 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.
01570 { 01571 switch (sig) { 01572 case SIG_FXOLS: 01573 return ANALOG_SIG_FXOLS; 01574 case SIG_FXOGS: 01575 return ANALOG_SIG_FXOGS; 01576 case SIG_FXOKS: 01577 return ANALOG_SIG_FXOKS; 01578 case SIG_FXSLS: 01579 return ANALOG_SIG_FXSLS; 01580 case SIG_FXSGS: 01581 return ANALOG_SIG_FXSGS; 01582 case SIG_FXSKS: 01583 return ANALOG_SIG_FXSKS; 01584 case SIG_EMWINK: 01585 return ANALOG_SIG_EMWINK; 01586 case SIG_EM: 01587 return ANALOG_SIG_EM; 01588 case SIG_EM_E1: 01589 return ANALOG_SIG_EM_E1; 01590 case SIG_FEATD: 01591 return ANALOG_SIG_FEATD; 01592 case SIG_FEATDMF: 01593 return ANALOG_SIG_FEATDMF; 01594 case SIG_E911: 01595 return SIG_E911; 01596 case SIG_FGC_CAMA: 01597 return ANALOG_SIG_FGC_CAMA; 01598 case SIG_FGC_CAMAMF: 01599 return ANALOG_SIG_FGC_CAMAMF; 01600 case SIG_FEATB: 01601 return ANALOG_SIG_FEATB; 01602 case SIG_SFWINK: 01603 return ANALOG_SIG_SFWINK; 01604 case SIG_SF: 01605 return ANALOG_SIG_SF; 01606 case SIG_SF_FEATD: 01607 return ANALOG_SIG_SF_FEATD; 01608 case SIG_SF_FEATDMF: 01609 return ANALOG_SIG_SF_FEATDMF; 01610 case SIG_FEATDMF_TA: 01611 return ANALOG_SIG_FEATDMF_TA; 01612 case SIG_SF_FEATB: 01613 return ANALOG_SIG_FEATB; 01614 default: 01615 return -1; 01616 } 01617 }
static void deep_copy_dahdi_chan_conf | ( | struct dahdi_chan_conf * | dest, | |
const struct dahdi_chan_conf * | src | |||
) | [static] |
Definition at line 17945 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().
17946 { 17947 struct ast_cc_config_params *cc_params; 17948 17949 cc_params = dest->chan.cc_params; 17950 *dest = *src; 17951 dest->chan.cc_params = cc_params; 17952 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params); 17953 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 5771 of file chan_dahdi.c.
References ast_db_del(), ast_db_get(), ast_mutex_lock, ast_mutex_unlock, ast_verb, dahdi_pvt::channel, dahdi_db, destroy_dahdi_pvt(), ifcount, iflist, iflock, sig_pri_span::lock, sig_pri_span::no_b_chan_iflist, num_restart_pending, NUM_SPANS, dahdi_pri::pri, dahdi_pvt::pri, sig_pri_span::pri, pris, dahdi_pvt::span, and SRVST_DBKEY.
Referenced by __unload_module().
05772 { 05773 int chan; 05774 #if defined(HAVE_PRI) 05775 unsigned span; 05776 struct sig_pri_span *pri; 05777 #endif /* defined(HAVE_PRI) */ 05778 struct dahdi_pvt *p; 05779 05780 while (num_restart_pending) { 05781 usleep(1); 05782 } 05783 05784 ast_mutex_lock(&iflock); 05785 /* Destroy all the interfaces and free their memory */ 05786 while (iflist) { 05787 p = iflist; 05788 05789 chan = p->channel; 05790 #if defined(HAVE_PRI_SERVICE_MESSAGES) 05791 { 05792 char db_chan_name[20]; 05793 char db_answer[5]; 05794 char state; 05795 int why = -1; 05796 05797 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan); 05798 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 05799 sscanf(db_answer, "%1c:%30d", &state, &why); 05800 } 05801 if (!why) { 05802 /* SRVST persistence is not required */ 05803 ast_db_del(db_chan_name, SRVST_DBKEY); 05804 } 05805 } 05806 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 05807 /* Free associated memory */ 05808 destroy_dahdi_pvt(p); 05809 ast_verb(3, "Unregistered channel %d\n", chan); 05810 } 05811 ifcount = 0; 05812 ast_mutex_unlock(&iflock); 05813 05814 #if defined(HAVE_PRI) 05815 /* Destroy all of the no B channel interface lists */ 05816 for (span = 0; span < NUM_SPANS; ++span) { 05817 if (!pris[span].dchannels[0]) { 05818 break; 05819 } 05820 pri = &pris[span].pri; 05821 ast_mutex_lock(&pri->lock); 05822 while (pri->no_b_chan_iflist) { 05823 p = pri->no_b_chan_iflist; 05824 05825 /* Free associated memory */ 05826 destroy_dahdi_pvt(p); 05827 } 05828 ast_mutex_unlock(&pri->lock); 05829 } 05830 #endif /* defined(HAVE_PRI) */ 05831 }
static void destroy_channel | ( | struct dahdi_pvt * | cur, | |
int | now | |||
) | [static] |
Definition at line 5753 of file chan_dahdi.c.
References dahdi_subchannel::owner, dahdi_pvt::owner, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().
05754 { 05755 int i; 05756 05757 if (!now) { 05758 /* Do not destroy the channel now if it is owned by someone. */ 05759 if (cur->owner) { 05760 return; 05761 } 05762 for (i = 0; i < 3; i++) { 05763 if (cur->subs[i].owner) { 05764 return; 05765 } 05766 } 05767 } 05768 destroy_dahdi_pvt(cur); 05769 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5683 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_NO_B_CHAN, DAHDI_IFLIST_NONE, dahdi_nobch_extract(), dahdi_unlink_pri_pvt(), 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::pri, 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(), and duplicate_pseudo().
05684 { 05685 struct dahdi_pvt *p = pvt; 05686 05687 if (p->manages_span_alarms) { 05688 struct dahdi_pvt *next = find_next_iface_in_span(p); 05689 if (next) { 05690 next->manages_span_alarms = 1; 05691 } 05692 } 05693 05694 /* Remove channel from the list */ 05695 #if defined(HAVE_PRI) 05696 dahdi_unlink_pri_pvt(p); 05697 #endif /* defined(HAVE_PRI) */ 05698 #if defined(HAVE_SS7) 05699 dahdi_unlink_ss7_pvt(p); 05700 #endif /* defined(HAVE_SS7) */ 05701 switch (pvt->which_iflist) { 05702 case DAHDI_IFLIST_NONE: 05703 break; 05704 case DAHDI_IFLIST_MAIN: 05705 dahdi_iflist_extract(p); 05706 break; 05707 #if defined(HAVE_PRI) 05708 case DAHDI_IFLIST_NO_B_CHAN: 05709 if (p->pri) { 05710 dahdi_nobch_extract(p->pri, p); 05711 } 05712 break; 05713 #endif /* defined(HAVE_PRI) */ 05714 } 05715 05716 if (p->sig_pvt) { 05717 if (analog_lib_handles(p->sig, 0, 0)) { 05718 analog_delete(p->sig_pvt); 05719 } 05720 switch (p->sig) { 05721 #if defined(HAVE_PRI) 05722 case SIG_PRI_LIB_HANDLE_CASES: 05723 sig_pri_chan_delete(p->sig_pvt); 05724 break; 05725 #endif /* defined(HAVE_PRI) */ 05726 #if defined(HAVE_SS7) 05727 case SIG_SS7: 05728 sig_ss7_chan_delete(p->sig_pvt); 05729 break; 05730 #endif /* defined(HAVE_SS7) */ 05731 default: 05732 break; 05733 } 05734 } 05735 ast_free(p->cidspill); 05736 if (p->use_smdi) 05737 ast_smdi_interface_unref(p->smdi_iface); 05738 if (p->mwi_event_sub) 05739 ast_event_unsubscribe(p->mwi_event_sub); 05740 if (p->vars) { 05741 ast_variables_destroy(p->vars); 05742 } 05743 if (p->cc_params) { 05744 ast_cc_config_params_destroy(p->cc_params); 05745 } 05746 ast_mutex_destroy(&p->lock); 05747 dahdi_close_sub(p, SUB_REAL); 05748 if (p->owner) 05749 p->owner->tech_pvt = NULL; 05750 ast_free(p); 05751 }
static struct dahdi_pvt* determine_starting_point | ( | const char * | data, | |
struct dahdi_starting_point * | param | |||
) | [static] |
Definition at line 13356 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(), CHAN_PSEUDO, errno, ifend, iflist, dahdi_pvt::next, dahdi_pvt::prev, and round_robin.
Referenced by dahdi_cc_callback(), and dahdi_request().
13357 { 13358 char *dest; 13359 char *s; 13360 int x; 13361 int res = 0; 13362 struct dahdi_pvt *p; 13363 char *subdir = NULL; 13364 AST_DECLARE_APP_ARGS(args, 13365 AST_APP_ARG(group); /* channel/group token */ 13366 //AST_APP_ARG(ext); /* extension token */ 13367 //AST_APP_ARG(opts); /* options token */ 13368 AST_APP_ARG(other); /* Any remining unused arguments */ 13369 ); 13370 13371 /* 13372 * data is ---v 13373 * Dial(DAHDI/pseudo[/extension[/options]]) 13374 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]]) 13375 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]]) 13376 * Dial(DAHDI/i<span>[/extension[/options]]) 13377 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]) 13378 * 13379 * i - ISDN span channel restriction. 13380 * Used by CC to ensure that the CC recall goes out the same span. 13381 * Also to make ISDN channel names dialable when the sequence number 13382 * is stripped off. (Used by DTMF attended transfer feature.) 13383 * 13384 * g - channel group allocation search forward 13385 * G - channel group allocation search backward 13386 * r - channel group allocation round robin search forward 13387 * R - channel group allocation round robin search backward 13388 * 13389 * c - Wait for DTMF digit to confirm answer 13390 * r<cadance#> - Set distintive ring cadance number 13391 * d - Force bearer capability for ISDN/SS7 call to digital. 13392 */ 13393 13394 if (data) { 13395 dest = ast_strdupa(data); 13396 } else { 13397 ast_log(LOG_WARNING, "Channel requested with no data\n"); 13398 return NULL; 13399 } 13400 AST_NONSTANDARD_APP_ARGS(args, dest, '/'); 13401 if (!args.argc || ast_strlen_zero(args.group)) { 13402 ast_log(LOG_WARNING, "No channel/group specified\n"); 13403 return NULL; 13404 } 13405 13406 /* Initialize the output parameters */ 13407 memset(param, 0, sizeof(*param)); 13408 param->channelmatch = -1; 13409 13410 if (strchr(args.group, '!') != NULL) { 13411 char *prev = args.group; 13412 while ((s = strchr(prev, '!')) != NULL) { 13413 *s++ = '/'; 13414 prev = s; 13415 } 13416 *(prev - 1) = '\0'; 13417 subdir = args.group; 13418 args.group = prev; 13419 } else if (args.group[0] == 'i') { 13420 /* Extract the ISDN span channel restriction specifier. */ 13421 res = sscanf(args.group + 1, "%30d", &x); 13422 if (res < 1) { 13423 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data); 13424 return NULL; 13425 } 13426 param->span = x; 13427 13428 /* Remove the ISDN span channel restriction specifier. */ 13429 s = strchr(args.group, '-'); 13430 if (!s) { 13431 /* Search all groups since we are ISDN span restricted. */ 13432 return iflist; 13433 } 13434 args.group = s + 1; 13435 res = 0; 13436 } 13437 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { 13438 /* Retrieve the group number */ 13439 s = args.group + 1; 13440 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13441 if (res < 1) { 13442 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data); 13443 return NULL; 13444 } 13445 param->groupmatch = ((ast_group_t) 1 << x); 13446 13447 if (toupper(args.group[0]) == 'G') { 13448 if (args.group[0] == 'G') { 13449 param->backwards = 1; 13450 p = ifend; 13451 } else 13452 p = iflist; 13453 } else { 13454 if (ARRAY_LEN(round_robin) <= x) { 13455 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n", 13456 x, data); 13457 return NULL; 13458 } 13459 if (args.group[0] == 'R') { 13460 param->backwards = 1; 13461 p = round_robin[x] ? round_robin[x]->prev : ifend; 13462 if (!p) 13463 p = ifend; 13464 } else { 13465 p = round_robin[x] ? round_robin[x]->next : iflist; 13466 if (!p) 13467 p = iflist; 13468 } 13469 param->roundrobin = 1; 13470 param->rr_starting_point = x; 13471 } 13472 } else { 13473 s = args.group; 13474 if (!strcasecmp(s, "pseudo")) { 13475 /* Special case for pseudo */ 13476 x = CHAN_PSEUDO; 13477 param->channelmatch = x; 13478 } else { 13479 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13480 if (res < 1) { 13481 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data); 13482 return NULL; 13483 } else { 13484 param->channelmatch = x; 13485 } 13486 } 13487 if (subdir) { 13488 char path[PATH_MAX]; 13489 struct stat stbuf; 13490 13491 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d", 13492 subdir, param->channelmatch); 13493 if (stat(path, &stbuf) < 0) { 13494 ast_log(LOG_WARNING, "stat(%s) failed: %s\n", 13495 path, strerror(errno)); 13496 return NULL; 13497 } 13498 if (!S_ISCHR(stbuf.st_mode)) { 13499 ast_log(LOG_ERROR, "%s: Not a character device file\n", 13500 path); 13501 return NULL; 13502 } 13503 param->channelmatch = minor(stbuf.st_rdev); 13504 } 13505 13506 p = iflist; 13507 } 13508 13509 if (param->opt == 'r' && res < 3) { 13510 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data); 13511 param->opt = '\0'; 13512 } 13513 13514 return p; 13515 }
static int device2chan | ( | const char * | subdir, | |
int | channel, | |||
char * | path, | |||
int | pathlen | |||
) | [static] |
Definition at line 12132 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.
Referenced by build_channels().
12133 { 12134 struct stat stbuf; 12135 int num; 12136 12137 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel); 12138 if (stat(path, &stbuf) < 0) { 12139 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno)); 12140 return -errno; 12141 } 12142 if (!S_ISCHR(stbuf.st_mode)) { 12143 ast_log(LOG_ERROR, "%s: Not a character device file\n", path); 12144 return -EINVAL; 12145 } 12146 num = minor(stbuf.st_rdev); 12147 ast_log(LOG_DEBUG, "%s -> %d\n", path, num); 12148 return num; 12149 12150 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 4385 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
04386 { 04387 if (isdigit(digit)) 04388 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 04389 else if (digit >= 'A' && digit <= 'D') 04390 return DAHDI_TONE_DTMF_A + (digit - 'A'); 04391 else if (digit >= 'a' && digit <= 'd') 04392 return DAHDI_TONE_DTMF_A + (digit - 'a'); 04393 else if (digit == '*') 04394 return DAHDI_TONE_DTMF_s; 04395 else if (digit == '#') 04396 return DAHDI_TONE_DTMF_p; 04397 else 04398 return -1; 04399 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6574 of file chan_dahdi.c.
References ast_dsp_set_features(), 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().
06575 { 06576 int val = 0; 06577 06578 p->ignoredtmf = 1; 06579 06580 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06581 06582 if (!p->hardwaredtmf && p->dsp) { 06583 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 06584 ast_dsp_set_features(p->dsp, p->dsp_features); 06585 } 06586 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 11557 of file chan_dahdi.c.
References analog_lib_handles(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, ifcount, iflist, iflock, last, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::oprmode, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
11558 { 11559 int count, res, res2, spoint, pollres=0; 11560 struct dahdi_pvt *i; 11561 struct dahdi_pvt *last = NULL; 11562 struct dahdi_pvt *doomed; 11563 time_t thispass = 0, lastpass = 0; 11564 int found; 11565 char buf[1024]; 11566 struct pollfd *pfds=NULL; 11567 int lastalloc = -1; 11568 /* This thread monitors all the frame relay interfaces which are not yet in use 11569 (and thus do not have a separate thread) indefinitely */ 11570 /* From here on out, we die whenever asked */ 11571 #if 0 11572 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 11573 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 11574 return NULL; 11575 } 11576 ast_debug(1, "Monitor starting...\n"); 11577 #endif 11578 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11579 11580 for (;;) { 11581 /* Lock the interface list */ 11582 ast_mutex_lock(&iflock); 11583 if (!pfds || (lastalloc != ifcount)) { 11584 if (pfds) { 11585 ast_free(pfds); 11586 pfds = NULL; 11587 } 11588 if (ifcount) { 11589 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 11590 ast_mutex_unlock(&iflock); 11591 return NULL; 11592 } 11593 } 11594 lastalloc = ifcount; 11595 } 11596 /* Build the stuff we're going to poll on, that is the socket of every 11597 dahdi_pvt that does not have an associated owner channel */ 11598 count = 0; 11599 for (i = iflist; i; i = i->next) { 11600 ast_mutex_lock(&i->lock); 11601 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 11602 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11603 struct analog_pvt *p = i->sig_pvt; 11604 11605 if (!p) 11606 ast_log(LOG_ERROR, "No sig_pvt?\n"); 11607 11608 if (!p->owner && !p->subs[SUB_REAL].owner) { 11609 /* This needs to be watched, as it lacks an owner */ 11610 pfds[count].fd = i->subs[SUB_REAL].dfd; 11611 pfds[count].events = POLLPRI; 11612 pfds[count].revents = 0; 11613 /* Message waiting or r2 channels also get watched for reading */ 11614 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11615 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11616 pfds[count].events |= POLLIN; 11617 } 11618 count++; 11619 } 11620 } else { 11621 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 11622 /* This needs to be watched, as it lacks an owner */ 11623 pfds[count].fd = i->subs[SUB_REAL].dfd; 11624 pfds[count].events = POLLPRI; 11625 pfds[count].revents = 0; 11626 /* If we are monitoring for VMWI or sending CID, we need to 11627 read from the channel as well */ 11628 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11629 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11630 pfds[count].events |= POLLIN; 11631 } 11632 count++; 11633 } 11634 } 11635 } 11636 ast_mutex_unlock(&i->lock); 11637 } 11638 /* Okay, now that we know what to do, release the interface lock */ 11639 ast_mutex_unlock(&iflock); 11640 11641 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11642 pthread_testcancel(); 11643 /* Wait at least a second for something to happen */ 11644 res = poll(pfds, count, 1000); 11645 pthread_testcancel(); 11646 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11647 11648 /* Okay, poll has finished. Let's see what happened. */ 11649 if (res < 0) { 11650 if ((errno != EAGAIN) && (errno != EINTR)) 11651 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 11652 continue; 11653 } 11654 /* Alright, lock the interface list again, and let's look and see what has 11655 happened */ 11656 ast_mutex_lock(&iflock); 11657 found = 0; 11658 spoint = 0; 11659 lastpass = thispass; 11660 thispass = time(NULL); 11661 doomed = NULL; 11662 for (i = iflist;; i = i->next) { 11663 if (doomed) { 11664 int res; 11665 res = dahdi_destroy_channel_bynum(doomed->channel); 11666 if (res != RESULT_SUCCESS) { 11667 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 11668 } 11669 doomed = NULL; 11670 } 11671 if (!i) { 11672 break; 11673 } 11674 11675 if (thispass != lastpass) { 11676 if (!found && ((i == last) || ((i == iflist) && !last))) { 11677 last = i; 11678 if (last) { 11679 struct analog_pvt *analog_p = last->sig_pvt; 11680 /* Only allow MWI to be initiated on a quiescent fxs port */ 11681 if (analog_p 11682 && !last->mwisendactive 11683 && (last->sig & __DAHDI_SIG_FXO) 11684 && !analog_p->fxsoffhookstate 11685 && !last->owner 11686 && !ast_strlen_zero(last->mailbox) 11687 && (thispass - analog_p->onhooktime > 3)) { 11688 res = has_voicemail(last); 11689 if (analog_p->msgstate != res) { 11690 /* Set driver resources for signalling VMWI */ 11691 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 11692 if (res2) { 11693 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 11694 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 11695 } 11696 /* If enabled for FSK spill then initiate it */ 11697 if (mwi_send_init(last)) { 11698 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 11699 } 11700 analog_p->msgstate = res; 11701 found ++; 11702 } 11703 } 11704 last = last->next; 11705 } 11706 } 11707 } 11708 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 11709 if (i->radio && !i->owner) 11710 { 11711 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11712 if (res) 11713 { 11714 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 11715 /* Don't hold iflock while handling init events */ 11716 ast_mutex_unlock(&iflock); 11717 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11718 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11719 else 11720 doomed = handle_init_event(i, res); 11721 ast_mutex_lock(&iflock); 11722 } 11723 continue; 11724 } 11725 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 11726 if (pollres & POLLIN) { 11727 if (i->owner || i->subs[SUB_REAL].owner) { 11728 #ifdef HAVE_PRI 11729 if (!i->pri) 11730 #endif 11731 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 11732 continue; 11733 } 11734 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { 11735 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 11736 continue; 11737 } 11738 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 11739 if (res > 0) { 11740 if (i->mwimonitor_fsk) { 11741 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 11742 pthread_attr_t attr; 11743 pthread_t threadid; 11744 struct mwi_thread_data *mtd; 11745 11746 pthread_attr_init(&attr); 11747 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11748 11749 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 11750 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 11751 mtd->pvt = i; 11752 memcpy(mtd->buf, buf, res); 11753 mtd->len = res; 11754 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 11755 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 11756 ast_free(mtd); 11757 } 11758 i->mwimonitoractive = 1; 11759 } 11760 } 11761 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 11762 } else if (i->cid_start == CID_START_DTMF_NOALERT) { 11763 int energy; 11764 struct timeval now; 11765 /* State machine dtmfcid_holdoff_state allows for the line to settle 11766 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 11767 */ 11768 if (1 == i->dtmfcid_holdoff_state) { 11769 gettimeofday(&i->dtmfcid_delay, NULL); 11770 i->dtmfcid_holdoff_state = 2; 11771 } else if (2 == i->dtmfcid_holdoff_state) { 11772 gettimeofday(&now, NULL); 11773 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 11774 i->dtmfcid_holdoff_state = 0; 11775 } 11776 } else { 11777 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 11778 if (!i->mwisendactive && energy > dtmfcid_level) { 11779 pthread_t threadid; 11780 struct ast_channel *chan; 11781 ast_mutex_unlock(&iflock); 11782 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11783 /* just in case this event changes or somehow destroys a channel, set doomed here too */ 11784 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); 11785 i->dtmfcid_holdoff_state = 1; 11786 } else { 11787 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11788 if (!chan) { 11789 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11790 } else { 11791 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11792 if (res) { 11793 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11794 } else { 11795 i->dtmfcid_holdoff_state = 1; 11796 } 11797 } 11798 } 11799 ast_mutex_lock(&iflock); 11800 } 11801 } 11802 } 11803 if (i->mwisendactive) { 11804 mwi_send_process_buffer(i, res); 11805 } 11806 } else { 11807 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 11808 } 11809 } 11810 if (pollres & POLLPRI) { 11811 if (i->owner || i->subs[SUB_REAL].owner) { 11812 #ifdef HAVE_PRI 11813 if (!i->pri) 11814 #endif 11815 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 11816 continue; 11817 } 11818 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11819 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 11820 /* Don't hold iflock while handling init events */ 11821 ast_mutex_unlock(&iflock); 11822 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 11823 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11824 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11825 else 11826 doomed = handle_init_event(i, res); 11827 } 11828 ast_mutex_lock(&iflock); 11829 } 11830 } 11831 } 11832 ast_mutex_unlock(&iflock); 11833 } 11834 /* Never reached */ 11835 return NULL; 11836 11837 }
static int drc_sample | ( | int | sample, | |
float | drc | |||
) | [static] |
Definition at line 4924 of file chan_dahdi.c.
Referenced by fill_rxgain(), and fill_txgain().
04925 { 04926 float neg; 04927 float shallow, steep; 04928 float max = SHRT_MAX; 04929 04930 neg = (sample < 0 ? -1 : 1); 04931 steep = drc*sample; 04932 shallow = neg*(max-max/drc)+(float)sample/drc; 04933 if (abs(steep) < abs(shallow)) { 04934 sample = steep; 04935 } 04936 else { 04937 sample = shallow; 04938 } 04939 04940 return sample; 04941 }
Definition at line 13292 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(), destroy_dahdi_pvt(), errno, and SUB_REAL.
Referenced by dahdi_request().
13293 { 13294 struct dahdi_pvt *p; 13295 struct dahdi_bufferinfo bi; 13296 int res; 13297 13298 p = ast_malloc(sizeof(*p)); 13299 if (!p) { 13300 return NULL; 13301 } 13302 *p = *src; 13303 13304 /* Must deep copy the cc_params. */ 13305 p->cc_params = ast_cc_config_params_init(); 13306 if (!p->cc_params) { 13307 ast_free(p); 13308 return NULL; 13309 } 13310 ast_cc_copy_config_params(p->cc_params, src->cc_params); 13311 13312 p->which_iflist = DAHDI_IFLIST_NONE; 13313 p->next = NULL; 13314 p->prev = NULL; 13315 ast_mutex_init(&p->lock); 13316 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13317 if (p->subs[SUB_REAL].dfd < 0) { 13318 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 13319 destroy_dahdi_pvt(p); 13320 return NULL; 13321 } 13322 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13323 if (!res) { 13324 bi.txbufpolicy = src->buf_policy; 13325 bi.rxbufpolicy = src->buf_policy; 13326 bi.numbufs = src->buf_no; 13327 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13328 if (res < 0) { 13329 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 13330 } 13331 } else 13332 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 13333 p->destroy = 1; 13334 dahdi_iflist_insert(p); 13335 return p; 13336 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6588 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, 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().
06589 { 06590 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06591 06592 if (p->channel == CHAN_PSEUDO) 06593 return; 06594 06595 p->ignoredtmf = 0; 06596 06597 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06598 06599 if (!p->hardwaredtmf && p->dsp) { 06600 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 06601 ast_dsp_set_features(p->dsp, p->dsp_features); 06602 } 06603 }
static const char * event2str | ( | int | event | ) | [static] |
Definition at line 4537 of file chan_dahdi.c.
References ARRAY_LEN.
Referenced by __dahdi_exception(), analog_ss_thread(), dahdi_handle_event(), mwi_thread(), my_distinctive_ring(), and my_handle_dchan_exception().
04538 { 04539 static char buf[256]; 04540 if ((event < (ARRAY_LEN(events))) && (event > -1)) 04541 return events[event]; 04542 sprintf(buf, "Event %d", event); /* safe */ 04543 return buf; 04544 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4988 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_rxgain().
04989 { 04990 int j; 04991 int k; 04992 float linear_gain = pow(10.0, gain / 20.0); 04993 04994 switch (law) { 04995 case DAHDI_LAW_ALAW: 04996 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 04997 if (gain || drc) { 04998 k = AST_ALAW(j); 04999 if (drc) { 05000 k = drc_sample(k, drc); 05001 } 05002 k = (float)k*linear_gain; 05003 if (k > 32767) k = 32767; 05004 if (k < -32767) k = -32767; 05005 g->rxgain[j] = AST_LIN2A(k); 05006 } else { 05007 g->rxgain[j] = j; 05008 } 05009 } 05010 break; 05011 case DAHDI_LAW_MULAW: 05012 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 05013 if (gain || drc) { 05014 k = AST_MULAW(j); 05015 if (drc) { 05016 k = drc_sample(k, drc); 05017 } 05018 k = (float)k*linear_gain; 05019 if (k > 32767) k = 32767; 05020 if (k < -32767) k = -32767; 05021 g->rxgain[j] = AST_LIN2MU(k); 05022 } else { 05023 g->rxgain[j] = j; 05024 } 05025 } 05026 break; 05027 } 05028 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4944 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_txgain().
04945 { 04946 int j; 04947 int k; 04948 04949 float linear_gain = pow(10.0, gain / 20.0); 04950 04951 switch (law) { 04952 case DAHDI_LAW_ALAW: 04953 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 04954 if (gain || drc) { 04955 k = AST_ALAW(j); 04956 if (drc) { 04957 k = drc_sample(k, drc); 04958 } 04959 k = (float)k*linear_gain; 04960 if (k > 32767) k = 32767; 04961 if (k < -32767) k = -32767; 04962 g->txgain[j] = AST_LIN2A(k); 04963 } else { 04964 g->txgain[j] = j; 04965 } 04966 } 04967 break; 04968 case DAHDI_LAW_MULAW: 04969 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 04970 if (gain || drc) { 04971 k = AST_MULAW(j); 04972 if (drc) { 04973 k = drc_sample(k, drc); 04974 } 04975 k = (float)k*linear_gain; 04976 if (k > 32767) k = 32767; 04977 if (k < -32767) k = -32767; 04978 g->txgain[j] = AST_LIN2MU(k); 04979 04980 } else { 04981 g->txgain[j] = j; 04982 } 04983 } 04984 break; 04985 } 04986 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 15767 of file chan_dahdi.c.
References ast_mutex_lock, dahdi_pvt::channel, iflist, and dahdi_pvt::next.
Referenced by find_channel_from_str().
15768 { 15769 struct dahdi_pvt *p; 15770 15771 ast_mutex_lock(&iflock); 15772 for (p = iflist; p; p = p->next) { 15773 if (p->channel == channel) { 15774 break; 15775 } 15776 } 15777 ast_mutex_unlock(&iflock); 15778 return p; 15779 }
static struct dahdi_pvt* find_channel_from_str | ( | const char * | channel | ) | [static] |
Definition at line 15790 of file chan_dahdi.c.
References find_channel().
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
15791 { 15792 int chan_num; 15793 15794 if (sscanf(channel, "%30d", &chan_num) != 1) { 15795 /* Not numeric string. */ 15796 return NULL; 15797 } 15798 15799 return find_channel(chan_num); 15800 }
Definition at line 5672 of file chan_dahdi.c.
References dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::span.
Referenced by destroy_dahdi_pvt().
05673 { 05674 if (cur->next && cur->next->span == cur->span) { 05675 return cur->next; 05676 } else if (cur->prev && cur->prev->span == cur->span) { 05677 return cur->prev; 05678 } 05679 05680 return NULL; 05681 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
p | a channel to check for alarms. |
Definition at line 7658 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by action_dahdishowchannels(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), mwi_thread(), and my_get_and_handle_alarms().
07659 { 07660 int res; 07661 struct dahdi_spaninfo zi; 07662 struct dahdi_params params; 07663 07664 memset(&zi, 0, sizeof(zi)); 07665 zi.spanno = p->span; 07666 07667 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 07668 if (zi.alarms != DAHDI_ALARM_NONE) 07669 return zi.alarms; 07670 } else { 07671 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 07672 return 0; 07673 } 07674 07675 /* No alarms on the span. Check for channel alarms. */ 07676 memset(¶ms, 0, sizeof(params)); 07677 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 07678 return params.chan_alarms; 07679 07680 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 07681 07682 return DAHDI_ALARM_NONE; 07683 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 7783 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.
Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), mwi_thread(), and my_get_and_handle_alarms().
07784 { 07785 const char *alarm_str = alarm2str(alms); 07786 07787 if (report_alarms & REPORT_CHANNEL_ALARMS) { 07788 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 07789 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 07790 "Alarm: %s\r\n" 07791 "Channel: %d\r\n", 07792 alarm_str, p->channel); 07793 } 07794 07795 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 07796 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); 07797 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", 07798 "Alarm: %s\r\n" 07799 "Span: %d\r\n", 07800 alarm_str, p->span); 07801 } 07802 }
static void handle_clear_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3760 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, LOG_NOTICE, manager_event, dahdi_pvt::manages_span_alarms, report_alarms, REPORT_CHANNEL_ALARMS, REPORT_SPAN_ALARMS, and dahdi_pvt::span.
Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), handle_init_event(), and mwi_thread().
03761 { 03762 if (report_alarms & REPORT_CHANNEL_ALARMS) { 03763 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 03764 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 03765 } 03766 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 03767 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); 03768 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); 03769 } 03770 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15385 of file chan_dahdi.c.
References ast_cli(), cadences, cidrings, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, num_cadence, term_color(), and ast_cli_entry::usage.
15386 { 15387 int i, j; 15388 switch (cmd) { 15389 case CLI_INIT: 15390 e->command = "dahdi show cadences"; 15391 e->usage = 15392 "Usage: dahdi show cadences\n" 15393 " Shows all cadences currently defined\n"; 15394 return NULL; 15395 case CLI_GENERATE: 15396 return NULL; 15397 } 15398 for (i = 0; i < num_cadence; i++) { 15399 char output[1024]; 15400 char tmp[16], tmp2[64]; 15401 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 15402 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 15403 15404 for (j = 0; j < 16; j++) { 15405 if (cadences[i].ringcadence[j] == 0) 15406 break; 15407 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 15408 if (cidrings[i] * 2 - 1 == j) 15409 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 15410 else 15411 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 15412 if (j != 0) 15413 strncat(output, ",", sizeof(output) - strlen(output) - 1); 15414 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 15415 } 15416 ast_cli(a->fd,"%s\n",output); 15417 } 15418 return CLI_SUCCESS; 15419 }
Definition at line 11311 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(), errno, get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, 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.
11312 { 11313 int res; 11314 pthread_t threadid; 11315 struct ast_channel *chan; 11316 11317 /* Handle an event on a given channel for the monitor thread. */ 11318 11319 switch (event) { 11320 case DAHDI_EVENT_NONE: 11321 case DAHDI_EVENT_BITSCHANGED: 11322 break; 11323 case DAHDI_EVENT_WINKFLASH: 11324 case DAHDI_EVENT_RINGOFFHOOK: 11325 if (i->inalarm) break; 11326 if (i->radio) break; 11327 /* Got a ring/answer. What kind of channel are we? */ 11328 switch (i->sig) { 11329 case SIG_FXOLS: 11330 case SIG_FXOGS: 11331 case SIG_FXOKS: 11332 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11333 if (res && (errno == EBUSY)) 11334 break; 11335 11336 /* Cancel VMWI spill */ 11337 ast_free(i->cidspill); 11338 i->cidspill = NULL; 11339 restore_conference(i); 11340 11341 if (i->immediate) { 11342 dahdi_enable_ec(i); 11343 /* The channel is immediately up. Start right away */ 11344 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 11345 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL); 11346 if (!chan) { 11347 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 11348 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11349 if (res < 0) 11350 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11351 } 11352 } else { 11353 /* Check for callerid, digits, etc */ 11354 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL); 11355 if (chan) { 11356 if (has_voicemail(i)) 11357 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 11358 else 11359 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 11360 if (res < 0) 11361 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 11362 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11363 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11364 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11365 if (res < 0) 11366 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11367 ast_hangup(chan); 11368 } 11369 } else 11370 ast_log(LOG_WARNING, "Unable to create channel\n"); 11371 } 11372 break; 11373 case SIG_FXSLS: 11374 case SIG_FXSGS: 11375 case SIG_FXSKS: 11376 i->ringt = i->ringt_base; 11377 /* Fall through */ 11378 case SIG_EMWINK: 11379 case SIG_FEATD: 11380 case SIG_FEATDMF: 11381 case SIG_FEATDMF_TA: 11382 case SIG_E911: 11383 case SIG_FGC_CAMA: 11384 case SIG_FGC_CAMAMF: 11385 case SIG_FEATB: 11386 case SIG_EM: 11387 case SIG_EM_E1: 11388 case SIG_SFWINK: 11389 case SIG_SF_FEATD: 11390 case SIG_SF_FEATDMF: 11391 case SIG_SF_FEATB: 11392 case SIG_SF: 11393 /* Check for callerid, digits, etc */ 11394 if (i->cid_start == CID_START_POLARITY_IN) { 11395 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11396 } else { 11397 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL); 11398 } 11399 11400 if (!chan) { 11401 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11402 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11403 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11404 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11405 if (res < 0) { 11406 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11407 } 11408 ast_hangup(chan); 11409 } 11410 break; 11411 default: 11412 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11413 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11414 if (res < 0) 11415 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11416 return NULL; 11417 } 11418 break; 11419 case DAHDI_EVENT_NOALARM: 11420 switch (i->sig) { 11421 #if defined(HAVE_PRI) 11422 case SIG_PRI_LIB_HANDLE_CASES: 11423 ast_mutex_lock(&i->lock); 11424 sig_pri_chan_alarm_notify(i->sig_pvt, 1); 11425 ast_mutex_unlock(&i->lock); 11426 break; 11427 #endif /* defined(HAVE_PRI) */ 11428 #if defined(HAVE_SS7) 11429 case SIG_SS7: 11430 sig_ss7_set_alarm(i->sig_pvt, 0); 11431 break; 11432 #endif /* defined(HAVE_SS7) */ 11433 default: 11434 i->inalarm = 0; 11435 break; 11436 } 11437 handle_clear_alarms(i); 11438 break; 11439 case DAHDI_EVENT_ALARM: 11440 switch (i->sig) { 11441 #if defined(HAVE_PRI) 11442 case SIG_PRI_LIB_HANDLE_CASES: 11443 ast_mutex_lock(&i->lock); 11444 sig_pri_chan_alarm_notify(i->sig_pvt, 0); 11445 ast_mutex_unlock(&i->lock); 11446 break; 11447 #endif /* defined(HAVE_PRI) */ 11448 #if defined(HAVE_SS7) 11449 case SIG_SS7: 11450 sig_ss7_set_alarm(i->sig_pvt, 1); 11451 break; 11452 #endif /* defined(HAVE_SS7) */ 11453 default: 11454 i->inalarm = 1; 11455 break; 11456 } 11457 res = get_alarms(i); 11458 handle_alarms(i, res); 11459 /* fall thru intentionally */ 11460 case DAHDI_EVENT_ONHOOK: 11461 if (i->radio) 11462 break; 11463 /* Back on hook. Hang up. */ 11464 switch (i->sig) { 11465 case SIG_FXOLS: 11466 case SIG_FXOGS: 11467 case SIG_FEATD: 11468 case SIG_FEATDMF: 11469 case SIG_FEATDMF_TA: 11470 case SIG_E911: 11471 case SIG_FGC_CAMA: 11472 case SIG_FGC_CAMAMF: 11473 case SIG_FEATB: 11474 case SIG_EM: 11475 case SIG_EM_E1: 11476 case SIG_EMWINK: 11477 case SIG_SF_FEATD: 11478 case SIG_SF_FEATDMF: 11479 case SIG_SF_FEATB: 11480 case SIG_SF: 11481 case SIG_SFWINK: 11482 case SIG_FXSLS: 11483 case SIG_FXSGS: 11484 case SIG_FXSKS: 11485 case SIG_FXOKS: 11486 dahdi_disable_ec(i); 11487 /* Diddle the battery for the zhone */ 11488 #ifdef ZHONE_HACK 11489 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11490 usleep(1); 11491 #endif 11492 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11493 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 11494 break; 11495 case SIG_SS7: 11496 case SIG_PRI_LIB_HANDLE_CASES: 11497 dahdi_disable_ec(i); 11498 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11499 break; 11500 default: 11501 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11502 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11503 return NULL; 11504 } 11505 break; 11506 case DAHDI_EVENT_POLARITY: 11507 switch (i->sig) { 11508 case SIG_FXSLS: 11509 case SIG_FXSKS: 11510 case SIG_FXSGS: 11511 /* We have already got a PR before the channel was 11512 created, but it wasn't handled. We need polarity 11513 to be REV for remote hangup detection to work. 11514 At least in Spain */ 11515 if (i->hanguponpolarityswitch) 11516 i->polarity = POLARITY_REV; 11517 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 11518 i->polarity = POLARITY_REV; 11519 ast_verb(2, "Starting post polarity " 11520 "CID detection on channel %d\n", 11521 i->channel); 11522 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11523 if (!chan) { 11524 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11525 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11526 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11527 } 11528 } 11529 break; 11530 default: 11531 ast_log(LOG_WARNING, "handle_init_event detected " 11532 "polarity reversal on non-FXO (SIG_FXS) " 11533 "interface %d\n", i->channel); 11534 } 11535 break; 11536 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 11537 ast_log(LOG_NOTICE, 11538 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 11539 i->channel); 11540 return i; 11541 case DAHDI_EVENT_NEONMWI_ACTIVE: 11542 if (i->mwimonitor_neon) { 11543 notify_message(i->mailbox, 1); 11544 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 11545 } 11546 break; 11547 case DAHDI_EVENT_NEONMWI_INACTIVE: 11548 if (i->mwimonitor_neon) { 11549 notify_message(i->mailbox, 0); 11550 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 11551 } 11552 break; 11553 } 11554 return NULL; 11555 }
static char* handle_mfcr2_call_files | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14753 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.
14754 { 14755 struct dahdi_pvt *p = NULL; 14756 int channo = 0; 14757 switch (cmd) { 14758 case CLI_INIT: 14759 e->command = "mfcr2 call files [on|off]"; 14760 e->usage = 14761 "Usage: mfcr2 call files [on|off] <channel>\n" 14762 " Enable call files creation on the specified channel.\n" 14763 " If no channel is specified call files creation policy will be applied to all channels.\n"; 14764 return NULL; 14765 case CLI_GENERATE: 14766 return NULL; 14767 } 14768 if (a->argc < 4) { 14769 return CLI_SHOWUSAGE; 14770 } 14771 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1; 14772 ast_mutex_lock(&iflock); 14773 for (p = iflist; p; p = p->next) { 14774 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14775 continue; 14776 } 14777 if ((channo != -1) && (p->channel != channo )) { 14778 continue; 14779 } 14780 if (ast_true(a->argv[3])) { 14781 openr2_chan_enable_call_files(p->r2chan); 14782 } else { 14783 openr2_chan_disable_call_files(p->r2chan); 14784 } 14785 if (channo != -1) { 14786 if (ast_true(a->argv[3])) { 14787 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 14788 } else { 14789 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 14790 } 14791 break; 14792 } 14793 } 14794 if ((channo != -1) && !p) { 14795 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14796 } 14797 if (channo == -1) { 14798 if (ast_true(a->argv[3])) { 14799 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n"); 14800 } else { 14801 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n"); 14802 } 14803 } 14804 ast_mutex_unlock(&iflock); 14805 return CLI_SUCCESS; 14806 }
static char* handle_mfcr2_set_blocked | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14849 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.
14850 { 14851 struct dahdi_pvt *p = NULL; 14852 int channo = 0; 14853 switch (cmd) { 14854 case CLI_INIT: 14855 e->command = "mfcr2 set blocked"; 14856 e->usage = 14857 "Usage: mfcr2 set blocked <channel>\n" 14858 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" 14859 " Force the given channel into BLOCKED state.\n" 14860 " If no channel is specified, all channels will be set to BLOCKED.\n"; 14861 return NULL; 14862 case CLI_GENERATE: 14863 return NULL; 14864 } 14865 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1; 14866 ast_mutex_lock(&iflock); 14867 for (p = iflist; p; p = p->next) { 14868 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14869 continue; 14870 } 14871 if ((channo != -1) && (p->channel != channo )) { 14872 continue; 14873 } 14874 openr2_chan_set_blocked(p->r2chan); 14875 ast_mutex_lock(&p->lock); 14876 p->locallyblocked = 1; 14877 ast_mutex_unlock(&p->lock); 14878 if (channo != -1) { 14879 break; 14880 } 14881 } 14882 if ((channo != -1) && !p) { 14883 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14884 } 14885 ast_mutex_unlock(&iflock); 14886 return CLI_SUCCESS; 14887 }
static char* handle_mfcr2_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14688 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_strdupa, dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.
14689 { 14690 struct dahdi_pvt *p = NULL; 14691 int channo = 0; 14692 char *toklevel = NULL; 14693 char *saveptr = NULL; 14694 char *logval = NULL; 14695 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 14696 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 14697 switch (cmd) { 14698 case CLI_INIT: 14699 e->command = "mfcr2 set debug"; 14700 e->usage = 14701 "Usage: mfcr2 set debug <loglevel> <channel>\n" 14702 " Set a new logging level for the specified channel.\n" 14703 " If no channel is specified the logging level will be applied to all channels.\n"; 14704 return NULL; 14705 case CLI_GENERATE: 14706 return NULL; 14707 } 14708 if (a->argc < 4) { 14709 return CLI_SHOWUSAGE; 14710 } 14711 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1; 14712 logval = ast_strdupa(a->argv[3]); 14713 toklevel = strtok_r(logval, ",", &saveptr); 14714 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14715 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]); 14716 return CLI_FAILURE; 14717 } else if (OR2_LOG_NOTHING == tmplevel) { 14718 loglevel = tmplevel; 14719 } else { 14720 loglevel |= tmplevel; 14721 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 14722 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14723 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 14724 continue; 14725 } 14726 loglevel |= tmplevel; 14727 } 14728 } 14729 ast_mutex_lock(&iflock); 14730 for (p = iflist; p; p = p->next) { 14731 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14732 continue; 14733 } 14734 if ((channo != -1) && (p->channel != channo )) { 14735 continue; 14736 } 14737 openr2_chan_set_log_level(p->r2chan, loglevel); 14738 if (channo != -1) { 14739 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel); 14740 break; 14741 } 14742 } 14743 if ((channo != -1) && !p) { 14744 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14745 } 14746 if (channo == -1) { 14747 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]); 14748 } 14749 ast_mutex_unlock(&iflock); 14750 return CLI_SUCCESS; 14751 }
static char* handle_mfcr2_set_idle | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14808 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, dahdi_pvt::channel, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.
14809 { 14810 struct dahdi_pvt *p = NULL; 14811 int channo = 0; 14812 switch (cmd) { 14813 case CLI_INIT: 14814 e->command = "mfcr2 set idle"; 14815 e->usage = 14816 "Usage: mfcr2 set idle <channel>\n" 14817 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" 14818 " Force the given channel into IDLE state.\n" 14819 " If no channel is specified, all channels will be set to IDLE.\n"; 14820 return NULL; 14821 case CLI_GENERATE: 14822 return NULL; 14823 } 14824 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1; 14825 ast_mutex_lock(&iflock); 14826 for (p = iflist; p; p = p->next) { 14827 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14828 continue; 14829 } 14830 if ((channo != -1) && (p->channel != channo )) { 14831 continue; 14832 } 14833 openr2_chan_set_idle(p->r2chan); 14834 ast_mutex_lock(&p->lock); 14835 p->locallyblocked = 0; 14836 p->mfcr2call = 0; 14837 ast_mutex_unlock(&p->lock); 14838 if (channo != -1) { 14839 break; 14840 } 14841 } 14842 if ((channo != -1) && !p) { 14843 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14844 } 14845 ast_mutex_unlock(&iflock); 14846 return CLI_SUCCESS; 14847 }
static char* handle_mfcr2_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14614 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_pvt::context, ast_cli_args::fd, FORMAT, dahdi_pvt::group, iflist, dahdi_pvt::next, dahdi_pvt::r2chan, dahdi_pvt::sig, SIG_MFCR2, and ast_cli_entry::usage.
14615 { 14616 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 14617 int filtertype = 0; 14618 int targetnum = 0; 14619 char channo[5]; 14620 char anino[5]; 14621 char dnisno[5]; 14622 struct dahdi_pvt *p; 14623 openr2_context_t *r2context; 14624 openr2_variant_t r2variant; 14625 switch (cmd) { 14626 case CLI_INIT: 14627 e->command = "mfcr2 show channels [group|context]"; 14628 e->usage = 14629 "Usage: mfcr2 show channels [group <group> | context <context>]\n" 14630 " Shows the DAHDI channels configured with MFC/R2 signaling.\n"; 14631 return NULL; 14632 case CLI_GENERATE: 14633 return NULL; 14634 } 14635 if (!((a->argc == 3) || (a->argc == 5))) { 14636 return CLI_SHOWUSAGE; 14637 } 14638 if (a->argc == 5) { 14639 if (!strcasecmp(a->argv[3], "group")) { 14640 targetnum = atoi(a->argv[4]); 14641 if ((targetnum < 0) || (targetnum > 63)) 14642 return CLI_SHOWUSAGE; 14643 targetnum = 1 << targetnum; 14644 filtertype = 1; 14645 } else if (!strcasecmp(a->argv[3], "context")) { 14646 filtertype = 2; 14647 } else { 14648 return CLI_SHOWUSAGE; 14649 } 14650 } 14651 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 14652 ast_mutex_lock(&iflock); 14653 for (p = iflist; p; p = p->next) { 14654 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14655 continue; 14656 } 14657 if (filtertype) { 14658 switch(filtertype) { 14659 case 1: /* mfcr2 show channels group <group> */ 14660 if (p->group != targetnum) { 14661 continue; 14662 } 14663 break; 14664 case 2: /* mfcr2 show channels context <context> */ 14665 if (strcasecmp(p->context, a->argv[4])) { 14666 continue; 14667 } 14668 break; 14669 default: 14670 ; 14671 } 14672 } 14673 r2context = openr2_chan_get_context(p->r2chan); 14674 r2variant = openr2_context_get_variant(r2context); 14675 snprintf(channo, sizeof(channo), "%d", p->channel); 14676 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 14677 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 14678 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 14679 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 14680 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 14681 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 14682 } 14683 ast_mutex_unlock(&iflock); 14684 return CLI_SUCCESS; 14685 #undef FORMAT 14686 }
static char* handle_mfcr2_show_variants | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14586 of file chan_dahdi.c.
References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, and ast_cli_entry::usage.
14587 { 14588 #define FORMAT "%4s %40s\n" 14589 int i = 0; 14590 int numvariants = 0; 14591 const openr2_variant_entry_t *variants; 14592 switch (cmd) { 14593 case CLI_INIT: 14594 e->command = "mfcr2 show variants"; 14595 e->usage = 14596 "Usage: mfcr2 show variants\n" 14597 " Shows the list of MFC/R2 variants supported.\n"; 14598 return NULL; 14599 case CLI_GENERATE: 14600 return NULL; 14601 } 14602 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 14603 ast_cli(a->fd, "Failed to get list of variants.\n"); 14604 return CLI_FAILURE; 14605 } 14606 ast_cli(a->fd, FORMAT, "Variant Code", "Country"); 14607 for (i = 0; i < numvariants; i++) { 14608 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country); 14609 } 14610 return CLI_SUCCESS; 14611 #undef FORMAT 14612 }
static char* handle_mfcr2_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14570 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
14571 { 14572 switch (cmd) { 14573 case CLI_INIT: 14574 e->command = "mfcr2 show version"; 14575 e->usage = 14576 "Usage: mfcr2 show version\n" 14577 " Shows the version of the OpenR2 library being used.\n"; 14578 return NULL; 14579 case CLI_GENERATE: 14580 return NULL; 14581 } 14582 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 14583 return CLI_SUCCESS; 14584 }
static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14181 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, dahdi_pri::pri, pris, SIG_PRI_DEBUG_INTENSE, SIG_PRI_DEBUG_NORMAL, ast_cli_entry::usage, and ast_cli_args::word.
14182 { 14183 int span; 14184 int x; 14185 int level = 0; 14186 switch (cmd) { 14187 case CLI_INIT: 14188 e->command = "pri set debug {on|off|0|1|2} span"; 14189 e->usage = 14190 "Usage: pri set debug {<level>|on|off} span <span>\n" 14191 " Enables debugging on a given PRI span\n"; 14192 return NULL; 14193 case CLI_GENERATE: 14194 return complete_span_4(a->line, a->word, a->pos, a->n); 14195 } 14196 if (a->argc < 6) { 14197 return CLI_SHOWUSAGE; 14198 } 14199 14200 if (!strcasecmp(a->argv[3], "on")) { 14201 level = 1; 14202 } else if (!strcasecmp(a->argv[3], "off")) { 14203 level = 0; 14204 } else { 14205 level = atoi(a->argv[3]); 14206 } 14207 span = atoi(a->argv[5]); 14208 if ((span < 1) || (span > NUM_SPANS)) { 14209 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS); 14210 return CLI_SUCCESS; 14211 } 14212 if (!pris[span-1].pri.pri) { 14213 ast_cli(a->fd, "No PRI running on span %d\n", span); 14214 return CLI_SUCCESS; 14215 } 14216 14217 /* Set debug level in libpri */ 14218 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) { 14219 if (pris[span - 1].pri.dchans[x]) { 14220 switch (level) { 14221 case 0: 14222 pri_set_debug(pris[span - 1].pri.dchans[x], 0); 14223 break; 14224 case 1: 14225 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL); 14226 break; 14227 default: 14228 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE); 14229 break; 14230 } 14231 } 14232 } 14233 if (level == 0) { 14234 /* Close the debugging file if it's set */ 14235 ast_mutex_lock(&pridebugfdlock); 14236 if (0 <= pridebugfd) { 14237 close(pridebugfd); 14238 pridebugfd = -1; 14239 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n", 14240 pridebugfilename); 14241 } 14242 ast_mutex_unlock(&pridebugfdlock); 14243 } 14244 pris[span - 1].pri.debug = (level) ? 1 : 0; 14245 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span); 14246 return CLI_SUCCESS; 14247 }
static char* handle_pri_service_disable_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14377 of file chan_dahdi.c.
References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.
14378 { 14379 switch (cmd) { 14380 case CLI_INIT: 14381 e->command = "pri service disable channel"; 14382 e->usage = 14383 "Usage: pri service disable channel <chan num> [<interface id>]\n" 14384 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" 14385 " to remove a channel from service, with optional interface id\n" 14386 " as agreed upon with remote switch operator\n"; 14387 return NULL; 14388 case CLI_GENERATE: 14389 return NULL; 14390 } 14391 return handle_pri_service_generic(e, cmd, a, 2); 14392 }
static char* handle_pri_service_enable_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14360 of file chan_dahdi.c.
References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.
14361 { 14362 switch (cmd) { 14363 case CLI_INIT: 14364 e->command = "pri service enable channel"; 14365 e->usage = 14366 "Usage: pri service enable channel <channel> [<interface id>]\n" 14367 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" 14368 " to restore a channel to service, with optional interface id\n" 14369 " as agreed upon with remote switch operator\n"; 14370 return NULL; 14371 case CLI_GENERATE: 14372 return NULL; 14373 } 14374 return handle_pri_service_generic(e, cmd, a, 0); 14375 }
static char* handle_pri_service_generic | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a, | |||
int | changestatus | |||
) | [static] |
Definition at line 14252 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_SHOWUSAGE, ast_cli_args::fd, dahdi_pri::pri, pris, and sig_pri_span::trunkgroup.
Referenced by handle_pri_service_disable_channel(), and handle_pri_service_enable_channel().
14253 { 14254 unsigned *why; 14255 int channel; 14256 int trunkgroup; 14257 int x, y, fd = a->fd; 14258 int interfaceid = 0; 14259 char *c; 14260 char db_chan_name[20], db_answer[5]; 14261 struct dahdi_pvt *tmp; 14262 struct dahdi_pri *pri; 14263 14264 if (a->argc < 5 || a->argc > 6) 14265 return CLI_SHOWUSAGE; 14266 if ((c = strchr(a->argv[4], ':'))) { 14267 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2) 14268 return CLI_SHOWUSAGE; 14269 if ((trunkgroup < 1) || (channel < 1)) 14270 return CLI_SHOWUSAGE; 14271 pri = NULL; 14272 for (x=0;x<NUM_SPANS;x++) { 14273 if (pris[x].pri.trunkgroup == trunkgroup) { 14274 pri = pris + x; 14275 break; 14276 } 14277 } 14278 if (!pri) { 14279 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 14280 return CLI_FAILURE; 14281 } 14282 } else 14283 channel = atoi(a->argv[4]); 14284 14285 if (a->argc == 6) 14286 interfaceid = atoi(a->argv[5]); 14287 14288 /* either servicing a D-Channel */ 14289 for (x = 0; x < NUM_SPANS; x++) { 14290 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 14291 if (pris[x].dchannels[y] == channel) { 14292 pri = pris + x; 14293 if (pri->pri.enable_service_message_support) { 14294 ast_mutex_lock(&pri->pri.lock); 14295 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus); 14296 ast_mutex_unlock(&pri->pri.lock); 14297 } else { 14298 ast_cli(fd, 14299 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n" 14300 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n"); 14301 } 14302 return CLI_SUCCESS; 14303 } 14304 } 14305 } 14306 14307 /* or servicing a B-Channel */ 14308 ast_mutex_lock(&iflock); 14309 for (tmp = iflist; tmp; tmp = tmp->next) { 14310 if (tmp->pri && tmp->channel == channel) { 14311 ast_mutex_unlock(&iflock); 14312 ast_mutex_lock(&tmp->pri->lock); 14313 if (!tmp->pri->enable_service_message_support) { 14314 ast_mutex_unlock(&tmp->pri->lock); 14315 ast_cli(fd, 14316 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n" 14317 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n"); 14318 return CLI_SUCCESS; 14319 } 14320 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel); 14321 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 14322 switch(changestatus) { 14323 case 0: /* enable */ 14324 /* Near end wants to be in service now. */ 14325 ast_db_del(db_chan_name, SRVST_DBKEY); 14326 *why &= ~SRVST_NEAREND; 14327 if (*why) { 14328 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why); 14329 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); 14330 } else { 14331 dahdi_pri_update_span_devstate(tmp->pri); 14332 } 14333 break; 14334 /* case 1: -- loop */ 14335 case 2: /* disable */ 14336 /* Near end wants to be out-of-service now. */ 14337 ast_db_del(db_chan_name, SRVST_DBKEY); 14338 *why |= SRVST_NEAREND; 14339 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why); 14340 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); 14341 dahdi_pri_update_span_devstate(tmp->pri); 14342 break; 14343 /* case 3: -- continuity */ 14344 /* case 4: -- shutdown */ 14345 default: 14346 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus); 14347 break; 14348 } 14349 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus); 14350 ast_mutex_unlock(&tmp->pri->lock); 14351 return CLI_SUCCESS; 14352 } 14353 } 14354 ast_mutex_unlock(&iflock); 14355 14356 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel); 14357 return CLI_FAILURE; 14358 }
static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14143 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_FILE_MODE, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfd, pridebugfdlock, pridebugfilename, and ast_cli_entry::usage.
14144 { 14145 int myfd; 14146 switch (cmd) { 14147 case CLI_INIT: 14148 e->command = "pri set debug file"; 14149 e->usage = "Usage: pri set debug file [output-file]\n" 14150 " Sends PRI debug output to the specified output file\n"; 14151 return NULL; 14152 case CLI_GENERATE: 14153 return NULL; 14154 } 14155 if (a->argc < 5) 14156 return CLI_SHOWUSAGE; 14157 14158 if (ast_strlen_zero(a->argv[4])) 14159 return CLI_SHOWUSAGE; 14160 14161 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 14162 if (myfd < 0) { 14163 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 14164 return CLI_SUCCESS; 14165 } 14166 14167 ast_mutex_lock(&pridebugfdlock); 14168 14169 if (pridebugfd >= 0) 14170 close(pridebugfd); 14171 14172 pridebugfd = myfd; 14173 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 14174 ast_mutex_unlock(&pridebugfdlock); 14175 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 14176 return CLI_SUCCESS; 14177 }
static char* handle_pri_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14397 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_channels(), sig_pri_cli_show_channels_header(), and ast_cli_entry::usage.
14398 { 14399 int span; 14400 14401 switch (cmd) { 14402 case CLI_INIT: 14403 e->command = "pri show channels"; 14404 e->usage = 14405 "Usage: pri show channels\n" 14406 " Displays PRI channel information such as the current mapping\n" 14407 " of DAHDI B channels to Asterisk channel names and which calls\n" 14408 " are on hold or call-waiting. Calls on hold or call-waiting\n" 14409 " are not associated with any B channel.\n"; 14410 return NULL; 14411 case CLI_GENERATE: 14412 return NULL; 14413 } 14414 14415 if (a->argc != 3) 14416 return CLI_SHOWUSAGE; 14417 14418 sig_pri_cli_show_channels_header(a->fd); 14419 for (span = 0; span < NUM_SPANS; ++span) { 14420 if (pris[span].pri.pri) { 14421 sig_pri_cli_show_channels(a->fd, &pris[span].pri); 14422 } 14423 } 14424 return CLI_SUCCESS; 14425 }
static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14491 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, sig_pri_span::dchans, debug, ast_cli_args::fd, sig_pri_span::pri, sig_pri_chan::pri, pris, and ast_cli_entry::usage.
14492 { 14493 int x; 14494 int span; 14495 int count=0; 14496 int debug; 14497 14498 switch (cmd) { 14499 case CLI_INIT: 14500 e->command = "pri show debug"; 14501 e->usage = 14502 "Usage: pri show debug\n" 14503 " Show the debug state of pri spans\n"; 14504 return NULL; 14505 case CLI_GENERATE: 14506 return NULL; 14507 } 14508 14509 for (span = 0; span < NUM_SPANS; span++) { 14510 if (pris[span].pri.pri) { 14511 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) { 14512 if (pris[span].pri.dchans[x]) { 14513 debug = pri_get_debug(pris[span].pri.dchans[x]); 14514 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" ); 14515 count++; 14516 } 14517 } 14518 } 14519 14520 } 14521 ast_mutex_lock(&pridebugfdlock); 14522 if (pridebugfd >= 0) 14523 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 14524 ast_mutex_unlock(&pridebugfdlock); 14525 14526 if (!count) 14527 ast_cli(a->fd, "No PRI running\n"); 14528 return CLI_SUCCESS; 14529 }
static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14457 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), dahdi_pri::dchannels, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_span(), ast_cli_entry::usage, and ast_cli_args::word.
14458 { 14459 int span; 14460 14461 switch (cmd) { 14462 case CLI_INIT: 14463 e->command = "pri show span"; 14464 e->usage = 14465 "Usage: pri show span <span>\n" 14466 " Displays PRI Information on a given PRI span\n"; 14467 return NULL; 14468 case CLI_GENERATE: 14469 return complete_span_4(a->line, a->word, a->pos, a->n); 14470 } 14471 14472 if (a->argc < 4) 14473 return CLI_SHOWUSAGE; 14474 span = atoi(a->argv[3]); 14475 if ((span < 1) || (span > NUM_SPANS)) { 14476 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 14477 return CLI_SUCCESS; 14478 } 14479 if (!pris[span-1].pri.pri) { 14480 ast_cli(a->fd, "No PRI running on span %d\n", span); 14481 return CLI_SUCCESS; 14482 } 14483 14484 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri); 14485 14486 return CLI_SUCCESS; 14487 }
static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14429 of file chan_dahdi.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, dahdi_pri::pri, sig_pri_span::pri, sig_pri_chan::pri, pris, sig_pri_cli_show_spans(), and ast_cli_entry::usage.
14430 { 14431 int span; 14432 14433 switch (cmd) { 14434 case CLI_INIT: 14435 e->command = "pri show spans"; 14436 e->usage = 14437 "Usage: pri show spans\n" 14438 " Displays PRI span information\n"; 14439 return NULL; 14440 case CLI_GENERATE: 14441 return NULL; 14442 } 14443 14444 if (a->argc != 3) 14445 return CLI_SHOWUSAGE; 14446 14447 for (span = 0; span < NUM_SPANS; span++) { 14448 if (pris[span].pri.pri) { 14449 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri); 14450 } 14451 } 14452 return CLI_SUCCESS; 14453 }
static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14533 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
14534 { 14535 switch (cmd) { 14536 case CLI_INIT: 14537 e->command = "pri show version"; 14538 e->usage = 14539 "Usage: pri show version\n" 14540 "Show libpri version information\n"; 14541 return NULL; 14542 case CLI_GENERATE: 14543 return NULL; 14544 } 14545 14546 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 14547 14548 return CLI_SUCCESS; 14549 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5207 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, mailbox, and strsep().
05208 { 05209 int new_msgs; 05210 struct ast_event *event; 05211 char *mailbox, *context; 05212 05213 mailbox = context = ast_strdupa(p->mailbox); 05214 strsep(&context, "@"); 05215 if (ast_strlen_zero(context)) 05216 context = "default"; 05217 05218 event = ast_event_get_cached(AST_EVENT_MWI, 05219 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 05220 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 05221 AST_EVENT_IE_END); 05222 05223 if (event) { 05224 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 05225 ast_event_destroy(event); 05226 } else 05227 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 05228 05229 return new_msgs; 05230 }
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 13051 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::group, dahdi_pvt::pri, and sig_pri_span::span.
Referenced by dahdi_cc_callback(), and dahdi_request().
13052 { 13053 #if defined(HAVE_PRI) 13054 if (0 < span) { 13055 /* The channel must be on the specified PRI span. */ 13056 if (!p->pri || p->pri->span != span) { 13057 return 0; 13058 } 13059 if (!groupmatch && channelmatch == -1) { 13060 /* Match any group since it only needs to be on the PRI span. */ 13061 *groupmatched = 1; 13062 return 1; 13063 } 13064 } 13065 #endif /* defined(HAVE_PRI) */ 13066 /* check group matching */ 13067 if (groupmatch) { 13068 if ((p->group & groupmatch) != groupmatch) 13069 /* Doesn't match the specified group, try the next one */ 13070 return 0; 13071 *groupmatched = 1; 13072 } 13073 /* Check to see if we have a channel match */ 13074 if (channelmatch != -1) { 13075 if (p->channel != channelmatch) 13076 /* Doesn't match the specified channel, try the next one */ 13077 return 0; 13078 *channelmatched = 1; 13079 } 13080 13081 return 1; 13082 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 4689 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
04690 { 04691 /* If they're listening to our channel, they're ours */ 04692 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 04693 return 1; 04694 /* If they're a talker on our (allocated) conference, they're ours */ 04695 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 04696 return 1; 04697 return 0; 04698 }
Definition at line 4719 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by my_complete_conference_update(), and update_conf().
04720 { 04721 int x; 04722 int useslavenative; 04723 struct dahdi_pvt *slave = NULL; 04724 /* Start out optimistic */ 04725 useslavenative = 1; 04726 /* Update conference state in a stateless fashion */ 04727 for (x = 0; x < 3; x++) { 04728 /* Any three-way calling makes slave native mode *definitely* out 04729 of the question */ 04730 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 04731 useslavenative = 0; 04732 } 04733 /* If we don't have any 3-way calls, check to see if we have 04734 precisely one slave */ 04735 if (useslavenative) { 04736 for (x = 0; x < MAX_SLAVES; x++) { 04737 if (p->slaves[x]) { 04738 if (slave) { 04739 /* Whoops already have a slave! No 04740 slave native and stop right away */ 04741 slave = NULL; 04742 useslavenative = 0; 04743 break; 04744 } else { 04745 /* We have one slave so far */ 04746 slave = p->slaves[x]; 04747 } 04748 } 04749 } 04750 } 04751 /* If no slave, slave native definitely out */ 04752 if (!slave) 04753 useslavenative = 0; 04754 else if (slave->law != p->law) { 04755 useslavenative = 0; 04756 slave = NULL; 04757 } 04758 if (out) 04759 *out = slave; 04760 return useslavenative; 04761 }
static int load_module | ( | void | ) | [static] |
Definition at line 18430 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, dahdi_accept_r2_call_exec(), dahdi_cli, dahdi_data_providers, dahdi_mfcr2_cli, dahdi_pri_cc_agent_callbacks, dahdi_pri_cc_monitor_callbacks, dahdi_pri_cc_type, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_callrerouting_facility_exec(), dahdi_send_keypad_facility_exec(), dahdi_tech, HAVE_PRI_CCSS, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_init_linkset(), and ss_thread_complete.
18431 { 18432 int res; 18433 #if defined(HAVE_PRI) || defined(HAVE_SS7) 18434 int y; 18435 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 18436 18437 #ifdef HAVE_PRI 18438 memset(pris, 0, sizeof(pris)); 18439 for (y = 0; y < NUM_SPANS; y++) { 18440 sig_pri_init_pri(&pris[y].pri); 18441 } 18442 pri_set_error(dahdi_pri_error); 18443 pri_set_message(dahdi_pri_message); 18444 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 18445 #ifdef HAVE_PRI_PROG_W_CAUSE 18446 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 18447 #endif 18448 #if defined(HAVE_PRI_CCSS) 18449 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks) 18450 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) { 18451 __unload_module(); 18452 return AST_MODULE_LOAD_FAILURE; 18453 } 18454 #endif /* defined(HAVE_PRI_CCSS) */ 18455 if (sig_pri_load( 18456 #if defined(HAVE_PRI_CCSS) 18457 dahdi_pri_cc_type 18458 #else 18459 NULL 18460 #endif /* defined(HAVE_PRI_CCSS) */ 18461 )) { 18462 __unload_module(); 18463 return AST_MODULE_LOAD_FAILURE; 18464 } 18465 #endif 18466 #if defined(HAVE_SS7) 18467 memset(linksets, 0, sizeof(linksets)); 18468 for (y = 0; y < NUM_SPANS; y++) { 18469 sig_ss7_init_linkset(&linksets[y].ss7); 18470 } 18471 ss7_set_error(dahdi_ss7_error); 18472 ss7_set_message(dahdi_ss7_message); 18473 #endif /* defined(HAVE_SS7) */ 18474 res = setup_dahdi(0); 18475 /* Make sure we can register our DAHDI channel type */ 18476 if (res) 18477 return AST_MODULE_LOAD_DECLINE; 18478 if (ast_channel_register(&dahdi_tech)) { 18479 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 18480 __unload_module(); 18481 return AST_MODULE_LOAD_FAILURE; 18482 } 18483 #ifdef HAVE_PRI 18484 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 18485 #endif 18486 #if defined(HAVE_SS7) 18487 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 18488 #endif /* defined(HAVE_SS7) */ 18489 #ifdef HAVE_OPENR2 18490 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 18491 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 18492 #endif 18493 18494 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 18495 /* register all the data providers */ 18496 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers)); 18497 memset(round_robin, 0, sizeof(round_robin)); 18498 ast_manager_register_xml("DAHDITransfer", 0, action_transfer); 18499 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup); 18500 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook); 18501 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon); 18502 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff); 18503 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels); 18504 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart); 18505 18506 ast_cond_init(&ss_thread_complete, NULL); 18507 18508 return res; 18509 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 13874 of file chan_dahdi.c.
References ast_log(), LOG_DEBUG, and SUB_REAL.
13875 { 13876 struct dahdi_mfcr2 *mfcr2 = data; 13877 /* we should be using pthread_key_create 13878 and allocate pollers dynamically. 13879 I think do_monitor() could be leaking, since it 13880 could be cancelled at any time and is not 13881 using thread keys, why?, */ 13882 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)]; 13883 int res = 0; 13884 int i = 0; 13885 int oldstate = 0; 13886 int quit_loop = 0; 13887 int maxsleep = 20; 13888 int was_idle = 0; 13889 int pollsize = 0; 13890 /* now that we're ready to get calls, unblock our side and 13891 get current line state */ 13892 for (i = 0; i < mfcr2->numchans; i++) { 13893 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan); 13894 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 13895 } 13896 while (1) { 13897 /* we trust here that the mfcr2 channel list will not ever change once 13898 the module is loaded */ 13899 pollsize = 0; 13900 for (i = 0; i < mfcr2->numchans; i++) { 13901 pollers[i].revents = 0; 13902 pollers[i].events = 0; 13903 if (mfcr2->pvts[i]->owner) { 13904 continue; 13905 } 13906 if (!mfcr2->pvts[i]->r2chan) { 13907 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 13908 quit_loop = 1; 13909 break; 13910 } 13911 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 13912 pollers[i].events = POLLIN | POLLPRI; 13913 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 13914 pollsize++; 13915 } 13916 if (quit_loop) { 13917 break; 13918 } 13919 if (pollsize == 0) { 13920 if (!was_idle) { 13921 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n"); 13922 was_idle = 1; 13923 } 13924 poll(NULL, 0, maxsleep); 13925 continue; 13926 } 13927 was_idle = 0; 13928 /* probably poll() is a valid cancel point, lets just be on the safe side 13929 by calling pthread_testcancel */ 13930 pthread_testcancel(); 13931 res = poll(pollers, mfcr2->numchans, maxsleep); 13932 pthread_testcancel(); 13933 if ((res < 0) && (errno != EINTR)) { 13934 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 13935 break; 13936 } 13937 /* do we want to allow to cancel while processing events? */ 13938 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 13939 for (i = 0; i < mfcr2->numchans; i++) { 13940 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) { 13941 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 13942 } 13943 } 13944 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 13945 } 13946 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 13947 return 0; 13948 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
int | reloading | |||
) | [static] |
Definition at line 12166 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::destroy, iflist, and dahdi_pvt::next.
Referenced by build_channels().
12167 { 12168 /* Make a dahdi_pvt structure for this interface */ 12169 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */ 12170 char fn[80]; 12171 struct dahdi_bufferinfo bi; 12172 12173 int res; 12174 #if defined(HAVE_PRI) 12175 int span = 0; 12176 #endif /* defined(HAVE_PRI) */ 12177 int here = 0;/*!< TRUE if the channel interface already exists. */ 12178 int x; 12179 struct analog_pvt *analog_p = NULL; 12180 struct dahdi_params p; 12181 #if defined(HAVE_PRI) 12182 struct dahdi_spaninfo si; 12183 struct sig_pri_chan *pri_chan = NULL; 12184 #endif /* defined(HAVE_PRI) */ 12185 #if defined(HAVE_SS7) 12186 struct sig_ss7_chan *ss7_chan = NULL; 12187 #endif /* defined(HAVE_SS7) */ 12188 12189 /* Search channel interface list to see if it already exists. */ 12190 for (tmp = iflist; tmp; tmp = tmp->next) { 12191 if (!tmp->destroy) { 12192 if (tmp->channel == channel) { 12193 /* The channel interface already exists. */ 12194 here = 1; 12195 break; 12196 } 12197 if (tmp->channel > channel) { 12198 /* No way it can be in the sorted list. */ 12199 tmp = NULL; 12200 break; 12201 } 12202 } 12203 } 12204 12205 if (!here && reloading != 1) { 12206 tmp = ast_calloc(1, sizeof(*tmp)); 12207 if (!tmp) { 12208 return NULL; 12209 } 12210 tmp->cc_params = ast_cc_config_params_init(); 12211 if (!tmp->cc_params) { 12212 ast_free(tmp); 12213 return NULL; 12214 } 12215 ast_mutex_init(&tmp->lock); 12216 ifcount++; 12217 for (x = 0; x < 3; x++) 12218 tmp->subs[x].dfd = -1; 12219 tmp->channel = channel; 12220 tmp->priindication_oob = conf->chan.priindication_oob; 12221 } 12222 12223 if (tmp) { 12224 int chan_sig = conf->chan.sig; 12225 12226 /* If there are variables in tmp before it is updated to match the new config, clear them */ 12227 if (reloading && tmp->vars) { 12228 ast_variables_destroy(tmp->vars); 12229 tmp->vars = NULL; 12230 } 12231 12232 12233 if (!here) { 12234 /* Can only get here if this is a new channel interface being created. */ 12235 if ((channel != CHAN_PSEUDO)) { 12236 int count = 0; 12237 12238 snprintf(fn, sizeof(fn), "%d", channel); 12239 /* Open non-blocking */ 12240 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12241 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 */ 12242 usleep(1); 12243 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 12244 count++; 12245 } 12246 /* Allocate a DAHDI structure */ 12247 if (tmp->subs[SUB_REAL].dfd < 0) { 12248 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); 12249 destroy_dahdi_pvt(tmp); 12250 return NULL; 12251 } 12252 memset(&p, 0, sizeof(p)); 12253 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12254 if (res < 0) { 12255 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 12256 destroy_dahdi_pvt(tmp); 12257 return NULL; 12258 } 12259 if (conf->is_sig_auto) 12260 chan_sig = sigtype_to_signalling(p.sigtype); 12261 if (p.sigtype != (chan_sig & 0x3ffff)) { 12262 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)); 12263 destroy_dahdi_pvt(tmp); 12264 return NULL; 12265 } 12266 tmp->law_default = p.curlaw; 12267 tmp->law = p.curlaw; 12268 tmp->span = p.spanno; 12269 #if defined(HAVE_PRI) 12270 span = p.spanno - 1; 12271 #endif /* defined(HAVE_PRI) */ 12272 } else { 12273 chan_sig = 0; 12274 } 12275 tmp->sig = chan_sig; 12276 tmp->outsigmod = conf->chan.outsigmod; 12277 12278 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) { 12279 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp); 12280 if (!analog_p) { 12281 destroy_dahdi_pvt(tmp); 12282 return NULL; 12283 } 12284 tmp->sig_pvt = analog_p; 12285 } 12286 #if defined(HAVE_SS7) 12287 if (chan_sig == SIG_SS7) { 12288 struct dahdi_ss7 *ss7; 12289 int clear = 0; 12290 12291 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 12292 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12293 destroy_dahdi_pvt(tmp); 12294 return NULL; 12295 } 12296 12297 ss7 = ss7_resolve_linkset(cur_linkset); 12298 if (!ss7) { 12299 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 12300 destroy_dahdi_pvt(tmp); 12301 return NULL; 12302 } 12303 ss7->ss7.span = cur_linkset; 12304 if (cur_cicbeginswith < 0) { 12305 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 12306 destroy_dahdi_pvt(tmp); 12307 return NULL; 12308 } 12309 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7); 12310 if (!ss7_chan) { 12311 destroy_dahdi_pvt(tmp); 12312 return NULL; 12313 } 12314 tmp->sig_pvt = ss7_chan; 12315 tmp->ss7 = &ss7->ss7; 12316 12317 ss7_chan->channel = tmp->channel; 12318 ss7_chan->cic = cur_cicbeginswith++; 12319 12320 /* DB: Add CIC's DPC information */ 12321 ss7_chan->dpc = cur_defaultdpc; 12322 12323 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan; 12324 12325 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix)); 12326 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix)); 12327 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix)); 12328 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix)); 12329 12330 ss7->ss7.called_nai = conf->ss7.ss7.called_nai; 12331 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai; 12332 } 12333 #endif /* defined(HAVE_SS7) */ 12334 #ifdef HAVE_OPENR2 12335 if (chan_sig == SIG_MFCR2) { 12336 struct dahdi_mfcr2 *r2_link; 12337 r2_link = dahdi_r2_get_link(); 12338 if (!r2_link) { 12339 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 12340 destroy_dahdi_pvt(tmp); 12341 return NULL; 12342 } 12343 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 12344 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 12345 destroy_dahdi_pvt(tmp); 12346 return NULL; 12347 } 12348 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) { 12349 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 12350 destroy_dahdi_pvt(tmp); 12351 return NULL; 12352 } 12353 r2_link->pvts[r2_link->numchans++] = tmp; 12354 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 12355 tmp->subs[SUB_REAL].dfd, 12356 NULL, NULL); 12357 if (!tmp->r2chan) { 12358 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 12359 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 12360 destroy_dahdi_pvt(tmp); 12361 return NULL; 12362 } 12363 tmp->mfcr2 = r2_link; 12364 if (conf->mfcr2.call_files) { 12365 openr2_chan_enable_call_files(tmp->r2chan); 12366 } 12367 openr2_chan_set_client_data(tmp->r2chan, tmp); 12368 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 12369 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 12370 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 12371 tmp->mfcr2_category = conf->mfcr2.category; 12372 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 12373 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 12374 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 12375 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 12376 tmp->mfcr2call = 0; 12377 tmp->mfcr2_dnis_index = 0; 12378 tmp->mfcr2_ani_index = 0; 12379 r2_link->monitored_count++; 12380 } 12381 #endif 12382 #ifdef HAVE_PRI 12383 if (dahdi_sig_pri_lib_handles(chan_sig)) { 12384 int offset; 12385 int matchesdchan; 12386 int x,y; 12387 int myswitchtype = 0; 12388 12389 offset = 0; 12390 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 12391 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12392 destroy_dahdi_pvt(tmp); 12393 return NULL; 12394 } 12395 if (span >= NUM_SPANS) { 12396 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 12397 destroy_dahdi_pvt(tmp); 12398 return NULL; 12399 } else { 12400 si.spanno = 0; 12401 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12402 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12403 destroy_dahdi_pvt(tmp); 12404 return NULL; 12405 } 12406 /* Store the logical span first based upon the real span */ 12407 tmp->logicalspan = pris[span].prilogicalspan; 12408 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 12409 if (span < 0) { 12410 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 12411 destroy_dahdi_pvt(tmp); 12412 return NULL; 12413 } 12414 myswitchtype = conf->pri.pri.switchtype; 12415 /* Make sure this isn't a d-channel */ 12416 matchesdchan=0; 12417 for (x = 0; x < NUM_SPANS; x++) { 12418 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 12419 if (pris[x].dchannels[y] == tmp->channel) { 12420 matchesdchan = 1; 12421 break; 12422 } 12423 } 12424 } 12425 if (!matchesdchan) { 12426 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) { 12427 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype)); 12428 destroy_dahdi_pvt(tmp); 12429 return NULL; 12430 } 12431 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) { 12432 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype)); 12433 destroy_dahdi_pvt(tmp); 12434 return NULL; 12435 } 12436 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) { 12437 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)); 12438 destroy_dahdi_pvt(tmp); 12439 return NULL; 12440 } 12441 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) { 12442 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial); 12443 destroy_dahdi_pvt(tmp); 12444 return NULL; 12445 } 12446 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) { 12447 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext); 12448 destroy_dahdi_pvt(tmp); 12449 return NULL; 12450 } 12451 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) { 12452 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused); 12453 destroy_dahdi_pvt(tmp); 12454 return NULL; 12455 } 12456 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) { 12457 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle); 12458 destroy_dahdi_pvt(tmp); 12459 return NULL; 12460 } 12461 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) { 12462 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 12463 pris[span].pri.trunkgroup); 12464 destroy_dahdi_pvt(tmp); 12465 return NULL; 12466 } 12467 12468 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel); 12469 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup); 12470 if (!pri_chan) { 12471 destroy_dahdi_pvt(tmp); 12472 return NULL; 12473 } 12474 tmp->sig_pvt = pri_chan; 12475 tmp->pri = &pris[span].pri; 12476 12477 tmp->priexclusive = conf->chan.priexclusive; 12478 12479 if (!tmp->pri->cc_params) { 12480 tmp->pri->cc_params = ast_cc_config_params_init(); 12481 if (!tmp->pri->cc_params) { 12482 destroy_dahdi_pvt(tmp); 12483 return NULL; 12484 } 12485 } 12486 ast_cc_copy_config_params(tmp->pri->cc_params, 12487 conf->chan.cc_params); 12488 12489 pris[span].pri.sig = chan_sig; 12490 pris[span].pri.nodetype = conf->pri.pri.nodetype; 12491 pris[span].pri.switchtype = myswitchtype; 12492 pris[span].pri.nsf = conf->pri.pri.nsf; 12493 pris[span].pri.dialplan = conf->pri.pri.dialplan; 12494 pris[span].pri.localdialplan = conf->pri.pri.localdialplan; 12495 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt; 12496 pris[span].pri.minunused = conf->pri.pri.minunused; 12497 pris[span].pri.minidle = conf->pri.pri.minidle; 12498 pris[span].pri.overlapdial = conf->pri.pri.overlapdial; 12499 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping; 12500 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval; 12501 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12502 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support; 12503 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12504 #ifdef HAVE_PRI_INBANDDISCONNECT 12505 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect; 12506 #endif 12507 #if defined(HAVE_PRI_CALL_HOLD) 12508 pris[span].pri.hold_disconnect_transfer = 12509 conf->pri.pri.hold_disconnect_transfer; 12510 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 12511 #if defined(HAVE_PRI_CCSS) 12512 pris[span].pri.cc_ptmp_recall_mode = 12513 conf->pri.pri.cc_ptmp_recall_mode; 12514 pris[span].pri.cc_qsig_signaling_link_req = 12515 conf->pri.pri.cc_qsig_signaling_link_req; 12516 pris[span].pri.cc_qsig_signaling_link_rsp = 12517 conf->pri.pri.cc_qsig_signaling_link_rsp; 12518 #endif /* defined(HAVE_PRI_CCSS) */ 12519 #if defined(HAVE_PRI_CALL_WAITING) 12520 pris[span].pri.max_call_waiting_calls = 12521 conf->pri.pri.max_call_waiting_calls; 12522 pris[span].pri.allow_call_waiting_calls = 12523 conf->pri.pri.allow_call_waiting_calls; 12524 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12525 pris[span].pri.transfer = conf->chan.transfer; 12526 pris[span].pri.facilityenable = conf->pri.pri.facilityenable; 12527 #if defined(HAVE_PRI_L2_PERSISTENCE) 12528 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence; 12529 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 12530 #if defined(HAVE_PRI_AOC_EVENTS) 12531 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag; 12532 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup; 12533 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 12534 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag; 12535 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag)); 12536 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list)); 12537 #if defined(HAVE_PRI_MWI) 12538 ast_copy_string(pris[span].pri.mwi_mailboxes, 12539 conf->pri.pri.mwi_mailboxes, 12540 sizeof(pris[span].pri.mwi_mailboxes)); 12541 #endif /* defined(HAVE_PRI_MWI) */ 12542 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial)); 12543 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext)); 12544 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix)); 12545 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix)); 12546 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix)); 12547 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix)); 12548 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix)); 12549 pris[span].pri.resetinterval = conf->pri.pri.resetinterval; 12550 12551 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12552 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x]; 12553 } 12554 12555 #if defined(HAVE_PRI_CALL_WAITING) 12556 /* Channel initial config parameters. */ 12557 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd; 12558 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid; 12559 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname; 12560 pris[span].pri.ch_cfg.immediate = conf->chan.immediate; 12561 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive; 12562 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob; 12563 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid; 12564 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres; 12565 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context)); 12566 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret)); 12567 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12568 } else { 12569 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos); 12570 destroy_dahdi_pvt(tmp); 12571 return NULL; 12572 } 12573 } 12574 } 12575 #endif 12576 } else { 12577 /* already exists in interface list */ 12578 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)); 12579 chan_sig = tmp->sig; 12580 if (tmp->subs[SUB_REAL].dfd > -1) { 12581 memset(&p, 0, sizeof(p)); 12582 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12583 } 12584 } 12585 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 12586 switch (chan_sig) { 12587 case SIG_FXSKS: 12588 case SIG_FXSLS: 12589 case SIG_EM: 12590 case SIG_EM_E1: 12591 case SIG_EMWINK: 12592 case SIG_FEATD: 12593 case SIG_FEATDMF: 12594 case SIG_FEATDMF_TA: 12595 case SIG_FEATB: 12596 case SIG_E911: 12597 case SIG_SF: 12598 case SIG_SFWINK: 12599 case SIG_FGC_CAMA: 12600 case SIG_FGC_CAMAMF: 12601 case SIG_SF_FEATD: 12602 case SIG_SF_FEATDMF: 12603 case SIG_SF_FEATB: 12604 p.starttime = 250; 12605 break; 12606 } 12607 12608 if (tmp->radio) { 12609 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 12610 p.channo = channel; 12611 p.rxwinktime = 1; 12612 p.rxflashtime = 1; 12613 p.starttime = 1; 12614 p.debouncetime = 5; 12615 } else { 12616 p.channo = channel; 12617 /* Override timing settings based on config file */ 12618 if (conf->timing.prewinktime >= 0) 12619 p.prewinktime = conf->timing.prewinktime; 12620 if (conf->timing.preflashtime >= 0) 12621 p.preflashtime = conf->timing.preflashtime; 12622 if (conf->timing.winktime >= 0) 12623 p.winktime = conf->timing.winktime; 12624 if (conf->timing.flashtime >= 0) 12625 p.flashtime = conf->timing.flashtime; 12626 if (conf->timing.starttime >= 0) 12627 p.starttime = conf->timing.starttime; 12628 if (conf->timing.rxwinktime >= 0) 12629 p.rxwinktime = conf->timing.rxwinktime; 12630 if (conf->timing.rxflashtime >= 0) 12631 p.rxflashtime = conf->timing.rxflashtime; 12632 if (conf->timing.debouncetime >= 0) 12633 p.debouncetime = conf->timing.debouncetime; 12634 } 12635 12636 /* don't set parms on a pseudo-channel */ 12637 if (tmp->subs[SUB_REAL].dfd >= 0) 12638 { 12639 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 12640 if (res < 0) { 12641 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 12642 destroy_dahdi_pvt(tmp); 12643 return NULL; 12644 } 12645 } 12646 #if 1 12647 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 12648 memset(&bi, 0, sizeof(bi)); 12649 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 12650 if (!res) { 12651 bi.txbufpolicy = conf->chan.buf_policy; 12652 bi.rxbufpolicy = conf->chan.buf_policy; 12653 bi.numbufs = conf->chan.buf_no; 12654 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 12655 if (res < 0) { 12656 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 12657 } 12658 } else { 12659 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 12660 } 12661 tmp->buf_policy = conf->chan.buf_policy; 12662 tmp->buf_no = conf->chan.buf_no; 12663 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 12664 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 12665 tmp->faxbuf_no = conf->chan.faxbuf_no; 12666 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 12667 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 12668 * The reason the ioctl call above failed should to be determined before worrying about the 12669 * faxbuffer-related ioctl calls */ 12670 tmp->bufsize = bi.bufsize; 12671 } 12672 #endif 12673 tmp->immediate = conf->chan.immediate; 12674 tmp->transfertobusy = conf->chan.transfertobusy; 12675 if (chan_sig & __DAHDI_SIG_FXS) { 12676 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 12677 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 12678 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 12679 } 12680 tmp->ringt_base = ringt_base; 12681 tmp->firstradio = 0; 12682 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 12683 tmp->permcallwaiting = conf->chan.callwaiting; 12684 else 12685 tmp->permcallwaiting = 0; 12686 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 12687 tmp->destroy = 0; 12688 tmp->drings = conf->chan.drings; 12689 12690 /* 10 is a nice default. */ 12691 if (tmp->drings.ringnum[0].range == 0) 12692 tmp->drings.ringnum[0].range = 10; 12693 if (tmp->drings.ringnum[1].range == 0) 12694 tmp->drings.ringnum[1].range = 10; 12695 if (tmp->drings.ringnum[2].range == 0) 12696 tmp->drings.ringnum[2].range = 10; 12697 12698 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 12699 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 12700 tmp->threewaycalling = conf->chan.threewaycalling; 12701 tmp->adsi = conf->chan.adsi; 12702 tmp->use_smdi = conf->chan.use_smdi; 12703 tmp->permhidecallerid = conf->chan.hidecallerid; 12704 tmp->hidecalleridname = conf->chan.hidecalleridname; 12705 tmp->callreturn = conf->chan.callreturn; 12706 tmp->echocancel = conf->chan.echocancel; 12707 tmp->echotraining = conf->chan.echotraining; 12708 tmp->pulse = conf->chan.pulse; 12709 if (tmp->echocancel.head.tap_length) { 12710 tmp->echocanbridged = conf->chan.echocanbridged; 12711 } else { 12712 if (conf->chan.echocanbridged) 12713 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 12714 tmp->echocanbridged = 0; 12715 } 12716 tmp->busydetect = conf->chan.busydetect; 12717 tmp->busycount = conf->chan.busycount; 12718 tmp->busycompare = conf->chan.busycompare; 12719 tmp->busytonelength = conf->chan.busytonelength; 12720 tmp->busyquietlength = conf->chan.busyquietlength; 12721 tmp->busyfuzziness = conf->chan.busyfuzziness; 12722 tmp->silencethreshold = conf->chan.silencethreshold; 12723 tmp->callprogress = conf->chan.callprogress; 12724 tmp->waitfordialtone = conf->chan.waitfordialtone; 12725 tmp->cancallforward = conf->chan.cancallforward; 12726 tmp->dtmfrelax = conf->chan.dtmfrelax; 12727 tmp->callwaiting = tmp->permcallwaiting; 12728 tmp->hidecallerid = tmp->permhidecallerid; 12729 tmp->channel = channel; 12730 tmp->stripmsd = conf->chan.stripmsd; 12731 tmp->use_callerid = conf->chan.use_callerid; 12732 tmp->cid_signalling = conf->chan.cid_signalling; 12733 tmp->cid_start = conf->chan.cid_start; 12734 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 12735 tmp->restrictcid = conf->chan.restrictcid; 12736 tmp->use_callingpres = conf->chan.use_callingpres; 12737 if (tmp->usedistinctiveringdetection) { 12738 if (!tmp->use_callerid) { 12739 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 12740 tmp->use_callerid = 1; 12741 } 12742 } 12743 12744 if (tmp->cid_signalling == CID_SIG_SMDI) { 12745 if (!tmp->use_smdi) { 12746 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 12747 tmp->use_smdi = 1; 12748 } 12749 } 12750 if (tmp->use_smdi) { 12751 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 12752 if (!(tmp->smdi_iface)) { 12753 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 12754 tmp->use_smdi = 0; 12755 } 12756 } 12757 12758 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 12759 tmp->amaflags = conf->chan.amaflags; 12760 if (!here) { 12761 tmp->confno = -1; 12762 tmp->propconfno = -1; 12763 } 12764 tmp->canpark = conf->chan.canpark; 12765 tmp->transfer = conf->chan.transfer; 12766 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 12767 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 12768 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 12769 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 12770 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 12771 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 12772 tmp->cid_ton = 0; 12773 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) { 12774 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 12775 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 12776 } else { 12777 tmp->cid_num[0] = '\0'; 12778 tmp->cid_name[0] = '\0'; 12779 } 12780 #if defined(HAVE_PRI) 12781 if (dahdi_sig_pri_lib_handles(tmp->sig)) { 12782 tmp->cid_tag[0] = '\0'; 12783 } else 12784 #endif /* defined(HAVE_PRI) */ 12785 { 12786 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); 12787 } 12788 tmp->cid_subaddr[0] = '\0'; 12789 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 12790 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 12791 char *mailbox, *context; 12792 mailbox = context = ast_strdupa(tmp->mailbox); 12793 strsep(&context, "@"); 12794 if (ast_strlen_zero(context)) 12795 context = "default"; 12796 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL, 12797 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 12798 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 12799 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 12800 AST_EVENT_IE_END); 12801 } 12802 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 12803 tmp->mwisend_setting = conf->chan.mwisend_setting; 12804 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 12805 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 12806 #endif 12807 12808 tmp->group = conf->chan.group; 12809 tmp->callgroup = conf->chan.callgroup; 12810 tmp->pickupgroup= conf->chan.pickupgroup; 12811 if (conf->chan.vars) { 12812 struct ast_variable *v, *tmpvar; 12813 for (v = conf->chan.vars ; v ; v = v->next) { 12814 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 12815 tmpvar->next = tmp->vars; 12816 tmp->vars = tmpvar; 12817 } 12818 } 12819 } 12820 tmp->cid_rxgain = conf->chan.cid_rxgain; 12821 tmp->rxgain = conf->chan.rxgain; 12822 tmp->txgain = conf->chan.txgain; 12823 tmp->txdrc = conf->chan.txdrc; 12824 tmp->rxdrc = conf->chan.rxdrc; 12825 tmp->tonezone = conf->chan.tonezone; 12826 if (tmp->subs[SUB_REAL].dfd > -1) { 12827 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law); 12828 if (tmp->dsp) 12829 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 12830 update_conf(tmp); 12831 if (!here) { 12832 switch (chan_sig) { 12833 case SIG_PRI_LIB_HANDLE_CASES: 12834 case SIG_SS7: 12835 case SIG_MFCR2: 12836 break; 12837 default: 12838 /* Hang it up to be sure it's good */ 12839 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 12840 break; 12841 } 12842 } 12843 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 12844 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 12845 /* the dchannel is down so put the channel in alarm */ 12846 switch (tmp->sig) { 12847 #ifdef HAVE_PRI 12848 case SIG_PRI_LIB_HANDLE_CASES: 12849 sig_pri_set_alarm(tmp->sig_pvt, 1); 12850 break; 12851 #endif 12852 #if defined(HAVE_SS7) 12853 case SIG_SS7: 12854 sig_ss7_set_alarm(tmp->sig_pvt, 1); 12855 break; 12856 #endif /* defined(HAVE_SS7) */ 12857 default: 12858 /* The only sig submodule left should be sig_analog. */ 12859 analog_p = tmp->sig_pvt; 12860 if (analog_p) { 12861 analog_p->inalarm = 1; 12862 } 12863 tmp->inalarm = 1; 12864 break; 12865 } 12866 handle_alarms(tmp, res); 12867 } 12868 } 12869 12870 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 12871 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 12872 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 12873 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 12874 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); 12875 12876 if (!here) { 12877 tmp->locallyblocked = 0; 12878 tmp->remotelyblocked = 0; 12879 switch (tmp->sig) { 12880 #if defined(HAVE_PRI) 12881 case SIG_PRI_LIB_HANDLE_CASES: 12882 tmp->inservice = 1;/* Inservice until actually implemented. */ 12883 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12884 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0; 12885 if (chan_sig == SIG_PRI) { 12886 char db_chan_name[20]; 12887 char db_answer[5]; 12888 12889 /* 12890 * Initialize the active out-of-service status 12891 * and delete any record if the feature is not enabled. 12892 */ 12893 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); 12894 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 12895 unsigned *why; 12896 12897 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 12898 if (tmp->pri->enable_service_message_support) { 12899 char state; 12900 12901 sscanf(db_answer, "%1c:%30u", &state, why); 12902 12903 /* Ensure that only the implemented bits could be set.*/ 12904 *why &= (SRVST_NEAREND | SRVST_FAREND); 12905 } 12906 if (!*why) { 12907 ast_db_del(db_chan_name, SRVST_DBKEY); 12908 } 12909 } 12910 } 12911 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12912 break; 12913 #endif /* defined(HAVE_PRI) */ 12914 #if defined(HAVE_SS7) 12915 case SIG_SS7: 12916 tmp->inservice = 0; 12917 break; 12918 #endif /* defined(HAVE_SS7) */ 12919 default: 12920 /* We default to in service on protocols that don't have a reset */ 12921 tmp->inservice = 1; 12922 break; 12923 } 12924 } 12925 12926 switch (tmp->sig) { 12927 #if defined(HAVE_PRI) 12928 case SIG_PRI_LIB_HANDLE_CASES: 12929 if (pri_chan) { 12930 pri_chan->channel = tmp->channel; 12931 pri_chan->hidecallerid = tmp->hidecallerid; 12932 pri_chan->hidecalleridname = tmp->hidecalleridname; 12933 pri_chan->immediate = tmp->immediate; 12934 pri_chan->inalarm = tmp->inalarm; 12935 pri_chan->priexclusive = tmp->priexclusive; 12936 pri_chan->priindication_oob = tmp->priindication_oob; 12937 pri_chan->use_callerid = tmp->use_callerid; 12938 pri_chan->use_callingpres = tmp->use_callingpres; 12939 ast_copy_string(pri_chan->context, tmp->context, 12940 sizeof(pri_chan->context)); 12941 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret, 12942 sizeof(pri_chan->mohinterpret)); 12943 pri_chan->stripmsd = tmp->stripmsd; 12944 } 12945 break; 12946 #endif /* defined(HAVE_PRI) */ 12947 #if defined(HAVE_SS7) 12948 case SIG_SS7: 12949 if (ss7_chan) { 12950 ss7_chan->inalarm = tmp->inalarm; 12951 12952 ss7_chan->stripmsd = tmp->stripmsd; 12953 ss7_chan->hidecallerid = tmp->hidecallerid; 12954 ss7_chan->use_callerid = tmp->use_callerid; 12955 ss7_chan->use_callingpres = tmp->use_callingpres; 12956 ss7_chan->immediate = tmp->immediate; 12957 ss7_chan->locallyblocked = tmp->locallyblocked; 12958 ss7_chan->remotelyblocked = tmp->remotelyblocked; 12959 ast_copy_string(ss7_chan->context, tmp->context, 12960 sizeof(ss7_chan->context)); 12961 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret, 12962 sizeof(ss7_chan->mohinterpret)); 12963 } 12964 break; 12965 #endif /* defined(HAVE_SS7) */ 12966 default: 12967 /* The only sig submodule left should be sig_analog. */ 12968 analog_p = tmp->sig_pvt; 12969 if (analog_p) { 12970 analog_p->channel = tmp->channel; 12971 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 12972 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 12973 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 12974 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ 12975 analog_p->callreturn = conf->chan.callreturn; 12976 analog_p->cancallforward = conf->chan.cancallforward; 12977 analog_p->canpark = conf->chan.canpark; 12978 analog_p->dahditrcallerid = conf->chan.dahditrcallerid; 12979 analog_p->immediate = conf->chan.immediate; 12980 analog_p->permhidecallerid = conf->chan.permhidecallerid; 12981 analog_p->pulse = conf->chan.pulse; 12982 analog_p->threewaycalling = conf->chan.threewaycalling; 12983 analog_p->transfer = conf->chan.transfer; 12984 analog_p->transfertobusy = conf->chan.transfertobusy; 12985 analog_p->use_callerid = tmp->use_callerid; 12986 analog_p->use_smdi = tmp->use_smdi; 12987 analog_p->smdi_iface = tmp->smdi_iface; 12988 analog_p->outsigmod = ANALOG_SIG_NONE; 12989 analog_p->echotraining = conf->chan.echotraining; 12990 analog_p->cid_signalling = conf->chan.cid_signalling; 12991 analog_p->stripmsd = conf->chan.stripmsd; 12992 switch (conf->chan.cid_start) { 12993 case CID_START_POLARITY: 12994 analog_p->cid_start = ANALOG_CID_START_POLARITY; 12995 break; 12996 case CID_START_POLARITY_IN: 12997 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; 12998 break; 12999 case CID_START_DTMF_NOALERT: 13000 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; 13001 break; 13002 default: 13003 analog_p->cid_start = ANALOG_CID_START_RING; 13004 break; 13005 } 13006 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; 13007 analog_p->ringt = conf->chan.ringt; 13008 analog_p->ringt_base = ringt_base; 13009 analog_p->chan_tech = &dahdi_tech; 13010 analog_p->onhooktime = time(NULL); 13011 if (chan_sig & __DAHDI_SIG_FXO) { 13012 memset(&p, 0, sizeof(p)); 13013 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 13014 if (!res) { 13015 analog_p->fxsoffhookstate = p.rxisoffhook; 13016 } 13017 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 13018 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 13019 #endif 13020 } 13021 analog_p->msgstate = -1; 13022 13023 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); 13024 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); 13025 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); 13026 13027 analog_config_complete(analog_p); 13028 } 13029 break; 13030 } 13031 #if defined(HAVE_PRI) 13032 if (tmp->channel == CHAN_PSEUDO) { 13033 /* 13034 * Save off pseudo channel buffer policy values for dynamic creation of 13035 * no B channel interfaces. 13036 */ 13037 dahdi_pseudo_parms.buf_no = tmp->buf_no; 13038 dahdi_pseudo_parms.buf_policy = tmp->buf_policy; 13039 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no; 13040 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy; 13041 } 13042 #endif /* defined(HAVE_PRI) */ 13043 } 13044 if (tmp && !here) { 13045 /* Add the new channel interface to the sorted channel interface list. */ 13046 dahdi_iflist_insert(tmp); 13047 } 13048 return tmp; 13049 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 480 of file chan_dahdi.c.
Referenced by add_peer_mwi_subs(), build_peer(), config_line(), and skinny_register().
00481 { 00482 /* This module does not handle MWI in an event-based manner. However, it 00483 * subscribes to MWI for each mailbox that is configured so that the core 00484 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00485 * event cache instead of checking the mailbox directly. */ 00486 }
static int mwi_send_init | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 11105 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, has_voicemail(), MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisend_fsk, dahdi_pvt::mwisend_rpas, dahdi_pvt::mwisendactive, SUB_REAL, and dahdi_pvt::subs.
11106 { 11107 int x; 11108 11109 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11110 /* Determine how this spill is to be sent */ 11111 if (pvt->mwisend_rpas) { 11112 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11113 pvt->mwisendactive = 1; 11114 } else if (pvt->mwisend_fsk) { 11115 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11116 pvt->mwisendactive = 1; 11117 } else { 11118 pvt->mwisendactive = 0; 11119 return 0; 11120 } 11121 #else 11122 if (mwisend_rpas) { 11123 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 11124 } else { 11125 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11126 } 11127 pvt->mwisendactive = 1; 11128 #endif 11129 11130 if (pvt->cidspill) { 11131 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 11132 ast_free(pvt->cidspill); 11133 pvt->cidspill = NULL; 11134 pvt->cidpos = 0; 11135 pvt->cidlen = 0; 11136 } 11137 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 11138 if (!pvt->cidspill) { 11139 pvt->mwisendactive = 0; 11140 return -1; 11141 } 11142 x = DAHDI_FLUSH_BOTH; 11143 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 11144 x = 3000; 11145 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 11146 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11147 if (pvt->mwisend_fsk) { 11148 #endif 11149 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 11150 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 11151 pvt->cidpos = 0; 11152 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11153 } 11154 #endif 11155 return 0; 11156 }
static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
int | num_read | |||
) | [static] |
Definition at line 11158 of file chan_dahdi.c.
References AS_RP_cadence, ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, 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::mwisend_fsk, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.
11159 { 11160 struct timeval now; 11161 int res; 11162 11163 /* sanity check to catch if this had been interrupted previously 11164 * i.e. state says there is more to do but there is no spill allocated 11165 */ 11166 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 11167 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11168 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11169 /* Normal processing -- Perform mwi send action */ 11170 switch ( pvt->mwisend_data.mwisend_current) { 11171 case MWI_SEND_SA: 11172 /* Send the Ring Pulse Signal Alert */ 11173 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 11174 if (res) { 11175 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 11176 goto quit; 11177 } 11178 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 11179 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 11180 break; 11181 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 11182 break; 11183 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 11184 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11185 if (pvt->mwisend_fsk) { 11186 #endif 11187 gettimeofday(&now, NULL); 11188 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 11189 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 11190 } 11191 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 11192 } else { /* support for mwisendtype=nofsk */ 11193 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11194 } 11195 #endif 11196 break; 11197 case MWI_SEND_SPILL: 11198 /* We read some number of bytes. Write an equal amount of data */ 11199 if(0 < num_read) { 11200 if (num_read > pvt->cidlen - pvt->cidpos) 11201 num_read = pvt->cidlen - pvt->cidpos; 11202 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 11203 if (res > 0) { 11204 pvt->cidpos += res; 11205 if (pvt->cidpos >= pvt->cidlen) { 11206 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 11207 } 11208 } else { 11209 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 11210 goto quit; 11211 } 11212 } 11213 break; 11214 case MWI_SEND_CLEANUP: 11215 /* For now, do nothing */ 11216 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11217 break; 11218 default: 11219 /* Should not get here, punt*/ 11220 goto quit; 11221 } 11222 } 11223 11224 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 11225 if (pvt->cidspill) { 11226 ast_free(pvt->cidspill); 11227 pvt->cidspill = NULL; 11228 pvt->cidpos = 0; 11229 pvt->cidlen = 0; 11230 } 11231 pvt->mwisendactive = 0; 11232 } 11233 return 0; 11234 quit: 11235 if (pvt->cidspill) { 11236 ast_free(pvt->cidspill); 11237 pvt->cidspill = NULL; 11238 pvt->cidpos = 0; 11239 pvt->cidlen = 0; 11240 } 11241 pvt->mwisendactive = 0; 11242 return -1; 11243 }
static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
int | event | |||
) | [static] |
Definition at line 11245 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), errno, 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.
11246 { 11247 int handled = 0; 11248 11249 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11250 switch (event) { 11251 case DAHDI_EVENT_RINGEROFF: 11252 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 11253 handled = 1; 11254 11255 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 11256 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno)); 11257 ast_free(pvt->cidspill); 11258 pvt->cidspill = NULL; 11259 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11260 pvt->mwisendactive = 0; 11261 } else { 11262 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 11263 gettimeofday(&pvt->mwisend_data.pause, NULL); 11264 } 11265 } 11266 break; 11267 /* Going off hook, I need to punt this spill */ 11268 case DAHDI_EVENT_RINGOFFHOOK: 11269 if (pvt->cidspill) { 11270 ast_free(pvt->cidspill); 11271 pvt->cidspill = NULL; 11272 pvt->cidpos = 0; 11273 pvt->cidlen = 0; 11274 } 11275 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11276 pvt->mwisendactive = 0; 11277 break; 11278 case DAHDI_EVENT_RINGERON: 11279 case DAHDI_EVENT_HOOKCOMPLETE: 11280 break; 11281 default: 11282 break; 11283 } 11284 } 11285 return handled; 11286 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 10949 of file chan_dahdi.c.
References analog_lib_handles(), analog_ss_thread(), analog_ss_thread_start(), 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_new(), dahdi_pvt::channel, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), errno, event2str(), get_alarms(), handle_alarms(), handle_clear_alarms(), dahdi_pvt::inalarm, analog_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, mwilevel, dahdi_pvt::mwimonitoractive, name, 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.
10950 { 10951 struct mwi_thread_data *mtd = data; 10952 struct callerid_state *cs; 10953 pthread_t threadid; 10954 int samples = 0; 10955 char *name, *number; 10956 int flags; 10957 int i, res; 10958 unsigned int spill_done = 0; 10959 int spill_result = -1; 10960 10961 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 10962 mtd->pvt->mwimonitoractive = 0; 10963 10964 return NULL; 10965 } 10966 10967 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 10968 10969 bump_gains(mtd->pvt); 10970 10971 for (;;) { 10972 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10973 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 10974 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10975 goto quit; 10976 } 10977 10978 if (i & DAHDI_IOMUX_SIGEVENT) { 10979 struct ast_channel *chan; 10980 10981 /* If we get an event, screen out events that we do not act on. 10982 * Otherwise, cancel and go to the simple switch to let it deal with it. 10983 */ 10984 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 10985 10986 switch (res) { 10987 case DAHDI_EVENT_NEONMWI_ACTIVE: 10988 case DAHDI_EVENT_NEONMWI_INACTIVE: 10989 case DAHDI_EVENT_NONE: 10990 case DAHDI_EVENT_BITSCHANGED: 10991 break; 10992 case DAHDI_EVENT_NOALARM: 10993 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 10994 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 10995 10996 analog_p->inalarm = 0; 10997 } 10998 mtd->pvt->inalarm = 0; 10999 handle_clear_alarms(mtd->pvt); 11000 break; 11001 case DAHDI_EVENT_ALARM: 11002 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11003 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 11004 11005 analog_p->inalarm = 1; 11006 } 11007 mtd->pvt->inalarm = 1; 11008 res = get_alarms(mtd->pvt); 11009 handle_alarms(mtd->pvt, res); 11010 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 11011 default: 11012 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res)); 11013 callerid_free(cs); 11014 11015 restore_gains(mtd->pvt); 11016 mtd->pvt->ringt = mtd->pvt->ringt_base; 11017 11018 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) { 11019 int result; 11020 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 11021 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan); 11022 } else { 11023 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11024 } 11025 if (result) { 11026 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 11027 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11028 if (res < 0) 11029 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 11030 ast_hangup(chan); 11031 goto quit; 11032 } 11033 goto quit_no_clean; 11034 11035 } else { 11036 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 11037 } 11038 } 11039 } else if (i & DAHDI_IOMUX_READ) { 11040 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 11041 if (errno != ELAST) { 11042 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 11043 goto quit; 11044 } 11045 break; 11046 } 11047 samples += res; 11048 if (!spill_done) { 11049 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 11050 /* 11051 * The previous diagnostic message output likely 11052 * explains why it failed. 11053 */ 11054 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 11055 break; 11056 } else if (spill_result) { 11057 spill_done = 1; 11058 } 11059 } else { 11060 /* keep reading data until the energy level drops below the threshold 11061 so we don't get another 'trigger' on the remaining carrier signal 11062 */ 11063 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 11064 break; 11065 } 11066 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 11067 break; 11068 } 11069 } 11070 11071 if (spill_result == 1) { 11072 callerid_get(cs, &name, &number, &flags); 11073 if (flags & CID_MSGWAITING) { 11074 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 11075 notify_message(mtd->pvt->mailbox, 1); 11076 } else if (flags & CID_NOMSGWAITING) { 11077 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 11078 notify_message(mtd->pvt->mailbox, 0); 11079 } else { 11080 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 11081 } 11082 } 11083 11084 11085 quit: 11086 callerid_free(cs); 11087 11088 restore_gains(mtd->pvt); 11089 11090 quit_no_clean: 11091 mtd->pvt->mwimonitoractive = 0; 11092 11093 ast_free(mtd); 11094 11095 return NULL; 11096 }
static void my_all_subchannels_hungup | ( | void * | pvt | ) | [static] |
Definition at line 2400 of file chan_dahdi.c.
References ast_dsp_free(), ast_log(), dahdi_pvt::channel, dahdi_setlinear(), dahdi_pvt::didtdd, dahdi_pvt::dsp, errno, dahdi_pvt::faxhandled, dahdi_pvt::law, dahdi_pvt::law_default, LOG_WARNING, num_restart_pending, dahdi_subchannel::owner, dahdi_pvt::owner, reset_conf(), restart_monitor(), SUB_REAL, and dahdi_pvt::subs.
02401 { 02402 struct dahdi_pvt *p = pvt; 02403 int res, law; 02404 02405 p->faxhandled = 0; 02406 p->didtdd = 0; 02407 02408 if (p->dsp) { 02409 ast_dsp_free(p->dsp); 02410 p->dsp = NULL; 02411 } 02412 02413 p->law = p->law_default; 02414 law = p->law_default; 02415 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02416 if (res < 0) 02417 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02418 02419 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02420 02421 #if 1 02422 { 02423 int i; 02424 p->owner = NULL; 02425 /* Cleanup owners here */ 02426 for (i = 0; i < 3; i++) { 02427 p->subs[i].owner = NULL; 02428 } 02429 } 02430 #endif 02431 02432 reset_conf(p); 02433 if (num_restart_pending == 0) { 02434 restart_monitor(); 02435 } 02436 }
static int my_allocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2678 of file chan_dahdi.c.
References alloc_sub(), and analogsub_to_dahdisub().
02679 { 02680 struct dahdi_pvt *p = pvt; 02681 02682 return alloc_sub(p, analogsub_to_dahdisub(analogsub)); 02683 }
static void my_ami_channel_event | ( | void * | pvt, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2175 of file chan_dahdi.c.
References dahdi_ami_channel_event().
02176 { 02177 struct dahdi_pvt *p = pvt; 02178 02179 dahdi_ami_channel_event(p, chan); 02180 }
static void my_answer_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2916 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().
02917 { 02918 struct dahdi_pvt *p = pvt; 02919 02920 if (!p->answeronpolarityswitch) { 02921 return; 02922 } 02923 02924 my_set_polarity(pvt, 1); 02925 }
static int my_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1904 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().
01905 { 01906 struct dahdi_pvt *p = pvt; 01907 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01908 if (p->cidspill) { 01909 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01910 ast_free(p->cidspill); 01911 } 01912 01913 /* 01914 * SAS: Subscriber Alert Signal, 440Hz for 300ms 01915 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 01916 */ 01917 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01918 return -1; 01919 save_conference(p); 01920 /* Silence */ 01921 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01922 if (!p->callwaitrings && p->callwaitingcallerid) { 01923 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01924 p->callwaitcas = 1; 01925 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01926 } else { 01927 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01928 p->callwaitcas = 0; 01929 p->cidlen = 2400 + READ_SIZE * 4; 01930 } 01931 p->cidpos = 0; 01932 send_callerid(p); 01933 01934 return 0; 01935 }
static void my_cancel_cidspill | ( | void * | pvt | ) | [static] |
Definition at line 2350 of file chan_dahdi.c.
References ast_free, dahdi_pvt::cidspill, and restore_conference().
02351 { 02352 struct dahdi_pvt *p = pvt; 02353 02354 ast_free(p->cidspill); 02355 p->cidspill = NULL; 02356 restore_conference(p); 02357 }
static int my_check_confirmanswer | ( | void * | pvt | ) | [static] |
Definition at line 2333 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02334 { 02335 struct dahdi_pvt *p = pvt; 02336 if (p->confirmanswer) { 02337 return 1; 02338 } 02339 02340 return 0; 02341 }
static int my_check_for_conference | ( | void * | pvt | ) | [static] |
Definition at line 2510 of file chan_dahdi.c.
References check_for_conference().
02511 { 02512 struct dahdi_pvt *p = pvt; 02513 return check_for_conference(p); 02514 }
static int my_check_waitingfordt | ( | void * | pvt | ) | [static] |
Definition at line 2316 of file chan_dahdi.c.
References dahdi_pvt::waitingfordt.
02317 { 02318 struct dahdi_pvt *p = pvt; 02319 02320 if (p->waitingfordt.tv_usec) { 02321 return 1; 02322 } 02323 02324 return 0; 02325 }
static int my_complete_conference_update | ( | void * | pvt, | |
int | needconference | |||
) | [static] |
Definition at line 2460 of file chan_dahdi.c.
References conf_add(), GET_CHANNEL, isslavenative(), MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
02461 { 02462 struct dahdi_pvt *p = pvt; 02463 int needconf = needconference; 02464 int x; 02465 int useslavenative; 02466 struct dahdi_pvt *slave = NULL; 02467 02468 useslavenative = isslavenative(p, &slave); 02469 02470 /* If we have a slave, add him to our conference now. or DAX 02471 if this is slave native */ 02472 for (x = 0; x < MAX_SLAVES; x++) { 02473 if (p->slaves[x]) { 02474 if (useslavenative) 02475 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02476 else { 02477 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02478 needconf++; 02479 } 02480 } 02481 } 02482 /* If we're supposed to be in there, do so now */ 02483 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02484 if (useslavenative) 02485 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02486 else { 02487 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02488 needconf++; 02489 } 02490 } 02491 /* If we have a master, add ourselves to his conference */ 02492 if (p->master) { 02493 if (isslavenative(p->master, NULL)) { 02494 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02495 } else { 02496 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02497 } 02498 } 02499 if (!needconf) { 02500 /* Nobody is left (or should be left) in our conference. 02501 Kill it. */ 02502 p->confno = -1; 02503 } 02504 02505 return 0; 02506 }
static int my_conf_add | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2450 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.
02451 { 02452 struct dahdi_pvt *p = pvt; 02453 int x = analogsub_to_dahdisub(sub); 02454 02455 return conf_add(p, &p->subs[x], x, 0); 02456 }
static int my_conf_del | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2440 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.
02441 { 02442 struct dahdi_pvt *p = pvt; 02443 int x = analogsub_to_dahdisub(sub); 02444 02445 return conf_del(p, &p->subs[x], x); 02446 }
static int my_confmute | ( | void * | pvt, | |
int | mute | |||
) | [static] |
Definition at line 2359 of file chan_dahdi.c.
References dahdi_confmute().
02360 { 02361 struct dahdi_pvt *p = pvt; 02362 return dahdi_confmute(p, mute); 02363 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | idx, | |||
int | linear | |||
) | [static] |
Definition at line 9224 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().
09225 { 09226 int sent=0; 09227 int size; 09228 int res; 09229 int fd; 09230 fd = p->subs[idx].dfd; 09231 while (len) { 09232 size = len; 09233 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 09234 size = (linear ? READ_SIZE * 2 : READ_SIZE); 09235 res = write(fd, buf, size); 09236 if (res != size) { 09237 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 09238 return sent; 09239 } 09240 len -= size; 09241 buf += size; 09242 } 09243 return sent; 09244 }
static void my_deadlock_avoidance_private | ( | void * | pvt | ) | [static] |
Definition at line 2122 of file chan_dahdi.c.
References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.
02123 { 02124 struct dahdi_pvt *p = pvt; 02125 02126 DEADLOCK_AVOIDANCE(&p->lock); 02127 }
static void my_decrease_ss_count | ( | void | ) | [static] |
Definition at line 2392 of file chan_dahdi.c.
References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ss_thread_complete, ss_thread_count, and ss_thread_lock.
02393 { 02394 ast_mutex_lock(&ss_thread_lock); 02395 ss_thread_count--; 02396 ast_cond_signal(&ss_thread_complete); 02397 ast_mutex_unlock(&ss_thread_lock); 02398 }
static int my_dial_digits | ( | void * | pvt, | |
enum analog_sub | sub, | |||
struct analog_dialoperation * | dop | |||
) | [static] |
Definition at line 2950 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, ast_channel::name, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.
02951 { 02952 int index = analogsub_to_dahdisub(sub); 02953 int res; 02954 struct dahdi_pvt *p = pvt; 02955 struct dahdi_dialoperation ddop; 02956 02957 if (dop->op != ANALOG_DIAL_OP_REPLACE) { 02958 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n"); 02959 return -1; 02960 } 02961 02962 if (sub != ANALOG_SUB_REAL) { 02963 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n", 02964 dop->dialstr, p->channel, sub); 02965 return -1; 02966 } 02967 02968 ddop.op = DAHDI_DIAL_OP_REPLACE; 02969 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr)); 02970 02971 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr); 02972 02973 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop); 02974 if (res == -1) { 02975 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno)); 02976 } 02977 02978 return res; 02979 }
static int my_distinctive_ring | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | idx, | |||
int * | ringdata | |||
) | [static] |
Definition at line 1768 of file chan_dahdi.c.
References ast_copy_string(), ast_hangup(), ast_log(), ast_verb, ast_channel::context, dahdi_pvt::context, dahdi_get_event(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, errno, event2str(), analog_pvt::inalarm, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, RING_PATTERNS, analog_pvt::ringt, analog_pvt::ringt_base, dahdi_pvt::sig_pvt, and dahdi_pvt::subs.
01769 { 01770 unsigned char buf[256]; 01771 int distMatches; 01772 int curRingData[RING_PATTERNS]; 01773 int receivedRingT; 01774 int counter1; 01775 int counter; 01776 int i; 01777 int res; 01778 int checkaftercid = 0; 01779 01780 struct dahdi_pvt *p = pvt; 01781 struct analog_pvt *analog_p = p->sig_pvt; 01782 01783 if (ringdata == NULL) { 01784 ringdata = curRingData; 01785 } else { 01786 checkaftercid = 1; 01787 } 01788 01789 /* We must have a ring by now, so, if configured, lets try to listen for 01790 * distinctive ringing */ 01791 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { 01792 /* Clear the current ring data array so we don't have old data in it. */ 01793 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++) 01794 ringdata[receivedRingT] = 0; 01795 receivedRingT = 0; 01796 if (checkaftercid && distinctiveringaftercid) 01797 ast_verb(3, "Detecting post-CID distinctive ring\n"); 01798 /* Check to see if context is what it should be, if not set to be. */ 01799 else if (strcmp(p->context,p->defcontext) != 0) { 01800 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 01801 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 01802 } 01803 01804 for (;;) { 01805 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 01806 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 01807 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 01808 ast_hangup(chan); 01809 return 1; 01810 } 01811 if (i & DAHDI_IOMUX_SIGEVENT) { 01812 res = dahdi_get_event(p->subs[idx].dfd); 01813 if (res == DAHDI_EVENT_NOALARM) { 01814 p->inalarm = 0; 01815 analog_p->inalarm = 0; 01816 } 01817 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 01818 res = 0; 01819 /* Let us detect distinctive ring */ 01820 01821 ringdata[receivedRingT] = analog_p->ringt; 01822 01823 if (analog_p->ringt < analog_p->ringt_base/2) 01824 break; 01825 /* Increment the ringT counter so we can match it against 01826 values in chan_dahdi.conf for distinctive ring */ 01827 if (++receivedRingT == RING_PATTERNS) 01828 break; 01829 } else if (i & DAHDI_IOMUX_READ) { 01830 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 01831 if (res < 0) { 01832 if (errno != ELAST) { 01833 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01834 ast_hangup(chan); 01835 return 1; 01836 } 01837 break; 01838 } 01839 if (analog_p->ringt > 0) { 01840 if (!(--analog_p->ringt)) { 01841 res = -1; 01842 break; 01843 } 01844 } 01845 } 01846 } 01847 } 01848 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { 01849 /* this only shows up if you have n of the dring patterns filled in */ 01850 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); 01851 for (counter = 0; counter < 3; counter++) { 01852 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ 01853 distMatches = 0; 01854 /* this only shows up if you have n of the dring patterns filled in */ 01855 ast_verb(3, "Checking %d,%d,%d\n", 01856 p->drings.ringnum[counter].ring[0], 01857 p->drings.ringnum[counter].ring[1], 01858 p->drings.ringnum[counter].ring[2]); 01859 for (counter1 = 0; counter1 < 3; counter1++) { 01860 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 01861 if (p->drings.ringnum[counter].ring[counter1] == -1) { 01862 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 01863 ringdata[counter1]); 01864 distMatches++; 01865 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 01866 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 01867 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 01868 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 01869 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 01870 distMatches++; 01871 } 01872 } 01873 01874 if (distMatches == 3) { 01875 /* The ring matches, set the context to whatever is for distinctive ring.. */ 01876 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 01877 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 01878 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 01879 break; 01880 } 01881 } 01882 } 01883 /* Restore linear mode (if appropriate) for Caller*ID processing */ 01884 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 01885 restore_gains(p); 01886 01887 return 0; 01888 }
static int my_dsp_reset_and_flush_digits | ( | void * | pvt | ) | [static] |
Definition at line 1972 of file chan_dahdi.c.
References ast_dsp_digitreset(), and dahdi_pvt::dsp.
01973 { 01974 struct dahdi_pvt *p = pvt; 01975 if (p->dsp) 01976 ast_dsp_digitreset(p->dsp); 01977 01978 return 0; 01979 }
static int my_dsp_set_digitmode | ( | void * | pvt, | |
enum analog_dsp_digitmode | mode | |||
) | [static] |
Definition at line 1981 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.
01982 { 01983 struct dahdi_pvt *p = pvt; 01984 01985 if (p->channel == CHAN_PSEUDO) 01986 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n"); 01987 01988 if (mode == ANALOG_DIGITMODE_DTMF) { 01989 /* If we do hardware dtmf, no need for a DSP */ 01990 if (p->hardwaredtmf) { 01991 if (p->dsp) { 01992 ast_dsp_free(p->dsp); 01993 p->dsp = NULL; 01994 } 01995 return 0; 01996 } 01997 01998 if (!p->dsp) { 01999 p->dsp = ast_dsp_new(); 02000 if (!p->dsp) { 02001 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02002 return -1; 02003 } 02004 } 02005 02006 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 02007 } else if (mode == ANALOG_DIGITMODE_MF) { 02008 if (!p->dsp) { 02009 p->dsp = ast_dsp_new(); 02010 if (!p->dsp) { 02011 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 02012 return -1; 02013 } 02014 } 02015 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 02016 } 02017 return 0; 02018 }
static int my_flash | ( | void * | pvt | ) | [static] |
Definition at line 2875 of file chan_dahdi.c.
References SUB_REAL, and dahdi_pvt::subs.
02876 { 02877 struct dahdi_pvt *p = pvt; 02878 int func = DAHDI_FLASH; 02879 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func); 02880 }
static void my_get_and_handle_alarms | ( | void * | pvt | ) | [static] |
Definition at line 2208 of file chan_dahdi.c.
References get_alarms(), and handle_alarms().
02209 { 02210 int res; 02211 struct dahdi_pvt *p = pvt; 02212 02213 res = get_alarms(p); 02214 handle_alarms(p, res); 02215 }
static int my_get_callerid | ( | void * | pvt, | |
char * | namebuf, | |||
char * | numbuf, | |||
enum analog_event * | ev, | |||
size_t | timeout | |||
) | [static] |
Definition at line 1691 of file chan_dahdi.c.
References ANALOG_EVENT_NONE, ANALOG_MAX_CID, ast_copy_string(), 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_DEBUG, LOG_WARNING, name, analog_pvt::ringt, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.
01692 { 01693 struct dahdi_pvt *p = pvt; 01694 struct analog_pvt *analog_p = p->sig_pvt; 01695 struct pollfd poller; 01696 char *name, *num; 01697 int index = SUB_REAL; 01698 int res; 01699 unsigned char buf[256]; 01700 int flags; 01701 01702 poller.fd = p->subs[SUB_REAL].dfd; 01703 poller.events = POLLPRI | POLLIN; 01704 poller.revents = 0; 01705 01706 res = poll(&poller, 1, timeout); 01707 01708 if (poller.revents & POLLPRI) { 01709 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd)); 01710 return 1; 01711 } 01712 01713 if (poller.revents & POLLIN) { 01714 /*** NOTES ***/ 01715 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function 01716 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until 01717 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be 01718 * a failure and die, and returning 2 means no event was received. */ 01719 res = read(p->subs[index].dfd, buf, sizeof(buf)); 01720 if (res < 0) { 01721 if (errno != ELAST) { 01722 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01723 callerid_free(p->cs); 01724 return -1; 01725 } 01726 } 01727 01728 if (analog_p->ringt > 0) { 01729 if (!(--analog_p->ringt)) { 01730 /* only return if we timeout from a ring event */ 01731 return -1; 01732 } 01733 } 01734 01735 if (p->cid_signalling == CID_SIG_V23_JP) { 01736 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); 01737 } else { 01738 res = callerid_feed(p->cs, buf, res, AST_LAW(p)); 01739 } 01740 if (res < 0) { 01741 /* 01742 * The previous diagnostic message output likely 01743 * explains why it failed. 01744 */ 01745 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 01746 return -1; 01747 } 01748 01749 if (res == 1) { 01750 callerid_get(p->cs, &name, &num, &flags); 01751 if (name) 01752 ast_copy_string(namebuf, name, ANALOG_MAX_CID); 01753 if (num) 01754 ast_copy_string(numbuf, num, ANALOG_MAX_CID); 01755 01756 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags); 01757 return 0; 01758 } 01759 } 01760 01761 *ev = ANALOG_EVENT_NONE; 01762 return 2; 01763 }
static int my_get_event | ( | void * | pvt | ) | [static] |
Definition at line 2808 of file chan_dahdi.c.
References dahdi_get_event(), dahdievent_to_analogevent(), dahdi_pvt::fake_event, SUB_REAL, and dahdi_pvt::subs.
02809 { 02810 struct dahdi_pvt *p = pvt; 02811 int res; 02812 02813 if (p->fake_event) { 02814 res = p->fake_event; 02815 p->fake_event = 0; 02816 } else 02817 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 02818 02819 return dahdievent_to_analogevent(res); 02820 }
static const char* my_get_orig_dialstring | ( | void * | pvt | ) | [static] |
Definition at line 2378 of file chan_dahdi.c.
References dahdi_pvt::dialstring.
02379 { 02380 struct dahdi_pvt *p = pvt; 02381 02382 return p->dialstring; 02383 }
static void* my_get_sigpvt_bridged_channel | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 2217 of file chan_dahdi.c.
References ast_bridged_channel(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.
02218 { 02219 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt; 02220 if (p) 02221 return p->sig_pvt; 02222 else 02223 return NULL; 02224 }
static int my_get_sub_fd | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2226 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02227 { 02228 struct dahdi_pvt *p = pvt; 02229 int dahdi_sub = analogsub_to_dahdisub(sub); 02230 return p->subs[dahdi_sub].dfd; 02231 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 9705 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by analog_ss_thread().
09706 { 09707 char c; 09708 09709 *str = 0; /* start with empty output buffer */ 09710 for (;;) 09711 { 09712 /* Wait for the first digit (up to specified ms). */ 09713 c = ast_waitfordigit(chan, ms); 09714 /* if timeout, hangup or error, return as such */ 09715 if (c < 1) 09716 return c; 09717 *str++ = c; 09718 *str = 0; 09719 if (strchr(term, c)) 09720 return 1; 09721 } 09722 }
static void my_handle_dchan_exception | ( | struct sig_pri_span * | pri, | |
int | index | |||
) | [static] |
Definition at line 3073 of file chan_dahdi.c.
References ast_log(), event2str(), sig_pri_span::fds, LOG_NOTICE, dahdi_pvt::pri, pri_event_alarm(), pri_event_noalarm(), and sig_pri_span::span.
03074 { 03075 int x; 03076 03077 ioctl(pri->fds[index], DAHDI_GETEVENT, &x); 03078 if (x) { 03079 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span); 03080 } 03081 /* Keep track of alarm state */ 03082 switch (x) { 03083 case DAHDI_EVENT_ALARM: 03084 pri_event_alarm(pri, index, 0); 03085 break; 03086 case DAHDI_EVENT_NOALARM: 03087 pri_event_noalarm(pri, index, 0); 03088 break; 03089 default: 03090 break; 03091 } 03092 }
static void my_handle_dtmf | ( | void * | pvt, | |
struct ast_channel * | ast, | |||
enum analog_sub | analog_index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 2038 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_channel::name, 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.
02039 { 02040 struct ast_frame *f = *dest; 02041 struct dahdi_pvt *p = pvt; 02042 int idx = analogsub_to_dahdisub(analog_index); 02043 02044 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 02045 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 02046 f->subclass.integer, f->subclass.integer, ast->name); 02047 02048 if (f->subclass.integer == 'f') { 02049 if (f->frametype == AST_FRAME_DTMF_END) { 02050 /* Fax tone -- Handle and return NULL */ 02051 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 02052 /* If faxbuffers are configured, use them for the fax transmission */ 02053 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 02054 struct dahdi_bufferinfo bi = { 02055 .txbufpolicy = p->faxbuf_policy, 02056 .bufsize = p->bufsize, 02057 .numbufs = p->faxbuf_no 02058 }; 02059 int res; 02060 02061 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 02062 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 02063 } else { 02064 p->bufferoverrideinuse = 1; 02065 } 02066 } 02067 p->faxhandled = 1; 02068 if (p->dsp) { 02069 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 02070 ast_dsp_set_features(p->dsp, p->dsp_features); 02071 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 02072 } 02073 if (strcmp(ast->exten, "fax")) { 02074 const char *target_context = S_OR(ast->macrocontext, ast->context); 02075 02076 /* We need to unlock 'ast' here because ast_exists_extension has the 02077 * potential to start autoservice on the channel. Such action is prone 02078 * to deadlock. 02079 */ 02080 ast_mutex_unlock(&p->lock); 02081 ast_channel_unlock(ast); 02082 if (ast_exists_extension(ast, target_context, "fax", 1, 02083 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 02084 ast_channel_lock(ast); 02085 ast_mutex_lock(&p->lock); 02086 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 02087 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 02088 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 02089 if (ast_async_goto(ast, target_context, "fax", 1)) 02090 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 02091 } else { 02092 ast_channel_lock(ast); 02093 ast_mutex_lock(&p->lock); 02094 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 02095 } 02096 } else { 02097 ast_debug(1, "Already in a fax extension, not redirecting\n"); 02098 } 02099 } else { 02100 ast_debug(1, "Fax already handled\n"); 02101 } 02102 dahdi_confmute(p, 0); 02103 } 02104 p->subs[idx].f.frametype = AST_FRAME_NULL; 02105 p->subs[idx].f.subclass.integer = 0; 02106 *dest = &p->subs[idx].f; 02107 } 02108 }
static void my_handle_notify_message | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | cid_flags, | |||
int | neon_mwievent | |||
) | [static] |
Definition at line 3577 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().
03578 { 03579 struct dahdi_pvt *p = pvt; 03580 03581 if (neon_mwievent > -1 && !p->mwimonitor_neon) 03582 return; 03583 03584 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) { 03585 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox); 03586 notify_message(p->mailbox, 1); 03587 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) { 03588 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox); 03589 notify_message(p->mailbox, 0); 03590 } 03591 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 03592 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 03593 if (neon_mwievent == -1 && p->mwimonitor_rpas) { 03594 ast_hangup(chan); 03595 return; 03596 } 03597 }
static void my_hangup_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2927 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
02928 { 02929 struct dahdi_pvt *p = pvt; 02930 02931 if (!p->hanguponpolarityswitch) { 02932 return; 02933 } 02934 02935 if (p->answeronpolarityswitch) { 02936 my_set_polarity(pvt, 0); 02937 } else { 02938 my_set_polarity(pvt, 1); 02939 } 02940 }
static int my_has_voicemail | ( | void * | pvt | ) | [static] |
Definition at line 2687 of file chan_dahdi.c.
References has_voicemail().
02688 { 02689 struct dahdi_pvt *p = pvt; 02690 02691 return has_voicemail(p); 02692 }
static int my_have_progressdetect | ( | void * | pvt | ) | [static] |
Definition at line 3599 of file chan_dahdi.c.
References dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, CANPROGRESSDETECT, dahdi_pvt::dsp, and dahdi_pvt::outgoing.
03600 { 03601 struct dahdi_pvt *p = pvt; 03602 03603 if ((p->callprogress & CALLPROGRESS_PROGRESS) 03604 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03605 return 1; 03606 } else { 03607 /* Don't have progress detection. */ 03608 return 0; 03609 } 03610 }
static void my_increase_ss_count | ( | void | ) | [static] |
Definition at line 2385 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, ss_thread_count, and ss_thread_lock.
02386 { 02387 ast_mutex_lock(&ss_thread_lock); 02388 ss_thread_count++; 02389 ast_mutex_unlock(&ss_thread_lock); 02390 }
static int my_is_dialing | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2992 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_subchannel::dfd, LOG_DEBUG, and dahdi_pvt::subs.
02993 { 02994 struct dahdi_pvt *p = pvt; 02995 int index; 02996 int x; 02997 02998 index = analogsub_to_dahdisub(sub); 02999 03000 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) { 03001 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n"); 03002 return -1; 03003 } 03004 03005 return x; 03006 }
static int my_is_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2822 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SUB_REAL, and dahdi_pvt::subs.
02823 { 02824 struct dahdi_pvt *p = pvt; 02825 int res; 02826 struct dahdi_params par; 02827 02828 memset(&par, 0, sizeof(par)); 02829 02830 if (p->subs[SUB_REAL].dfd > -1) 02831 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02832 else { 02833 /* Assume not off hook on CVRS */ 02834 res = 0; 02835 par.rxisoffhook = 0; 02836 } 02837 if (res) { 02838 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 02839 } 02840 02841 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 02842 /* When "onhook" that means no battery on the line, and thus 02843 it is out of service..., if it's on a TDM card... If it's a channel 02844 bank, there is no telling... */ 02845 return (par.rxbits > -1) || par.rxisoffhook; 02846 } 02847 02848 return par.rxisoffhook; 02849 }
static void my_lock_private | ( | void * | pvt | ) | [static] |
Definition at line 2110 of file chan_dahdi.c.
References ast_mutex_lock, and dahdi_pvt::lock.
02111 { 02112 struct dahdi_pvt *p = pvt; 02113 ast_mutex_lock(&p->lock); 02114 }
static void my_module_ref | ( | void | ) | [static] |
Definition at line 3314 of file chan_dahdi.c.
References ast_module_ref().
03315 { 03316 ast_module_ref(ast_module_info->self); 03317 }
static void my_module_unref | ( | void | ) | [static] |
Definition at line 3328 of file chan_dahdi.c.
References ast_module_unref().
03329 { 03330 ast_module_unref(ast_module_info->self); 03331 }
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] |
Definition at line 2550 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_new(), and ast_channel::linkedid.
02551 { 02552 struct dahdi_pvt *p = pvt; 02553 int dsub = analogsub_to_dahdisub(sub); 02554 02555 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : ""); 02556 }
static struct ast_channel* my_new_pri_ast_channel | ( | void * | pvt, | |
int | state, | |||
enum sig_pri_law | law, | |||
char * | exten, | |||
const struct ast_channel * | requestor | |||
) | [static] |
Definition at line 2570 of file chan_dahdi.c.
References ast_copy_string(), ast_log(), dahdi_pvt::channel, dahdi_new(), dahdi_setlaw(), errno, dahdi_pvt::exten, ast_channel::linkedid, LOG_WARNING, dahdi_pvt::sig, SIG_PRI_ALAW, SIG_PRI_DEFLAW, SIG_PRI_LIB_HANDLE_CASES, SIG_PRI_ULAW, dahdi_pvt::sig_pvt, SUB_REAL, and dahdi_pvt::subs.
02571 { 02572 struct dahdi_pvt *p = pvt; 02573 int audio; 02574 int newlaw = -1; 02575 02576 switch (p->sig) { 02577 case SIG_PRI_LIB_HANDLE_CASES: 02578 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 02579 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 02580 break; 02581 } 02582 /* Fall through */ 02583 default: 02584 /* Set to audio mode at this point */ 02585 audio = 1; 02586 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) { 02587 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", 02588 p->channel, audio, strerror(errno)); 02589 } 02590 break; 02591 } 02592 02593 if (law != SIG_PRI_DEFLAW) { 02594 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW); 02595 } 02596 02597 ast_copy_string(p->exten, exten, sizeof(p->exten)); 02598 02599 switch (law) { 02600 case SIG_PRI_DEFLAW: 02601 newlaw = 0; 02602 break; 02603 case SIG_PRI_ALAW: 02604 newlaw = DAHDI_LAW_ALAW; 02605 break; 02606 case SIG_PRI_ULAW: 02607 newlaw = DAHDI_LAW_MULAW; 02608 break; 02609 } 02610 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : ""); 02611 }
static int my_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2884 of file chan_dahdi.c.
References dahdi_set_hook(), SUB_REAL, and dahdi_pvt::subs.
02885 { 02886 struct dahdi_pvt *p = pvt; 02887 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02888 }
static int my_on_hook | ( | void * | pvt | ) | [static] |
Definition at line 3008 of file chan_dahdi.c.
References ANALOG_SUB_REAL, dahdi_set_hook(), and dahdi_pvt::subs.
03009 { 03010 struct dahdi_pvt *p = pvt; 03011 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK); 03012 }
static int my_play_tone | ( | void * | pvt, | |
enum analog_sub | sub, | |||
enum analog_tone | tone | |||
) | [static] |
Definition at line 2694 of file chan_dahdi.c.
References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02695 { 02696 struct dahdi_pvt *p = pvt; 02697 int index; 02698 02699 index = analogsub_to_dahdisub(sub); 02700 02701 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone)); 02702 }
static void my_pri_fixup_chans | ( | void * | chan_old, | |
void * | chan_new | |||
) | [static] |
Definition at line 3015 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dialstring, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, ast_channel::fds, dahdi_pvt::law, dahdi_pvt::outgoing, dahdi_subchannel::owner, dahdi_pvt::owner, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
03016 { 03017 struct dahdi_pvt *old_chan = chan_old; 03018 struct dahdi_pvt *new_chan = chan_new; 03019 03020 new_chan->owner = old_chan->owner; 03021 old_chan->owner = NULL; 03022 if (new_chan->owner) { 03023 new_chan->owner->tech_pvt = new_chan; 03024 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd; 03025 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner; 03026 old_chan->subs[SUB_REAL].owner = NULL; 03027 } 03028 /* Copy any DSP that may be present */ 03029 new_chan->dsp = old_chan->dsp; 03030 new_chan->dsp_features = old_chan->dsp_features; 03031 old_chan->dsp = NULL; 03032 old_chan->dsp_features = 0; 03033 03034 /* Transfer flags from the old channel. */ 03035 new_chan->dialing = old_chan->dialing; 03036 new_chan->digital = old_chan->digital; 03037 new_chan->outgoing = old_chan->outgoing; 03038 old_chan->dialing = 0; 03039 old_chan->digital = 0; 03040 old_chan->outgoing = 0; 03041 03042 /* More stuff to transfer to the new channel. */ 03043 new_chan->law = old_chan->law; 03044 strcpy(new_chan->dialstring, old_chan->dialstring); 03045 }
static void my_pri_init_config | ( | void * | priv, | |
struct sig_pri_span * | pri | |||
) | [static] |
Definition at line 13151 of file chan_dahdi.c.
References ast_copy_string(), sig_pri_span::ch_cfg, sig_pri_span::context, dahdi_pvt::context, sig_pri_span::hidecallerid, dahdi_pvt::hidecallerid, sig_pri_span::hidecalleridname, dahdi_pvt::hidecalleridname, sig_pri_span::immediate, dahdi_pvt::immediate, sig_pri_span::mohinterpret, dahdi_pvt::mohinterpret, dahdi_pvt::pri, sig_pri_span::priexclusive, dahdi_pvt::priexclusive, sig_pri_span::priindication_oob, dahdi_pvt::priindication_oob, sig_pri_span::stripmsd, dahdi_pvt::stripmsd, sig_pri_span::use_callerid, dahdi_pvt::use_callerid, sig_pri_span::use_callingpres, and dahdi_pvt::use_callingpres.
13152 { 13153 struct dahdi_pvt *pvt = priv; 13154 13155 pvt->stripmsd = pri->ch_cfg.stripmsd; 13156 pvt->hidecallerid = pri->ch_cfg.hidecallerid; 13157 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname; 13158 pvt->immediate = pri->ch_cfg.immediate; 13159 pvt->priexclusive = pri->ch_cfg.priexclusive; 13160 pvt->priindication_oob = pri->ch_cfg.priindication_oob; 13161 pvt->use_callerid = pri->ch_cfg.use_callerid; 13162 pvt->use_callingpres = pri->ch_cfg.use_callingpres; 13163 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context)); 13164 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret)); 13165 }
static void my_pri_make_cc_dialstring | ( | void * | priv, | |
char * | buf, | |||
size_t | buf_size | |||
) | [static] |
Definition at line 3203 of file chan_dahdi.c.
References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, and ast_strdupa.
03204 { 03205 char *dial; 03206 struct dahdi_pvt *pvt; 03207 AST_DECLARE_APP_ARGS(args, 03208 AST_APP_ARG(tech); /* channel technology token */ 03209 AST_APP_ARG(group); /* channel/group token */ 03210 //AST_APP_ARG(ext); /* extension token */ 03211 //AST_APP_ARG(opts); /* options token */ 03212 //AST_APP_ARG(other); /* Any remining unused arguments */ 03213 ); 03214 03215 pvt = priv; 03216 dial = ast_strdupa(pvt->dialstring); 03217 AST_NONSTANDARD_APP_ARGS(args, dial, '/'); 03218 if (!args.tech) { 03219 ast_copy_string(buf, pvt->dialstring, buf_size); 03220 return; 03221 } 03222 if (!args.group) { 03223 /* Append the ISDN span channel restriction to the dialstring. */ 03224 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span); 03225 return; 03226 } 03227 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) { 03228 /* The ISDN span channel restriction is not needed or already 03229 * in the dialstring. */ 03230 ast_copy_string(buf, pvt->dialstring, buf_size); 03231 return; 03232 } 03233 /* Insert the ISDN span channel restriction into the dialstring. */ 03234 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group); 03235 }
static void my_pri_open_media | ( | void * | p | ) | [static] |
Definition at line 2626 of file chan_dahdi.c.
References ast_dsp_set_features(), ast_log(), dahdi_pvt::channel, dahdi_setlaw(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dsp, dahdi_pvt::dsp_features, 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.
02627 { 02628 struct dahdi_pvt *pvt = p; 02629 int res; 02630 int dfd; 02631 int set_val; 02632 02633 dfd = pvt->subs[SUB_REAL].dfd; 02634 02635 /* Open the media path. */ 02636 set_val = 1; 02637 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val); 02638 if (res < 0) { 02639 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", 02640 pvt->channel, strerror(errno)); 02641 } 02642 02643 /* Set correct companding law for this call. */ 02644 res = dahdi_setlaw(dfd, pvt->law); 02645 if (res < 0) { 02646 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel); 02647 } 02648 02649 /* Set correct gain for this call. */ 02650 if (pvt->digital) { 02651 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law); 02652 } else { 02653 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc, 02654 pvt->law); 02655 } 02656 if (res < 0) { 02657 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel); 02658 } 02659 02660 if (pvt->dsp_features && pvt->dsp) { 02661 ast_dsp_set_features(pvt->dsp, pvt->dsp_features); 02662 pvt->dsp_features = 0; 02663 } 02664 }
static int my_pri_play_tone | ( | void * | pvt, | |
enum sig_pri_tone | tone | |||
) | [static] |
Definition at line 3096 of file chan_dahdi.c.
References sig_pri_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.
03097 { 03098 struct dahdi_pvt *p = pvt; 03099 03100 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone)); 03101 }
static int my_ring | ( | void * | pvt | ) | [static] |
Definition at line 2868 of file chan_dahdi.c.
References dahdi_ring_phone().
02869 { 02870 struct dahdi_pvt *p = pvt; 02871 02872 return dahdi_ring_phone(p); 02873 }
static int my_send_callerid | ( | void * | pvt, | |
int | cwcid, | |||
struct ast_party_caller * | caller | |||
) | [static] |
Definition at line 1937 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.
01938 { 01939 struct dahdi_pvt *p = pvt; 01940 01941 ast_debug(2, "Starting cid spill\n"); 01942 01943 if (p->cidspill) { 01944 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01945 ast_free(p->cidspill); 01946 } 01947 01948 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01949 if (cwcid == 0) { 01950 p->cidlen = ast_callerid_generate(p->cidspill, 01951 caller->id.name.str, 01952 caller->id.number.str, 01953 AST_LAW(p)); 01954 } else { 01955 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", 01956 caller->id.name.str, caller->id.number.str); 01957 p->callwaitcas = 0; 01958 p->cidcwexpire = 0; 01959 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, 01960 caller->id.name.str, 01961 caller->id.number.str, 01962 AST_LAW(p)); 01963 p->cidlen += READ_SIZE * 4; 01964 } 01965 p->cidpos = 0; 01966 p->cid_suppress_expire = 0; 01967 send_callerid(p); 01968 } 01969 return 0; 01970 }
static void my_set_alarm | ( | void * | pvt, | |
int | in_alarm | |||
) | [static] |
static void my_set_cadence | ( | void * | pvt, | |
int * | cidrings, | |||
struct ast_channel * | ast | |||
) | [static] |
Definition at line 2233 of file chan_dahdi.c.
References ast_log(), cadences, dahdi_pvt::distinctivering, errno, LOG_WARNING, ast_channel::name, num_cadence, dahdi_pvt::sendcalleridafter, SUB_REAL, and dahdi_pvt::subs.
02234 { 02235 struct dahdi_pvt *p = pvt; 02236 02237 /* Choose proper cadence */ 02238 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02239 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02240 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02241 *cidrings = cidrings[p->distinctivering - 1]; 02242 } else { 02243 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02244 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02245 *cidrings = p->sendcalleridafter; 02246 } 02247 }
static void my_set_callerid | ( | void * | pvt, | |
const struct ast_party_caller * | caller | |||
) | [static] |
Definition at line 3115 of file chan_dahdi.c.
References ast_party_caller::ani, ast_party_caller::ani2, ast_copy_string(), ast_party_id_presentation(), dahdi_pvt::callingpres, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_subaddr, dahdi_pvt::cid_tag, dahdi_pvt::cid_ton, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::plan, S_COR, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_party_id::subaddress, ast_party_id::tag, ast_party_subaddress::valid, ast_party_name::valid, and ast_party_number::valid.
03116 { 03117 struct dahdi_pvt *p = pvt; 03118 03119 ast_copy_string(p->cid_num, 03120 S_COR(caller->id.number.valid, caller->id.number.str, ""), 03121 sizeof(p->cid_num)); 03122 ast_copy_string(p->cid_name, 03123 S_COR(caller->id.name.valid, caller->id.name.str, ""), 03124 sizeof(p->cid_name)); 03125 ast_copy_string(p->cid_subaddr, 03126 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""), 03127 sizeof(p->cid_subaddr)); 03128 p->cid_ton = caller->id.number.plan; 03129 p->callingpres = ast_party_id_presentation(&caller->id); 03130 if (caller->id.tag) { 03131 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag)); 03132 } 03133 ast_copy_string(p->cid_ani, 03134 S_COR(caller->ani.number.valid, caller->ani.number.str, ""), 03135 sizeof(p->cid_ani)); 03136 p->cid_ani2 = caller->ani2; 03137 }
static void my_set_callwaiting | ( | void * | pvt, | |
int | callwaiting_enable | |||
) | [static] |
Definition at line 2343 of file chan_dahdi.c.
References dahdi_pvt::callwaiting.
02344 { 02345 struct dahdi_pvt *p = pvt; 02346 02347 p->callwaiting = callwaiting_enable; 02348 }
static void my_set_confirmanswer | ( | void * | pvt, | |
int | flag | |||
) | [static] |
Definition at line 2327 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02328 { 02329 struct dahdi_pvt *p = pvt; 02330 p->confirmanswer = flag; 02331 }
static void my_set_dialing | ( | void * | pvt, | |
int | is_dialing | |||
) | [static] |
static void my_set_digital | ( | void * | pvt, | |
int | is_digital | |||
) | [static] |
static void my_set_dnid | ( | void * | pvt, | |
const char * | dnid | |||
) | [static] |
Definition at line 3151 of file chan_dahdi.c.
References ast_copy_string(), and dahdi_pvt::dnid.
03152 { 03153 struct dahdi_pvt *p = pvt; 03154 03155 ast_copy_string(p->dnid, dnid, sizeof(p->dnid)); 03156 }
static int my_set_echocanceller | ( | void * | pvt, | |
int | enable | |||
) | [static] |
Definition at line 2854 of file chan_dahdi.c.
References dahdi_disable_ec(), and dahdi_enable_ec().
02855 { 02856 struct dahdi_pvt *p = pvt; 02857 02858 if (enable) 02859 dahdi_enable_ec(p); 02860 else 02861 dahdi_disable_ec(p); 02862 02863 return 0; 02864 }
static void my_set_inthreeway | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | inthreeway | |||
) | [static] |
Definition at line 2198 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.
02199 { 02200 struct dahdi_pvt *p = pvt; 02201 int idx = analogsub_to_dahdisub(sub); 02202 02203 p->subs[idx].inthreeway = inthreeway; 02204 }
static int my_set_linear_mode | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | linear_mode | |||
) | [static] |
Definition at line 2186 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.
02187 { 02188 struct dahdi_pvt *p = pvt; 02189 int oldval; 02190 int idx = analogsub_to_dahdisub(sub); 02191 02192 dahdi_setlinear(p->subs[idx].dfd, linear_mode); 02193 oldval = p->subs[idx].linear; 02194 p->subs[idx].linear = linear_mode ? 1 : 0; 02195 return oldval; 02196 }
static void my_set_needringing | ( | void * | pvt, | |
int | value | |||
) | [static] |
Definition at line 2890 of file chan_dahdi.c.
References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
02891 { 02892 struct dahdi_pvt *p = pvt; 02893 p->subs[SUB_REAL].needringing = value; 02894 }
static void my_set_new_owner | ( | void * | pvt, | |
struct ast_channel * | new_owner | |||
) | [static] |
static void my_set_polarity | ( | void * | pvt, | |
int | value | |||
) | [static] |
Definition at line 2896 of file chan_dahdi.c.
References CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::polarity, SUB_REAL, and dahdi_pvt::subs.
Referenced by my_answer_polarityswitch(), my_hangup_polarityswitch(), and my_start_polarityswitch().
02897 { 02898 struct dahdi_pvt *p = pvt; 02899 02900 if (p->channel == CHAN_PSEUDO) { 02901 return; 02902 } 02903 p->polarity = value; 02904 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value); 02905 }
static void my_set_pulsedial | ( | void * | pvt, | |
int | flag | |||
) | [static] |
static void my_set_rdnis | ( | void * | pvt, | |
const char * | rdnis | |||
) | [static] |
Definition at line 3170 of file chan_dahdi.c.
References ast_copy_string(), and dahdi_pvt::rdnis.
03171 { 03172 struct dahdi_pvt *p = pvt; 03173 03174 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis)); 03175 }
static void my_set_ringtimeout | ( | void * | pvt, | |
int | ringt | |||
) | [static] |
static void my_set_waitingfordt | ( | void * | pvt, | |
struct ast_channel * | ast | |||
) | [static] |
Definition at line 2305 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.
02306 { 02307 struct dahdi_pvt *p = pvt; 02308 02309 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) { 02310 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone); 02311 gettimeofday(&p->waitingfordt, NULL); 02312 ast_setstate(ast, AST_STATE_OFFHOOK); 02313 } 02314 }
static int my_start | ( | void * | pvt | ) | [static] |
Definition at line 2942 of file chan_dahdi.c.
References SUB_REAL, and dahdi_pvt::subs.
02943 { 02944 struct dahdi_pvt *p = pvt; 02945 int x = DAHDI_START; 02946 02947 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02948 }
static int my_start_cid_detect | ( | void * | pvt, | |
int | cid_signalling | |||
) | [static] |
Definition at line 1666 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.
01667 { 01668 struct dahdi_pvt *p = pvt; 01669 int index = SUB_REAL; 01670 p->cs = callerid_new(cid_signalling); 01671 if (!p->cs) { 01672 ast_log(LOG_ERROR, "Unable to alloc callerid\n"); 01673 return -1; 01674 } 01675 bump_gains(p); 01676 dahdi_setlinear(p->subs[index].dfd, 0); 01677 01678 return 0; 01679 }
static void my_start_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2907 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
02908 { 02909 struct dahdi_pvt *p = pvt; 02910 02911 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02912 my_set_polarity(pvt, 0); 02913 } 02914 }
static int my_stop_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1890 of file chan_dahdi.c.
References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.
01891 { 01892 struct dahdi_pvt *p = pvt; 01893 p->callwaitingrepeat = 0; 01894 p->cidcwexpire = 0; 01895 p->cid_suppress_expire = 0; 01896 01897 return 0; 01898 }
static int my_stop_cid_detect | ( | void * | pvt | ) | [static] |
Definition at line 1681 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.
01682 { 01683 struct dahdi_pvt *p = pvt; 01684 int index = SUB_REAL; 01685 if (p->cs) 01686 callerid_free(p->cs); 01687 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 01688 return 0; 01689 }
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 2516 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().
02517 { 02518 struct dahdi_pvt *p = pvt; 02519 int da, db; 02520 int tchan; 02521 int tinthreeway; 02522 02523 da = analogsub_to_dahdisub(a); 02524 db = analogsub_to_dahdisub(b); 02525 02526 tchan = p->subs[da].chan; 02527 p->subs[da].chan = p->subs[db].chan; 02528 p->subs[db].chan = tchan; 02529 02530 tinthreeway = p->subs[da].inthreeway; 02531 p->subs[da].inthreeway = p->subs[db].inthreeway; 02532 p->subs[db].inthreeway = tinthreeway; 02533 02534 p->subs[da].owner = ast_a; 02535 p->subs[db].owner = ast_b; 02536 02537 if (ast_a) 02538 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); 02539 if (ast_b) 02540 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); 02541 02542 wakeup_sub(p, a); 02543 wakeup_sub(p, b); 02544 02545 return; 02546 }
static int my_train_echocanceller | ( | void * | pvt | ) | [static] |
Definition at line 2983 of file chan_dahdi.c.
References dahdi_train_ec().
02984 { 02985 struct dahdi_pvt *p = pvt; 02986 02987 dahdi_train_ec(p); 02988 02989 return 0; 02990 }
static int my_unallocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2669 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and unalloc_sub().
02670 { 02671 struct dahdi_pvt *p = pvt; 02672 02673 return unalloc_sub(p, analogsub_to_dahdisub(analogsub)); 02674 }
static void my_unlock_private | ( | void * | pvt | ) | [static] |
Definition at line 2116 of file chan_dahdi.c.
References ast_mutex_unlock, and dahdi_pvt::lock.
02117 { 02118 struct dahdi_pvt *p = pvt; 02119 ast_mutex_unlock(&p->lock); 02120 }
static int my_wait_event | ( | void * | pvt | ) | [static] |
Definition at line 2801 of file chan_dahdi.c.
References dahdi_wait_event(), SUB_REAL, and dahdi_pvt::subs.
02802 { 02803 struct dahdi_pvt *p = pvt; 02804 02805 return dahdi_wait_event(p->subs[SUB_REAL].dfd); 02806 }
static int my_wink | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2022 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.
02023 { 02024 struct dahdi_pvt *p = pvt; 02025 int index = analogsub_to_dahdisub(sub); 02026 if (index != SUB_REAL) { 02027 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n"); 02028 } 02029 return dahdi_wink(p, index); 02030 }
static void notify_message | ( | char * | mailbox_full, | |
int | thereornot | |||
) | [static] |
Send MWI state change.
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 3548 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, mailbox, mwimonitornotify, and strsep().
Referenced by handle_init_event(), and my_handle_notify_message().
03549 { 03550 char s[sizeof(mwimonitornotify) + 80]; 03551 struct ast_event *event; 03552 char *mailbox, *context; 03553 03554 /* Strip off @default */ 03555 context = mailbox = ast_strdupa(mailbox_full); 03556 strsep(&context, "@"); 03557 if (ast_strlen_zero(context)) 03558 context = "default"; 03559 03560 if (!(event = ast_event_new(AST_EVENT_MWI, 03561 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03562 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03563 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03564 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03565 AST_EVENT_IE_END))) { 03566 return; 03567 } 03568 03569 ast_event_queue_and_cache(event); 03570 03571 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 03572 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 03573 ast_safe_system(s); 03574 } 03575 }
static int parse_buffers_policy | ( | const char * | parse, | |
int * | num_buffers, | |||
int * | policy | |||
) | [static] |
Definition at line 6975 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write().
06976 { 06977 int res; 06978 char policy_str[21] = ""; 06979 06980 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) { 06981 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 06982 return 1; 06983 } 06984 if (*num_buffers < 0) { 06985 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 06986 return -1; 06987 } 06988 if (!strcasecmp(policy_str, "full")) { 06989 *policy = DAHDI_POLICY_WHEN_FULL; 06990 } else if (!strcasecmp(policy_str, "immediate")) { 06991 *policy = DAHDI_POLICY_IMMEDIATE; 06992 #if defined(HAVE_DAHDI_HALF_FULL) 06993 } else if (!strcasecmp(policy_str, "half")) { 06994 *policy = DAHDI_POLICY_HALF_FULL; 06995 #endif 06996 } else { 06997 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 06998 return -1; 06999 } 07000 07001 return 0; 07002 }
static char* parse_spanchan | ( | char * | chanstr, | |
char ** | subdir | |||
) | [static] |
Definition at line 16686 of file chan_dahdi.c.
References string_replace().
Referenced by build_channels().
16687 { 16688 char *p; 16689 16690 if ((p = strrchr(chanstr, '!')) == NULL) { 16691 *subdir = NULL; 16692 return chanstr; 16693 } 16694 *p++ = '\0'; 16695 string_replace(chanstr, '!', '/'); 16696 *subdir = chanstr; 16697 return p; 16698 }
static int prepare_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 14057 of file chan_dahdi.c.
References ast_log(), sig_pri_span::calls, dahdi_close_pri_fd(), dahdi_pri_callbacks, sig_pri_span::dchan_logical_span, dahdi_pri::dchannels, errno, sig_pri_span::fds, dahdi_pri::pri, pri_event_alarm(), pri_event_noalarm(), dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi_int().
14058 { 14059 int i, res, x; 14060 struct dahdi_params p; 14061 struct dahdi_bufferinfo bi; 14062 struct dahdi_spaninfo si; 14063 14064 pri->pri.calls = &dahdi_pri_callbacks; 14065 14066 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) { 14067 if (!pri->dchannels[i]) 14068 break; 14069 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR); 14070 x = pri->dchannels[i]; 14071 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) { 14072 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 14073 return -1; 14074 } 14075 memset(&p, 0, sizeof(p)); 14076 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p); 14077 if (res) { 14078 dahdi_close_pri_fd(pri, i); 14079 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 14080 return -1; 14081 } 14082 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 14083 dahdi_close_pri_fd(pri, i); 14084 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 14085 return -1; 14086 } 14087 memset(&si, 0, sizeof(si)); 14088 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si); 14089 if (res) { 14090 dahdi_close_pri_fd(pri, i); 14091 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 14092 } 14093 if (!si.alarms) { 14094 pri_event_noalarm(&pri->pri, i, 1); 14095 } else { 14096 pri_event_alarm(&pri->pri, i, 1); 14097 } 14098 memset(&bi, 0, sizeof(bi)); 14099 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 14100 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 14101 bi.numbufs = 32; 14102 bi.bufsize = 1024; 14103 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) { 14104 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 14105 dahdi_close_pri_fd(pri, i); 14106 return -1; 14107 } 14108 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan; 14109 } 14110 return 0; 14111 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 11975 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi_int().
11976 { 11977 if (pris[span].mastertrunkgroup) { 11978 ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup); 11979 return -1; 11980 } 11981 pris[span].mastertrunkgroup = trunkgroup; 11982 pris[span].prilogicalspan = logicalspan; 11983 return 0; 11984 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 11912 of file chan_dahdi.c.
References ast_log(), NUM_SPANS, and pris.
Referenced by setup_dahdi_int().
11913 { 11914 struct dahdi_spaninfo si; 11915 struct dahdi_params p; 11916 int fd; 11917 int span; 11918 int ospan=0; 11919 int x,y; 11920 for (x = 0; x < NUM_SPANS; x++) { 11921 if (pris[x].pri.trunkgroup == trunkgroup) { 11922 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 11923 return -1; 11924 } 11925 } 11926 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 11927 if (!channels[y]) 11928 break; 11929 memset(&si, 0, sizeof(si)); 11930 memset(&p, 0, sizeof(p)); 11931 fd = open("/dev/dahdi/channel", O_RDWR); 11932 if (fd < 0) { 11933 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 11934 return -1; 11935 } 11936 x = channels[y]; 11937 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 11938 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 11939 close(fd); 11940 return -1; 11941 } 11942 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 11943 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 11944 return -1; 11945 } 11946 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 11947 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 11948 close(fd); 11949 return -1; 11950 } 11951 span = p.spanno - 1; 11952 if (pris[span].pri.trunkgroup) { 11953 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup); 11954 close(fd); 11955 return -1; 11956 } 11957 if (pris[span].pri.pvts[0]) { 11958 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 11959 close(fd); 11960 return -1; 11961 } 11962 if (!y) { 11963 pris[span].pri.trunkgroup = trunkgroup; 11964 ospan = span; 11965 } 11966 pris[ospan].dchannels[y] = channels[y]; 11967 pris[span].pri.span = span + 1; 11968 close(fd); 11969 } 11970 return 0; 11971 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 11866 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pvt::pri, pris, and sig_pri_span::trunkgroup.
11867 { 11868 int x; 11869 int trunkgroup; 11870 /* Get appropriate trunk group if there is one */ 11871 trunkgroup = pris[*span].mastertrunkgroup; 11872 if (trunkgroup) { 11873 /* Select a specific trunk group */ 11874 for (x = 0; x < NUM_SPANS; x++) { 11875 if (pris[x].pri.trunkgroup == trunkgroup) { 11876 *span = x; 11877 return 0; 11878 } 11879 } 11880 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 11881 *span = -1; 11882 } else { 11883 if (pris[*span].pri.trunkgroup) { 11884 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup); 11885 *span = -1; 11886 } else if (pris[*span].mastertrunkgroup) { 11887 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 11888 *span = -1; 11889 } else { 11890 if (si->totalchans == 31) { 11891 /* E1 */ 11892 pris[*span].dchannels[0] = 16 + offset; 11893 } else if (si->totalchans == 24) { 11894 /* T1 or J1 */ 11895 pris[*span].dchannels[0] = 24 + offset; 11896 } else if (si->totalchans == 3) { 11897 /* BRI */ 11898 pris[*span].dchannels[0] = 3 + offset; 11899 } else { 11900 ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans); 11901 *span = -1; 11902 return 0; 11903 } 11904 pris[*span].pri.span = *span + 1; 11905 } 11906 } 11907 return 0; 11908 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 16829 of file chan_dahdi.c.
References ast_jb_read_conf(), ast_log(), build_channels(), global_jbconf, ast_variable::lineno, ast_variable::name, ast_variable::next, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.
Referenced by setup_dahdi_int().
16830 { 16831 struct dahdi_pvt *tmp; 16832 int y; 16833 int found_pseudo = 0; 16834 struct ast_variable *dahdichan = NULL; 16835 16836 for (; v; v = v->next) { 16837 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 16838 continue; 16839 16840 /* Create the interface list */ 16841 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) { 16842 if (options & PROC_DAHDI_OPT_NOCHAN) { 16843 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 16844 continue; 16845 } 16846 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) { 16847 if (confp->ignore_failed_channels) { 16848 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value); 16849 continue; 16850 } else { 16851 return -1; 16852 } 16853 } 16854 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 16855 } else if (!strcasecmp(v->name, "ignore_failed_channels")) { 16856 confp->ignore_failed_channels = ast_true(v->value); 16857 } else if (!strcasecmp(v->name, "buffers")) { 16858 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 16859 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 16860 confp->chan.buf_no = numbufs; 16861 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 16862 } 16863 } else if (!strcasecmp(v->name, "faxbuffers")) { 16864 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) { 16865 confp->chan.usefaxbuffers = 1; 16866 } 16867 } else if (!strcasecmp(v->name, "dahdichan")) { 16868 /* Only process the last dahdichan value. */ 16869 dahdichan = v; 16870 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 16871 usedistinctiveringdetection = ast_true(v->value); 16872 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 16873 distinctiveringaftercid = ast_true(v->value); 16874 } else if (!strcasecmp(v->name, "dring1context")) { 16875 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 16876 } else if (!strcasecmp(v->name, "dring2context")) { 16877 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 16878 } else if (!strcasecmp(v->name, "dring3context")) { 16879 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 16880 } else if (!strcasecmp(v->name, "dring1range")) { 16881 confp->chan.drings.ringnum[0].range = atoi(v->value); 16882 } else if (!strcasecmp(v->name, "dring2range")) { 16883 confp->chan.drings.ringnum[1].range = atoi(v->value); 16884 } else if (!strcasecmp(v->name, "dring3range")) { 16885 confp->chan.drings.ringnum[2].range = atoi(v->value); 16886 } else if (!strcasecmp(v->name, "dring1")) { 16887 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]); 16888 } else if (!strcasecmp(v->name, "dring2")) { 16889 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]); 16890 } else if (!strcasecmp(v->name, "dring3")) { 16891 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]); 16892 } else if (!strcasecmp(v->name, "usecallerid")) { 16893 confp->chan.use_callerid = ast_true(v->value); 16894 } else if (!strcasecmp(v->name, "cidsignalling")) { 16895 if (!strcasecmp(v->value, "bell")) 16896 confp->chan.cid_signalling = CID_SIG_BELL; 16897 else if (!strcasecmp(v->value, "v23")) 16898 confp->chan.cid_signalling = CID_SIG_V23; 16899 else if (!strcasecmp(v->value, "dtmf")) 16900 confp->chan.cid_signalling = CID_SIG_DTMF; 16901 else if (!strcasecmp(v->value, "smdi")) 16902 confp->chan.cid_signalling = CID_SIG_SMDI; 16903 else if (!strcasecmp(v->value, "v23_jp")) 16904 confp->chan.cid_signalling = CID_SIG_V23_JP; 16905 else if (ast_true(v->value)) 16906 confp->chan.cid_signalling = CID_SIG_BELL; 16907 } else if (!strcasecmp(v->name, "cidstart")) { 16908 if (!strcasecmp(v->value, "ring")) 16909 confp->chan.cid_start = CID_START_RING; 16910 else if (!strcasecmp(v->value, "polarity_in")) 16911 confp->chan.cid_start = CID_START_POLARITY_IN; 16912 else if (!strcasecmp(v->value, "polarity")) 16913 confp->chan.cid_start = CID_START_POLARITY; 16914 else if (!strcasecmp(v->value, "dtmf")) 16915 confp->chan.cid_start = CID_START_DTMF_NOALERT; 16916 else if (ast_true(v->value)) 16917 confp->chan.cid_start = CID_START_RING; 16918 } else if (!strcasecmp(v->name, "threewaycalling")) { 16919 confp->chan.threewaycalling = ast_true(v->value); 16920 } else if (!strcasecmp(v->name, "cancallforward")) { 16921 confp->chan.cancallforward = ast_true(v->value); 16922 } else if (!strcasecmp(v->name, "relaxdtmf")) { 16923 if (ast_true(v->value)) 16924 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 16925 else 16926 confp->chan.dtmfrelax = 0; 16927 } else if (!strcasecmp(v->name, "mailbox")) { 16928 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 16929 } else if (!strcasecmp(v->name, "hasvoicemail")) { 16930 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 16931 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 16932 } 16933 } else if (!strcasecmp(v->name, "adsi")) { 16934 confp->chan.adsi = ast_true(v->value); 16935 } else if (!strcasecmp(v->name, "usesmdi")) { 16936 confp->chan.use_smdi = ast_true(v->value); 16937 } else if (!strcasecmp(v->name, "smdiport")) { 16938 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 16939 } else if (!strcasecmp(v->name, "transfer")) { 16940 confp->chan.transfer = ast_true(v->value); 16941 } else if (!strcasecmp(v->name, "canpark")) { 16942 confp->chan.canpark = ast_true(v->value); 16943 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 16944 confp->chan.echocanbridged = ast_true(v->value); 16945 } else if (!strcasecmp(v->name, "busydetect")) { 16946 confp->chan.busydetect = ast_true(v->value); 16947 } else if (!strcasecmp(v->name, "busycount")) { 16948 confp->chan.busycount = atoi(v->value); 16949 } else if (!strcasecmp(v->name, "silencethreshold")) { 16950 confp->chan.silencethreshold = atoi(v->value); 16951 } else if (!strcasecmp(v->name, "busycompare")) { 16952 confp->chan.busycompare = ast_true(v->value); 16953 } else if (!strcasecmp(v->name, "busypattern")) { 16954 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 16955 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 16956 } 16957 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 16958 if (count == 1) 16959 confp->chan.busyquietlength = 0; 16960 else if (count < 1) 16961 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 16962 } else if (!strcasecmp(v->name, "busyfuzziness")) { 16963 confp->chan.busyfuzziness = atoi(v->value); 16964 } else if (!strcasecmp(v->name, "callprogress")) { 16965 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 16966 if (ast_true(v->value)) 16967 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 16968 } else if (!strcasecmp(v->name, "waitfordialtone")) { 16969 confp->chan.waitfordialtone = atoi(v->value); 16970 } else if (!strcasecmp(v->name, "faxdetect")) { 16971 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 16972 if (!strcasecmp(v->value, "incoming")) { 16973 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 16974 } else if (!strcasecmp(v->value, "outgoing")) { 16975 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 16976 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 16977 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 16978 } else if (!strcasecmp(v->name, "echocancel")) { 16979 process_echocancel(confp, v->value, v->lineno); 16980 } else if (!strcasecmp(v->name, "echotraining")) { 16981 if (sscanf(v->value, "%30d", &y) == 1) { 16982 if ((y < 10) || (y > 4000)) { 16983 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 16984 } else { 16985 confp->chan.echotraining = y; 16986 } 16987 } else if (ast_true(v->value)) { 16988 confp->chan.echotraining = 400; 16989 } else 16990 confp->chan.echotraining = 0; 16991 } else if (!strcasecmp(v->name, "hidecallerid")) { 16992 confp->chan.hidecallerid = ast_true(v->value); 16993 } else if (!strcasecmp(v->name, "hidecalleridname")) { 16994 confp->chan.hidecalleridname = ast_true(v->value); 16995 } else if (!strcasecmp(v->name, "pulsedial")) { 16996 confp->chan.pulse = ast_true(v->value); 16997 } else if (!strcasecmp(v->name, "callreturn")) { 16998 confp->chan.callreturn = ast_true(v->value); 16999 } else if (!strcasecmp(v->name, "callwaiting")) { 17000 confp->chan.callwaiting = ast_true(v->value); 17001 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 17002 confp->chan.callwaitingcallerid = ast_true(v->value); 17003 } else if (!strcasecmp(v->name, "context")) { 17004 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 17005 } else if (!strcasecmp(v->name, "language")) { 17006 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 17007 } else if (!strcasecmp(v->name, "progzone")) { 17008 ast_copy_string(progzone, v->value, sizeof(progzone)); 17009 } else if (!strcasecmp(v->name, "mohinterpret") 17010 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 17011 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 17012 } else if (!strcasecmp(v->name, "mohsuggest")) { 17013 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 17014 } else if (!strcasecmp(v->name, "parkinglot")) { 17015 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 17016 } else if (!strcasecmp(v->name, "stripmsd")) { 17017 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 17018 confp->chan.stripmsd = atoi(v->value); 17019 } else if (!strcasecmp(v->name, "jitterbuffers")) { 17020 numbufs = atoi(v->value); 17021 } else if (!strcasecmp(v->name, "group")) { 17022 confp->chan.group = ast_get_group(v->value); 17023 } else if (!strcasecmp(v->name, "callgroup")) { 17024 if (!strcasecmp(v->value, "none")) 17025 confp->chan.callgroup = 0; 17026 else 17027 confp->chan.callgroup = ast_get_group(v->value); 17028 } else if (!strcasecmp(v->name, "pickupgroup")) { 17029 if (!strcasecmp(v->value, "none")) 17030 confp->chan.pickupgroup = 0; 17031 else 17032 confp->chan.pickupgroup = ast_get_group(v->value); 17033 } else if (!strcasecmp(v->name, "setvar")) { 17034 char *varname = ast_strdupa(v->value), *varval = NULL; 17035 struct ast_variable *tmpvar; 17036 if (varname && (varval = strchr(varname, '='))) { 17037 *varval++ = '\0'; 17038 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 17039 tmpvar->next = confp->chan.vars; 17040 confp->chan.vars = tmpvar; 17041 } 17042 } 17043 } else if (!strcasecmp(v->name, "immediate")) { 17044 confp->chan.immediate = ast_true(v->value); 17045 } else if (!strcasecmp(v->name, "transfertobusy")) { 17046 confp->chan.transfertobusy = ast_true(v->value); 17047 } else if (!strcasecmp(v->name, "mwimonitor")) { 17048 confp->chan.mwimonitor_neon = 0; 17049 confp->chan.mwimonitor_fsk = 0; 17050 confp->chan.mwimonitor_rpas = 0; 17051 if (strcasestr(v->value, "fsk")) { 17052 confp->chan.mwimonitor_fsk = 1; 17053 } 17054 if (strcasestr(v->value, "rpas")) { 17055 confp->chan.mwimonitor_rpas = 1; 17056 } 17057 if (strcasestr(v->value, "neon")) { 17058 confp->chan.mwimonitor_neon = 1; 17059 } 17060 /* If set to true or yes, assume that simple fsk is desired */ 17061 if (ast_true(v->value)) { 17062 confp->chan.mwimonitor_fsk = 1; 17063 } 17064 } else if (!strcasecmp(v->name, "cid_rxgain")) { 17065 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 17066 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 17067 } 17068 } else if (!strcasecmp(v->name, "rxgain")) { 17069 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 17070 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 17071 } 17072 } else if (!strcasecmp(v->name, "txgain")) { 17073 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 17074 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 17075 } 17076 } else if (!strcasecmp(v->name, "txdrc")) { 17077 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) { 17078 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value); 17079 } 17080 } else if (!strcasecmp(v->name, "rxdrc")) { 17081 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) { 17082 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value); 17083 } 17084 } else if (!strcasecmp(v->name, "tonezone")) { 17085 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 17086 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 17087 } 17088 } else if (!strcasecmp(v->name, "callerid")) { 17089 if (!strcasecmp(v->value, "asreceived")) { 17090 confp->chan.cid_num[0] = '\0'; 17091 confp->chan.cid_name[0] = '\0'; 17092 } else { 17093 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 17094 } 17095 } else if (!strcasecmp(v->name, "fullname")) { 17096 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 17097 } else if (!strcasecmp(v->name, "cid_number")) { 17098 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 17099 } else if (!strcasecmp(v->name, "cid_tag")) { 17100 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); 17101 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 17102 confp->chan.dahditrcallerid = ast_true(v->value); 17103 } else if (!strcasecmp(v->name, "restrictcid")) { 17104 confp->chan.restrictcid = ast_true(v->value); 17105 } else if (!strcasecmp(v->name, "usecallingpres")) { 17106 confp->chan.use_callingpres = ast_true(v->value); 17107 } else if (!strcasecmp(v->name, "accountcode")) { 17108 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 17109 } else if (!strcasecmp(v->name, "amaflags")) { 17110 y = ast_cdr_amaflags2int(v->value); 17111 if (y < 0) 17112 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 17113 else 17114 confp->chan.amaflags = y; 17115 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 17116 confp->chan.polarityonanswerdelay = atoi(v->value); 17117 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 17118 confp->chan.answeronpolarityswitch = ast_true(v->value); 17119 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 17120 confp->chan.hanguponpolarityswitch = ast_true(v->value); 17121 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 17122 confp->chan.sendcalleridafter = atoi(v->value); 17123 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 17124 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 17125 } else if (ast_cc_is_config_param(v->name)) { 17126 ast_cc_set_param(confp->chan.cc_params, v->name, v->value); 17127 } else if (!strcasecmp(v->name, "mwisendtype")) { 17128 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 17129 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 17130 mwisend_rpas = 1; 17131 } else { 17132 mwisend_rpas = 0; 17133 } 17134 #else 17135 /* Default is fsk, to turn it off you must specify nofsk */ 17136 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 17137 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 17138 confp->chan.mwisend_fsk = 0; 17139 } else { /* Default FSK */ 17140 confp->chan.mwisend_fsk = 1; 17141 } 17142 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 17143 confp->chan.mwisend_rpas = 1; 17144 } else { 17145 confp->chan.mwisend_rpas = 0; 17146 } 17147 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 17148 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 17149 } 17150 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 17151 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 17152 } 17153 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 17154 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 17155 } 17156 #endif 17157 } else if (reload != 1) { 17158 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 17159 int orig_radio = confp->chan.radio; 17160 int orig_outsigmod = confp->chan.outsigmod; 17161 int orig_auto = confp->is_sig_auto; 17162 17163 confp->chan.radio = 0; 17164 confp->chan.outsigmod = -1; 17165 confp->is_sig_auto = 0; 17166 if (!strcasecmp(v->value, "em")) { 17167 confp->chan.sig = SIG_EM; 17168 } else if (!strcasecmp(v->value, "em_e1")) { 17169 confp->chan.sig = SIG_EM_E1; 17170 } else if (!strcasecmp(v->value, "em_w")) { 17171 confp->chan.sig = SIG_EMWINK; 17172 } else if (!strcasecmp(v->value, "fxs_ls")) { 17173 confp->chan.sig = SIG_FXSLS; 17174 } else if (!strcasecmp(v->value, "fxs_gs")) { 17175 confp->chan.sig = SIG_FXSGS; 17176 } else if (!strcasecmp(v->value, "fxs_ks")) { 17177 confp->chan.sig = SIG_FXSKS; 17178 } else if (!strcasecmp(v->value, "fxo_ls")) { 17179 confp->chan.sig = SIG_FXOLS; 17180 } else if (!strcasecmp(v->value, "fxo_gs")) { 17181 confp->chan.sig = SIG_FXOGS; 17182 } else if (!strcasecmp(v->value, "fxo_ks")) { 17183 confp->chan.sig = SIG_FXOKS; 17184 } else if (!strcasecmp(v->value, "fxs_rx")) { 17185 confp->chan.sig = SIG_FXSKS; 17186 confp->chan.radio = 1; 17187 } else if (!strcasecmp(v->value, "fxo_rx")) { 17188 confp->chan.sig = SIG_FXOLS; 17189 confp->chan.radio = 1; 17190 } else if (!strcasecmp(v->value, "fxs_tx")) { 17191 confp->chan.sig = SIG_FXSLS; 17192 confp->chan.radio = 1; 17193 } else if (!strcasecmp(v->value, "fxo_tx")) { 17194 confp->chan.sig = SIG_FXOGS; 17195 confp->chan.radio = 1; 17196 } else if (!strcasecmp(v->value, "em_rx")) { 17197 confp->chan.sig = SIG_EM; 17198 confp->chan.radio = 1; 17199 } else if (!strcasecmp(v->value, "em_tx")) { 17200 confp->chan.sig = SIG_EM; 17201 confp->chan.radio = 1; 17202 } else if (!strcasecmp(v->value, "em_rxtx")) { 17203 confp->chan.sig = SIG_EM; 17204 confp->chan.radio = 2; 17205 } else if (!strcasecmp(v->value, "em_txrx")) { 17206 confp->chan.sig = SIG_EM; 17207 confp->chan.radio = 2; 17208 } else if (!strcasecmp(v->value, "sf")) { 17209 confp->chan.sig = SIG_SF; 17210 } else if (!strcasecmp(v->value, "sf_w")) { 17211 confp->chan.sig = SIG_SFWINK; 17212 } else if (!strcasecmp(v->value, "sf_featd")) { 17213 confp->chan.sig = SIG_FEATD; 17214 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17215 confp->chan.sig = SIG_FEATDMF; 17216 } else if (!strcasecmp(v->value, "sf_featb")) { 17217 confp->chan.sig = SIG_SF_FEATB; 17218 } else if (!strcasecmp(v->value, "sf")) { 17219 confp->chan.sig = SIG_SF; 17220 } else if (!strcasecmp(v->value, "sf_rx")) { 17221 confp->chan.sig = SIG_SF; 17222 confp->chan.radio = 1; 17223 } else if (!strcasecmp(v->value, "sf_tx")) { 17224 confp->chan.sig = SIG_SF; 17225 confp->chan.radio = 1; 17226 } else if (!strcasecmp(v->value, "sf_rxtx")) { 17227 confp->chan.sig = SIG_SF; 17228 confp->chan.radio = 2; 17229 } else if (!strcasecmp(v->value, "sf_txrx")) { 17230 confp->chan.sig = SIG_SF; 17231 confp->chan.radio = 2; 17232 } else if (!strcasecmp(v->value, "featd")) { 17233 confp->chan.sig = SIG_FEATD; 17234 } else if (!strcasecmp(v->value, "featdmf")) { 17235 confp->chan.sig = SIG_FEATDMF; 17236 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17237 confp->chan.sig = SIG_FEATDMF_TA; 17238 } else if (!strcasecmp(v->value, "e911")) { 17239 confp->chan.sig = SIG_E911; 17240 } else if (!strcasecmp(v->value, "fgccama")) { 17241 confp->chan.sig = SIG_FGC_CAMA; 17242 } else if (!strcasecmp(v->value, "fgccamamf")) { 17243 confp->chan.sig = SIG_FGC_CAMAMF; 17244 } else if (!strcasecmp(v->value, "featb")) { 17245 confp->chan.sig = SIG_FEATB; 17246 #ifdef HAVE_PRI 17247 } else if (!strcasecmp(v->value, "pri_net")) { 17248 confp->chan.sig = SIG_PRI; 17249 confp->pri.pri.nodetype = PRI_NETWORK; 17250 } else if (!strcasecmp(v->value, "pri_cpe")) { 17251 confp->chan.sig = SIG_PRI; 17252 confp->pri.pri.nodetype = PRI_CPE; 17253 } else if (!strcasecmp(v->value, "bri_cpe")) { 17254 confp->chan.sig = SIG_BRI; 17255 confp->pri.pri.nodetype = PRI_CPE; 17256 } else if (!strcasecmp(v->value, "bri_net")) { 17257 confp->chan.sig = SIG_BRI; 17258 confp->pri.pri.nodetype = PRI_NETWORK; 17259 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 17260 confp->chan.sig = SIG_BRI_PTMP; 17261 confp->pri.pri.nodetype = PRI_CPE; 17262 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 17263 #if defined(HAVE_PRI_CALL_HOLD) 17264 confp->chan.sig = SIG_BRI_PTMP; 17265 confp->pri.pri.nodetype = PRI_NETWORK; 17266 #else 17267 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 17268 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 17269 #endif 17270 #if defined(HAVE_SS7) 17271 } else if (!strcasecmp(v->value, "ss7")) { 17272 confp->chan.sig = SIG_SS7; 17273 #endif /* defined(HAVE_SS7) */ 17274 #ifdef HAVE_OPENR2 17275 } else if (!strcasecmp(v->value, "mfcr2")) { 17276 confp->chan.sig = SIG_MFCR2; 17277 #endif 17278 } else if (!strcasecmp(v->value, "auto")) { 17279 confp->is_sig_auto = 1; 17280 } else { 17281 confp->chan.outsigmod = orig_outsigmod; 17282 confp->chan.radio = orig_radio; 17283 confp->is_sig_auto = orig_auto; 17284 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17285 } 17286 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 17287 if (!strcasecmp(v->value, "em")) { 17288 confp->chan.outsigmod = SIG_EM; 17289 } else if (!strcasecmp(v->value, "em_e1")) { 17290 confp->chan.outsigmod = SIG_EM_E1; 17291 } else if (!strcasecmp(v->value, "em_w")) { 17292 confp->chan.outsigmod = SIG_EMWINK; 17293 } else if (!strcasecmp(v->value, "sf")) { 17294 confp->chan.outsigmod = SIG_SF; 17295 } else if (!strcasecmp(v->value, "sf_w")) { 17296 confp->chan.outsigmod = SIG_SFWINK; 17297 } else if (!strcasecmp(v->value, "sf_featd")) { 17298 confp->chan.outsigmod = SIG_FEATD; 17299 } else if (!strcasecmp(v->value, "sf_featdmf")) { 17300 confp->chan.outsigmod = SIG_FEATDMF; 17301 } else if (!strcasecmp(v->value, "sf_featb")) { 17302 confp->chan.outsigmod = SIG_SF_FEATB; 17303 } else if (!strcasecmp(v->value, "sf")) { 17304 confp->chan.outsigmod = SIG_SF; 17305 } else if (!strcasecmp(v->value, "featd")) { 17306 confp->chan.outsigmod = SIG_FEATD; 17307 } else if (!strcasecmp(v->value, "featdmf")) { 17308 confp->chan.outsigmod = SIG_FEATDMF; 17309 } else if (!strcasecmp(v->value, "featdmf_ta")) { 17310 confp->chan.outsigmod = SIG_FEATDMF_TA; 17311 } else if (!strcasecmp(v->value, "e911")) { 17312 confp->chan.outsigmod = SIG_E911; 17313 } else if (!strcasecmp(v->value, "fgccama")) { 17314 confp->chan.outsigmod = SIG_FGC_CAMA; 17315 } else if (!strcasecmp(v->value, "fgccamamf")) { 17316 confp->chan.outsigmod = SIG_FGC_CAMAMF; 17317 } else if (!strcasecmp(v->value, "featb")) { 17318 confp->chan.outsigmod = SIG_FEATB; 17319 } else { 17320 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 17321 } 17322 #ifdef HAVE_PRI 17323 } else if (!strcasecmp(v->name, "pridialplan")) { 17324 if (!strcasecmp(v->value, "national")) { 17325 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1; 17326 } else if (!strcasecmp(v->value, "unknown")) { 17327 confp->pri.pri.dialplan = PRI_UNKNOWN + 1; 17328 } else if (!strcasecmp(v->value, "private")) { 17329 confp->pri.pri.dialplan = PRI_PRIVATE + 1; 17330 } else if (!strcasecmp(v->value, "international")) { 17331 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 17332 } else if (!strcasecmp(v->value, "local")) { 17333 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1; 17334 } else if (!strcasecmp(v->value, "dynamic")) { 17335 confp->pri.pri.dialplan = -1; 17336 } else if (!strcasecmp(v->value, "redundant")) { 17337 confp->pri.pri.dialplan = -2; 17338 } else { 17339 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 17340 } 17341 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 17342 if (!strcasecmp(v->value, "national")) { 17343 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1; 17344 } else if (!strcasecmp(v->value, "unknown")) { 17345 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1; 17346 } else if (!strcasecmp(v->value, "private")) { 17347 confp->pri.pri.localdialplan = PRI_PRIVATE + 1; 17348 } else if (!strcasecmp(v->value, "international")) { 17349 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 17350 } else if (!strcasecmp(v->value, "local")) { 17351 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1; 17352 } else if (!strcasecmp(v->value, "dynamic")) { 17353 confp->pri.pri.localdialplan = -1; 17354 } else if (!strcasecmp(v->value, "redundant")) { 17355 confp->pri.pri.localdialplan = -2; 17356 } else { 17357 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 17358 } 17359 } else if (!strcasecmp(v->name, "switchtype")) { 17360 if (!strcasecmp(v->value, "national")) 17361 confp->pri.pri.switchtype = PRI_SWITCH_NI2; 17362 else if (!strcasecmp(v->value, "ni1")) 17363 confp->pri.pri.switchtype = PRI_SWITCH_NI1; 17364 else if (!strcasecmp(v->value, "dms100")) 17365 confp->pri.pri.switchtype = PRI_SWITCH_DMS100; 17366 else if (!strcasecmp(v->value, "4ess")) 17367 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS; 17368 else if (!strcasecmp(v->value, "5ess")) 17369 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E; 17370 else if (!strcasecmp(v->value, "euroisdn")) 17371 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1; 17372 else if (!strcasecmp(v->value, "qsig")) 17373 confp->pri.pri.switchtype = PRI_SWITCH_QSIG; 17374 else { 17375 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 17376 return -1; 17377 } 17378 } else if (!strcasecmp(v->name, "msn")) { 17379 ast_copy_string(confp->pri.pri.msn_list, v->value, 17380 sizeof(confp->pri.pri.msn_list)); 17381 } else if (!strcasecmp(v->name, "nsf")) { 17382 if (!strcasecmp(v->value, "sdn")) 17383 confp->pri.pri.nsf = PRI_NSF_SDN; 17384 else if (!strcasecmp(v->value, "megacom")) 17385 confp->pri.pri.nsf = PRI_NSF_MEGACOM; 17386 else if (!strcasecmp(v->value, "tollfreemegacom")) 17387 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 17388 else if (!strcasecmp(v->value, "accunet")) 17389 confp->pri.pri.nsf = PRI_NSF_ACCUNET; 17390 else if (!strcasecmp(v->value, "none")) 17391 confp->pri.pri.nsf = PRI_NSF_NONE; 17392 else { 17393 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 17394 confp->pri.pri.nsf = PRI_NSF_NONE; 17395 } 17396 } else if (!strcasecmp(v->name, "priindication")) { 17397 if (!strcasecmp(v->value, "outofband")) 17398 confp->chan.priindication_oob = 1; 17399 else if (!strcasecmp(v->value, "inband")) 17400 confp->chan.priindication_oob = 0; 17401 else 17402 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 17403 v->value, v->lineno); 17404 } else if (!strcasecmp(v->name, "priexclusive")) { 17405 confp->chan.priexclusive = ast_true(v->value); 17406 } else if (!strcasecmp(v->name, "internationalprefix")) { 17407 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix)); 17408 } else if (!strcasecmp(v->name, "nationalprefix")) { 17409 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix)); 17410 } else if (!strcasecmp(v->name, "localprefix")) { 17411 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix)); 17412 } else if (!strcasecmp(v->name, "privateprefix")) { 17413 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix)); 17414 } else if (!strcasecmp(v->name, "unknownprefix")) { 17415 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix)); 17416 } else if (!strcasecmp(v->name, "resetinterval")) { 17417 if (!strcasecmp(v->value, "never")) 17418 confp->pri.pri.resetinterval = -1; 17419 else if (atoi(v->value) >= 60) 17420 confp->pri.pri.resetinterval = atoi(v->value); 17421 else 17422 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 17423 v->value, v->lineno); 17424 } else if (!strcasecmp(v->name, "minunused")) { 17425 confp->pri.pri.minunused = atoi(v->value); 17426 } else if (!strcasecmp(v->name, "minidle")) { 17427 confp->pri.pri.minidle = atoi(v->value); 17428 } else if (!strcasecmp(v->name, "idleext")) { 17429 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext)); 17430 } else if (!strcasecmp(v->name, "idledial")) { 17431 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial)); 17432 } else if (!strcasecmp(v->name, "overlapdial")) { 17433 if (ast_true(v->value)) { 17434 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17435 } else if (!strcasecmp(v->value, "incoming")) { 17436 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 17437 } else if (!strcasecmp(v->value, "outgoing")) { 17438 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 17439 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 17440 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17441 } else { 17442 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 17443 } 17444 #ifdef HAVE_PRI_PROG_W_CAUSE 17445 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 17446 if (!strcasecmp(v->value, "logical")) { 17447 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 17448 } else if (!strcasecmp(v->value, "physical")) { 17449 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17450 } else { 17451 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17452 } 17453 #endif 17454 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 17455 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value); 17456 #if defined(HAVE_PRI_SERVICE_MESSAGES) 17457 } else if (!strcasecmp(v->name, "service_message_support")) { 17458 /* assuming switchtype for this channel group has been configured already */ 17459 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 17460 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E 17461 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) { 17462 confp->pri.pri.enable_service_message_support = 1; 17463 } else { 17464 confp->pri.pri.enable_service_message_support = 0; 17465 } 17466 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 17467 #ifdef HAVE_PRI_INBANDDISCONNECT 17468 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 17469 confp->pri.pri.inbanddisconnect = ast_true(v->value); 17470 #endif 17471 } else if (!strcasecmp(v->name, "pritimer")) { 17472 #ifdef PRI_GETSET_TIMERS 17473 char tmp[20]; 17474 char *timerc; 17475 char *c; 17476 int timer; 17477 int timeridx; 17478 17479 ast_copy_string(tmp, v->value, sizeof(tmp)); 17480 c = tmp; 17481 timerc = strsep(&c, ","); 17482 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 17483 timeridx = pri_timer2idx(timerc); 17484 timer = atoi(c); 17485 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 17486 ast_log(LOG_WARNING, 17487 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 17488 v->lineno); 17489 } else if (!timer) { 17490 ast_log(LOG_WARNING, 17491 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 17492 c, timerc, v->lineno); 17493 } else { 17494 confp->pri.pri.pritimers[timeridx] = timer; 17495 } 17496 } else { 17497 ast_log(LOG_WARNING, 17498 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 17499 v->value, v->lineno); 17500 } 17501 #endif /* PRI_GETSET_TIMERS */ 17502 } else if (!strcasecmp(v->name, "facilityenable")) { 17503 confp->pri.pri.facilityenable = ast_true(v->value); 17504 #if defined(HAVE_PRI_AOC_EVENTS) 17505 } else if (!strcasecmp(v->name, "aoc_enable")) { 17506 confp->pri.pri.aoc_passthrough_flag = 0; 17507 if (strchr(v->value, 's') || strchr(v->value, 'S')) { 17508 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S; 17509 } 17510 if (strchr(v->value, 'd') || strchr(v->value, 'D')) { 17511 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D; 17512 } 17513 if (strchr(v->value, 'e') || strchr(v->value, 'E')) { 17514 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E; 17515 } 17516 } else if (!strcasecmp(v->name, "aoce_delayhangup")) { 17517 confp->pri.pri.aoce_delayhangup = ast_true(v->value); 17518 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 17519 #if defined(HAVE_PRI_CALL_HOLD) 17520 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) { 17521 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value); 17522 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 17523 #if defined(HAVE_PRI_CCSS) 17524 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) { 17525 if (!strcasecmp(v->value, "global")) { 17526 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */ 17527 } else if (!strcasecmp(v->value, "specific")) { 17528 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17529 } else { 17530 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17531 } 17532 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) { 17533 if (!strcasecmp(v->value, "release")) { 17534 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */ 17535 } else if (!strcasecmp(v->value, "retain")) { 17536 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17537 } else if (!strcasecmp(v->value, "do_not_care")) { 17538 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */ 17539 } else { 17540 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17541 } 17542 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) { 17543 if (!strcasecmp(v->value, "release")) { 17544 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */ 17545 } else if (!strcasecmp(v->value, "retain")) { 17546 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17547 } else { 17548 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17549 } 17550 #endif /* defined(HAVE_PRI_CCSS) */ 17551 #if defined(HAVE_PRI_CALL_WAITING) 17552 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) { 17553 confp->pri.pri.max_call_waiting_calls = atoi(v->value); 17554 if (confp->pri.pri.max_call_waiting_calls < 0) { 17555 /* Negative values are not allowed. */ 17556 confp->pri.pri.max_call_waiting_calls = 0; 17557 } 17558 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) { 17559 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value); 17560 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 17561 #if defined(HAVE_PRI_MWI) 17562 } else if (!strcasecmp(v->name, "mwi_mailboxes")) { 17563 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value, 17564 sizeof(confp->pri.pri.mwi_mailboxes)); 17565 #endif /* defined(HAVE_PRI_MWI) */ 17566 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) { 17567 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value); 17568 #if defined(HAVE_PRI_L2_PERSISTENCE) 17569 } else if (!strcasecmp(v->name, "layer2_persistence")) { 17570 if (!strcasecmp(v->value, "keep_up")) { 17571 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP; 17572 } else if (!strcasecmp(v->value, "leave_down")) { 17573 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN; 17574 } else { 17575 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT; 17576 } 17577 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */ 17578 #endif /* HAVE_PRI */ 17579 #if defined(HAVE_SS7) 17580 } else if (!strcasecmp(v->name, "ss7type")) { 17581 if (!strcasecmp(v->value, "itu")) { 17582 cur_ss7type = SS7_ITU; 17583 } else if (!strcasecmp(v->value, "ansi")) { 17584 cur_ss7type = SS7_ANSI; 17585 } else 17586 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 17587 } else if (!strcasecmp(v->name, "linkset")) { 17588 cur_linkset = atoi(v->value); 17589 } else if (!strcasecmp(v->name, "pointcode")) { 17590 cur_pointcode = parse_pointcode(v->value); 17591 } else if (!strcasecmp(v->name, "adjpointcode")) { 17592 cur_adjpointcode = parse_pointcode(v->value); 17593 } else if (!strcasecmp(v->name, "defaultdpc")) { 17594 cur_defaultdpc = parse_pointcode(v->value); 17595 } else if (!strcasecmp(v->name, "cicbeginswith")) { 17596 cur_cicbeginswith = atoi(v->value); 17597 } else if (!strcasecmp(v->name, "networkindicator")) { 17598 if (!strcasecmp(v->value, "national")) 17599 cur_networkindicator = SS7_NI_NAT; 17600 else if (!strcasecmp(v->value, "national_spare")) 17601 cur_networkindicator = SS7_NI_NAT_SPARE; 17602 else if (!strcasecmp(v->value, "international")) 17603 cur_networkindicator = SS7_NI_INT; 17604 else if (!strcasecmp(v->value, "international_spare")) 17605 cur_networkindicator = SS7_NI_INT_SPARE; 17606 else 17607 cur_networkindicator = -1; 17608 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 17609 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix)); 17610 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 17611 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix)); 17612 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 17613 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix)); 17614 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 17615 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix)); 17616 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 17617 if (!strcasecmp(v->value, "national")) { 17618 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL; 17619 } else if (!strcasecmp(v->value, "international")) { 17620 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL; 17621 } else if (!strcasecmp(v->value, "subscriber")) { 17622 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER; 17623 } else if (!strcasecmp(v->value, "unknown")) { 17624 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN; 17625 } else if (!strcasecmp(v->value, "dynamic")) { 17626 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC; 17627 } else { 17628 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 17629 } 17630 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 17631 if (!strcasecmp(v->value, "national")) { 17632 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL; 17633 } else if (!strcasecmp(v->value, "international")) { 17634 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL; 17635 } else if (!strcasecmp(v->value, "subscriber")) { 17636 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER; 17637 } else if (!strcasecmp(v->value, "unknown")) { 17638 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN; 17639 } else if (!strcasecmp(v->value, "dynamic")) { 17640 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC; 17641 } else { 17642 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 17643 } 17644 } else if (!strcasecmp(v->name, "sigchan")) { 17645 int sigchan, res; 17646 sigchan = atoi(v->value); 17647 res = linkset_addsigchan(sigchan); 17648 if (res < 0) 17649 return -1; 17650 17651 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 17652 struct dahdi_ss7 *link; 17653 link = ss7_resolve_linkset(cur_linkset); 17654 if (!link) { 17655 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 17656 return -1; 17657 } 17658 if (ast_true(v->value)) 17659 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM; 17660 #endif /* defined(HAVE_SS7) */ 17661 #ifdef HAVE_OPENR2 17662 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 17663 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 17664 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); 17665 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 17666 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 17667 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 17668 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 17669 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 17670 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 17671 confp->mfcr2.variant = OR2_VAR_ITU; 17672 } 17673 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 17674 confp->mfcr2.mfback_timeout = atoi(v->value); 17675 if (!confp->mfcr2.mfback_timeout) { 17676 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 17677 confp->mfcr2.mfback_timeout = -1; 17678 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 17679 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 17680 } 17681 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 17682 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 17683 if (confp->mfcr2.metering_pulse_timeout > 500) { 17684 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 17685 } 17686 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 17687 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 17688 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 17689 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 17690 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 17691 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 17692 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 17693 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 17694 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 17695 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 17696 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 17697 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 17698 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 17699 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 17700 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 17701 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 17702 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0; 17703 #endif 17704 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 17705 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 17706 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 17707 confp->mfcr2.max_ani = atoi(v->value); 17708 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 17709 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 17710 } 17711 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 17712 confp->mfcr2.max_dnis = atoi(v->value); 17713 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 17714 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 17715 } 17716 } else if (!strcasecmp(v->name, "mfcr2_category")) { 17717 confp->mfcr2.category = openr2_proto_get_category(v->value); 17718 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 17719 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 17720 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 17721 v->value, v->lineno); 17722 } 17723 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 17724 openr2_log_level_t tmplevel; 17725 char *clevel; 17726 char *logval = ast_strdupa(v->value); 17727 while (logval) { 17728 clevel = strsep(&logval,","); 17729 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 17730 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 17731 continue; 17732 } 17733 confp->mfcr2.loglevel |= tmplevel; 17734 } 17735 #endif /* HAVE_OPENR2 */ 17736 } else if (!strcasecmp(v->name, "cadence")) { 17737 /* setup to scan our argument */ 17738 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 17739 int i; 17740 struct dahdi_ring_cadence new_cadence; 17741 int cid_location = -1; 17742 int firstcadencepos = 0; 17743 char original_args[80]; 17744 int cadence_is_ok = 1; 17745 17746 ast_copy_string(original_args, v->value, sizeof(original_args)); 17747 /* 16 cadences allowed (8 pairs) */ 17748 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]); 17749 17750 /* Cadence must be even (on/off) */ 17751 if (element_count % 2 == 1) { 17752 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 17753 cadence_is_ok = 0; 17754 } 17755 17756 /* Ring cadences cannot be negative */ 17757 for (i = 0; i < element_count; i++) { 17758 if (c[i] == 0) { 17759 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 17760 cadence_is_ok = 0; 17761 break; 17762 } else if (c[i] < 0) { 17763 if (i % 2 == 1) { 17764 /* Silence duration, negative possibly okay */ 17765 if (cid_location == -1) { 17766 cid_location = i; 17767 c[i] *= -1; 17768 } else { 17769 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 17770 cadence_is_ok = 0; 17771 break; 17772 } 17773 } else { 17774 if (firstcadencepos == 0) { 17775 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 17776 /* duration will be passed negative to the DAHDI driver */ 17777 } else { 17778 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 17779 cadence_is_ok = 0; 17780 break; 17781 } 17782 } 17783 } 17784 } 17785 17786 /* Substitute our scanned cadence */ 17787 for (i = 0; i < 16; i++) { 17788 new_cadence.ringcadence[i] = c[i]; 17789 } 17790 17791 if (cadence_is_ok) { 17792 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 17793 if (element_count < 2) { 17794 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 17795 } else { 17796 if (cid_location == -1) { 17797 /* user didn't say; default to first pause */ 17798 cid_location = 1; 17799 } else { 17800 /* convert element_index to cidrings value */ 17801 cid_location = (cid_location + 1) / 2; 17802 } 17803 /* ---we like their cadence; try to install it--- */ 17804 if (!user_has_defined_cadences++) 17805 /* this is the first user-defined cadence; clear the default user cadences */ 17806 num_cadence = 0; 17807 if ((num_cadence+1) >= NUM_CADENCE_MAX) 17808 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 17809 else { 17810 cadences[num_cadence] = new_cadence; 17811 cidrings[num_cadence++] = cid_location; 17812 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 17813 } 17814 } 17815 } 17816 } else if (!strcasecmp(v->name, "ringtimeout")) { 17817 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 17818 } else if (!strcasecmp(v->name, "prewink")) { 17819 confp->timing.prewinktime = atoi(v->value); 17820 } else if (!strcasecmp(v->name, "preflash")) { 17821 confp->timing.preflashtime = atoi(v->value); 17822 } else if (!strcasecmp(v->name, "wink")) { 17823 confp->timing.winktime = atoi(v->value); 17824 } else if (!strcasecmp(v->name, "flash")) { 17825 confp->timing.flashtime = atoi(v->value); 17826 } else if (!strcasecmp(v->name, "start")) { 17827 confp->timing.starttime = atoi(v->value); 17828 } else if (!strcasecmp(v->name, "rxwink")) { 17829 confp->timing.rxwinktime = atoi(v->value); 17830 } else if (!strcasecmp(v->name, "rxflash")) { 17831 confp->timing.rxflashtime = atoi(v->value); 17832 } else if (!strcasecmp(v->name, "debounce")) { 17833 confp->timing.debouncetime = atoi(v->value); 17834 } else if (!strcasecmp(v->name, "toneduration")) { 17835 int toneduration; 17836 int ctlfd; 17837 int res; 17838 struct dahdi_dialparams dps; 17839 17840 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 17841 if (ctlfd == -1) { 17842 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 17843 return -1; 17844 } 17845 17846 toneduration = atoi(v->value); 17847 if (toneduration > -1) { 17848 memset(&dps, 0, sizeof(dps)); 17849 17850 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 17851 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 17852 if (res < 0) { 17853 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 17854 close(ctlfd); 17855 return -1; 17856 } 17857 } 17858 close(ctlfd); 17859 } else if (!strcasecmp(v->name, "defaultcic")) { 17860 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 17861 } else if (!strcasecmp(v->name, "defaultozz")) { 17862 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 17863 } else if (!strcasecmp(v->name, "mwilevel")) { 17864 mwilevel = atoi(v->value); 17865 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 17866 dtmfcid_level = atoi(v->value); 17867 } else if (!strcasecmp(v->name, "reportalarms")) { 17868 if (!strcasecmp(v->value, "all")) 17869 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; 17870 if (!strcasecmp(v->value, "none")) 17871 report_alarms = 0; 17872 else if (!strcasecmp(v->value, "channels")) 17873 report_alarms = REPORT_CHANNEL_ALARMS; 17874 else if (!strcasecmp(v->value, "spans")) 17875 report_alarms = REPORT_SPAN_ALARMS; 17876 } 17877 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 17878 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 17879 } 17880 17881 /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */ 17882 if (confp->chan.vars) { 17883 ast_variables_destroy(confp->chan.vars); 17884 confp->chan.vars = NULL; 17885 } 17886 17887 if (dahdichan) { 17888 /* Process the deferred dahdichan value. */ 17889 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno, 17890 &found_pseudo)) { 17891 if (confp->ignore_failed_channels) { 17892 ast_log(LOG_WARNING, 17893 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n", 17894 dahdichan->value); 17895 } else { 17896 return -1; 17897 } 17898 } 17899 } 17900 17901 /* mark the first channels of each DAHDI span to watch for their span alarms */ 17902 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { 17903 if (!tmp->destroy && tmp->span != y) { 17904 tmp->manages_span_alarms = 1; 17905 y = tmp->span; 17906 } else { 17907 tmp->manages_span_alarms = 0; 17908 } 17909 } 17910 17911 /*< \todo why check for the pseudo in the per-channel section. 17912 * Any actual use for manual setup of the pseudo channel? */ 17913 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) { 17914 /* use the default configuration for a channel, so 17915 that any settings from real configured channels 17916 don't "leak" into the pseudo channel config 17917 */ 17918 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 17919 17920 if (conf.chan.cc_params) { 17921 tmp = mkintf(CHAN_PSEUDO, &conf, reload); 17922 } else { 17923 tmp = NULL; 17924 } 17925 if (tmp) { 17926 ast_verb(3, "Automatically generated pseudo channel\n"); 17927 } else { 17928 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 17929 } 17930 ast_cc_config_params_destroy(conf.chan.cc_params); 17931 } 17932 return 0; 17933 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 16773 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, name, dahdi_pvt::params, parse(), and value.
16774 { 16775 char *parse = ast_strdupa(data); 16776 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 16777 unsigned int param_count; 16778 unsigned int x; 16779 16780 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 16781 return; 16782 16783 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 16784 16785 /* first parameter is tap length, process it here */ 16786 16787 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 16788 16789 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 16790 confp->chan.echocancel.head.tap_length = x; 16791 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 16792 confp->chan.echocancel.head.tap_length = 128; 16793 16794 /* now process any remaining parameters */ 16795 16796 for (x = 1; x < param_count; x++) { 16797 struct { 16798 char *name; 16799 char *value; 16800 } param; 16801 16802 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 16803 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 16804 continue; 16805 } 16806 16807 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 16808 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 16809 continue; 16810 } 16811 16812 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 16813 16814 if (param.value) { 16815 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 16816 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 16817 continue; 16818 } 16819 } 16820 confp->chan.echocancel.head.param_count++; 16821 } 16822 }
static int reload | ( | void | ) | [static] |
Definition at line 18611 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
18612 { 18613 int res = 0; 18614 18615 res = setup_dahdi(1); 18616 if (res) { 18617 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 18618 return -1; 18619 } 18620 return 0; 18621 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4763 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup(), and my_all_subchannels_hungup().
04764 { 04765 p->confno = -1; 04766 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 04767 if (p->subs[SUB_REAL].dfd > -1) { 04768 struct dahdi_confinfo zi; 04769 04770 memset(&zi, 0, sizeof(zi)); 04771 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 04772 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 04773 } 04774 return 0; 04775 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 11839 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, monitor_thread, and monlock.
Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), my_all_subchannels_hungup(), oh323_request(), phone_hangup(), phone_request(), sip_reload(), sip_request_call(), skinny_request(), unistim_reload(), and unistim_request().
11840 { 11841 /* If we're supposed to be stopped -- stay stopped */ 11842 if (monitor_thread == AST_PTHREADT_STOP) 11843 return 0; 11844 ast_mutex_lock(&monlock); 11845 if (monitor_thread == pthread_self()) { 11846 ast_mutex_unlock(&monlock); 11847 ast_log(LOG_WARNING, "Cannot kill myself\n"); 11848 return -1; 11849 } 11850 if (monitor_thread != AST_PTHREADT_NULL) { 11851 /* Wake up the thread */ 11852 pthread_kill(monitor_thread, SIGURG); 11853 } else { 11854 /* Start a new monitor */ 11855 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 11856 ast_mutex_unlock(&monlock); 11857 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 11858 return -1; 11859 } 11860 } 11861 ast_mutex_unlock(&monlock); 11862 return 0; 11863 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5176 of file chan_dahdi.c.
References ast_debug, ast_log(), 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().
05177 { 05178 int res; 05179 if (p->saveconf.confmode) { 05180 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 05181 p->saveconf.confmode = 0; 05182 if (res) { 05183 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 05184 return -1; 05185 } 05186 ast_debug(1, "Restored conferencing\n"); 05187 } 05188 return 0; 05189 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5083 of file chan_dahdi.c.
References ast_log(), 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(), and mwi_thread().
05084 { 05085 int res; 05086 05087 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05088 if (res) { 05089 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 05090 return -1; 05091 } 05092 05093 return 0; 05094 }
static int revert_fax_buffers | ( | struct dahdi_pvt * | p, | |
struct ast_channel * | ast | |||
) | [static] |
Definition at line 6066 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, errno, LOG_WARNING, ast_channel::name, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
06067 { 06068 if (p->bufferoverrideinuse) { 06069 /* faxbuffers are in use, revert them */ 06070 struct dahdi_bufferinfo bi = { 06071 .txbufpolicy = p->buf_policy, 06072 .rxbufpolicy = p->buf_policy, 06073 .bufsize = p->bufsize, 06074 .numbufs = p->buf_no 06075 }; 06076 int bpres; 06077 06078 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06079 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno)); 06080 } 06081 p->bufferoverrideinuse = 0; 06082 return bpres; 06083 } 06084 06085 return -1; 06086 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5150 of file chan_dahdi.c.
References ast_debug, ast_log(), errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), dahdi_handle_event(), and my_callwait().
05151 { 05152 struct dahdi_confinfo c; 05153 int res; 05154 if (p->saveconf.confmode) { 05155 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 05156 return -1; 05157 } 05158 p->saveconf.chan = 0; 05159 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 05160 if (res) { 05161 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 05162 p->saveconf.confmode = 0; 05163 return -1; 05164 } 05165 memset(&c, 0, sizeof(c)); 05166 c.confmode = DAHDI_CONF_NORMAL; 05167 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 05168 if (res) { 05169 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 05170 return -1; 05171 } 05172 ast_debug(1, "Disabled conferencing\n"); 05173 return 0; 05174 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5234 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(), 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().
05235 { 05236 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 05237 int res; 05238 /* Take out of linear mode if necessary */ 05239 if (p->subs[SUB_REAL].linear) { 05240 p->subs[SUB_REAL].linear = 0; 05241 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 05242 } 05243 while (p->cidpos < p->cidlen) { 05244 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 05245 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res); 05246 if (res < 0) { 05247 if (errno == EAGAIN) 05248 return 0; 05249 else { 05250 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05251 return -1; 05252 } 05253 } 05254 if (!res) 05255 return 0; 05256 p->cidpos += res; 05257 } 05258 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 05259 ast_free(p->cidspill); 05260 p->cidspill = NULL; 05261 if (p->callwaitcas) { 05262 /* Wait for CID/CW to expire */ 05263 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 05264 p->cid_suppress_expire = p->cidcwexpire; 05265 } else 05266 restore_conference(p); 05267 return 0; 05268 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5191 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().
05192 { 05193 p->callwaitcas = 0; 05194 p->cidcwexpire = 0; 05195 p->cid_suppress_expire = 0; 05196 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 05197 return -1; 05198 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 05199 /* Make sure we account for the end */ 05200 p->cidlen += READ_SIZE * 4; 05201 p->cidpos = 0; 05202 send_callerid(p); 05203 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 05204 return 0; 05205 }
static int set_actual_gain | ( | int | fd, | |
float | rxgain, | |||
float | txgain, | |||
float | rxdrc, | |||
float | txdrc, | |||
int | law | |||
) | [static] |
Definition at line 5064 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), my_pri_open_media(), and restore_gains().
05065 { 05066 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law); 05067 }
static int set_actual_rxgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5047 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05048 { 05049 struct dahdi_gains g; 05050 int res; 05051 05052 memset(&g, 0, sizeof(g)); 05053 res = ioctl(fd, DAHDI_GETGAINS, &g); 05054 if (res) { 05055 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05056 return res; 05057 } 05058 05059 fill_rxgain(&g, gain, drc, law); 05060 05061 return ioctl(fd, DAHDI_SETGAINS, &g); 05062 }
static int set_actual_txgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 5030 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
05031 { 05032 struct dahdi_gains g; 05033 int res; 05034 05035 memset(&g, 0, sizeof(g)); 05036 res = ioctl(fd, DAHDI_GETGAINS, &g); 05037 if (res) { 05038 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 05039 return res; 05040 } 05041 05042 fill_txgain(&g, gain, drc, law); 05043 05044 return ioctl(fd, DAHDI_SETGAINS, &g); 05045 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 18254 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 load_module(), and reload().
18255 { 18256 int res; 18257 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default(); 18258 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 18259 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 18260 18261 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) { 18262 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf); 18263 } else { 18264 res = -1; 18265 } 18266 ast_cc_config_params_destroy(default_conf.chan.cc_params); 18267 ast_cc_config_params_destroy(base_conf.chan.cc_params); 18268 ast_cc_config_params_destroy(conf.chan.cc_params); 18269 18270 return res; 18271 }
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 17967 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_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, deep_copy_dahdi_chan_conf(), default_jbconf, global_jbconf, ast_variable::lineno, LOG_NOTICE, mwimonitornotify, ast_variable::name, ast_variable::next, prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.
Referenced by setup_dahdi().
17968 { 17969 struct ast_config *cfg; 17970 struct ast_config *ucfg; 17971 struct ast_variable *v; 17972 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 17973 const char *chans; 17974 const char *cat; 17975 int res; 17976 17977 #ifdef HAVE_PRI 17978 char *c; 17979 int spanno; 17980 int i; 17981 int logicalspan; 17982 int trunkgroup; 17983 int dchannels[SIG_PRI_NUM_DCHANS]; 17984 #endif 17985 int have_cfg_now; 17986 static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */ 17987 17988 cfg = ast_config_load(config, config_flags); 17989 have_cfg_now = !!cfg; 17990 if (!cfg) { 17991 /* Error if we have no config file */ 17992 if (had_cfg_before) { 17993 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 17994 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 17995 } 17996 cfg = ast_config_new();/* Dummy config */ 17997 if (!cfg) { 17998 return 0; 17999 } 18000 ucfg = ast_config_load("users.conf", config_flags); 18001 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18002 ast_config_destroy(cfg); 18003 return 0; 18004 } 18005 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18006 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18007 ast_config_destroy(cfg); 18008 return 0; 18009 } 18010 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 18011 ucfg = ast_config_load("users.conf", config_flags); 18012 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 18013 return 0; 18014 } 18015 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18016 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18017 return 0; 18018 } 18019 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18020 cfg = ast_config_load(config, config_flags); 18021 have_cfg_now = !!cfg; 18022 if (!cfg) { 18023 if (had_cfg_before) { 18024 /* We should have been able to load the config. */ 18025 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config); 18026 ast_config_destroy(ucfg); 18027 return 0; 18028 } 18029 cfg = ast_config_new();/* Dummy config */ 18030 if (!cfg) { 18031 ast_config_destroy(ucfg); 18032 return 0; 18033 } 18034 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18035 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18036 ast_config_destroy(ucfg); 18037 return 0; 18038 } 18039 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 18040 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 18041 return 0; 18042 } else { 18043 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 18044 ucfg = ast_config_load("users.conf", config_flags); 18045 if (ucfg == CONFIG_STATUS_FILEINVALID) { 18046 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 18047 ast_config_destroy(cfg); 18048 return 0; 18049 } 18050 } 18051 had_cfg_before = have_cfg_now; 18052 18053 /* It's a little silly to lock it, but we might as well just to be sure */ 18054 ast_mutex_lock(&iflock); 18055 #ifdef HAVE_PRI 18056 if (reload != 1) { 18057 /* Process trunkgroups first */ 18058 v = ast_variable_browse(cfg, "trunkgroups"); 18059 while (v) { 18060 if (!strcasecmp(v->name, "trunkgroup")) { 18061 trunkgroup = atoi(v->value); 18062 if (trunkgroup > 0) { 18063 if ((c = strchr(v->value, ','))) { 18064 i = 0; 18065 memset(dchannels, 0, sizeof(dchannels)); 18066 while (c && (i < SIG_PRI_NUM_DCHANS)) { 18067 dchannels[i] = atoi(c + 1); 18068 if (dchannels[i] < 0) { 18069 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); 18070 } else 18071 i++; 18072 c = strchr(c + 1, ','); 18073 } 18074 if (i) { 18075 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 18076 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); 18077 } else 18078 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"); 18079 } else 18080 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18081 } else 18082 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 18083 } else 18084 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 18085 } else if (!strcasecmp(v->name, "spanmap")) { 18086 spanno = atoi(v->value); 18087 if (spanno > 0) { 18088 if ((c = strchr(v->value, ','))) { 18089 trunkgroup = atoi(c + 1); 18090 if (trunkgroup > 0) { 18091 if ((c = strchr(c + 1, ','))) 18092 logicalspan = atoi(c + 1); 18093 else 18094 logicalspan = 0; 18095 if (logicalspan >= 0) { 18096 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 18097 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18098 } else 18099 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 18100 } else 18101 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); 18102 } else 18103 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 18104 } else 18105 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 18106 } else 18107 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 18108 } else { 18109 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 18110 } 18111 v = v->next; 18112 } 18113 } 18114 #endif 18115 18116 /* Copy the default jb config over global_jbconf */ 18117 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 18118 18119 mwimonitornotify[0] = '\0'; 18120 18121 v = ast_variable_browse(cfg, "channels"); 18122 if ((res = process_dahdi(base_conf, 18123 "" /* Must be empty for the channels category. Silly voicemail mailbox. */, 18124 v, reload, 0))) { 18125 ast_mutex_unlock(&iflock); 18126 ast_config_destroy(cfg); 18127 if (ucfg) { 18128 ast_config_destroy(ucfg); 18129 } 18130 return res; 18131 } 18132 18133 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 18134 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 18135 /* [channels] and [trunkgroups] are used. Let's also reserve 18136 * [globals] and [general] for future use 18137 */ 18138 if (!strcasecmp(cat, "general") || 18139 !strcasecmp(cat, "trunkgroups") || 18140 !strcasecmp(cat, "globals") || 18141 !strcasecmp(cat, "channels")) { 18142 continue; 18143 } 18144 18145 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 18146 if (ast_strlen_zero(chans)) { 18147 /* Section is useless without a dahdichan value present. */ 18148 continue; 18149 } 18150 18151 /* Copy base_conf to conf. */ 18152 deep_copy_dahdi_chan_conf(conf, base_conf); 18153 18154 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 18155 ast_mutex_unlock(&iflock); 18156 ast_config_destroy(cfg); 18157 if (ucfg) { 18158 ast_config_destroy(ucfg); 18159 } 18160 return res; 18161 } 18162 } 18163 18164 ast_config_destroy(cfg); 18165 18166 if (ucfg) { 18167 /* Reset base_conf, so things don't leak from chan_dahdi.conf */ 18168 deep_copy_dahdi_chan_conf(base_conf, default_conf); 18169 process_dahdi(base_conf, 18170 "" /* Must be empty for the general category. Silly voicemail mailbox. */, 18171 ast_variable_browse(ucfg, "general"), 1, 0); 18172 18173 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 18174 if (!strcasecmp(cat, "general")) { 18175 continue; 18176 } 18177 18178 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 18179 if (ast_strlen_zero(chans)) { 18180 /* Section is useless without a dahdichan value present. */ 18181 continue; 18182 } 18183 18184 /* Copy base_conf to conf. */ 18185 deep_copy_dahdi_chan_conf(conf, base_conf); 18186 18187 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 18188 ast_config_destroy(ucfg); 18189 ast_mutex_unlock(&iflock); 18190 return res; 18191 } 18192 } 18193 ast_config_destroy(ucfg); 18194 } 18195 ast_mutex_unlock(&iflock); 18196 18197 #ifdef HAVE_PRI 18198 if (reload != 1) { 18199 int x; 18200 for (x = 0; x < NUM_SPANS; x++) { 18201 if (pris[x].pri.pvts[0]) { 18202 prepare_pri(pris + x); 18203 if (sig_pri_start_pri(&pris[x].pri)) { 18204 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 18205 return -1; 18206 } else 18207 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 18208 } 18209 } 18210 } 18211 #endif 18212 #if defined(HAVE_SS7) 18213 if (reload != 1) { 18214 int x; 18215 for (x = 0; x < NUM_SPANS; x++) { 18216 if (linksets[x].ss7.ss7) { 18217 linksets[x].ss7.calls = &dahdi_ss7_callbacks; 18218 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) { 18219 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 18220 return -1; 18221 } else 18222 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 18223 } 18224 } 18225 } 18226 #endif /* defined(HAVE_SS7) */ 18227 #ifdef HAVE_OPENR2 18228 if (reload != 1) { 18229 int x; 18230 for (x = 0; x < r2links_count; x++) { 18231 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 18232 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 18233 return -1; 18234 } else { 18235 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 18236 } 18237 } 18238 } 18239 #endif 18240 /* And start the monitor for the first time */ 18241 restart_monitor(); 18242 return 0; 18243 }
static int sig_pri_tone_to_dahditone | ( | enum sig_pri_tone | tone | ) | [static] |
Definition at line 3049 of file chan_dahdi.c.
References SIG_PRI_TONE_BUSY, SIG_PRI_TONE_CONGESTION, SIG_PRI_TONE_DIALRECALL, SIG_PRI_TONE_DIALTONE, SIG_PRI_TONE_INFO, SIG_PRI_TONE_RINGTONE, and SIG_PRI_TONE_STUTTER.
Referenced by my_pri_play_tone().
03050 { 03051 switch (tone) { 03052 case SIG_PRI_TONE_RINGTONE: 03053 return DAHDI_TONE_RINGTONE; 03054 case SIG_PRI_TONE_STUTTER: 03055 return DAHDI_TONE_STUTTER; 03056 case SIG_PRI_TONE_CONGESTION: 03057 return DAHDI_TONE_CONGESTION; 03058 case SIG_PRI_TONE_DIALTONE: 03059 return DAHDI_TONE_DIALTONE; 03060 case SIG_PRI_TONE_DIALRECALL: 03061 return DAHDI_TONE_DIALRECALL; 03062 case SIG_PRI_TONE_INFO: 03063 return DAHDI_TONE_INFO; 03064 case SIG_PRI_TONE_BUSY: 03065 return DAHDI_TONE_BUSY; 03066 default: 03067 return -1; 03068 } 03069 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
static void string_replace | ( | char * | str, | |
int | char1, | |||
int | char2 | |||
) | [static] |
Definition at line 16677 of file chan_dahdi.c.
Referenced by parse_spanchan().
16678 { 16679 for (; *str; str++) { 16680 if (*str == char1) { 16681 *str = char2; 16682 } 16683 } 16684 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 4222 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(), dahdi_hangup(), HandleCallOutgoing(), and unistim_hangup().
04223 { 04224 int tchan; 04225 int tinthreeway; 04226 struct ast_channel *towner; 04227 04228 ast_debug(1, "Swapping %d and %d\n", a, b); 04229 04230 tchan = p->subs[a].chan; 04231 towner = p->subs[a].owner; 04232 tinthreeway = p->subs[a].inthreeway; 04233 04234 p->subs[a].chan = p->subs[b].chan; 04235 p->subs[a].owner = p->subs[b].owner; 04236 p->subs[a].inthreeway = p->subs[b].inthreeway; 04237 04238 p->subs[b].chan = tchan; 04239 p->subs[b].owner = towner; 04240 p->subs[b].inthreeway = tinthreeway; 04241 04242 if (p->subs[a].owner) 04243 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 04244 if (p->subs[b].owner) 04245 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 04246 wakeup_sub(p, a); 04247 wakeup_sub(p, b); 04248 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4368 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(), my_unallocate_sub(), and unistim_hangup().
04369 { 04370 if (!x) { 04371 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 04372 return -1; 04373 } 04374 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 04375 dahdi_close_sub(p, x); 04376 p->subs[x].linear = 0; 04377 p->subs[x].chan = 0; 04378 p->subs[x].owner = NULL; 04379 p->subs[x].inthreeway = 0; 04380 p->polarity = POLARITY_IDLE; 04381 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 04382 return 0; 04383 }
static int unload_module | ( | void | ) | [static] |
Definition at line 16661 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, sig_pri_span::lock, and dahdi_pvt::pri.
16662 { 16663 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16664 int y; 16665 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16666 #ifdef HAVE_PRI 16667 for (y = 0; y < NUM_SPANS; y++) 16668 ast_mutex_destroy(&pris[y].pri.lock); 16669 #endif 16670 #if defined(HAVE_SS7) 16671 for (y = 0; y < NUM_SPANS; y++) 16672 ast_mutex_destroy(&linksets[y].ss7.lock); 16673 #endif /* defined(HAVE_SS7) */ 16674 return __unload_module(); 16675 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4777 of file chan_dahdi.c.
References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), and dahdi_hangup().
04778 { 04779 int needconf = 0; 04780 int x; 04781 int useslavenative; 04782 struct dahdi_pvt *slave = NULL; 04783 04784 useslavenative = isslavenative(p, &slave); 04785 /* Start with the obvious, general stuff */ 04786 for (x = 0; x < 3; x++) { 04787 /* Look for three way calls */ 04788 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 04789 conf_add(p, &p->subs[x], x, 0); 04790 needconf++; 04791 } else { 04792 conf_del(p, &p->subs[x], x); 04793 } 04794 } 04795 /* If we have a slave, add him to our conference now. or DAX 04796 if this is slave native */ 04797 for (x = 0; x < MAX_SLAVES; x++) { 04798 if (p->slaves[x]) { 04799 if (useslavenative) 04800 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 04801 else { 04802 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 04803 needconf++; 04804 } 04805 } 04806 } 04807 /* If we're supposed to be in there, do so now */ 04808 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 04809 if (useslavenative) 04810 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 04811 else { 04812 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 04813 needconf++; 04814 } 04815 } 04816 /* If we have a master, add ourselves to his conference */ 04817 if (p->master) { 04818 if (isslavenative(p->master, NULL)) { 04819 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 04820 } else { 04821 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 04822 } 04823 } 04824 if (!needconf) { 04825 /* Nobody is left (or should be left) in our conference. 04826 Kill it. */ 04827 p->confno = -1; 04828 } 04829 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 04830 return 0; 04831 }
static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
int | a | |||
) | [static] |
Definition at line 3735 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().
03736 { 03737 dahdi_lock_sub_owner(p, a); 03738 if (p->subs[a].owner) { 03739 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 03740 ast_channel_unlock(p->subs[a].owner); 03741 } 03742 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = tdesc , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static] |
Definition at line 18633 of file chan_dahdi.c.
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 18633 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 387 of file chan_dahdi.c.
Referenced by handle_dahdi_show_cadences(), and my_set_cadence().
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 398 of file chan_dahdi.c.
Referenced by handle_dahdi_show_cadences().
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 341 of file chan_dahdi.c.
const char* const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 5924 of file chan_dahdi.c.
struct analog_callback dahdi_analog_callbacks [static] |
Definition at line 3612 of file chan_dahdi.c.
struct ast_data_handler dahdi_channels_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = dahdi_channels_data_provider_get }
Definition at line 18414 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
struct ast_data_entry dahdi_data_providers[] [static] |
Initial value:
{ 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 18424 of file chan_dahdi.c.
Referenced by load_module().
struct ast_cli_entry dahdi_mfcr2_cli[] [static] |
struct sig_pri_callback dahdi_pri_callbacks [static] |
struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks [static] |
struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks [static] |
const char dahdi_pri_cc_type[] = "DAHDI/PRI" [static] |
DAHDI PRI CCSS agent and monitor type name.
Definition at line 599 of file chan_dahdi.c.
Referenced by dahdi_queryoption(), and load_module().
struct ast_cli_entry dahdi_pri_cli[] [static] |
struct dahdi_parms_pseudo dahdi_pseudo_parms [static] |
openr2_event_interface_t dahdi_r2_event_iface [static] |
Definition at line 4184 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 4215 of file chan_dahdi.c.
char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static] |
Definition at line 5861 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 5834 of file chan_dahdi.c.
struct ast_data_handler dahdi_status_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = dahdi_status_data_provider_get }
Definition at line 18409 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1512 of file chan_dahdi.c.
Referenced by __unload_module(), analog_ss_thread(), dahdi_accept_r2_call_exec(), dahdi_new(), dahdi_send_callrerouting_facility_exec(), and load_module().
struct ast_data_handler dahdi_version_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = dahdi_version_data_provider_get }
Definition at line 18419 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 290 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 414 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 415 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 426 of file chan_dahdi.c.
int dtmfcid_level = 256 [static] |
Definition at line 431 of file chan_dahdi.c.
const char* const events[] [static] |
Definition at line 4492 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 443 of file chan_dahdi.c.
Referenced by analog_ss_thread(), disa_exec(), and mgcp_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 446 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and mgcp_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 298 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 455 of file chan_dahdi.c.
Referenced by destroy_all_channels(), and do_monitor().
Main interface list end
Definition at line 1316 of file chan_dahdi.c.
Referenced by dahdi_iflist_extract(), dahdi_request(), and determine_starting_point().
Main interface list start
Definition at line 1315 of file chan_dahdi.c.
Referenced by __oh323_destroy(), __unload_module(), action_dahdishowchannels(), dahdi_channels_data_provider_get(), dahdi_destroy_channel_bynum(), dahdi_iflist_extract(), dahdi_iflist_insert(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), determine_starting_point(), do_monitor(), find_call_locked(), find_channel(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), load_module(), mkintf(), oh323_alloc(), phone_request(), and unload_module().
ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 452 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_cc_callback(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), destroy_all_channels(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), and unload_module().
const char* const lbostr[] [static] |
Definition at line 277 of file chan_dahdi.c.
Referenced by dahdi_show_status(), and dahdi_status_data_provider_get().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 449 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and mgcp_ss().
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 467 of file chan_dahdi.c.
Referenced by __sip_reliable_xmit(), __unload_module(), restart_monitor(), and unload_module().
ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 463 of file chan_dahdi.c.
Referenced by __unload_module(), do_monitor(), restart_monitor(), and unload_module().
int mwilevel = 512 [static] |
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 418 of file chan_dahdi.c.
Referenced by notify_message(), and setup_dahdi_int().
char* name |
Definition at line 4516 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 384 of file chan_dahdi.c.
Referenced by handle_dahdi_show_cadences(), and my_set_cadence().
int num_restart_pending = 0 [static] |
Definition at line 472 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_softhangup_all(), destroy_all_channels(), and my_all_subchannels_hungup().
int numbufs = 4 [static] |
Definition at line 428 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
char pridebugfilename[1024] = "" [static] |
Definition at line 595 of file chan_dahdi.c.
Referenced by complete_span_helper(), dahdi_devicestate(), dahdi_pri_error(), dahdi_pri_message(), dahdi_restart(), destroy_all_channels(), handle_pri_debug(), handle_pri_service_generic(), handle_pri_show_channels(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), prepare_pri(), pri_create_spanmap(), pri_create_trunkgroup(), and pri_resolve_span().
char progzone[10] = "" [static] |
struct dahdi_mfcr2** r2links [static] |
Definition at line 580 of file chan_dahdi.c.
Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().
int r2links_count = 0 [static] |
Definition at line 582 of file chan_dahdi.c.
Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().
int report_alarms = REPORT_CHANNEL_ALARMS [static] |
Definition at line 435 of file chan_dahdi.c.
Referenced by handle_alarms(), and handle_clear_alarms().
ast_mutex_t restart_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 528 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] [static] |
Round robin search locations.
Definition at line 3682 of file chan_dahdi.c.
Referenced by dahdi_request(), determine_starting_point(), and load_module().
ast_cond_t ss_thread_complete [static] |
Definition at line 468 of file chan_dahdi.c.
Referenced by __unload_module(), load_module(), and my_decrease_ss_count().
int ss_thread_count = 0 [static] |
Definition at line 471 of file chan_dahdi.c.
Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().
ast_mutex_t ss_thread_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 469 of file chan_dahdi.c.
Referenced by analog_ss_thread(), my_decrease_ss_count(), and my_increase_ss_count().
const char* const subnames[] [static] |
Initial value:
{ "Real", "Callwait", "Threeway" }
Definition at line 628 of file chan_dahdi.c.
Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().
const char tdesc[] [static] |
Definition at line 320 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 425 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 385 of file chan_dahdi.c.