#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 | 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 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_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_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_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_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 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_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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_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 char | parkinglot [AST_MAX_EXTENSION] = "" |
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 293 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 360 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 |
#define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) |
10,000 ms
Definition at line 497 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 496 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 391 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and my_set_waitingfordt().
#define CHAN_PSEUDO -2 |
Definition at line 355 of file chan_dahdi.c.
Referenced by build_channels(), create_channel_name(), 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 633 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 634 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 3600 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 1225 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 291 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 501 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 15431 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 387 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 493 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 494 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 16390 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_SLAVES 4 |
Definition at line 636 of file chan_dahdi.c.
Referenced by isslavenative(), and my_complete_conference_update().
#define MIN_MS_SINCE_FLASH ((2000) ) |
2000 ms
Definition at line 500 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 297 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and dahdi_new().
#define NUM_CADENCE_MAX 25 |
Definition at line 362 of file chan_dahdi.c.
#define NUM_SPANS 32 |
Definition at line 352 of file chan_dahdi.c.
Referenced by destroy_all_channels(), pri_create_trunkgroup(), and pri_resolve_span().
#define POLARITY_IDLE 0 |
Definition at line 593 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 594 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 16444 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi_int().
#define PROC_DAHDI_OPT_NOWARN (1 << 1) |
process_dahdi() - No warnings on non-existing cofiguration keywords
Definition at line 16446 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 491 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 414 of file chan_dahdi.c.
Referenced by handle_alarms(), and handle_clear_alarms().
#define REPORT_SPAN_ALARMS 2 |
Definition at line 415 of file chan_dahdi.c.
Referenced by handle_alarms(), and handle_clear_alarms().
#define sig2str dahdi_sig2str |
Definition at line 4526 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 338 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 339 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 327 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 322 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 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_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 323 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 326 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 324 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 325 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 328 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 329 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 330 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 335 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 336 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 334 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 332 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 333 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 331 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 341 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), 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 83 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 1520 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 342 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 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_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
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_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
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_SFWINK (0x0100000 | DAHDI_SIG_SF) |
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_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 340 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), 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 589 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 588 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 590 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 15430 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 657 of file chan_dahdi.c.
00657 { 00658 DAHDI_IFLIST_NONE, /*!< The dahdi_pvt is not in any list. */ 00659 DAHDI_IFLIST_MAIN, /*!< The dahdi_pvt is in the main interface list */ 00660 #if defined(HAVE_PRI) 00661 DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */ 00662 #endif /* defined(HAVE_PRI) */ 00663 };
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 641 of file chan_dahdi.c.
00641 { 00642 MWI_SEND_NULL = 0, 00643 MWI_SEND_SA, 00644 MWI_SEND_SA_WAIT, 00645 MWI_SEND_PAUSE, 00646 MWI_SEND_SPILL, 00647 MWI_SEND_CLEANUP, 00648 MWI_SEND_DONE, 00649 } mwisend_states;
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8513 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().
08514 { 08515 int res; 08516 int idx; 08517 struct ast_frame *f; 08518 int usedindex = -1; 08519 struct dahdi_pvt *p = ast->tech_pvt; 08520 08521 idx = dahdi_get_index(ast, p, 1); 08522 08523 p->subs[idx].f.frametype = AST_FRAME_NULL; 08524 p->subs[idx].f.datalen = 0; 08525 p->subs[idx].f.samples = 0; 08526 p->subs[idx].f.mallocd = 0; 08527 p->subs[idx].f.offset = 0; 08528 p->subs[idx].f.subclass.integer = 0; 08529 p->subs[idx].f.delivery = ast_tv(0,0); 08530 p->subs[idx].f.src = "dahdi_exception"; 08531 p->subs[idx].f.data.ptr = NULL; 08532 08533 08534 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 08535 /* If nobody owns us, absorb the event appropriately, otherwise 08536 we loop indefinitely. This occurs when, during call waiting, the 08537 other end hangs up our channel so that it no longer exists, but we 08538 have neither FLASH'd nor ONHOOK'd to signify our desire to 08539 change to the other channel. */ 08540 if (p->fake_event) { 08541 res = p->fake_event; 08542 p->fake_event = 0; 08543 } else 08544 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 08545 /* Switch to real if there is one and this isn't something really silly... */ 08546 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 08547 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 08548 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 08549 p->owner = p->subs[SUB_REAL].owner; 08550 if (p->owner && ast_bridged_channel(p->owner)) 08551 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08552 p->subs[SUB_REAL].needunhold = 1; 08553 } 08554 switch (res) { 08555 case DAHDI_EVENT_ONHOOK: 08556 dahdi_disable_ec(p); 08557 if (p->owner) { 08558 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 08559 dahdi_ring_phone(p); 08560 p->callwaitingrepeat = 0; 08561 p->cidcwexpire = 0; 08562 p->cid_suppress_expire = 0; 08563 } else 08564 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08565 update_conf(p); 08566 break; 08567 case DAHDI_EVENT_RINGOFFHOOK: 08568 dahdi_enable_ec(p); 08569 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08570 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 08571 p->subs[SUB_REAL].needanswer = 1; 08572 p->dialing = 0; 08573 } 08574 break; 08575 case DAHDI_EVENT_HOOKCOMPLETE: 08576 case DAHDI_EVENT_RINGERON: 08577 case DAHDI_EVENT_RINGEROFF: 08578 /* Do nothing */ 08579 break; 08580 case DAHDI_EVENT_WINKFLASH: 08581 p->flashtime = ast_tvnow(); 08582 if (p->owner) { 08583 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 08584 if (p->owner->_state != AST_STATE_UP) { 08585 /* Answer if necessary */ 08586 usedindex = dahdi_get_index(p->owner, p, 0); 08587 if (usedindex > -1) { 08588 p->subs[usedindex].needanswer = 1; 08589 } 08590 ast_setstate(p->owner, AST_STATE_UP); 08591 } 08592 p->callwaitingrepeat = 0; 08593 p->cidcwexpire = 0; 08594 p->cid_suppress_expire = 0; 08595 if (ast_bridged_channel(p->owner)) 08596 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08597 p->subs[SUB_REAL].needunhold = 1; 08598 } else 08599 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 08600 update_conf(p); 08601 break; 08602 default: 08603 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 08604 } 08605 f = &p->subs[idx].f; 08606 return f; 08607 } 08608 if (!(p->radio || (p->oprmode < 0))) 08609 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 08610 /* If it's not us, return NULL immediately */ 08611 if (ast != p->owner) { 08612 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 08613 f = &p->subs[idx].f; 08614 return f; 08615 } 08616 f = dahdi_handle_event(ast); 08617 08618 /* tell the cdr this zap device hung up */ 08619 if (f == NULL) { 08620 ast_set_hangupsource(ast, ast->name, 0); 08621 } 08622 08623 return f; 08624 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 18188 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 16190 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_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().
16191 { 16192 struct dahdi_pvt *p; 16193 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16194 int i, j; 16195 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16196 16197 #ifdef HAVE_PRI 16198 for (i = 0; i < NUM_SPANS; i++) { 16199 if (pris[i].pri.master != AST_PTHREADT_NULL) 16200 pthread_cancel(pris[i].pri.master); 16201 } 16202 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 16203 ast_unregister_application(dahdi_send_keypad_facility_app); 16204 #ifdef HAVE_PRI_PROG_W_CAUSE 16205 ast_unregister_application(dahdi_send_callrerouting_facility_app); 16206 #endif 16207 #endif 16208 #if defined(HAVE_SS7) 16209 for (i = 0; i < NUM_SPANS; i++) { 16210 if (linksets[i].ss7.master != AST_PTHREADT_NULL) 16211 pthread_cancel(linksets[i].ss7.master); 16212 } 16213 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 16214 #endif /* defined(HAVE_SS7) */ 16215 #if defined(HAVE_OPENR2) 16216 dahdi_r2_destroy_links(); 16217 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 16218 ast_unregister_application(dahdi_accept_r2_call_app); 16219 #endif 16220 16221 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 16222 ast_manager_unregister("DAHDIDialOffhook"); 16223 ast_manager_unregister("DAHDIHangup"); 16224 ast_manager_unregister("DAHDITransfer"); 16225 ast_manager_unregister("DAHDIDNDoff"); 16226 ast_manager_unregister("DAHDIDNDon"); 16227 ast_manager_unregister("DAHDIShowChannels"); 16228 ast_manager_unregister("DAHDIRestart"); 16229 ast_data_unregister(NULL); 16230 ast_channel_unregister(&dahdi_tech); 16231 16232 /* Hangup all interfaces if they have an owner */ 16233 ast_mutex_lock(&iflock); 16234 for (p = iflist; p; p = p->next) { 16235 if (p->owner) 16236 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 16237 } 16238 ast_mutex_unlock(&iflock); 16239 16240 ast_mutex_lock(&monlock); 16241 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 16242 pthread_cancel(monitor_thread); 16243 pthread_kill(monitor_thread, SIGURG); 16244 pthread_join(monitor_thread, NULL); 16245 } 16246 monitor_thread = AST_PTHREADT_STOP; 16247 ast_mutex_unlock(&monlock); 16248 16249 destroy_all_channels(); 16250 16251 #if defined(HAVE_PRI) 16252 for (i = 0; i < NUM_SPANS; i++) { 16253 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) 16254 pthread_join(pris[i].pri.master, NULL); 16255 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) { 16256 dahdi_close_pri_fd(&(pris[i]), j); 16257 } 16258 sig_pri_stop_pri(&pris[i].pri); 16259 } 16260 #if defined(HAVE_PRI_CCSS) 16261 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks); 16262 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks); 16263 #endif /* defined(HAVE_PRI_CCSS) */ 16264 sig_pri_unload(); 16265 #endif 16266 16267 #if defined(HAVE_SS7) 16268 for (i = 0; i < NUM_SPANS; i++) { 16269 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) 16270 pthread_join(linksets[i].ss7.master, NULL); 16271 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) { 16272 dahdi_close_ss7_fd(&(linksets[i]), j); 16273 } 16274 } 16275 #endif /* defined(HAVE_SS7) */ 16276 ast_cond_destroy(&ss_thread_complete); 16277 return 0; 16278 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 18188 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 3601 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.
03602 { 03603 int res; 03604 if (p->subs[SUB_REAL].owner == ast) 03605 res = 0; 03606 else if (p->subs[SUB_CALLWAIT].owner == ast) 03607 res = 1; 03608 else if (p->subs[SUB_THREEWAY].owner == ast) 03609 res = 2; 03610 else { 03611 res = -1; 03612 if (!nullok) 03613 ast_log(LOG_WARNING, 03614 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 03615 ast ? ast->name : "", p->channel, fname, line); 03616 } 03617 return res; 03618 }
static int action_dahdidialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15539 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(), and dahdi_pvt::owner.
Referenced by load_module().
15540 { 15541 struct dahdi_pvt *p = NULL; 15542 const char *channel = astman_get_header(m, "DAHDIChannel"); 15543 const char *number = astman_get_header(m, "Number"); 15544 int i; 15545 15546 if (ast_strlen_zero(channel)) { 15547 astman_send_error(s, m, "No channel specified"); 15548 return 0; 15549 } 15550 if (ast_strlen_zero(number)) { 15551 astman_send_error(s, m, "No number specified"); 15552 return 0; 15553 } 15554 p = find_channel(atoi(channel)); 15555 if (!p) { 15556 astman_send_error(s, m, "No such channel"); 15557 return 0; 15558 } 15559 if (!p->owner) { 15560 astman_send_error(s, m, "Channel does not have it's owner"); 15561 return 0; 15562 } 15563 for (i = 0; i < strlen(number); i++) { 15564 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] }; 15565 dahdi_queue_frame(p, &f); 15566 } 15567 astman_send_ack(s, m, "DAHDIDialOffhook"); 15568 return 0; 15569 }
static int action_dahdidndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15482 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().
Referenced by load_module().
15483 { 15484 struct dahdi_pvt *p = NULL; 15485 const char *channel = astman_get_header(m, "DAHDIChannel"); 15486 15487 if (ast_strlen_zero(channel)) { 15488 astman_send_error(s, m, "No channel specified"); 15489 return 0; 15490 } 15491 p = find_channel(atoi(channel)); 15492 if (!p) { 15493 astman_send_error(s, m, "No such channel"); 15494 return 0; 15495 } 15496 dahdi_dnd(p, 0); 15497 astman_send_ack(s, m, "DND Disabled"); 15498 return 0; 15499 }
static int action_dahdidndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15463 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().
Referenced by load_module().
15464 { 15465 struct dahdi_pvt *p = NULL; 15466 const char *channel = astman_get_header(m, "DAHDIChannel"); 15467 15468 if (ast_strlen_zero(channel)) { 15469 astman_send_error(s, m, "No channel specified"); 15470 return 0; 15471 } 15472 p = find_channel(atoi(channel)); 15473 if (!p) { 15474 astman_send_error(s, m, "No such channel"); 15475 return 0; 15476 } 15477 dahdi_dnd(p, 1); 15478 astman_send_ack(s, m, "DND Enabled"); 15479 return 0; 15480 }
static int action_dahdirestart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 14771 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
14772 { 14773 if (dahdi_restart() != 0) { 14774 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 14775 return 1; 14776 } 14777 astman_send_ack(s, m, "DAHDIRestart: Success"); 14778 return 0; 14779 }
static int action_dahdishowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15571 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().
15572 { 15573 struct dahdi_pvt *tmp = NULL; 15574 const char *id = astman_get_header(m, "ActionID"); 15575 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 15576 char idText[256] = ""; 15577 int channels = 0; 15578 int dahdichanquery = -1; 15579 if (!ast_strlen_zero(dahdichannel)) { 15580 dahdichanquery = atoi(dahdichannel); 15581 } 15582 15583 astman_send_ack(s, m, "DAHDI channel status will follow"); 15584 if (!ast_strlen_zero(id)) 15585 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 15586 15587 ast_mutex_lock(&iflock); 15588 15589 for (tmp = iflist; tmp; tmp = tmp->next) { 15590 if (tmp->channel > 0) { 15591 int alm; 15592 15593 /* If a specific channel is queried for, only deliver status for that channel */ 15594 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 15595 continue; 15596 15597 alm = get_alarms(tmp); 15598 channels++; 15599 if (tmp->owner) { 15600 /* Add data if we have a current call */ 15601 astman_append(s, 15602 "Event: DAHDIShowChannels\r\n" 15603 "DAHDIChannel: %d\r\n" 15604 "Channel: %s\r\n" 15605 "Uniqueid: %s\r\n" 15606 "AccountCode: %s\r\n" 15607 "Signalling: %s\r\n" 15608 "SignallingCode: %d\r\n" 15609 "Context: %s\r\n" 15610 "DND: %s\r\n" 15611 "Alarm: %s\r\n" 15612 "%s" 15613 "\r\n", 15614 tmp->channel, 15615 tmp->owner->name, 15616 tmp->owner->uniqueid, 15617 tmp->owner->accountcode, 15618 sig2str(tmp->sig), 15619 tmp->sig, 15620 tmp->context, 15621 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15622 alarm2str(alm), idText); 15623 } else { 15624 astman_append(s, 15625 "Event: DAHDIShowChannels\r\n" 15626 "DAHDIChannel: %d\r\n" 15627 "Signalling: %s\r\n" 15628 "SignallingCode: %d\r\n" 15629 "Context: %s\r\n" 15630 "DND: %s\r\n" 15631 "Alarm: %s\r\n" 15632 "%s" 15633 "\r\n", 15634 tmp->channel, sig2str(tmp->sig), tmp->sig, 15635 tmp->context, 15636 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled", 15637 alarm2str(alm), idText); 15638 } 15639 } 15640 } 15641 15642 ast_mutex_unlock(&iflock); 15643 15644 astman_append(s, 15645 "Event: DAHDIShowChannelsComplete\r\n" 15646 "%s" 15647 "Items: %d\r\n" 15648 "\r\n", 15649 idText, 15650 channels); 15651 return 0; 15652 }
static int action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15501 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), and TRANSFER.
Referenced by load_module().
15502 { 15503 struct dahdi_pvt *p = NULL; 15504 const char *channel = astman_get_header(m, "DAHDIChannel"); 15505 15506 if (ast_strlen_zero(channel)) { 15507 astman_send_error(s, m, "No channel specified"); 15508 return 0; 15509 } 15510 p = find_channel(atoi(channel)); 15511 if (!p) { 15512 astman_send_error(s, m, "No such channel"); 15513 return 0; 15514 } 15515 dahdi_fake_event(p,TRANSFER); 15516 astman_send_ack(s, m, "DAHDITransfer"); 15517 return 0; 15518 }
static int action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 15520 of file chan_dahdi.c.
References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), and HANGUP.
Referenced by load_module().
15521 { 15522 struct dahdi_pvt *p = NULL; 15523 const char *channel = astman_get_header(m, "DAHDIChannel"); 15524 15525 if (ast_strlen_zero(channel)) { 15526 astman_send_error(s, m, "No channel specified"); 15527 return 0; 15528 } 15529 p = find_channel(atoi(channel)); 15530 if (!p) { 15531 astman_send_error(s, m, "No such channel"); 15532 return 0; 15533 } 15534 dahdi_fake_event(p,HANGUP); 15535 astman_send_ack(s, m, "DAHDIHangup"); 15536 return 0; 15537 }
static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 4443 of file chan_dahdi.c.
References alarm, alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
04444 { 04445 int x; 04446 for (x = 0; x < ARRAY_LEN(alarms); x++) { 04447 if (alarms[x].alarm & alm) 04448 return alarms[x].name; 04449 } 04450 return alm ? "Unknown Alarm" : "No Alarm"; 04451 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4247 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().
04248 { 04249 struct dahdi_bufferinfo bi; 04250 int res; 04251 if (p->subs[x].dfd >= 0) { 04252 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 04253 return -1; 04254 } 04255 04256 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 04257 if (p->subs[x].dfd <= -1) { 04258 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 04259 return -1; 04260 } 04261 04262 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 04263 if (!res) { 04264 bi.txbufpolicy = p->buf_policy; 04265 bi.rxbufpolicy = p->buf_policy; 04266 bi.numbufs = p->buf_no; 04267 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 04268 if (res < 0) { 04269 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 04270 } 04271 } else 04272 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 04273 04274 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 04275 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 04276 dahdi_close_sub(p, x); 04277 p->subs[x].dfd = -1; 04278 return -1; 04279 } 04280 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 04281 return 0; 04282 }
static int analog_lib_handles | ( | int | signalling, | |
int | radio, | |||
int | oprmode | |||
) | [static] |
Definition at line 4528 of file chan_dahdi.c.
References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_dnd(), dahdi_exception(), dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_request(), destroy_dahdi_pvt(), do_monitor(), and mwi_thread().
04529 { 04530 switch (signalling) { 04531 case SIG_FXOLS: 04532 case SIG_FXOGS: 04533 case SIG_FXOKS: 04534 case SIG_FXSLS: 04535 case SIG_FXSGS: 04536 case SIG_FXSKS: 04537 case SIG_EMWINK: 04538 case SIG_EM: 04539 case SIG_EM_E1: 04540 case SIG_FEATD: 04541 case SIG_FEATDMF: 04542 case SIG_E911: 04543 case SIG_FGC_CAMA: 04544 case SIG_FGC_CAMAMF: 04545 case SIG_FEATB: 04546 case SIG_SFWINK: 04547 case SIG_SF: 04548 case SIG_SF_FEATD: 04549 case SIG_SF_FEATDMF: 04550 case SIG_FEATDMF_TA: 04551 case SIG_SF_FEATB: 04552 break; 04553 default: 04554 /* The rest of the function should cover the remainder of signalling types */ 04555 return 0; 04556 } 04557 04558 if (radio) 04559 return 0; 04560 04561 if (oprmode) 04562 return 0; 04563 04564 return 1; 04565 }
static void * analog_ss_thread | ( | void * | data | ) | [static] |
Definition at line 9576 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(), 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, 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().
09577 { 09578 struct ast_channel *chan = data; 09579 struct dahdi_pvt *p = chan->tech_pvt; 09580 char exten[AST_MAX_EXTENSION] = ""; 09581 char exten2[AST_MAX_EXTENSION] = ""; 09582 unsigned char buf[256]; 09583 char dtmfcid[300]; 09584 char dtmfbuf[300]; 09585 struct callerid_state *cs = NULL; 09586 char *name = NULL, *number = NULL; 09587 int distMatches; 09588 int curRingData[3]; 09589 int receivedRingT; 09590 int counter1; 09591 int counter; 09592 int samples = 0; 09593 struct ast_smdi_md_message *smdi_msg = NULL; 09594 int flags = 0; 09595 int i; 09596 int timeout; 09597 int getforward = 0; 09598 char *s1, *s2; 09599 int len = 0; 09600 int res; 09601 int idx; 09602 09603 ast_mutex_lock(&ss_thread_lock); 09604 ss_thread_count++; 09605 ast_mutex_unlock(&ss_thread_lock); 09606 /* in the bizarre case where the channel has become a zombie before we 09607 even get started here, abort safely 09608 */ 09609 if (!p) { 09610 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 09611 ast_hangup(chan); 09612 goto quit; 09613 } 09614 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 09615 idx = dahdi_get_index(chan, p, 1); 09616 if (idx < 0) { 09617 ast_log(LOG_WARNING, "Huh?\n"); 09618 ast_hangup(chan); 09619 goto quit; 09620 } 09621 if (p->dsp) 09622 ast_dsp_digitreset(p->dsp); 09623 switch (p->sig) { 09624 case SIG_FEATD: 09625 case SIG_FEATDMF: 09626 case SIG_FEATDMF_TA: 09627 case SIG_E911: 09628 case SIG_FGC_CAMAMF: 09629 case SIG_FEATB: 09630 case SIG_EMWINK: 09631 case SIG_SF_FEATD: 09632 case SIG_SF_FEATDMF: 09633 case SIG_SF_FEATB: 09634 case SIG_SFWINK: 09635 if (dahdi_wink(p, idx)) 09636 goto quit; 09637 /* Fall through */ 09638 case SIG_EM: 09639 case SIG_EM_E1: 09640 case SIG_SF: 09641 case SIG_FGC_CAMA: 09642 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09643 if (p->dsp) 09644 ast_dsp_digitreset(p->dsp); 09645 /* set digit mode appropriately */ 09646 if (p->dsp) { 09647 if (NEED_MFDETECT(p)) 09648 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 09649 else 09650 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09651 } 09652 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 09653 /* Wait for the first digit only if immediate=no */ 09654 if (!p->immediate) 09655 /* Wait for the first digit (up to 5 seconds). */ 09656 res = ast_waitfordigit(chan, 5000); 09657 else 09658 res = 0; 09659 if (res > 0) { 09660 /* save first char */ 09661 dtmfbuf[0] = res; 09662 switch (p->sig) { 09663 case SIG_FEATD: 09664 case SIG_SF_FEATD: 09665 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 09666 if (res > 0) 09667 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 09668 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09669 break; 09670 case SIG_FEATDMF_TA: 09671 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09672 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09673 if (dahdi_wink(p, idx)) goto quit; 09674 dtmfbuf[0] = 0; 09675 /* Wait for the first digit (up to 5 seconds). */ 09676 res = ast_waitfordigit(chan, 5000); 09677 if (res <= 0) break; 09678 dtmfbuf[0] = res; 09679 /* fall through intentionally */ 09680 case SIG_FEATDMF: 09681 case SIG_E911: 09682 case SIG_FGC_CAMAMF: 09683 case SIG_SF_FEATDMF: 09684 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09685 /* if international caca, do it again to get real ANO */ 09686 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 09687 { 09688 if (dahdi_wink(p, idx)) goto quit; 09689 dtmfbuf[0] = 0; 09690 /* Wait for the first digit (up to 5 seconds). */ 09691 res = ast_waitfordigit(chan, 5000); 09692 if (res <= 0) break; 09693 dtmfbuf[0] = res; 09694 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09695 } 09696 if (res > 0) { 09697 /* if E911, take off hook */ 09698 if (p->sig == SIG_E911) 09699 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 09701 } 09702 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09703 break; 09704 case SIG_FEATB: 09705 case SIG_SF_FEATB: 09706 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 09707 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09708 break; 09709 case SIG_EMWINK: 09710 /* if we received a '*', we are actually receiving Feature Group D 09711 dial syntax, so use that mode; otherwise, fall through to normal 09712 mode 09713 */ 09714 if (res == '*') { 09715 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 09716 if (res > 0) 09717 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 09718 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 09719 break; 09720 } 09721 default: 09722 /* If we got the first digit, get the rest */ 09723 len = 1; 09724 dtmfbuf[len] = '\0'; 09725 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 09726 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 09727 timeout = matchdigittimeout; 09728 } else { 09729 timeout = gendigittimeout; 09730 } 09731 res = ast_waitfordigit(chan, timeout); 09732 if (res < 0) { 09733 ast_debug(1, "waitfordigit returned < 0...\n"); 09734 ast_hangup(chan); 09735 goto quit; 09736 } else if (res) { 09737 dtmfbuf[len++] = res; 09738 dtmfbuf[len] = '\0'; 09739 } else { 09740 break; 09741 } 09742 } 09743 break; 09744 } 09745 } 09746 if (res == -1) { 09747 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 09748 ast_hangup(chan); 09749 goto quit; 09750 } else if (res < 0) { 09751 ast_debug(1, "Got hung up before digits finished\n"); 09752 ast_hangup(chan); 09753 goto quit; 09754 } 09755 09756 if (p->sig == SIG_FGC_CAMA) { 09757 char anibuf[100]; 09758 09759 if (ast_safe_sleep(chan,1000) == -1) { 09760 ast_hangup(chan); 09761 goto quit; 09762 } 09763 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09764 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 09765 res = my_getsigstr(chan, anibuf, "#", 10000); 09766 if ((res > 0) && (strlen(anibuf) > 2)) { 09767 if (anibuf[strlen(anibuf) - 1] == '#') 09768 anibuf[strlen(anibuf) - 1] = 0; 09769 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 09770 } 09771 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09772 } 09773 09774 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 09775 if (ast_strlen_zero(exten)) 09776 ast_copy_string(exten, "s", sizeof(exten)); 09777 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 09778 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 09779 if (exten[0] == '*') { 09780 char *stringp=NULL; 09781 ast_copy_string(exten2, exten, sizeof(exten2)); 09782 /* Parse out extension and callerid */ 09783 stringp=exten2 +1; 09784 s1 = strsep(&stringp, "*"); 09785 s2 = strsep(&stringp, "*"); 09786 if (s2) { 09787 if (!ast_strlen_zero(p->cid_num)) 09788 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09789 else 09790 ast_set_callerid(chan, s1, NULL, s1); 09791 ast_copy_string(exten, s2, sizeof(exten)); 09792 } else 09793 ast_copy_string(exten, s1, sizeof(exten)); 09794 } else if (p->sig == SIG_FEATD) 09795 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 09796 } 09797 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 09798 if (exten[0] == '*') { 09799 char *stringp=NULL; 09800 ast_copy_string(exten2, exten, sizeof(exten2)); 09801 /* Parse out extension and callerid */ 09802 stringp=exten2 +1; 09803 s1 = strsep(&stringp, "#"); 09804 s2 = strsep(&stringp, "#"); 09805 if (s2) { 09806 if (!ast_strlen_zero(p->cid_num)) 09807 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09808 else 09809 if (*(s1 + 2)) 09810 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 09811 ast_copy_string(exten, s2 + 1, sizeof(exten)); 09812 } else 09813 ast_copy_string(exten, s1 + 2, sizeof(exten)); 09814 } else 09815 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 09816 } 09817 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 09818 if (exten[0] == '*') { 09819 char *stringp=NULL; 09820 ast_copy_string(exten2, exten, sizeof(exten2)); 09821 /* Parse out extension and callerid */ 09822 stringp=exten2 +1; 09823 s1 = strsep(&stringp, "#"); 09824 s2 = strsep(&stringp, "#"); 09825 if (s2 && (*(s2 + 1) == '0')) { 09826 if (*(s2 + 2)) 09827 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 09828 } 09829 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 09830 else ast_copy_string(exten, "911", sizeof(exten)); 09831 } else 09832 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 09833 } 09834 if (p->sig == SIG_FEATB) { 09835 if (exten[0] == '*') { 09836 char *stringp=NULL; 09837 ast_copy_string(exten2, exten, sizeof(exten2)); 09838 /* Parse out extension and callerid */ 09839 stringp=exten2 +1; 09840 s1 = strsep(&stringp, "#"); 09841 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 09842 } else 09843 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 09844 } 09845 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 09846 dahdi_wink(p, idx); 09847 /* some switches require a minimum guard time between 09848 the last FGD wink and something that answers 09849 immediately. This ensures it */ 09850 if (ast_safe_sleep(chan,100)) goto quit; 09851 } 09852 dahdi_enable_ec(p); 09853 if (NEED_MFDETECT(p)) { 09854 if (p->dsp) { 09855 if (!p->hardwaredtmf) 09856 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 09857 else { 09858 ast_dsp_free(p->dsp); 09859 p->dsp = NULL; 09860 } 09861 } 09862 } 09863 09864 if (ast_exists_extension(chan, chan->context, exten, 1, 09865 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 09866 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 09867 if (p->dsp) ast_dsp_digitreset(p->dsp); 09868 res = ast_pbx_run(chan); 09869 if (res) { 09870 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 09871 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09872 } 09873 goto quit; 09874 } else { 09875 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 09876 sleep(2); 09877 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 09878 if (res < 0) 09879 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 09880 else 09881 sleep(1); 09882 res = ast_streamfile(chan, "ss-noservice", chan->language); 09883 if (res >= 0) 09884 ast_waitstream(chan, ""); 09885 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09886 ast_hangup(chan); 09887 goto quit; 09888 } 09889 break; 09890 case SIG_FXOLS: 09891 case SIG_FXOGS: 09892 case SIG_FXOKS: 09893 /* Read the first digit */ 09894 timeout = firstdigittimeout; 09895 /* If starting a threeway call, never timeout on the first digit so someone 09896 can use flash-hook as a "hold" feature */ 09897 if (p->subs[SUB_THREEWAY].owner) 09898 timeout = 999999; 09899 while (len < AST_MAX_EXTENSION-1) { 09900 /* Read digit unless it's supposed to be immediate, in which case the 09901 only answer is 's' */ 09902 if (p->immediate) 09903 res = 's'; 09904 else 09905 res = ast_waitfordigit(chan, timeout); 09906 timeout = 0; 09907 if (res < 0) { 09908 ast_debug(1, "waitfordigit returned < 0...\n"); 09909 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09910 ast_hangup(chan); 09911 goto quit; 09912 } else if (res) { 09913 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 09914 exten[len++]=res; 09915 exten[len] = '\0'; 09916 } 09917 if (!ast_ignore_pattern(chan->context, exten)) 09918 tone_zone_play_tone(p->subs[idx].dfd, -1); 09919 else 09920 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 09921 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) { 09922 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 09923 if (getforward) { 09924 /* Record this as the forwarding extension */ 09925 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 09926 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 09927 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09928 if (res) 09929 break; 09930 usleep(500000); 09931 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09932 sleep(1); 09933 memset(exten, 0, sizeof(exten)); 09934 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 09935 len = 0; 09936 getforward = 0; 09937 } else { 09938 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09939 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 09940 if (!ast_strlen_zero(p->cid_num)) { 09941 if (!p->hidecallerid) 09942 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 09943 else 09944 ast_set_callerid(chan, NULL, NULL, p->cid_num); 09945 } 09946 if (!ast_strlen_zero(p->cid_name)) { 09947 if (!p->hidecallerid) 09948 ast_set_callerid(chan, NULL, p->cid_name, NULL); 09949 } 09950 ast_setstate(chan, AST_STATE_RING); 09951 dahdi_enable_ec(p); 09952 res = ast_pbx_run(chan); 09953 if (res) { 09954 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 09955 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09956 } 09957 goto quit; 09958 } 09959 } else { 09960 /* It's a match, but they just typed a digit, and there is an ambiguous match, 09961 so just set the timeout to matchdigittimeout and wait some more */ 09962 timeout = matchdigittimeout; 09963 } 09964 } else if (res == 0) { 09965 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 09966 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 09967 dahdi_wait_event(p->subs[idx].dfd); 09968 ast_hangup(chan); 09969 goto quit; 09970 } else if (p->callwaiting && !strcmp(exten, "*70")) { 09971 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 09972 /* Disable call waiting if enabled */ 09973 p->callwaiting = 0; 09974 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 09975 if (res) { 09976 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 09977 chan->name, strerror(errno)); 09978 } 09979 len = 0; 09980 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 09981 memset(exten, 0, sizeof(exten)); 09982 timeout = firstdigittimeout; 09983 09984 } else if (!strcmp(exten,ast_pickup_ext())) { 09985 /* Scan all channels and see if there are any 09986 * ringing channels that have call groups 09987 * that equal this channels pickup group 09988 */ 09989 if (idx == SUB_REAL) { 09990 /* Switch us from Third call to Call Wait */ 09991 if (p->subs[SUB_THREEWAY].owner) { 09992 /* If you make a threeway call and the *8# a call, it should actually 09993 look like a callwait */ 09994 alloc_sub(p, SUB_CALLWAIT); 09995 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 09996 unalloc_sub(p, SUB_THREEWAY); 09997 } 09998 dahdi_enable_ec(p); 09999 if (ast_pickup_call(chan)) { 10000 ast_debug(1, "No call pickup possible...\n"); 10001 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10002 dahdi_wait_event(p->subs[idx].dfd); 10003 } 10004 ast_hangup(chan); 10005 goto quit; 10006 } else { 10007 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 10008 ast_hangup(chan); 10009 goto quit; 10010 } 10011 10012 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 10013 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 10014 /* Disable Caller*ID if enabled */ 10015 p->hidecallerid = 1; 10016 ast_party_number_free(&chan->caller.id.number); 10017 ast_party_number_init(&chan->caller.id.number); 10018 ast_party_name_free(&chan->caller.id.name); 10019 ast_party_name_init(&chan->caller.id.name); 10020 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10021 if (res) { 10022 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10023 chan->name, strerror(errno)); 10024 } 10025 len = 0; 10026 memset(exten, 0, sizeof(exten)); 10027 timeout = firstdigittimeout; 10028 } else if (p->callreturn && !strcmp(exten, "*69")) { 10029 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10030 break; 10031 } else if (!strcmp(exten, "*78")) { 10032 dahdi_dnd(p, 1); 10033 /* Do not disturb */ 10034 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10035 getforward = 0; 10036 memset(exten, 0, sizeof(exten)); 10037 len = 0; 10038 } else if (!strcmp(exten, "*79")) { 10039 dahdi_dnd(p, 0); 10040 /* Do not disturb */ 10041 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10042 getforward = 0; 10043 memset(exten, 0, sizeof(exten)); 10044 len = 0; 10045 } else if (p->cancallforward && !strcmp(exten, "*72")) { 10046 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10047 getforward = 1; 10048 memset(exten, 0, sizeof(exten)); 10049 len = 0; 10050 } else if (p->cancallforward && !strcmp(exten, "*73")) { 10051 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 10052 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10053 memset(p->call_forward, 0, sizeof(p->call_forward)); 10054 getforward = 0; 10055 memset(exten, 0, sizeof(exten)); 10056 len = 0; 10057 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) && 10058 p->subs[SUB_THREEWAY].owner && 10059 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 10060 /* This is a three way call, the main call being a real channel, 10061 and we're parking the first call. */ 10062 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 10063 ast_verb(3, "Parking call to '%s'\n", chan->name); 10064 break; 10065 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 10066 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 10067 /* Enable Caller*ID if enabled */ 10068 p->hidecallerid = 0; 10069 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 10070 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 10071 if (res) { 10072 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 10073 chan->name, strerror(errno)); 10074 } 10075 len = 0; 10076 memset(exten, 0, sizeof(exten)); 10077 timeout = firstdigittimeout; 10078 } else if (!strcmp(exten, "*0")) { 10079 struct ast_channel *nbridge = 10080 p->subs[SUB_THREEWAY].owner; 10081 struct dahdi_pvt *pbridge = NULL; 10082 /* set up the private struct of the bridged one, if any */ 10083 if (nbridge && ast_bridged_channel(nbridge)) 10084 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 10085 if (nbridge && pbridge && 10086 (nbridge->tech == &dahdi_tech) && 10087 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 10088 ISTRUNK(pbridge)) { 10089 int func = DAHDI_FLASH; 10090 /* Clear out the dial buffer */ 10091 p->dop.dialstr[0] = '\0'; 10092 /* flash hookswitch */ 10093 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 10094 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 10095 nbridge->name, strerror(errno)); 10096 } 10097 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10098 unalloc_sub(p, SUB_THREEWAY); 10099 p->owner = p->subs[SUB_REAL].owner; 10100 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 10101 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 10102 ast_hangup(chan); 10103 goto quit; 10104 } else { 10105 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10106 dahdi_wait_event(p->subs[idx].dfd); 10107 tone_zone_play_tone(p->subs[idx].dfd, -1); 10108 swap_subs(p, SUB_REAL, SUB_THREEWAY); 10109 unalloc_sub(p, SUB_THREEWAY); 10110 p->owner = p->subs[SUB_REAL].owner; 10111 ast_hangup(chan); 10112 goto quit; 10113 } 10114 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, 10115 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 10116 && ((exten[0] != '*') || (strlen(exten) > 2))) { 10117 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, 10118 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 10119 chan->context); 10120 break; 10121 } 10122 if (!timeout) 10123 timeout = gendigittimeout; 10124 if (len && !ast_ignore_pattern(chan->context, exten)) 10125 tone_zone_play_tone(p->subs[idx].dfd, -1); 10126 } 10127 break; 10128 case SIG_FXSLS: 10129 case SIG_FXSGS: 10130 case SIG_FXSKS: 10131 /* check for SMDI messages */ 10132 if (p->use_smdi && p->smdi_iface) { 10133 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 10134 10135 if (smdi_msg != NULL) { 10136 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 10137 10138 if (smdi_msg->type == 'B') 10139 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 10140 else if (smdi_msg->type == 'N') 10141 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 10142 10143 ast_debug(1, "Received SMDI message on %s\n", chan->name); 10144 } else { 10145 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 10146 } 10147 } 10148 10149 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 10150 number = smdi_msg->calling_st; 10151 10152 /* If we want caller id, we're in a prering state due to a polarity reversal 10153 * and we're set to use a polarity reversal to trigger the start of caller id, 10154 * grab the caller id and wait for ringing to start... */ 10155 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 10156 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) { 10157 /* If set to use DTMF CID signalling, listen for DTMF */ 10158 if (p->cid_signalling == CID_SIG_DTMF) { 10159 int k = 0; 10160 cs = NULL; 10161 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name); 10162 dahdi_setlinear(p->subs[idx].dfd, 0); 10163 /* 10164 * We are the only party interested in the Rx stream since 10165 * we have not answered yet. We don't need or even want DTMF 10166 * emulation. The DTMF digits can come so fast that emulation 10167 * can drop some of them. 10168 */ 10169 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 10170 res = 4000;/* This is a typical OFF time between rings. */ 10171 for (;;) { 10172 struct ast_frame *f; 10173 res = ast_waitfor(chan, res); 10174 if (res <= 0) { 10175 /* 10176 * We do not need to restore the dahdi_setlinear() 10177 * or AST_FLAG_END_DTMF_ONLY flag settings since we 10178 * are hanging up the channel. 10179 */ 10180 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10181 "Exiting simple switch\n"); 10182 ast_hangup(chan); 10183 goto quit; 10184 } 10185 f = ast_read(chan); 10186 if (!f) 10187 break; 10188 if (f->frametype == AST_FRAME_DTMF) { 10189 if (k < ARRAY_LEN(dtmfbuf) - 1) { 10190 dtmfbuf[k++] = f->subclass.integer; 10191 } 10192 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer); 10193 res = 4000;/* This is a typical OFF time between rings. */ 10194 } 10195 ast_frfree(f); 10196 if (chan->_state == AST_STATE_RING || 10197 chan->_state == AST_STATE_RINGING) 10198 break; /* Got ring */ 10199 } 10200 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 10201 dtmfbuf[k] = '\0'; 10202 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10203 /* Got cid and ring. */ 10204 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 10205 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10206 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags); 10207 /* If first byte is NULL, we have no cid */ 10208 if (!ast_strlen_zero(dtmfcid)) 10209 number = dtmfcid; 10210 else 10211 number = NULL; 10212 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10213 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 10214 cs = callerid_new(p->cid_signalling); 10215 if (cs) { 10216 samples = 0; 10217 #if 1 10218 bump_gains(p); 10219 #endif 10220 /* Take out of linear mode for Caller*ID processing */ 10221 dahdi_setlinear(p->subs[idx].dfd, 0); 10222 10223 /* First we wait and listen for the Caller*ID */ 10224 for (;;) { 10225 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10226 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10227 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10228 callerid_free(cs); 10229 ast_hangup(chan); 10230 goto quit; 10231 } 10232 if (i & DAHDI_IOMUX_SIGEVENT) { 10233 res = dahdi_get_event(p->subs[idx].dfd); 10234 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10235 if (res == DAHDI_EVENT_NOALARM) { 10236 p->inalarm = 0; 10237 } 10238 10239 if (p->cid_signalling == CID_SIG_V23_JP) { 10240 if (res == DAHDI_EVENT_RINGBEGIN) { 10241 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 10242 usleep(1); 10243 } 10244 } else { 10245 res = 0; 10246 break; 10247 } 10248 } else if (i & DAHDI_IOMUX_READ) { 10249 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10250 if (res < 0) { 10251 if (errno != ELAST) { 10252 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10253 callerid_free(cs); 10254 ast_hangup(chan); 10255 goto quit; 10256 } 10257 break; 10258 } 10259 samples += res; 10260 10261 if (p->cid_signalling == CID_SIG_V23_JP) { 10262 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 10263 } else { 10264 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10265 } 10266 if (res < 0) { 10267 /* 10268 * The previous diagnostic message output likely 10269 * explains why it failed. 10270 */ 10271 ast_log(LOG_WARNING, 10272 "Failed to decode CallerID on channel '%s'\n", 10273 chan->name); 10274 break; 10275 } else if (res) 10276 break; 10277 else if (samples > (8000 * 10)) 10278 break; 10279 } 10280 } 10281 if (res == 1) { 10282 callerid_get(cs, &name, &number, &flags); 10283 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10284 } 10285 10286 if (p->cid_signalling == CID_SIG_V23_JP) { 10287 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10288 usleep(1); 10289 } 10290 10291 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 10292 res = 4000;/* This is a typical OFF time between rings. */ 10293 for (;;) { 10294 struct ast_frame *f; 10295 res = ast_waitfor(chan, res); 10296 if (res <= 0) { 10297 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 10298 "Exiting simple switch\n"); 10299 ast_hangup(chan); 10300 goto quit; 10301 } 10302 if (!(f = ast_read(chan))) { 10303 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 10304 ast_hangup(chan); 10305 goto quit; 10306 } 10307 ast_frfree(f); 10308 if (chan->_state == AST_STATE_RING || 10309 chan->_state == AST_STATE_RINGING) 10310 break; /* Got ring */ 10311 } 10312 10313 /* We must have a ring by now, so, if configured, lets try to listen for 10314 * distinctive ringing */ 10315 if (p->usedistinctiveringdetection) { 10316 len = 0; 10317 distMatches = 0; 10318 /* Clear the current ring data array so we don't have old data in it. */ 10319 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10320 curRingData[receivedRingT] = 0; 10321 receivedRingT = 0; 10322 counter = 0; 10323 counter1 = 0; 10324 /* Check to see if context is what it should be, if not set to be. */ 10325 if (strcmp(p->context,p->defcontext) != 0) { 10326 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10327 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10328 } 10329 10330 for (;;) { 10331 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10332 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10333 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10334 callerid_free(cs); 10335 ast_hangup(chan); 10336 goto quit; 10337 } 10338 if (i & DAHDI_IOMUX_SIGEVENT) { 10339 res = dahdi_get_event(p->subs[idx].dfd); 10340 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10341 if (res == DAHDI_EVENT_NOALARM) { 10342 p->inalarm = 0; 10343 } 10344 res = 0; 10345 /* Let us detect distinctive ring */ 10346 10347 curRingData[receivedRingT] = p->ringt; 10348 10349 if (p->ringt < p->ringt_base/2) 10350 break; 10351 /* Increment the ringT counter so we can match it against 10352 values in chan_dahdi.conf for distinctive ring */ 10353 if (++receivedRingT == ARRAY_LEN(curRingData)) 10354 break; 10355 } else if (i & DAHDI_IOMUX_READ) { 10356 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10357 if (res < 0) { 10358 if (errno != ELAST) { 10359 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10360 callerid_free(cs); 10361 ast_hangup(chan); 10362 goto quit; 10363 } 10364 break; 10365 } 10366 if (p->ringt > 0) { 10367 if (!(--p->ringt)) { 10368 res = -1; 10369 break; 10370 } 10371 } 10372 } 10373 } 10374 /* this only shows up if you have n of the dring patterns filled in */ 10375 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10376 for (counter = 0; counter < 3; counter++) { 10377 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10378 channel */ 10379 distMatches = 0; 10380 for (counter1 = 0; counter1 < 3; counter1++) { 10381 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10382 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10383 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10384 curRingData[counter1]); 10385 distMatches++; 10386 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10387 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10388 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10389 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10390 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10391 distMatches++; 10392 } 10393 } 10394 10395 if (distMatches == 3) { 10396 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10397 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10398 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10399 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10400 break; 10401 } 10402 } 10403 } 10404 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10405 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10406 #if 1 10407 restore_gains(p); 10408 #endif 10409 } else 10410 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10411 } else { 10412 ast_log(LOG_WARNING, "Channel %s in prering " 10413 "state, but I have nothing to do. " 10414 "Terminating simple switch, should be " 10415 "restarted by the actual ring.\n", 10416 chan->name); 10417 ast_hangup(chan); 10418 goto quit; 10419 } 10420 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 10421 if (p->cid_signalling == CID_SIG_DTMF) { 10422 int k = 0; 10423 cs = NULL; 10424 dahdi_setlinear(p->subs[idx].dfd, 0); 10425 res = 2000; 10426 for (;;) { 10427 struct ast_frame *f; 10428 res = ast_waitfor(chan, res); 10429 if (res <= 0) { 10430 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 10431 "Exiting simple switch\n"); 10432 ast_hangup(chan); 10433 return NULL; 10434 } 10435 f = ast_read(chan); 10436 if (f->frametype == AST_FRAME_DTMF) { 10437 dtmfbuf[k++] = f->subclass.integer; 10438 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer); 10439 res = 2000; 10440 } 10441 ast_frfree(f); 10442 10443 if (p->ringt_base == p->ringt) 10444 break; 10445 } 10446 dtmfbuf[k] = '\0'; 10447 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10448 /* Got cid and ring. */ 10449 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 10450 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 10451 dtmfcid, flags); 10452 /* If first byte is NULL, we have no cid */ 10453 if (!ast_strlen_zero(dtmfcid)) 10454 number = dtmfcid; 10455 else 10456 number = NULL; 10457 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 10458 } else { 10459 /* FSK Bell202 callerID */ 10460 cs = callerid_new(p->cid_signalling); 10461 if (cs) { 10462 #if 1 10463 bump_gains(p); 10464 #endif 10465 samples = 0; 10466 len = 0; 10467 distMatches = 0; 10468 /* Clear the current ring data array so we don't have old data in it. */ 10469 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 10470 curRingData[receivedRingT] = 0; 10471 receivedRingT = 0; 10472 counter = 0; 10473 counter1 = 0; 10474 /* Check to see if context is what it should be, if not set to be. */ 10475 if (strcmp(p->context,p->defcontext) != 0) { 10476 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 10477 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 10478 } 10479 10480 /* Take out of linear mode for Caller*ID processing */ 10481 dahdi_setlinear(p->subs[idx].dfd, 0); 10482 for (;;) { 10483 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10484 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10485 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10486 callerid_free(cs); 10487 ast_hangup(chan); 10488 goto quit; 10489 } 10490 if (i & DAHDI_IOMUX_SIGEVENT) { 10491 res = dahdi_get_event(p->subs[idx].dfd); 10492 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10493 if (res == DAHDI_EVENT_NOALARM) { 10494 p->inalarm = 0; 10495 } 10496 /* If we get a PR event, they hung up while processing calerid */ 10497 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 10498 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 10499 p->polarity = POLARITY_IDLE; 10500 callerid_free(cs); 10501 ast_hangup(chan); 10502 goto quit; 10503 } 10504 res = 0; 10505 /* Let us detect callerid when the telco uses distinctive ring */ 10506 10507 curRingData[receivedRingT] = p->ringt; 10508 10509 if (p->ringt < p->ringt_base/2) 10510 break; 10511 /* Increment the ringT counter so we can match it against 10512 values in chan_dahdi.conf for distinctive ring */ 10513 if (++receivedRingT == ARRAY_LEN(curRingData)) 10514 break; 10515 } else if (i & DAHDI_IOMUX_READ) { 10516 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10517 if (res < 0) { 10518 if (errno != ELAST) { 10519 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10520 callerid_free(cs); 10521 ast_hangup(chan); 10522 goto quit; 10523 } 10524 break; 10525 } 10526 if (p->ringt > 0) { 10527 if (!(--p->ringt)) { 10528 res = -1; 10529 break; 10530 } 10531 } 10532 samples += res; 10533 res = callerid_feed(cs, buf, res, AST_LAW(p)); 10534 if (res < 0) { 10535 /* 10536 * The previous diagnostic message output likely 10537 * explains why it failed. 10538 */ 10539 ast_log(LOG_WARNING, 10540 "Failed to decode CallerID on channel '%s'\n", 10541 chan->name); 10542 break; 10543 } else if (res) 10544 break; 10545 else if (samples > (8000 * 10)) 10546 break; 10547 } 10548 } 10549 if (res == 1) { 10550 callerid_get(cs, &name, &number, &flags); 10551 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 10552 } 10553 if (distinctiveringaftercid == 1) { 10554 /* Clear the current ring data array so we don't have old data in it. */ 10555 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 10556 curRingData[receivedRingT] = 0; 10557 } 10558 receivedRingT = 0; 10559 ast_verb(3, "Detecting post-CID distinctive ring\n"); 10560 for (;;) { 10561 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10562 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 10563 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10564 callerid_free(cs); 10565 ast_hangup(chan); 10566 goto quit; 10567 } 10568 if (i & DAHDI_IOMUX_SIGEVENT) { 10569 res = dahdi_get_event(p->subs[idx].dfd); 10570 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 10571 if (res == DAHDI_EVENT_NOALARM) { 10572 p->inalarm = 0; 10573 } 10574 res = 0; 10575 /* Let us detect callerid when the telco uses distinctive ring */ 10576 10577 curRingData[receivedRingT] = p->ringt; 10578 10579 if (p->ringt < p->ringt_base/2) 10580 break; 10581 /* Increment the ringT counter so we can match it against 10582 values in chan_dahdi.conf for distinctive ring */ 10583 if (++receivedRingT == ARRAY_LEN(curRingData)) 10584 break; 10585 } else if (i & DAHDI_IOMUX_READ) { 10586 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 10587 if (res < 0) { 10588 if (errno != ELAST) { 10589 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10590 callerid_free(cs); 10591 ast_hangup(chan); 10592 goto quit; 10593 } 10594 break; 10595 } 10596 if (p->ringt > 0) { 10597 if (!(--p->ringt)) { 10598 res = -1; 10599 break; 10600 } 10601 } 10602 } 10603 } 10604 } 10605 if (p->usedistinctiveringdetection) { 10606 /* this only shows up if you have n of the dring patterns filled in */ 10607 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 10608 10609 for (counter = 0; counter < 3; counter++) { 10610 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 10611 channel */ 10612 /* this only shows up if you have n of the dring patterns filled in */ 10613 ast_verb(3, "Checking %d,%d,%d\n", 10614 p->drings.ringnum[counter].ring[0], 10615 p->drings.ringnum[counter].ring[1], 10616 p->drings.ringnum[counter].ring[2]); 10617 distMatches = 0; 10618 for (counter1 = 0; counter1 < 3; counter1++) { 10619 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 10620 if (p->drings.ringnum[counter].ring[counter1] == -1) { 10621 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 10622 curRingData[counter1]); 10623 distMatches++; 10624 } 10625 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 10626 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 10627 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 10628 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 10629 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 10630 distMatches++; 10631 } 10632 } 10633 if (distMatches == 3) { 10634 /* The ring matches, set the context to whatever is for distinctive ring.. */ 10635 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 10636 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 10637 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 10638 break; 10639 } 10640 } 10641 } 10642 /* Restore linear mode (if appropriate) for Caller*ID processing */ 10643 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 10644 #if 1 10645 restore_gains(p); 10646 #endif 10647 if (res < 0) { 10648 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 10649 } 10650 } else 10651 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 10652 } 10653 } else 10654 cs = NULL; 10655 10656 if (number) 10657 ast_shrink_phone_number(number); 10658 ast_set_callerid(chan, number, name, number); 10659 10660 if (smdi_msg) 10661 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 10662 10663 if (cs) 10664 callerid_free(cs); 10665 10666 my_handle_notify_message(chan, p, flags, -1); 10667 10668 ast_setstate(chan, AST_STATE_RING); 10669 chan->rings = 1; 10670 p->ringt = p->ringt_base; 10671 res = ast_pbx_run(chan); 10672 if (res) { 10673 ast_hangup(chan); 10674 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 10675 } 10676 goto quit; 10677 default: 10678 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 10679 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10680 if (res < 0) 10681 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 10682 } 10683 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 10684 if (res < 0) 10685 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 10686 ast_hangup(chan); 10687 quit: 10688 ast_mutex_lock(&ss_thread_lock); 10689 ss_thread_count--; 10690 ast_cond_signal(&ss_thread_complete); 10691 ast_mutex_unlock(&ss_thread_lock); 10692 return NULL; 10693 }
static int analog_tone_to_dahditone | ( | enum analog_tone | tone | ) | [static] |
Definition at line 1601 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().
01602 { 01603 switch (tone) { 01604 case ANALOG_TONE_RINGTONE: 01605 return DAHDI_TONE_RINGTONE; 01606 case ANALOG_TONE_STUTTER: 01607 return DAHDI_TONE_STUTTER; 01608 case ANALOG_TONE_CONGESTION: 01609 return DAHDI_TONE_CONGESTION; 01610 case ANALOG_TONE_DIALTONE: 01611 return DAHDI_TONE_DIALTONE; 01612 case ANALOG_TONE_DIALRECALL: 01613 return DAHDI_TONE_DIALRECALL; 01614 case ANALOG_TONE_INFO: 01615 return DAHDI_TONE_INFO; 01616 default: 01617 return -1; 01618 } 01619 }
static int analogsub_to_dahdisub | ( | enum analog_sub | analogsub | ) | [static] |
Definition at line 1621 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().
01622 { 01623 int index; 01624 01625 switch (analogsub) { 01626 case ANALOG_SUB_REAL: 01627 index = SUB_REAL; 01628 break; 01629 case ANALOG_SUB_CALLWAIT: 01630 index = SUB_CALLWAIT; 01631 break; 01632 case ANALOG_SUB_THREEWAY: 01633 index = SUB_THREEWAY; 01634 break; 01635 default: 01636 ast_log(LOG_ERROR, "Unidentified sub!\n"); 01637 index = SUB_REAL; 01638 } 01639 01640 return index; 01641 }
AST_DATA_STRUCTURE | ( | dahdi_pvt | , | |
DATA_EXPORT_DAHDI_PVT | ||||
) |
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7421 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().
07422 { 07423 /* In order to transfer, we need at least one of the channels to 07424 actually be in a call bridge. We can't conference two applications 07425 together (but then, why would we want to?) */ 07426 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 07427 /* The three-way person we're about to transfer to could still be in MOH, so 07428 stop if now if appropriate */ 07429 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 07430 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 07431 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 07432 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 07433 } 07434 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 07435 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 07436 } 07437 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 07438 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07439 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 07440 return -1; 07441 } 07442 /* Orphan the channel after releasing the lock */ 07443 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07444 unalloc_sub(p, SUB_THREEWAY); 07445 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07446 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07447 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 07448 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 07449 } 07450 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 07451 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07452 } 07453 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 07454 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 07455 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 07456 return -1; 07457 } 07458 /* Three-way is now the REAL */ 07459 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07460 ast_channel_unlock(p->subs[SUB_REAL].owner); 07461 unalloc_sub(p, SUB_THREEWAY); 07462 /* Tell the caller not to hangup */ 07463 return 1; 07464 } else { 07465 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 07466 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 07467 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07468 return -1; 07469 } 07470 return 0; 07471 }
static int available | ( | struct dahdi_pvt ** | pvt, | |
int | is_specific_channel | |||
) | [static] |
Definition at line 12840 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().
12841 { 12842 struct dahdi_pvt *p = *pvt; 12843 12844 if (p->inalarm) 12845 return 0; 12846 12847 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) 12848 return analog_available(p->sig_pvt); 12849 12850 switch (p->sig) { 12851 #if defined(HAVE_PRI) 12852 case SIG_PRI_LIB_HANDLE_CASES: 12853 { 12854 struct sig_pri_chan *pvt_chan; 12855 int res; 12856 12857 pvt_chan = p->sig_pvt; 12858 res = sig_pri_available(&pvt_chan, is_specific_channel); 12859 *pvt = pvt_chan->chan_pvt; 12860 return res; 12861 } 12862 #endif /* defined(HAVE_PRI) */ 12863 #if defined(HAVE_SS7) 12864 case SIG_SS7: 12865 return sig_ss7_available(p->sig_pvt); 12866 #endif /* defined(HAVE_SS7) */ 12867 default: 12868 break; 12869 } 12870 12871 if (p->locallyblocked || p->remotelyblocked) { 12872 return 0; 12873 } 12874 12875 /* If no owner definitely available */ 12876 if (!p->owner) { 12877 #ifdef HAVE_OPENR2 12878 /* Trust MFC/R2 */ 12879 if (p->mfcr2) { 12880 if (p->mfcr2call) { 12881 return 0; 12882 } else { 12883 return 1; 12884 } 12885 } 12886 #endif 12887 return 1; 12888 } 12889 12890 return 0; 12891 }
static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
const char * | value, | |||
int | reload, | |||
int | lineno, | |||
int * | found_pseudo | |||
) | [static] |
Definition at line 16319 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().
16320 { 16321 char *c, *chan; 16322 char *subdir; 16323 int x, start, finish; 16324 struct dahdi_pvt *tmp; 16325 16326 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 16327 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 16328 return -1; 16329 } 16330 16331 c = ast_strdupa(value); 16332 c = parse_spanchan(c, &subdir); 16333 16334 while ((chan = strsep(&c, ","))) { 16335 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 16336 /* Range */ 16337 } else if (sscanf(chan, "%30d", &start)) { 16338 /* Just one */ 16339 finish = start; 16340 } else if (!strcasecmp(chan, "pseudo")) { 16341 finish = start = CHAN_PSEUDO; 16342 if (found_pseudo) 16343 *found_pseudo = 1; 16344 } else { 16345 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 16346 return -1; 16347 } 16348 if (finish < start) { 16349 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 16350 x = finish; 16351 finish = start; 16352 start = x; 16353 } 16354 16355 for (x = start; x <= finish; x++) { 16356 char fn[PATH_MAX]; 16357 int real_channel = x; 16358 16359 if (!ast_strlen_zero(subdir)) { 16360 real_channel = device2chan(subdir, x, fn, sizeof(fn)); 16361 if (real_channel < 0) { 16362 if (conf->ignore_failed_channels) { 16363 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n", 16364 subdir, x, real_channel); 16365 continue; 16366 } else { 16367 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n", 16368 subdir, x, real_channel); 16369 return -1; 16370 } 16371 } 16372 } 16373 tmp = mkintf(real_channel, conf, reload); 16374 16375 if (tmp) { 16376 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig)); 16377 } else { 16378 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 16379 (reload == 1) ? "reconfigure" : "register", value); 16380 return -1; 16381 } 16382 } 16383 } 16384 16385 return 0; 16386 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4985 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().
04986 { 04987 int res; 04988 04989 /* Bump receive gain by value stored in cid_rxgain */ 04990 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 04991 if (res) { 04992 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 04993 return -1; 04994 } 04995 04996 return 0; 04997 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
format_t | law | |||
) | [static] |
Definition at line 10701 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by mwi_thread().
10702 { 10703 int x; 10704 int sum = 0; 10705 10706 if (!len) 10707 return 0; 10708 10709 for (x = 0; x < len; x++) 10710 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 10711 10712 return sum / len; 10713 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7473 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().
07474 { 07475 struct dahdi_confinfo ci; 07476 /* Fine if we already have a master, etc */ 07477 if (p->master || (p->confno > -1)) 07478 return 0; 07479 memset(&ci, 0, sizeof(ci)); 07480 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 07481 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 07482 return 0; 07483 } 07484 /* If we have no master and don't have a confno, then 07485 if we're in a conference, it's probably a MeetMe room or 07486 some such, so don't let us 3-way out! */ 07487 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 07488 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 07489 return 1; 07490 } 07491 return 0; 07492 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 13856 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
13857 { 13858 return complete_span_helper(line,word,pos,state,3); 13859 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 13835 of file chan_dahdi.c.
References asprintf, ast_log(), errno, dahdi_pri::pri, and pris.
Referenced by complete_span_4().
13836 { 13837 int which, span; 13838 char *ret = NULL; 13839 13840 if (pos != rpos) 13841 return ret; 13842 13843 for (which = span = 0; span < NUM_SPANS; span++) { 13844 if (pris[span].pri.pri && ++which > state) { 13845 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 13846 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 13847 } 13848 break; 13849 } 13850 } 13851 return ret; 13852 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 4567 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().
04568 { 04569 /* If the conference already exists, and we're already in it 04570 don't bother doing anything */ 04571 struct dahdi_confinfo zi; 04572 04573 memset(&zi, 0, sizeof(zi)); 04574 zi.chan = 0; 04575 04576 if (slavechannel > 0) { 04577 /* If we have only one slave, do a digital mon */ 04578 zi.confmode = DAHDI_CONF_DIGITALMON; 04579 zi.confno = slavechannel; 04580 } else { 04581 if (!idx) { 04582 /* Real-side and pseudo-side both participate in conference */ 04583 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 04584 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 04585 } else 04586 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 04587 zi.confno = p->confno; 04588 } 04589 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 04590 return 0; 04591 if (c->dfd < 0) 04592 return 0; 04593 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04594 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 04595 return -1; 04596 } 04597 if (slavechannel < 1) { 04598 p->confno = zi.confno; 04599 } 04600 c->curconf = zi; 04601 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04602 return 0; 04603 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 4616 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().
04617 { 04618 struct dahdi_confinfo zi; 04619 if (/* Can't delete if there's no dfd */ 04620 (c->dfd < 0) || 04621 /* Don't delete from the conference if it's not our conference */ 04622 !isourconf(p, c) 04623 /* Don't delete if we don't think it's conferenced at all (implied) */ 04624 ) return 0; 04625 memset(&zi, 0, sizeof(zi)); 04626 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 04627 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 04628 return -1; 04629 } 04630 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 04631 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 04632 return 0; 04633 }
static struct ast_str* create_channel_name | ( | struct dahdi_pvt * | i, | |
int | is_outgoing, | |||
char * | address | |||
) | [static] |
Definition at line 9244 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().
09248 { 09249 struct ast_str *chan_name; 09250 int x, y; 09251 09252 /* Create the new channel name tail. */ 09253 if (!(chan_name = ast_str_create(32))) { 09254 return NULL; 09255 } 09256 if (i->channel == CHAN_PSEUDO) { 09257 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 09258 #if defined(HAVE_PRI) 09259 } else if (i->pri) { 09260 ast_mutex_lock(&i->pri->lock); 09261 y = ++i->pri->new_chan_seq; 09262 if (is_outgoing) { 09263 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y); 09264 address[0] = '\0'; 09265 } else if (ast_strlen_zero(i->cid_subaddr)) { 09266 /* Put in caller-id number only since there is no subaddress. */ 09267 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y); 09268 } else { 09269 /* Put in caller-id number and subaddress. */ 09270 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num, 09271 i->cid_subaddr, y); 09272 } 09273 ast_mutex_unlock(&i->pri->lock); 09274 #endif /* defined(HAVE_PRI) */ 09275 } else { 09276 y = 1; 09277 do { 09278 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 09279 for (x = 0; x < 3; ++x) { 09280 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), 09281 i->subs[x].owner->name + 6)) { 09282 break; 09283 } 09284 } 09285 ++y; 09286 } while (x < 3); 09287 } 09288 return chan_name; 09289 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 5842 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().
05843 { 05844 /* data is whether to accept with charge or no charge */ 05845 openr2_call_mode_t accept_mode; 05846 int res, timeout, maxloops; 05847 struct ast_frame *f; 05848 struct dahdi_pvt *p; 05849 char *parse; 05850 AST_DECLARE_APP_ARGS(args, 05851 AST_APP_ARG(charge); 05852 ); 05853 05854 if (ast_strlen_zero(data)) { 05855 ast_log(LOG_DEBUG, "No data sent to application!\n"); 05856 return -1; 05857 } 05858 05859 if (chan->tech != &dahdi_tech) { 05860 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 05861 return -1; 05862 } 05863 05864 p = (struct dahdi_pvt *)chan->tech_pvt; 05865 if (!p) { 05866 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 05867 return -1; 05868 } 05869 05870 parse = ast_strdupa(data); 05871 AST_STANDARD_APP_ARGS(args, parse); 05872 05873 if (ast_strlen_zero(args.charge)) { 05874 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 05875 return -1; 05876 } 05877 05878 ast_mutex_lock(&p->lock); 05879 if (!p->mfcr2 || !p->mfcr2call) { 05880 ast_mutex_unlock(&p->lock); 05881 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 05882 return -1; 05883 } 05884 05885 if (p->mfcr2_call_accepted) { 05886 ast_mutex_unlock(&p->lock); 05887 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 05888 return 0; 05889 } 05890 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 05891 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 05892 ast_mutex_unlock(&p->lock); 05893 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 05894 return -1; 05895 } 05896 ast_mutex_unlock(&p->lock); 05897 05898 res = 0; 05899 timeout = 100; 05900 maxloops = 50; /* wait up to 5 seconds */ 05901 /* we need to read() until the call is accepted */ 05902 while (maxloops > 0) { 05903 maxloops--; 05904 if (ast_check_hangup(chan)) { 05905 break; 05906 } 05907 res = ast_waitfor(chan, timeout); 05908 if (res < 0) { 05909 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 05910 res = -1; 05911 break; 05912 } 05913 if (res == 0) { 05914 continue; 05915 } 05916 f = ast_read(chan); 05917 if (!f) { 05918 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 05919 res = -1; 05920 break; 05921 } 05922 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) { 05923 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 05924 ast_frfree(f); 05925 res = -1; 05926 break; 05927 } 05928 ast_frfree(f); 05929 ast_mutex_lock(&p->lock); 05930 if (p->mfcr2_call_accepted) { 05931 ast_mutex_unlock(&p->lock); 05932 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 05933 break; 05934 } 05935 ast_mutex_unlock(&p->lock); 05936 } 05937 if (res == -1) { 05938 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 05939 } 05940 return res; 05941 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6397 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.
06398 { 06399 struct dahdi_pvt *p = ast->tech_pvt; 06400 int res = 0; 06401 int idx; 06402 ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */ 06403 ast_mutex_lock(&p->lock); 06404 idx = dahdi_get_index(ast, p, 0); 06405 if (idx < 0) 06406 idx = SUB_REAL; 06407 /* nothing to do if a radio channel */ 06408 if ((p->radio || (p->oprmode < 0))) { 06409 ast_mutex_unlock(&p->lock); 06410 return 0; 06411 } 06412 06413 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06414 res = analog_answer(p->sig_pvt, ast); 06415 ast_mutex_unlock(&p->lock); 06416 return res; 06417 } 06418 06419 switch (p->sig) { 06420 #if defined(HAVE_PRI) 06421 case SIG_PRI_LIB_HANDLE_CASES: 06422 res = sig_pri_answer(p->sig_pvt, ast); 06423 break; 06424 #endif /* defined(HAVE_PRI) */ 06425 #if defined(HAVE_SS7) 06426 case SIG_SS7: 06427 res = sig_ss7_answer(p->sig_pvt, ast); 06428 break; 06429 #endif /* defined(HAVE_SS7) */ 06430 #ifdef HAVE_OPENR2 06431 case SIG_MFCR2: 06432 if (!p->mfcr2_call_accepted) { 06433 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 06434 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 06435 p->mfcr2_answer_pending = 1; 06436 if (p->mfcr2_charge_calls) { 06437 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 06438 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 06439 } else { 06440 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 06441 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 06442 } 06443 } else { 06444 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 06445 dahdi_r2_answer(p); 06446 } 06447 break; 06448 #endif 06449 case 0: 06450 ast_mutex_unlock(&p->lock); 06451 return 0; 06452 default: 06453 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 06454 res = -1; 06455 break; 06456 } 06457 ast_mutex_unlock(&p->lock); 06458 return res; 06459 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 5943 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().
05944 { 05945 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 05946 switch (cause) { 05947 case AST_CAUSE_USER_BUSY: 05948 case AST_CAUSE_CALL_REJECTED: 05949 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 05950 r2cause = OR2_CAUSE_BUSY_NUMBER; 05951 break; 05952 05953 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 05954 case AST_CAUSE_SWITCH_CONGESTION: 05955 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 05956 break; 05957 05958 case AST_CAUSE_UNALLOCATED: 05959 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 05960 break; 05961 05962 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 05963 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 05964 r2cause = OR2_CAUSE_OUT_OF_ORDER; 05965 break; 05966 05967 case AST_CAUSE_NO_ANSWER: 05968 case AST_CAUSE_NO_USER_RESPONSE: 05969 r2cause = OR2_CAUSE_NO_ANSWER; 05970 break; 05971 05972 default: 05973 r2cause = OR2_CAUSE_NORMAL_CLEARING; 05974 break; 05975 } 05976 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n", 05977 cause, r2cause, openr2_proto_get_disconnect_string(r2cause)); 05978 return r2cause; 05979 }
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 6998 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().
06999 { 07000 struct ast_channel *who; 07001 struct dahdi_pvt *p0, *p1, *op0, *op1; 07002 struct dahdi_pvt *master = NULL, *slave = NULL; 07003 struct ast_frame *f; 07004 int inconf = 0; 07005 int nothingok = 1; 07006 int ofd0, ofd1; 07007 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 07008 int os0 = -1, os1 = -1; 07009 int priority = 0; 07010 struct ast_channel *oc0, *oc1; 07011 enum ast_bridge_result res; 07012 #ifdef PRI_2BCT 07013 int triedtopribridge = 0; 07014 q931_call *q931c0; 07015 q931_call *q931c1; 07016 #endif 07017 07018 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 07019 There is code below to handle it properly until DTMF is actually seen, 07020 but due to currently unresolved issues it's ignored... 07021 */ 07022 07023 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 07024 return AST_BRIDGE_FAILED_NOWARN; 07025 07026 ast_channel_lock(c0); 07027 while (ast_channel_trylock(c1)) { 07028 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07029 } 07030 07031 p0 = c0->tech_pvt; 07032 p1 = c1->tech_pvt; 07033 /* cant do pseudo-channels here */ 07034 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 07035 ast_channel_unlock(c0); 07036 ast_channel_unlock(c1); 07037 return AST_BRIDGE_FAILED_NOWARN; 07038 } 07039 07040 oi0 = dahdi_get_index(c0, p0, 0); 07041 oi1 = dahdi_get_index(c1, p1, 0); 07042 if ((oi0 < 0) || (oi1 < 0)) { 07043 ast_channel_unlock(c0); 07044 ast_channel_unlock(c1); 07045 return AST_BRIDGE_FAILED; 07046 } 07047 07048 op0 = p0 = c0->tech_pvt; 07049 op1 = p1 = c1->tech_pvt; 07050 ofd0 = c0->fds[0]; 07051 ofd1 = c1->fds[0]; 07052 oc0 = p0->owner; 07053 oc1 = p1->owner; 07054 07055 if (ast_mutex_trylock(&p0->lock)) { 07056 /* Don't block, due to potential for deadlock */ 07057 ast_channel_unlock(c0); 07058 ast_channel_unlock(c1); 07059 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07060 return AST_BRIDGE_RETRY; 07061 } 07062 if (ast_mutex_trylock(&p1->lock)) { 07063 /* Don't block, due to potential for deadlock */ 07064 ast_mutex_unlock(&p0->lock); 07065 ast_channel_unlock(c0); 07066 ast_channel_unlock(c1); 07067 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 07068 return AST_BRIDGE_RETRY; 07069 } 07070 07071 if ((p0->callwaiting && p0->callwaitingcallerid) 07072 || (p1->callwaiting && p1->callwaitingcallerid)) { 07073 /* 07074 * Call Waiting Caller ID requires DTMF detection to know if it 07075 * can send the CID spill. 07076 * 07077 * For now, don't attempt to native bridge if either channel 07078 * needs DTMF detection. There is code below to handle it 07079 * properly until DTMF is actually seen, but due to currently 07080 * unresolved issues it's ignored... 07081 */ 07082 ast_mutex_unlock(&p0->lock); 07083 ast_mutex_unlock(&p1->lock); 07084 ast_channel_unlock(c0); 07085 ast_channel_unlock(c1); 07086 return AST_BRIDGE_FAILED_NOWARN; 07087 } 07088 07089 #if defined(HAVE_PRI) 07090 if ((dahdi_sig_pri_lib_handles(p0->sig) 07091 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel) 07092 || (dahdi_sig_pri_lib_handles(p1->sig) 07093 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) { 07094 /* 07095 * PRI nobch channels (hold and call waiting) are equivalent to 07096 * pseudo channels and cannot be done here. 07097 */ 07098 ast_mutex_unlock(&p0->lock); 07099 ast_mutex_unlock(&p1->lock); 07100 ast_channel_unlock(c0); 07101 ast_channel_unlock(c1); 07102 return AST_BRIDGE_FAILED_NOWARN; 07103 } 07104 #endif /* defined(HAVE_PRI) */ 07105 07106 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07107 if (p0->owner && p1->owner) { 07108 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 07109 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 07110 master = p0; 07111 slave = p1; 07112 inconf = 1; 07113 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 07114 master = p1; 07115 slave = p0; 07116 inconf = 1; 07117 } else { 07118 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 07119 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 07120 p0->channel, 07121 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07122 p0->subs[SUB_REAL].inthreeway, p0->channel, 07123 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 07124 p1->subs[SUB_REAL].inthreeway); 07125 } 07126 nothingok = 0; 07127 } 07128 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 07129 if (p1->subs[SUB_THREEWAY].inthreeway) { 07130 master = p1; 07131 slave = p0; 07132 nothingok = 0; 07133 } 07134 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 07135 if (p0->subs[SUB_THREEWAY].inthreeway) { 07136 master = p0; 07137 slave = p1; 07138 nothingok = 0; 07139 } 07140 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 07141 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 07142 don't put us in anything */ 07143 if (p1->subs[SUB_CALLWAIT].inthreeway) { 07144 master = p1; 07145 slave = p0; 07146 nothingok = 0; 07147 } 07148 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 07149 /* Same as previous */ 07150 if (p0->subs[SUB_CALLWAIT].inthreeway) { 07151 master = p0; 07152 slave = p1; 07153 nothingok = 0; 07154 } 07155 } 07156 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 07157 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 07158 if (master && slave) { 07159 /* Stop any tones, or play ringtone as appropriate. If they're bridged 07160 in an active threeway call with a channel that is ringing, we should 07161 indicate ringing. */ 07162 if ((oi1 == SUB_THREEWAY) && 07163 p1->subs[SUB_THREEWAY].inthreeway && 07164 p1->subs[SUB_REAL].owner && 07165 p1->subs[SUB_REAL].inthreeway && 07166 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07167 ast_debug(1, 07168 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07169 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07170 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 07171 os1 = p1->subs[SUB_REAL].owner->_state; 07172 } else { 07173 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07174 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 07175 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 07176 } 07177 if ((oi0 == SUB_THREEWAY) && 07178 p0->subs[SUB_THREEWAY].inthreeway && 07179 p0->subs[SUB_REAL].owner && 07180 p0->subs[SUB_REAL].inthreeway && 07181 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 07182 ast_debug(1, 07183 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 07184 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07185 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 07186 os0 = p0->subs[SUB_REAL].owner->_state; 07187 } else { 07188 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 07189 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 07190 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 07191 } 07192 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 07193 if (!p0->echocanbridged || !p1->echocanbridged) { 07194 /* Disable echo cancellation if appropriate */ 07195 dahdi_disable_ec(p0); 07196 dahdi_disable_ec(p1); 07197 } 07198 } 07199 dahdi_link(slave, master); 07200 master->inconference = inconf; 07201 } else if (!nothingok) 07202 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 07203 07204 update_conf(p0); 07205 update_conf(p1); 07206 t0 = p0->subs[SUB_REAL].inthreeway; 07207 t1 = p1->subs[SUB_REAL].inthreeway; 07208 07209 ast_mutex_unlock(&p0->lock); 07210 ast_mutex_unlock(&p1->lock); 07211 07212 ast_channel_unlock(c0); 07213 ast_channel_unlock(c1); 07214 07215 /* Native bridge failed */ 07216 if ((!master || !slave) && !nothingok) { 07217 dahdi_enable_ec(p0); 07218 dahdi_enable_ec(p1); 07219 return AST_BRIDGE_FAILED; 07220 } 07221 07222 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 07223 07224 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07225 disable_dtmf_detect(op0); 07226 07227 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07228 disable_dtmf_detect(op1); 07229 07230 for (;;) { 07231 struct ast_channel *c0_priority[2] = {c0, c1}; 07232 struct ast_channel *c1_priority[2] = {c1, c0}; 07233 07234 /* Here's our main loop... Start by locking things, looking for private parts, 07235 and then balking if anything is wrong */ 07236 07237 ast_channel_lock(c0); 07238 while (ast_channel_trylock(c1)) { 07239 CHANNEL_DEADLOCK_AVOIDANCE(c0); 07240 } 07241 07242 p0 = c0->tech_pvt; 07243 p1 = c1->tech_pvt; 07244 07245 if (op0 == p0) 07246 i0 = dahdi_get_index(c0, p0, 1); 07247 if (op1 == p1) 07248 i1 = dahdi_get_index(c1, p1, 1); 07249 07250 ast_channel_unlock(c0); 07251 ast_channel_unlock(c1); 07252 07253 if (!timeoutms || 07254 (op0 != p0) || 07255 (op1 != p1) || 07256 (ofd0 != c0->fds[0]) || 07257 (ofd1 != c1->fds[0]) || 07258 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 07259 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 07260 (oc0 != p0->owner) || 07261 (oc1 != p1->owner) || 07262 (t0 != p0->subs[SUB_REAL].inthreeway) || 07263 (t1 != p1->subs[SUB_REAL].inthreeway) || 07264 (oi0 != i0) || 07265 (oi1 != i1)) { 07266 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 07267 op0->channel, oi0, op1->channel, oi1); 07268 res = AST_BRIDGE_RETRY; 07269 goto return_from_bridge; 07270 } 07271 07272 #ifdef PRI_2BCT 07273 if (!triedtopribridge) { 07274 triedtopribridge = 1; 07275 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) { 07276 ast_mutex_lock(&p0->pri->lock); 07277 switch (p0->sig) { 07278 case SIG_PRI_LIB_HANDLE_CASES: 07279 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call; 07280 break; 07281 default: 07282 q931c0 = NULL; 07283 break; 07284 } 07285 switch (p1->sig) { 07286 case SIG_PRI_LIB_HANDLE_CASES: 07287 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call; 07288 break; 07289 default: 07290 q931c1 = NULL; 07291 break; 07292 } 07293 if (q931c0 && q931c1) { 07294 pri_channel_bridge(q931c0, q931c1); 07295 } 07296 ast_mutex_unlock(&p0->pri->lock); 07297 } 07298 } 07299 #endif 07300 07301 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 07302 if (!who) { 07303 ast_debug(1, "Ooh, empty read...\n"); 07304 continue; 07305 } 07306 f = ast_read(who); 07307 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 07308 *fo = f; 07309 *rc = who; 07310 res = AST_BRIDGE_COMPLETE; 07311 goto return_from_bridge; 07312 } 07313 if (f->frametype == AST_FRAME_DTMF) { 07314 if ((who == c0) && p0->pulsedial) { 07315 ast_write(c1, f); 07316 } else if ((who == c1) && p1->pulsedial) { 07317 ast_write(c0, f); 07318 } else { 07319 *fo = f; 07320 *rc = who; 07321 res = AST_BRIDGE_COMPLETE; 07322 goto return_from_bridge; 07323 } 07324 } 07325 ast_frfree(f); 07326 07327 /* Swap who gets priority */ 07328 priority = !priority; 07329 } 07330 07331 return_from_bridge: 07332 if (op0 == p0) 07333 dahdi_enable_ec(p0); 07334 07335 if (op1 == p1) 07336 dahdi_enable_ec(p1); 07337 07338 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 07339 enable_dtmf_detect(op0); 07340 07341 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 07342 enable_dtmf_detect(op1); 07343 07344 dahdi_unlink(slave, master, 1); 07345 07346 return res; 07347 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 5219 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, ast_channel::caller, dahdi_pvt::callwaitrings, dahdi_pvt::channel, 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_caller::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.
05220 { 05221 struct dahdi_pvt *p = ast->tech_pvt; 05222 int x, res, mysig; 05223 char dest[256]; /* must be same length as p->dialdest */ 05224 05225 ast_mutex_lock(&p->lock); 05226 ast_copy_string(dest, rdest, sizeof(dest)); 05227 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 05228 if ((ast->_state == AST_STATE_BUSY)) { 05229 p->subs[SUB_REAL].needbusy = 1; 05230 ast_mutex_unlock(&p->lock); 05231 return 0; 05232 } 05233 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05234 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 05235 ast_mutex_unlock(&p->lock); 05236 return -1; 05237 } 05238 p->waitingfordt.tv_sec = 0; 05239 p->dialednone = 0; 05240 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 05241 { 05242 /* Special pseudo -- automatically up */ 05243 ast_setstate(ast, AST_STATE_UP); 05244 ast_mutex_unlock(&p->lock); 05245 return 0; 05246 } 05247 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 05248 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 05249 if (res) 05250 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 05251 p->outgoing = 1; 05252 05253 if (IS_DIGITAL(ast->transfercapability)){ 05254 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law); 05255 } else { 05256 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05257 } 05258 05259 #ifdef HAVE_PRI 05260 if (dahdi_sig_pri_lib_handles(p->sig)) { 05261 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, 05262 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW); 05263 ast_mutex_unlock(&p->lock); 05264 return res; 05265 } 05266 #endif 05267 05268 #if defined(HAVE_SS7) 05269 if (p->sig == SIG_SS7) { 05270 res = sig_ss7_call(p->sig_pvt, ast, rdest); 05271 ast_mutex_unlock(&p->lock); 05272 return res; 05273 } 05274 #endif /* defined(HAVE_SS7) */ 05275 05276 /* If this is analog signalling we can exit here */ 05277 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 05278 p->callwaitrings = 0; 05279 res = analog_call(p->sig_pvt, ast, rdest, timeout); 05280 ast_mutex_unlock(&p->lock); 05281 return res; 05282 } 05283 05284 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; 05285 switch (mysig) { 05286 case 0: 05287 /* Special pseudo -- automatically up*/ 05288 ast_setstate(ast, AST_STATE_UP); 05289 break; 05290 case SIG_MFCR2: 05291 break; 05292 default: 05293 ast_debug(1, "not yet implemented\n"); 05294 ast_mutex_unlock(&p->lock); 05295 return -1; 05296 } 05297 05298 #ifdef HAVE_OPENR2 05299 if (p->mfcr2) { 05300 openr2_calling_party_category_t chancat; 05301 int callres = 0; 05302 char *c, *l; 05303 05304 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 05305 p->dialdest[0] = '\0'; 05306 05307 c = strchr(dest, '/'); 05308 if (c) { 05309 c++; 05310 } else { 05311 c = ""; 05312 } 05313 if (!p->hidecallerid) { 05314 l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL; 05315 } else { 05316 l = NULL; 05317 } 05318 if (strlen(c) < p->stripmsd) { 05319 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 05320 ast_mutex_unlock(&p->lock); 05321 return -1; 05322 } 05323 p->dialing = 1; 05324 chancat = dahdi_r2_get_channel_category(ast); 05325 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 05326 if (-1 == callres) { 05327 ast_mutex_unlock(&p->lock); 05328 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 05329 return -1; 05330 } 05331 p->mfcr2_call_accepted = 0; 05332 p->mfcr2_progress = 0; 05333 ast_setstate(ast, AST_STATE_DIALING); 05334 } 05335 #endif /* HAVE_OPENR2 */ 05336 ast_mutex_unlock(&p->lock); 05337 return 0; 05338 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5186 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().
05187 { 05188 struct dahdi_pvt *p = ast->tech_pvt; 05189 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 05190 if (p->cidspill) { 05191 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 05192 ast_free(p->cidspill); 05193 } 05194 05195 /* 05196 * SAS: Subscriber Alert Signal, 440Hz for 300ms 05197 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 05198 */ 05199 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 05200 return -1; 05201 save_conference(p); 05202 /* Silence */ 05203 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 05204 if (!p->callwaitrings && p->callwaitingcallerid) { 05205 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 05206 p->callwaitcas = 1; 05207 p->cidlen = 2400 + 680 + READ_SIZE * 4; 05208 } else { 05209 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 05210 p->callwaitcas = 0; 05211 p->cidlen = 2400 + READ_SIZE * 4; 05212 } 05213 p->cidpos = 0; 05214 send_callerid(p); 05215 05216 return 0; 05217 }
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 13486 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.
13487 { 13488 struct dahdi_pvt *p; 13489 struct dahdi_pvt *exitpvt; 13490 struct dahdi_starting_point start; 13491 int groupmatched = 0; 13492 int channelmatched = 0; 13493 13494 ast_mutex_lock(&iflock); 13495 p = determine_starting_point(dest, &start); 13496 if (!p) { 13497 ast_mutex_unlock(&iflock); 13498 return -1; 13499 } 13500 exitpvt = p; 13501 for (;;) { 13502 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) { 13503 /* We found a potential match. call the callback */ 13504 struct ast_str *device_name; 13505 char *dash; 13506 const char *monitor_type; 13507 char dialstring[AST_CHANNEL_NAME]; 13508 char full_device_name[AST_CHANNEL_NAME]; 13509 13510 switch (ast_get_cc_monitor_policy(p->cc_params)) { 13511 case AST_CC_MONITOR_NEVER: 13512 break; 13513 case AST_CC_MONITOR_NATIVE: 13514 case AST_CC_MONITOR_ALWAYS: 13515 case AST_CC_MONITOR_GENERIC: 13516 #if defined(HAVE_PRI) 13517 if (dahdi_sig_pri_lib_handles(p->sig)) { 13518 /* 13519 * ISDN is in a trunk busy condition so we need to monitor 13520 * the span congestion device state. 13521 */ 13522 snprintf(full_device_name, sizeof(full_device_name), 13523 "DAHDI/I%d/congestion", p->pri->span); 13524 } else 13525 #endif /* defined(HAVE_PRI) */ 13526 { 13527 #if defined(HAVE_PRI) 13528 device_name = create_channel_name(p, 1, ""); 13529 #else 13530 device_name = create_channel_name(p); 13531 #endif /* defined(HAVE_PRI) */ 13532 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", 13533 device_name ? ast_str_buffer(device_name) : ""); 13534 ast_free(device_name); 13535 /* 13536 * The portion after the '-' in the channel name is either a random 13537 * number, a sequence number, or a subchannel number. None are 13538 * necessary so strip them off. 13539 */ 13540 dash = strrchr(full_device_name, '-'); 13541 if (dash) { 13542 *dash = '\0'; 13543 } 13544 } 13545 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest); 13546 13547 /* 13548 * Analog can only do generic monitoring. 13549 * ISDN is in a trunk busy condition and any "device" is going 13550 * to be busy until a B channel becomes available. The generic 13551 * monitor can do this task. 13552 */ 13553 monitor_type = AST_CC_GENERIC_MONITOR_TYPE; 13554 callback(inbound, 13555 #if defined(HAVE_PRI) 13556 p->pri ? p->pri->cc_params : p->cc_params, 13557 #else 13558 p->cc_params, 13559 #endif /* defined(HAVE_PRI) */ 13560 monitor_type, full_device_name, dialstring, NULL); 13561 break; 13562 } 13563 } 13564 p = start.backwards ? p->prev : p->next; 13565 if (!p) { 13566 p = start.backwards ? ifend : iflist; 13567 } 13568 if (p == exitpvt) { 13569 break; 13570 } 13571 } 13572 ast_mutex_unlock(&iflock); 13573 return 0; 13574 }
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 1344 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().
01345 { 01346 /* recall that if a field is not included here it is initialized 01347 * to 0 or equivalent 01348 */ 01349 struct dahdi_chan_conf conf = { 01350 #ifdef HAVE_PRI 01351 .pri.pri = { 01352 .nsf = PRI_NSF_NONE, 01353 .switchtype = PRI_SWITCH_NI2, 01354 .dialplan = PRI_UNKNOWN + 1, 01355 .localdialplan = PRI_NATIONAL_ISDN + 1, 01356 .nodetype = PRI_CPE, 01357 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01358 01359 #if defined(HAVE_PRI_CCSS) 01360 .cc_ptmp_recall_mode = 1,/* specificRecall */ 01361 .cc_qsig_signaling_link_req = 1,/* retain */ 01362 .cc_qsig_signaling_link_rsp = 1,/* retain */ 01363 #endif /* defined(HAVE_PRI_CCSS) */ 01364 01365 .minunused = 2, 01366 .idleext = "", 01367 .idledial = "", 01368 .internationalprefix = "", 01369 .nationalprefix = "", 01370 .localprefix = "", 01371 .privateprefix = "", 01372 .unknownprefix = "", 01373 .resetinterval = -1, 01374 }, 01375 #endif 01376 #if defined(HAVE_SS7) 01377 .ss7.ss7 = { 01378 .called_nai = SS7_NAI_NATIONAL, 01379 .calling_nai = SS7_NAI_NATIONAL, 01380 .internationalprefix = "", 01381 .nationalprefix = "", 01382 .subscriberprefix = "", 01383 .unknownprefix = "" 01384 }, 01385 #endif /* defined(HAVE_SS7) */ 01386 #ifdef HAVE_OPENR2 01387 .mfcr2 = { 01388 .variant = OR2_VAR_ITU, 01389 .mfback_timeout = -1, 01390 .metering_pulse_timeout = -1, 01391 .max_ani = 10, 01392 .max_dnis = 4, 01393 .get_ani_first = -1, 01394 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01395 .skip_category_request = -1, 01396 #endif 01397 .call_files = 0, 01398 .allow_collect_calls = 0, 01399 .charge_calls = 1, 01400 .accept_on_offer = 1, 01401 .forced_release = 0, 01402 .double_answer = 0, 01403 .immediate_accept = -1, 01404 .logdir = "", 01405 .r2proto_file = "", 01406 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01407 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01408 }, 01409 #endif 01410 .chan = { 01411 .context = "default", 01412 .cid_num = "", 01413 .cid_name = "", 01414 .cid_tag = "", 01415 .mohinterpret = "default", 01416 .mohsuggest = "", 01417 .parkinglot = "", 01418 .transfertobusy = 1, 01419 01420 .cid_signalling = CID_SIG_BELL, 01421 .cid_start = CID_START_RING, 01422 .dahditrcallerid = 0, 01423 .use_callerid = 1, 01424 .sig = -1, 01425 .outsigmod = -1, 01426 01427 .cid_rxgain = +5.0, 01428 01429 .tonezone = -1, 01430 01431 .echocancel.head.tap_length = 1, 01432 01433 .busycount = 3, 01434 .busycompare = 0, 01435 .busytonelength = 0, 01436 .busyquietlength = 0, 01437 .busyfuzziness = 0, 01438 .silencethreshold = 0, 01439 01440 .accountcode = "", 01441 01442 .mailbox = "", 01443 01444 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01445 .mwisend_fsk = 1, 01446 #endif 01447 .polarityonanswerdelay = 600, 01448 01449 .sendcalleridafter = DEFAULT_CIDRINGS, 01450 01451 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01452 .buf_no = numbufs, 01453 .usefaxbuffers = 0, 01454 .cc_params = ast_cc_config_params_init(), 01455 }, 01456 .timing = { 01457 .prewinktime = -1, 01458 .preflashtime = -1, 01459 .winktime = -1, 01460 .flashtime = -1, 01461 .starttime = -1, 01462 .rxwinktime = -1, 01463 .rxflashtime = -1, 01464 .debouncetime = -1 01465 }, 01466 .is_sig_auto = 1, 01467 .smdi_port = "/dev/ttyS0", 01468 }; 01469 01470 return conf; 01471 }
static int dahdi_channels_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 17906 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.
17908 { 17909 struct dahdi_pvt *tmp; 17910 struct ast_data *data_channel; 17911 17912 ast_mutex_lock(&iflock); 17913 for (tmp = iflist; tmp; tmp = tmp->next) { 17914 data_channel = ast_data_add_node(data_root, "channel"); 17915 if (!data_channel) { 17916 continue; 17917 } 17918 17919 ast_data_add_structure(dahdi_pvt, data_channel, tmp); 17920 17921 /* if this channel doesn't match remove it. */ 17922 if (!ast_data_search_match(search, data_channel)) { 17923 ast_data_remove_node(data_root, data_channel); 17924 } 17925 } 17926 ast_mutex_unlock(&iflock); 17927 17928 return 0; 17929 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 4213 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 4226 of file chan_dahdi.c.
References dahdi_close(), sig_pri_span::fds, and dahdi_pri::pri.
Referenced by __unload_module(), and prepare_pri().
04227 { 04228 dahdi_close(pri->pri.fds[fd_num]); 04229 pri->pri.fds[fd_num] = -1; 04230 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 4219 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().
04220 { 04221 dahdi_close(chan_pvt->subs[sub_num].dfd); 04222 chan_pvt->subs[sub_num].dfd = -1; 04223 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 5029 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().
05030 { 05031 int x, res; 05032 05033 x = muted; 05034 #if defined(HAVE_PRI) || defined(HAVE_SS7) 05035 switch (p->sig) { 05036 #if defined(HAVE_PRI) 05037 case SIG_PRI_LIB_HANDLE_CASES: 05038 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 05039 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 05040 break; 05041 } 05042 /* Fall through */ 05043 #endif /* defined(HAVE_PRI) */ 05044 #if defined(HAVE_SS7) 05045 case SIG_SS7: 05046 #endif /* defined(HAVE_SS7) */ 05047 { 05048 int y = 1; 05049 05050 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 05051 if (res) 05052 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", 05053 p->channel, strerror(errno)); 05054 } 05055 break; 05056 default: 05057 break; 05058 } 05059 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 05060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 05061 if (res < 0) 05062 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 05063 return res; 05064 }
static char* dahdi_destroy_channel | ( | 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_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.
14587 { 14588 int channel; 14589 int ret; 14590 switch (cmd) { 14591 case CLI_INIT: 14592 e->command = "dahdi destroy channel"; 14593 e->usage = 14594 "Usage: dahdi destroy channel <chan num>\n" 14595 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 14596 return NULL; 14597 case CLI_GENERATE: 14598 return NULL; 14599 } 14600 if (a->argc != 4) 14601 return CLI_SHOWUSAGE; 14602 14603 channel = atoi(a->argv[3]); 14604 ret = dahdi_destroy_channel_bynum(channel); 14605 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 14606 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 11055 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().
11056 { 11057 struct dahdi_pvt *cur; 11058 11059 ast_mutex_lock(&iflock); 11060 for (cur = iflist; cur; cur = cur->next) { 11061 if (cur->channel == channel) { 11062 int x = DAHDI_FLASH; 11063 11064 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 11065 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11066 11067 destroy_channel(cur, 1); 11068 ast_mutex_unlock(&iflock); 11069 ast_module_unref(ast_module_info->self); 11070 return RESULT_SUCCESS; 11071 } 11072 } 11073 ast_mutex_unlock(&iflock); 11074 return RESULT_FAILURE; 11075 }
static int dahdi_devicestate | ( | void * | data | ) | [static] |
Definition at line 13424 of file chan_dahdi.c.
References AST_DEVICE_UNKNOWN, sig_pri_span::congestion_devstate, dahdi_pri::pri, and pris.
13425 { 13426 #if defined(HAVE_PRI) 13427 char *device; 13428 unsigned span; 13429 int res; 13430 13431 device = data; 13432 13433 if (*device != 'I') { 13434 /* The request is not for an ISDN span device. */ 13435 return AST_DEVICE_UNKNOWN; 13436 } 13437 res = sscanf(device, "I%30u", &span); 13438 if (res != 1 || !span || NUM_SPANS < span) { 13439 /* Bad format for ISDN span device name. */ 13440 return AST_DEVICE_UNKNOWN; 13441 } 13442 device = strchr(device, '/'); 13443 if (!device) { 13444 /* Bad format for ISDN span device name. */ 13445 return AST_DEVICE_UNKNOWN; 13446 } 13447 13448 /* 13449 * Since there are currently no other span devstate's defined, 13450 * it must be congestion. 13451 */ 13452 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13453 ++device; 13454 if (!strcmp(device, "congestion")) 13455 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13456 { 13457 return pris[span - 1].pri.congestion_devstate; 13458 } 13459 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 13460 else if (!strcmp(device, "threshold")) { 13461 return pris[span - 1].pri.threshold_devstate; 13462 } 13463 return AST_DEVICE_UNKNOWN; 13464 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 13465 #else 13466 return AST_DEVICE_UNKNOWN; 13467 #endif /* defined(HAVE_PRI) */ 13468 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 4317 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.
04318 { 04319 struct dahdi_pvt *pvt; 04320 int idx; 04321 int dtmf = -1; 04322 int res; 04323 04324 pvt = chan->tech_pvt; 04325 04326 ast_mutex_lock(&pvt->lock); 04327 04328 idx = dahdi_get_index(chan, pvt, 0); 04329 04330 if ((idx != SUB_REAL) || !pvt->owner) 04331 goto out; 04332 04333 #ifdef HAVE_PRI 04334 switch (pvt->sig) { 04335 case SIG_PRI_LIB_HANDLE_CASES: 04336 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit); 04337 if (!res) 04338 goto out; 04339 break; 04340 default: 04341 break; 04342 } 04343 #endif 04344 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 04345 goto out; 04346 04347 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 04348 struct dahdi_dialoperation zo = { 04349 .op = DAHDI_DIAL_OP_APPEND, 04350 }; 04351 04352 zo.dialstr[0] = 'T'; 04353 zo.dialstr[1] = digit; 04354 zo.dialstr[2] = '\0'; 04355 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 04356 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 04357 else 04358 pvt->dialing = 1; 04359 } else { 04360 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 04361 pvt->dialing = 1; 04362 pvt->begindigit = digit; 04363 } 04364 04365 out: 04366 ast_mutex_unlock(&pvt->lock); 04367 04368 return 0; 04369 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 4371 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.
04372 { 04373 struct dahdi_pvt *pvt; 04374 int res = 0; 04375 int idx; 04376 int x; 04377 04378 pvt = chan->tech_pvt; 04379 04380 ast_mutex_lock(&pvt->lock); 04381 04382 idx = dahdi_get_index(chan, pvt, 0); 04383 04384 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 04385 goto out; 04386 04387 #ifdef HAVE_PRI 04388 /* This means that the digit was already sent via PRI signalling */ 04389 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) { 04390 goto out; 04391 } 04392 #endif 04393 04394 if (pvt->begindigit) { 04395 x = -1; 04396 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 04397 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 04398 pvt->dialing = 0; 04399 pvt->begindigit = 0; 04400 } 04401 04402 out: 04403 ast_mutex_unlock(&pvt->lock); 04404 04405 return res; 04406 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4821 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().
04822 { 04823 int res; 04824 04825 if (p->echocanon) { 04826 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 04827 04828 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 04829 04830 if (res) 04831 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 04832 else 04833 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 04834 } 04835 04836 p->echocanon = 0; 04837 }
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 9553 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().
09554 { 09555 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) { 09556 return analog_dnd(dahdichan->sig_pvt, flag); 09557 } 09558 09559 if (flag == -1) { 09560 return dahdichan->dnd; 09561 } 09562 09563 /* Do not disturb */ 09564 dahdichan->dnd = flag; 09565 ast_verb(3, "%s DND on channel %d\n", 09566 flag? "Enabled" : "Disabled", 09567 dahdichan->channel); 09568 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 09569 "Channel: DAHDI/%d\r\n" 09570 "Status: %s\r\n", dahdichan->channel, 09571 flag? "enabled" : "disabled"); 09572 09573 return 0; 09574 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4749 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().
04750 { 04751 int res; 04752 if (!p) 04753 return; 04754 if (p->echocanon) { 04755 ast_debug(1, "Echo cancellation already on\n"); 04756 return; 04757 } 04758 if (p->digital) { 04759 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 04760 return; 04761 } 04762 if (p->echocancel.head.tap_length) { 04763 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04764 switch (p->sig) { 04765 #if defined(HAVE_PRI) 04766 case SIG_PRI_LIB_HANDLE_CASES: 04767 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 04768 /* 04769 * PRI nobch pseudo channel. Does not need ec anyway. 04770 * Does not handle ioctl(DAHDI_AUDIOMODE) 04771 */ 04772 return; 04773 } 04774 /* Fall through */ 04775 #endif /* defined(HAVE_PRI) */ 04776 #if defined(HAVE_SS7) 04777 case SIG_SS7: 04778 #endif /* defined(HAVE_SS7) */ 04779 { 04780 int x = 1; 04781 04782 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 04783 if (res) 04784 ast_log(LOG_WARNING, 04785 "Unable to enable audio mode on channel %d (%s)\n", 04786 p->channel, strerror(errno)); 04787 } 04788 break; 04789 default: 04790 break; 04791 } 04792 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 04793 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 04794 if (res) { 04795 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 04796 } else { 04797 p->echocanon = 1; 04798 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 04799 } 04800 } else 04801 ast_debug(1, "No echo cancellation requested\n"); 04802 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8626 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.
08627 { 08628 struct dahdi_pvt *p = ast->tech_pvt; 08629 struct ast_frame *f; 08630 ast_mutex_lock(&p->lock); 08631 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08632 struct analog_pvt *analog_p = p->sig_pvt; 08633 f = analog_exception(analog_p, ast); 08634 } else { 08635 f = __dahdi_exception(ast); 08636 } 08637 ast_mutex_unlock(&p->lock); 08638 return f; 08639 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 15433 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().
15434 { 15435 if (p) { 15436 switch (mode) { 15437 case TRANSFER: 15438 p->fake_event = DAHDI_EVENT_WINKFLASH; 15439 break; 15440 case HANGUP: 15441 p->fake_event = DAHDI_EVENT_ONHOOK; 15442 break; 15443 default: 15444 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 15445 } 15446 } 15447 return 0; 15448 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 7349 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.
07350 { 07351 struct dahdi_pvt *p = newchan->tech_pvt; 07352 int x; 07353 07354 ast_mutex_lock(&p->lock); 07355 07356 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 07357 if (p->owner == oldchan) { 07358 p->owner = newchan; 07359 } 07360 for (x = 0; x < 3; x++) { 07361 if (p->subs[x].owner == oldchan) { 07362 if (!x) { 07363 dahdi_unlink(NULL, p, 0); 07364 } 07365 p->subs[x].owner = newchan; 07366 } 07367 } 07368 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 07369 analog_fixup(oldchan, newchan, p->sig_pvt); 07370 #if defined(HAVE_PRI) 07371 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 07372 sig_pri_fixup(oldchan, newchan, p->sig_pvt); 07373 #endif /* defined(HAVE_PRI) */ 07374 #if defined(HAVE_SS7) 07375 } else if (p->sig == SIG_SS7) { 07376 sig_ss7_fixup(oldchan, newchan, p->sig_pvt); 07377 #endif /* defined(HAVE_SS7) */ 07378 } 07379 update_conf(p); 07380 07381 ast_mutex_unlock(&p->lock); 07382 07383 if (newchan->_state == AST_STATE_RINGING) { 07384 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 07385 } 07386 return 0; 07387 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 6752 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, dahdi_pvt::rxgain, dahdi_pvt::sig, SIG_PRI_LIB_HANDLE_CASES, dahdi_pvt::sig_pvt, ast_channel::tech_pvt, and dahdi_pvt::txgain.
06753 { 06754 struct dahdi_pvt *p = chan->tech_pvt; 06755 int res = 0; 06756 06757 if (!strcasecmp(data, "rxgain")) { 06758 ast_mutex_lock(&p->lock); 06759 snprintf(buf, len, "%f", p->rxgain); 06760 ast_mutex_unlock(&p->lock); 06761 } else if (!strcasecmp(data, "txgain")) { 06762 ast_mutex_lock(&p->lock); 06763 snprintf(buf, len, "%f", p->txgain); 06764 ast_mutex_unlock(&p->lock); 06765 #if defined(HAVE_PRI) 06766 #if defined(HAVE_PRI_REVERSE_CHARGE) 06767 } else if (!strcasecmp(data, "reversecharge")) { 06768 ast_mutex_lock(&p->lock); 06769 switch (p->sig) { 06770 case SIG_PRI_LIB_HANDLE_CASES: 06771 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication); 06772 break; 06773 default: 06774 *buf = '\0'; 06775 res = -1; 06776 break; 06777 } 06778 ast_mutex_unlock(&p->lock); 06779 #endif 06780 #if defined(HAVE_PRI_SETUP_KEYPAD) 06781 } else if (!strcasecmp(data, "keypad_digits")) { 06782 ast_mutex_lock(&p->lock); 06783 switch (p->sig) { 06784 case SIG_PRI_LIB_HANDLE_CASES: 06785 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits, 06786 len); 06787 break; 06788 default: 06789 *buf = '\0'; 06790 res = -1; 06791 break; 06792 } 06793 ast_mutex_unlock(&p->lock); 06794 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ 06795 } else if (!strcasecmp(data, "no_media_path")) { 06796 ast_mutex_lock(&p->lock); 06797 switch (p->sig) { 06798 case SIG_PRI_LIB_HANDLE_CASES: 06799 /* 06800 * TRUE if the call is on hold or is call waiting because 06801 * there is no media path available. 06802 */ 06803 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel); 06804 break; 06805 default: 06806 *buf = '\0'; 06807 res = -1; 06808 break; 06809 } 06810 ast_mutex_unlock(&p->lock); 06811 #endif /* defined(HAVE_PRI) */ 06812 } else { 06813 *buf = '\0'; 06814 res = -1; 06815 } 06816 06817 return res; 06818 }
static int dahdi_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 6850 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.
06851 { 06852 struct dahdi_pvt *p = chan->tech_pvt; 06853 int res = 0; 06854 06855 if (!strcasecmp(data, "buffers")) { 06856 int num_bufs, policy; 06857 06858 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 06859 struct dahdi_bufferinfo bi = { 06860 .txbufpolicy = policy, 06861 .rxbufpolicy = policy, 06862 .bufsize = p->bufsize, 06863 .numbufs = num_bufs, 06864 }; 06865 int bpres; 06866 06867 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 06868 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 06869 } else { 06870 p->bufferoverrideinuse = 1; 06871 } 06872 } else { 06873 res = -1; 06874 } 06875 } else if (!strcasecmp(data, "echocan_mode")) { 06876 if (!strcasecmp(value, "on")) { 06877 ast_mutex_lock(&p->lock); 06878 dahdi_enable_ec(p); 06879 ast_mutex_unlock(&p->lock); 06880 } else if (!strcasecmp(value, "off")) { 06881 ast_mutex_lock(&p->lock); 06882 dahdi_disable_ec(p); 06883 ast_mutex_unlock(&p->lock); 06884 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 06885 } else if (!strcasecmp(value, "fax")) { 06886 int blah = 1; 06887 06888 ast_mutex_lock(&p->lock); 06889 if (!p->echocanon) { 06890 dahdi_enable_ec(p); 06891 } 06892 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 06893 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno)); 06894 } 06895 ast_mutex_unlock(&p->lock); 06896 } else if (!strcasecmp(value, "voice")) { 06897 int blah = 0; 06898 06899 ast_mutex_lock(&p->lock); 06900 if (!p->echocanon) { 06901 dahdi_enable_ec(p); 06902 } 06903 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) { 06904 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno)); 06905 } 06906 ast_mutex_unlock(&p->lock); 06907 #endif 06908 } else { 06909 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data); 06910 res = -1; 06911 } 06912 } else { 06913 res = -1; 06914 } 06915 06916 return res; 06917 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 470 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().
00471 { 00472 int j; 00473 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00474 return -1; 00475 return j; 00476 }
static void dahdi_handle_dtmf | ( | struct ast_channel * | ast, | |
int | idx, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 7526 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().
07527 { 07528 struct dahdi_pvt *p = ast->tech_pvt; 07529 struct ast_frame *f = *dest; 07530 07531 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 07532 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 07533 f->subclass.integer, f->subclass.integer, ast->name); 07534 07535 if (p->confirmanswer) { 07536 if (f->frametype == AST_FRAME_DTMF_END) { 07537 ast_debug(1, "Confirm answer on %s!\n", ast->name); 07538 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 07539 of a DTMF digit */ 07540 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07541 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07542 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 07543 p->confirmanswer = 0; 07544 } else { 07545 p->subs[idx].f.frametype = AST_FRAME_NULL; 07546 p->subs[idx].f.subclass.integer = 0; 07547 } 07548 *dest = &p->subs[idx].f; 07549 } else if (p->callwaitcas) { 07550 if (f->frametype == AST_FRAME_DTMF_END) { 07551 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) { 07552 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 07553 ast_free(p->cidspill); 07554 p->cidspill = NULL; 07555 send_cwcidspill(p); 07556 } 07557 p->callwaitcas = 0; 07558 } 07559 p->subs[idx].f.frametype = AST_FRAME_NULL; 07560 p->subs[idx].f.subclass.integer = 0; 07561 *dest = &p->subs[idx].f; 07562 } else if (f->subclass.integer == 'f') { 07563 if (f->frametype == AST_FRAME_DTMF_END) { 07564 /* Fax tone -- Handle and return NULL */ 07565 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 07566 /* If faxbuffers are configured, use them for the fax transmission */ 07567 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 07568 struct dahdi_bufferinfo bi = { 07569 .txbufpolicy = p->faxbuf_policy, 07570 .bufsize = p->bufsize, 07571 .numbufs = p->faxbuf_no 07572 }; 07573 int res; 07574 07575 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 07576 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 07577 } else { 07578 p->bufferoverrideinuse = 1; 07579 } 07580 } 07581 p->faxhandled = 1; 07582 if (p->dsp) { 07583 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 07584 ast_dsp_set_features(p->dsp, p->dsp_features); 07585 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 07586 } 07587 if (strcmp(ast->exten, "fax")) { 07588 const char *target_context = S_OR(ast->macrocontext, ast->context); 07589 07590 /* We need to unlock 'ast' here because ast_exists_extension has the 07591 * potential to start autoservice on the channel. Such action is prone 07592 * to deadlock. 07593 */ 07594 ast_mutex_unlock(&p->lock); 07595 ast_channel_unlock(ast); 07596 if (ast_exists_extension(ast, target_context, "fax", 1, 07597 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 07598 ast_channel_lock(ast); 07599 ast_mutex_lock(&p->lock); 07600 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 07601 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 07602 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 07603 if (ast_async_goto(ast, target_context, "fax", 1)) 07604 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 07605 } else { 07606 ast_channel_lock(ast); 07607 ast_mutex_lock(&p->lock); 07608 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 07609 } 07610 } else { 07611 ast_debug(1, "Already in a fax extension, not redirecting\n"); 07612 } 07613 } else { 07614 ast_debug(1, "Fax already handled\n"); 07615 } 07616 dahdi_confmute(p, 0); 07617 } 07618 p->subs[idx].f.frametype = AST_FRAME_NULL; 07619 p->subs[idx].f.subclass.integer = 0; 07620 *dest = &p->subs[idx].f; 07621 } 07622 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 7645 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().
07646 { 07647 int res, x; 07648 int idx, mysig; 07649 char *c; 07650 struct dahdi_pvt *p = ast->tech_pvt; 07651 pthread_t threadid; 07652 struct ast_channel *chan; 07653 struct ast_frame *f; 07654 07655 idx = dahdi_get_index(ast, p, 0); 07656 mysig = p->sig; 07657 if (p->outsigmod > -1) 07658 mysig = p->outsigmod; 07659 p->subs[idx].f.frametype = AST_FRAME_NULL; 07660 p->subs[idx].f.subclass.integer = 0; 07661 p->subs[idx].f.datalen = 0; 07662 p->subs[idx].f.samples = 0; 07663 p->subs[idx].f.mallocd = 0; 07664 p->subs[idx].f.offset = 0; 07665 p->subs[idx].f.src = "dahdi_handle_event"; 07666 p->subs[idx].f.data.ptr = NULL; 07667 f = &p->subs[idx].f; 07668 07669 if (idx < 0) 07670 return &p->subs[idx].f; 07671 if (p->fake_event) { 07672 res = p->fake_event; 07673 p->fake_event = 0; 07674 } else 07675 res = dahdi_get_event(p->subs[idx].dfd); 07676 07677 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 07678 07679 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 07680 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 07681 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 07682 #if defined(HAVE_PRI) 07683 if (dahdi_sig_pri_lib_handles(p->sig) 07684 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07685 && p->pri 07686 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07687 /* absorb event */ 07688 } else 07689 #endif /* defined(HAVE_PRI) */ 07690 { 07691 /* Unmute conference */ 07692 dahdi_confmute(p, 0); 07693 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 07694 p->subs[idx].f.subclass.integer = res & 0xff; 07695 dahdi_handle_dtmf(ast, idx, &f); 07696 } 07697 return f; 07698 } 07699 07700 if (res & DAHDI_EVENT_DTMFDOWN) { 07701 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 07702 #if defined(HAVE_PRI) 07703 if (dahdi_sig_pri_lib_handles(p->sig) 07704 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 07705 && p->pri 07706 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 07707 /* absorb event */ 07708 } else 07709 #endif /* defined(HAVE_PRI) */ 07710 { 07711 /* Mute conference */ 07712 dahdi_confmute(p, 1); 07713 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 07714 p->subs[idx].f.subclass.integer = res & 0xff; 07715 dahdi_handle_dtmf(ast, idx, &f); 07716 } 07717 return &p->subs[idx].f; 07718 } 07719 07720 switch (res) { 07721 case DAHDI_EVENT_EC_DISABLED: 07722 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel); 07723 p->echocanon = 0; 07724 break; 07725 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 07726 case DAHDI_EVENT_TX_CED_DETECTED: 07727 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel); 07728 break; 07729 case DAHDI_EVENT_RX_CED_DETECTED: 07730 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel); 07731 break; 07732 case DAHDI_EVENT_EC_NLP_DISABLED: 07733 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel); 07734 break; 07735 case DAHDI_EVENT_EC_NLP_ENABLED: 07736 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel); 07737 break; 07738 #endif 07739 case DAHDI_EVENT_BITSCHANGED: 07740 #ifdef HAVE_OPENR2 07741 if (p->sig != SIG_MFCR2) { 07742 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07743 } else { 07744 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 07745 openr2_chan_handle_cas(p->r2chan); 07746 } 07747 #else 07748 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 07749 #endif 07750 case DAHDI_EVENT_PULSE_START: 07751 /* Stop tone if there's a pulse start and the PBX isn't started */ 07752 if (!ast->pbx) 07753 tone_zone_play_tone(p->subs[idx].dfd, -1); 07754 break; 07755 case DAHDI_EVENT_DIALCOMPLETE: 07756 #ifdef HAVE_OPENR2 07757 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 07758 /* we don't need to do anything for this event for R2 signaling 07759 if the call is being setup */ 07760 break; 07761 } 07762 #endif 07763 if (p->inalarm) break; 07764 if ((p->radio || (p->oprmode < 0))) break; 07765 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 07766 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 07767 return NULL; 07768 } 07769 if (!x) { /* if not still dialing in driver */ 07770 dahdi_enable_ec(p); 07771 if (p->echobreak) { 07772 dahdi_train_ec(p); 07773 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 07774 p->dop.op = DAHDI_DIAL_OP_REPLACE; 07775 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07776 p->echobreak = 0; 07777 } else { 07778 p->dialing = 0; 07779 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 07780 /* if thru with dialing after offhook */ 07781 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 07782 ast_setstate(ast, AST_STATE_UP); 07783 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07784 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07785 break; 07786 } else { /* if to state wait for offhook to dial rest */ 07787 /* we now wait for off hook */ 07788 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 07789 } 07790 } 07791 if (ast->_state == AST_STATE_DIALING) { 07792 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 07793 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 07794 } else if (p->confirmanswer || (!p->dialednone 07795 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 07796 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 07797 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 07798 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 07799 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 07800 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 07801 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 07802 || (mysig == SIG_SF_FEATB)))) { 07803 ast_setstate(ast, AST_STATE_RINGING); 07804 } else if (!p->answeronpolarityswitch) { 07805 ast_setstate(ast, AST_STATE_UP); 07806 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07807 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 07808 /* If aops=0 and hops=1, this is necessary */ 07809 p->polarity = POLARITY_REV; 07810 } else { 07811 /* Start clean, so we can catch the change to REV polarity when party answers */ 07812 p->polarity = POLARITY_IDLE; 07813 } 07814 } 07815 } 07816 } 07817 break; 07818 case DAHDI_EVENT_ALARM: 07819 switch (p->sig) { 07820 #if defined(HAVE_PRI) 07821 case SIG_PRI_LIB_HANDLE_CASES: 07822 sig_pri_chan_alarm_notify(p->sig_pvt, 0); 07823 break; 07824 #endif /* defined(HAVE_PRI) */ 07825 #if defined(HAVE_SS7) 07826 case SIG_SS7: 07827 sig_ss7_set_alarm(p->sig_pvt, 1); 07828 break; 07829 #endif /* defined(HAVE_SS7) */ 07830 default: 07831 p->inalarm = 1; 07832 break; 07833 } 07834 res = get_alarms(p); 07835 handle_alarms(p, res); 07836 #ifdef HAVE_PRI 07837 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 07838 /* fall through intentionally */ 07839 } else { 07840 break; 07841 } 07842 #endif 07843 #if defined(HAVE_SS7) 07844 if (p->sig == SIG_SS7) 07845 break; 07846 #endif /* defined(HAVE_SS7) */ 07847 #ifdef HAVE_OPENR2 07848 if (p->sig == SIG_MFCR2) 07849 break; 07850 #endif 07851 case DAHDI_EVENT_ONHOOK: 07852 if (p->radio) { 07853 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07854 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 07855 break; 07856 } 07857 if (p->oprmode < 0) 07858 { 07859 if (p->oprmode != -1) break; 07860 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 07861 { 07862 /* Make sure it starts ringing */ 07863 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 07864 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 07865 save_conference(p->oprpeer); 07866 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07867 } 07868 break; 07869 } 07870 switch (p->sig) { 07871 case SIG_FXOLS: 07872 case SIG_FXOGS: 07873 case SIG_FXOKS: 07874 /* Check for some special conditions regarding call waiting */ 07875 if (idx == SUB_REAL) { 07876 /* The normal line was hung up */ 07877 if (p->subs[SUB_CALLWAIT].owner) { 07878 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 07879 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 07880 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 07881 unalloc_sub(p, SUB_CALLWAIT); 07882 #if 0 07883 p->subs[idx].needanswer = 0; 07884 p->subs[idx].needringing = 0; 07885 #endif 07886 p->callwaitingrepeat = 0; 07887 p->cidcwexpire = 0; 07888 p->cid_suppress_expire = 0; 07889 p->owner = NULL; 07890 /* Don't start streaming audio yet if the incoming call isn't up yet */ 07891 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 07892 p->dialing = 1; 07893 dahdi_ring_phone(p); 07894 } else if (p->subs[SUB_THREEWAY].owner) { 07895 unsigned int mssinceflash; 07896 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 07897 the private structure -- not especially easy or clean */ 07898 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 07899 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 07900 DLA_UNLOCK(&p->lock); 07901 CHANNEL_DEADLOCK_AVOIDANCE(ast); 07902 /* We can grab ast and p in that order, without worry. We should make sure 07903 nothing seriously bad has happened though like some sort of bizarre double 07904 masquerade! */ 07905 DLA_LOCK(&p->lock); 07906 if (p->owner != ast) { 07907 ast_log(LOG_WARNING, "This isn't good...\n"); 07908 return NULL; 07909 } 07910 } 07911 if (!p->subs[SUB_THREEWAY].owner) { 07912 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 07913 return NULL; 07914 } 07915 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 07916 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 07917 if (mssinceflash < MIN_MS_SINCE_FLASH) { 07918 /* It hasn't been long enough since the last flashook. This is probably a bounce on 07919 hanging up. Hangup both channels now */ 07920 if (p->subs[SUB_THREEWAY].owner) 07921 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 07922 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07923 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 07924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07925 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 07926 if (p->transfer) { 07927 /* In any case this isn't a threeway call anymore */ 07928 p->subs[SUB_REAL].inthreeway = 0; 07929 p->subs[SUB_THREEWAY].inthreeway = 0; 07930 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 07931 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 07932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07933 /* Swap subs and dis-own channel */ 07934 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07935 p->owner = NULL; 07936 /* Ring the phone */ 07937 dahdi_ring_phone(p); 07938 } else { 07939 if ((res = attempt_transfer(p)) < 0) { 07940 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07941 if (p->subs[SUB_THREEWAY].owner) 07942 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07943 } else if (res) { 07944 /* Don't actually hang up at this point */ 07945 if (p->subs[SUB_THREEWAY].owner) 07946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07947 break; 07948 } 07949 } 07950 } else { 07951 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 07952 if (p->subs[SUB_THREEWAY].owner) 07953 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07954 } 07955 } else { 07956 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 07957 /* Swap subs and dis-own channel */ 07958 swap_subs(p, SUB_THREEWAY, SUB_REAL); 07959 p->owner = NULL; 07960 /* Ring the phone */ 07961 dahdi_ring_phone(p); 07962 } 07963 } 07964 } else { 07965 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 07966 } 07967 /* Fall through */ 07968 default: 07969 dahdi_disable_ec(p); 07970 return NULL; 07971 } 07972 break; 07973 case DAHDI_EVENT_RINGOFFHOOK: 07974 if (p->inalarm) break; 07975 if (p->oprmode < 0) 07976 { 07977 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 07978 { 07979 /* Make sure it stops ringing */ 07980 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 07981 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 07982 restore_conference(p->oprpeer); 07983 } 07984 break; 07985 } 07986 if (p->radio) 07987 { 07988 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 07989 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 07990 break; 07991 } 07992 /* for E911, its supposed to wait for offhook then dial 07993 the second half of the dial string */ 07994 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 07995 c = strchr(p->dialdest, '/'); 07996 if (c) 07997 c++; 07998 else 07999 c = p->dialdest; 08000 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 08001 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 08002 if (strlen(p->dop.dialstr) > 4) { 08003 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 08004 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 08005 p->echorest[sizeof(p->echorest) - 1] = '\0'; 08006 p->echobreak = 1; 08007 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 08008 } else 08009 p->echobreak = 0; 08010 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 08011 int saveerr = errno; 08012 08013 x = DAHDI_ONHOOK; 08014 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 08015 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 08016 return NULL; 08017 } 08018 p->dialing = 1; 08019 return &p->subs[idx].f; 08020 } 08021 switch (p->sig) { 08022 case SIG_FXOLS: 08023 case SIG_FXOGS: 08024 case SIG_FXOKS: 08025 switch (ast->_state) { 08026 case AST_STATE_RINGING: 08027 dahdi_enable_ec(p); 08028 dahdi_train_ec(p); 08029 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08030 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08031 /* Make sure it stops ringing */ 08032 p->subs[SUB_REAL].needringing = 0; 08033 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08034 ast_debug(1, "channel %d answered\n", p->channel); 08035 08036 /* Cancel any running CallerID spill */ 08037 ast_free(p->cidspill); 08038 p->cidspill = NULL; 08039 restore_conference(p); 08040 08041 p->dialing = 0; 08042 p->callwaitcas = 0; 08043 if (p->confirmanswer) { 08044 /* Ignore answer if "confirm answer" is enabled */ 08045 p->subs[idx].f.frametype = AST_FRAME_NULL; 08046 p->subs[idx].f.subclass.integer = 0; 08047 } else if (!ast_strlen_zero(p->dop.dialstr)) { 08048 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 08049 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08050 if (res < 0) { 08051 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08052 p->dop.dialstr[0] = '\0'; 08053 return NULL; 08054 } else { 08055 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 08056 p->subs[idx].f.frametype = AST_FRAME_NULL; 08057 p->subs[idx].f.subclass.integer = 0; 08058 p->dialing = 1; 08059 } 08060 p->dop.dialstr[0] = '\0'; 08061 ast_setstate(ast, AST_STATE_DIALING); 08062 } else 08063 ast_setstate(ast, AST_STATE_UP); 08064 return &p->subs[idx].f; 08065 case AST_STATE_DOWN: 08066 ast_setstate(ast, AST_STATE_RING); 08067 ast->rings = 1; 08068 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08069 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK; 08070 ast_debug(1, "channel %d picked up\n", p->channel); 08071 return &p->subs[idx].f; 08072 case AST_STATE_UP: 08073 /* Make sure it stops ringing */ 08074 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 08075 /* Okay -- probably call waiting*/ 08076 if (ast_bridged_channel(p->owner)) 08077 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08078 p->subs[idx].needunhold = 1; 08079 break; 08080 case AST_STATE_RESERVED: 08081 /* Start up dialtone */ 08082 if (has_voicemail(p)) 08083 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08084 else 08085 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08086 break; 08087 default: 08088 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 08089 } 08090 break; 08091 case SIG_FXSLS: 08092 case SIG_FXSGS: 08093 case SIG_FXSKS: 08094 if (ast->_state == AST_STATE_RING) { 08095 p->ringt = p->ringt_base; 08096 } 08097 08098 /* If we get a ring then we cannot be in 08099 * reversed polarity. So we reset to idle */ 08100 ast_debug(1, "Setting IDLE polarity due " 08101 "to ring. Old polarity was %d\n", 08102 p->polarity); 08103 p->polarity = POLARITY_IDLE; 08104 08105 /* Fall through */ 08106 case SIG_EM: 08107 case SIG_EM_E1: 08108 case SIG_EMWINK: 08109 case SIG_FEATD: 08110 case SIG_FEATDMF: 08111 case SIG_FEATDMF_TA: 08112 case SIG_E911: 08113 case SIG_FGC_CAMA: 08114 case SIG_FGC_CAMAMF: 08115 case SIG_FEATB: 08116 case SIG_SF: 08117 case SIG_SFWINK: 08118 case SIG_SF_FEATD: 08119 case SIG_SF_FEATDMF: 08120 case SIG_SF_FEATB: 08121 if (ast->_state == AST_STATE_PRERING) 08122 ast_setstate(ast, AST_STATE_RING); 08123 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 08124 ast_debug(1, "Ring detected\n"); 08125 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08126 p->subs[idx].f.subclass.integer = AST_CONTROL_RING; 08127 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 08128 ast_debug(1, "Line answered\n"); 08129 if (p->confirmanswer) { 08130 p->subs[idx].f.frametype = AST_FRAME_NULL; 08131 p->subs[idx].f.subclass.integer = 0; 08132 } else { 08133 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08134 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08135 ast_setstate(ast, AST_STATE_UP); 08136 } 08137 } else if (ast->_state != AST_STATE_RING) 08138 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 08139 break; 08140 default: 08141 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08142 } 08143 break; 08144 case DAHDI_EVENT_RINGBEGIN: 08145 switch (p->sig) { 08146 case SIG_FXSLS: 08147 case SIG_FXSGS: 08148 case SIG_FXSKS: 08149 if (ast->_state == AST_STATE_RING) { 08150 p->ringt = p->ringt_base; 08151 } 08152 break; 08153 } 08154 break; 08155 case DAHDI_EVENT_RINGERON: 08156 break; 08157 case DAHDI_EVENT_NOALARM: 08158 switch (p->sig) { 08159 #if defined(HAVE_PRI) 08160 case SIG_PRI_LIB_HANDLE_CASES: 08161 sig_pri_chan_alarm_notify(p->sig_pvt, 1); 08162 break; 08163 #endif /* defined(HAVE_PRI) */ 08164 #if defined(HAVE_SS7) 08165 case SIG_SS7: 08166 sig_ss7_set_alarm(p->sig_pvt, 0); 08167 break; 08168 #endif /* defined(HAVE_SS7) */ 08169 default: 08170 p->inalarm = 0; 08171 break; 08172 } 08173 handle_clear_alarms(p); 08174 break; 08175 case DAHDI_EVENT_WINKFLASH: 08176 if (p->inalarm) break; 08177 if (p->radio) break; 08178 if (p->oprmode < 0) break; 08179 if (p->oprmode > 1) 08180 { 08181 struct dahdi_params par; 08182 08183 memset(&par, 0, sizeof(par)); 08184 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 08185 { 08186 if (!par.rxisoffhook) 08187 { 08188 /* Make sure it stops ringing */ 08189 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 08190 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 08191 save_conference(p); 08192 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08193 } 08194 } 08195 break; 08196 } 08197 /* Remember last time we got a flash-hook */ 08198 p->flashtime = ast_tvnow(); 08199 switch (mysig) { 08200 case SIG_FXOLS: 08201 case SIG_FXOGS: 08202 case SIG_FXOKS: 08203 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 08204 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 08205 08206 /* Cancel any running CallerID spill */ 08207 ast_free(p->cidspill); 08208 p->cidspill = NULL; 08209 restore_conference(p); 08210 p->callwaitcas = 0; 08211 08212 if (idx != SUB_REAL) { 08213 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 08214 goto winkflashdone; 08215 } 08216 08217 if (p->subs[SUB_CALLWAIT].owner) { 08218 /* Swap to call-wait */ 08219 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 08220 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 08221 p->owner = p->subs[SUB_REAL].owner; 08222 ast_debug(1, "Making %s the new owner\n", p->owner->name); 08223 if (p->owner->_state == AST_STATE_RINGING) { 08224 ast_setstate(p->owner, AST_STATE_UP); 08225 p->subs[SUB_REAL].needanswer = 1; 08226 } 08227 p->callwaitingrepeat = 0; 08228 p->cidcwexpire = 0; 08229 p->cid_suppress_expire = 0; 08230 /* Start music on hold if appropriate */ 08231 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 08232 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 08233 S_OR(p->mohsuggest, NULL), 08234 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08235 } 08236 p->subs[SUB_CALLWAIT].needhold = 1; 08237 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 08238 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 08239 S_OR(p->mohsuggest, NULL), 08240 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08241 } 08242 p->subs[SUB_REAL].needunhold = 1; 08243 } else if (!p->subs[SUB_THREEWAY].owner) { 08244 if (!p->threewaycalling) { 08245 /* Just send a flash if no 3-way calling */ 08246 p->subs[SUB_REAL].needflash = 1; 08247 goto winkflashdone; 08248 } else if (!check_for_conference(p)) { 08249 char cid_num[256]; 08250 char cid_name[256]; 08251 08252 cid_num[0] = 0; 08253 cid_name[0] = 0; 08254 if (p->dahditrcallerid && p->owner) { 08255 if (p->owner->caller.id.number.valid 08256 && p->owner->caller.id.number.str) { 08257 ast_copy_string(cid_num, p->owner->caller.id.number.str, 08258 sizeof(cid_num)); 08259 } 08260 if (p->owner->caller.id.name.valid 08261 && p->owner->caller.id.name.str) { 08262 ast_copy_string(cid_name, p->owner->caller.id.name.str, 08263 sizeof(cid_name)); 08264 } 08265 } 08266 /* XXX This section needs much more error checking!!! XXX */ 08267 /* Start a 3-way call if feasible */ 08268 if (!((ast->pbx) || 08269 (ast->_state == AST_STATE_UP) || 08270 (ast->_state == AST_STATE_RING))) { 08271 ast_debug(1, "Flash when call not up or ringing\n"); 08272 goto winkflashdone; 08273 } 08274 if (alloc_sub(p, SUB_THREEWAY)) { 08275 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 08276 goto winkflashdone; 08277 } 08278 /* Make new channel */ 08279 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL); 08280 if (p->dahditrcallerid) { 08281 if (!p->origcid_num) 08282 p->origcid_num = ast_strdup(p->cid_num); 08283 if (!p->origcid_name) 08284 p->origcid_name = ast_strdup(p->cid_name); 08285 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 08286 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 08287 } 08288 /* Swap things around between the three-way and real call */ 08289 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08290 /* Disable echo canceller for better dialing */ 08291 dahdi_disable_ec(p); 08292 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 08293 if (res) 08294 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 08295 p->owner = chan; 08296 if (!chan) { 08297 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 08298 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 08299 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 08300 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08301 dahdi_enable_ec(p); 08302 ast_hangup(chan); 08303 } else { 08304 ast_verb(3, "Started three way call on channel %d\n", p->channel); 08305 08306 /* Start music on hold if appropriate */ 08307 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08308 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 08309 S_OR(p->mohsuggest, NULL), 08310 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08311 } 08312 p->subs[SUB_THREEWAY].needhold = 1; 08313 } 08314 } 08315 } else { 08316 /* Already have a 3 way call */ 08317 if (p->subs[SUB_THREEWAY].inthreeway) { 08318 /* Call is already up, drop the last person */ 08319 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 08320 /* If the primary call isn't answered yet, use it */ 08321 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 08322 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 08323 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08324 p->owner = p->subs[SUB_REAL].owner; 08325 } 08326 /* Drop the last call and stop the conference */ 08327 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 08328 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08329 p->subs[SUB_REAL].inthreeway = 0; 08330 p->subs[SUB_THREEWAY].inthreeway = 0; 08331 } else { 08332 /* Lets see what we're up to */ 08333 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 08334 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 08335 int otherindex = SUB_THREEWAY; 08336 08337 ast_verb(3, "Building conference call with %s and %s\n", 08338 p->subs[SUB_THREEWAY].owner->name, 08339 p->subs[SUB_REAL].owner->name); 08340 /* Put them in the threeway, and flip */ 08341 p->subs[SUB_THREEWAY].inthreeway = 1; 08342 p->subs[SUB_REAL].inthreeway = 1; 08343 if (ast->_state == AST_STATE_UP) { 08344 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08345 otherindex = SUB_REAL; 08346 } 08347 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 08348 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 08349 p->subs[otherindex].needunhold = 1; 08350 p->owner = p->subs[SUB_REAL].owner; 08351 } else { 08352 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 08353 swap_subs(p, SUB_THREEWAY, SUB_REAL); 08354 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 08355 p->owner = p->subs[SUB_REAL].owner; 08356 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 08357 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08358 p->subs[SUB_REAL].needunhold = 1; 08359 dahdi_enable_ec(p); 08360 } 08361 } 08362 } 08363 winkflashdone: 08364 update_conf(p); 08365 break; 08366 case SIG_EM: 08367 case SIG_EM_E1: 08368 case SIG_FEATD: 08369 case SIG_SF: 08370 case SIG_SFWINK: 08371 case SIG_SF_FEATD: 08372 case SIG_FXSLS: 08373 case SIG_FXSGS: 08374 if (p->dialing) 08375 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 08376 else 08377 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 08378 break; 08379 case SIG_FEATDMF_TA: 08380 switch (p->whichwink) { 08381 case 0: 08382 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2, 08383 S_COR(p->owner->caller.ani.number.valid, 08384 p->owner->caller.ani.number.str, "")); 08385 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", 08386 p->owner->caller.ani2, 08387 S_COR(p->owner->caller.ani.number.valid, 08388 p->owner->caller.ani.number.str, "")); 08389 break; 08390 case 1: 08391 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 08392 break; 08393 case 2: 08394 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 08395 return NULL; 08396 } 08397 p->whichwink++; 08398 /* Fall through */ 08399 case SIG_FEATDMF: 08400 case SIG_E911: 08401 case SIG_FGC_CAMAMF: 08402 case SIG_FGC_CAMA: 08403 case SIG_FEATB: 08404 case SIG_SF_FEATDMF: 08405 case SIG_SF_FEATB: 08406 case SIG_EMWINK: 08407 /* FGD MF and EMWINK *Must* wait for wink */ 08408 if (!ast_strlen_zero(p->dop.dialstr)) { 08409 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08410 if (res < 0) { 08411 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08412 p->dop.dialstr[0] = '\0'; 08413 return NULL; 08414 } else 08415 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08416 } 08417 p->dop.dialstr[0] = '\0'; 08418 break; 08419 default: 08420 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 08421 } 08422 break; 08423 case DAHDI_EVENT_HOOKCOMPLETE: 08424 if (p->inalarm) break; 08425 if ((p->radio || (p->oprmode < 0))) break; 08426 if (p->waitingfordt.tv_sec) break; 08427 switch (mysig) { 08428 case SIG_FXSLS: /* only interesting for FXS */ 08429 case SIG_FXSGS: 08430 case SIG_FXSKS: 08431 case SIG_EM: 08432 case SIG_EM_E1: 08433 case SIG_EMWINK: 08434 case SIG_FEATD: 08435 case SIG_SF: 08436 case SIG_SFWINK: 08437 case SIG_SF_FEATD: 08438 if (!ast_strlen_zero(p->dop.dialstr)) { 08439 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08440 if (res < 0) { 08441 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 08442 p->dop.dialstr[0] = '\0'; 08443 return NULL; 08444 } else 08445 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 08446 } 08447 p->dop.dialstr[0] = '\0'; 08448 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08449 break; 08450 case SIG_FEATDMF: 08451 case SIG_FEATDMF_TA: 08452 case SIG_E911: 08453 case SIG_FGC_CAMA: 08454 case SIG_FGC_CAMAMF: 08455 case SIG_FEATB: 08456 case SIG_SF_FEATDMF: 08457 case SIG_SF_FEATB: 08458 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 08459 break; 08460 default: 08461 break; 08462 } 08463 break; 08464 case DAHDI_EVENT_POLARITY: 08465 /* 08466 * If we get a Polarity Switch event, check to see 08467 * if we should change the polarity state and 08468 * mark the channel as UP or if this is an indication 08469 * of remote end disconnect. 08470 */ 08471 if (p->polarity == POLARITY_IDLE) { 08472 p->polarity = POLARITY_REV; 08473 if (p->answeronpolarityswitch && 08474 ((ast->_state == AST_STATE_DIALING) || 08475 (ast->_state == AST_STATE_RINGING))) { 08476 ast_debug(1, "Answering on polarity switch!\n"); 08477 ast_setstate(p->owner, AST_STATE_UP); 08478 if (p->hanguponpolarityswitch) { 08479 p->polaritydelaytv = ast_tvnow(); 08480 } 08481 } else 08482 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 08483 } 08484 /* Removed else statement from here as it was preventing hangups from ever happening*/ 08485 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 08486 if (p->hanguponpolarityswitch && 08487 (p->polarityonanswerdelay > 0) && 08488 (p->polarity == POLARITY_REV) && 08489 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 08490 /* Added log_debug information below to provide a better indication of what is going on */ 08491 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) ); 08492 08493 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 08494 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 08495 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 08496 p->polarity = POLARITY_IDLE; 08497 } else 08498 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); 08499 08500 } else { 08501 p->polarity = POLARITY_IDLE; 08502 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 08503 } 08504 /* Added more log_debug information below to provide a better indication of what is going on */ 08505 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) ); 08506 break; 08507 default: 08508 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 08509 } 08510 return &p->subs[idx].f; 08511 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6004 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.
06005 { 06006 int res = 0; 06007 int idx,x; 06008 int law; 06009 /*static int restore_gains(struct dahdi_pvt *p);*/ 06010 struct dahdi_pvt *p = ast->tech_pvt; 06011 struct dahdi_params par; 06012 06013 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 06014 if (!ast->tech_pvt) { 06015 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 06016 return 0; 06017 } 06018 06019 ast_mutex_lock(&p->lock); 06020 p->exten[0] = '\0'; 06021 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 06022 dahdi_confmute(p, 0); 06023 restore_gains(p); 06024 p->ignoredtmf = 0; 06025 p->waitingfordt.tv_sec = 0; 06026 06027 res = analog_hangup(p->sig_pvt, ast); 06028 revert_fax_buffers(p, ast); 06029 06030 goto hangup_out; 06031 } else { 06032 p->cid_num[0] = '\0'; 06033 p->cid_name[0] = '\0'; 06034 p->cid_subaddr[0] = '\0'; 06035 } 06036 06037 #ifdef HAVE_PRI 06038 if (dahdi_sig_pri_lib_handles(p->sig)) { 06039 x = 1; 06040 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06041 dahdi_confmute(p, 0); 06042 p->muting = 0; 06043 restore_gains(p); 06044 if (p->dsp) { 06045 ast_dsp_free(p->dsp); 06046 p->dsp = NULL; 06047 } 06048 p->ignoredtmf = 0; 06049 revert_fax_buffers(p, ast); 06050 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06051 p->law = p->law_default; 06052 law = p->law_default; 06053 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06054 dahdi_disable_ec(p); 06055 update_conf(p); 06056 reset_conf(p); 06057 sig_pri_hangup(p->sig_pvt, ast); 06058 p->subs[SUB_REAL].owner = NULL; 06059 p->subs[SUB_REAL].needbusy = 0; 06060 p->owner = NULL; 06061 p->cid_tag[0] = '\0'; 06062 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06063 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06064 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06065 p->outgoing = 0; 06066 p->digital = 0; 06067 p->faxhandled = 0; 06068 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06069 goto hangup_out; 06070 } 06071 #endif 06072 06073 #if defined(HAVE_SS7) 06074 if (p->sig == SIG_SS7) { 06075 x = 1; 06076 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06077 06078 dahdi_confmute(p, 0); 06079 p->muting = 0; 06080 restore_gains(p); 06081 if (p->dsp) { 06082 ast_dsp_free(p->dsp); 06083 p->dsp = NULL; 06084 } 06085 p->ignoredtmf = 0; 06086 06087 /* Real channel, do some fixup */ 06088 p->subs[SUB_REAL].owner = NULL; 06089 p->subs[SUB_REAL].needbusy = 0; 06090 p->polarity = POLARITY_IDLE; 06091 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 06092 06093 p->owner = NULL; 06094 p->ringt = 0;/* Probably not used in this mode. Reset anyway. */ 06095 p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */ 06096 p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */ 06097 p->outgoing = 0; 06098 p->digital = 0; 06099 p->faxhandled = 0; 06100 p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */ 06101 06102 revert_fax_buffers(p, ast); 06103 06104 p->law = p->law_default; 06105 law = p->law_default; 06106 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06107 if (res < 0) 06108 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06109 06110 sig_ss7_hangup(p->sig_pvt, ast); 06111 06112 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06113 dahdi_disable_ec(p); 06114 x = 0; 06115 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06116 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06117 p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */ 06118 update_conf(p); 06119 reset_conf(p); 06120 06121 /* Restore data mode */ 06122 x = 0; 06123 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06124 06125 if (num_restart_pending == 0) 06126 restart_monitor(); 06127 06128 ast->tech_pvt = NULL; 06129 goto hangup_out; 06130 } 06131 #endif /* defined(HAVE_SS7) */ 06132 06133 idx = dahdi_get_index(ast, p, 1); 06134 06135 dahdi_confmute(p, 0); 06136 p->muting = 0; 06137 restore_gains(p); 06138 if (p->origcid_num) { 06139 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 06140 ast_free(p->origcid_num); 06141 p->origcid_num = NULL; 06142 } 06143 if (p->origcid_name) { 06144 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 06145 ast_free(p->origcid_name); 06146 p->origcid_name = NULL; 06147 } 06148 if (p->dsp) 06149 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06150 06151 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 06152 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06153 p->ignoredtmf = 0; 06154 06155 if (idx > -1) { 06156 /* Real channel, do some fixup */ 06157 p->subs[idx].owner = NULL; 06158 p->subs[idx].needanswer = 0; 06159 p->subs[idx].needflash = 0; 06160 p->subs[idx].needringing = 0; 06161 p->subs[idx].needbusy = 0; 06162 p->subs[idx].needcongestion = 0; 06163 p->subs[idx].linear = 0; 06164 p->polarity = POLARITY_IDLE; 06165 dahdi_setlinear(p->subs[idx].dfd, 0); 06166 if (idx == SUB_REAL) { 06167 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 06168 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 06169 if (p->subs[SUB_CALLWAIT].inthreeway) { 06170 /* We had flipped over to answer a callwait and now it's gone */ 06171 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 06172 /* Move to the call-wait, but un-own us until they flip back. */ 06173 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06174 unalloc_sub(p, SUB_CALLWAIT); 06175 p->owner = NULL; 06176 } else { 06177 /* The three way hung up, but we still have a call wait */ 06178 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 06179 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06180 unalloc_sub(p, SUB_THREEWAY); 06181 if (p->subs[SUB_REAL].inthreeway) { 06182 /* This was part of a three way call. Immediately make way for 06183 another call */ 06184 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06185 p->owner = p->subs[SUB_REAL].owner; 06186 } else { 06187 /* This call hasn't been completed yet... Set owner to NULL */ 06188 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06189 p->owner = NULL; 06190 } 06191 p->subs[SUB_REAL].inthreeway = 0; 06192 } 06193 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 06194 /* Move to the call-wait and switch back to them. */ 06195 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 06196 unalloc_sub(p, SUB_CALLWAIT); 06197 p->owner = p->subs[SUB_REAL].owner; 06198 if (p->owner->_state != AST_STATE_UP) 06199 p->subs[SUB_REAL].needanswer = 1; 06200 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06201 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06202 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 06203 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06204 unalloc_sub(p, SUB_THREEWAY); 06205 if (p->subs[SUB_REAL].inthreeway) { 06206 /* This was part of a three way call. Immediately make way for 06207 another call */ 06208 ast_debug(1, "Call was complete, setting owner to former third call\n"); 06209 p->owner = p->subs[SUB_REAL].owner; 06210 } else { 06211 /* This call hasn't been completed yet... Set owner to NULL */ 06212 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 06213 p->owner = NULL; 06214 } 06215 p->subs[SUB_REAL].inthreeway = 0; 06216 } 06217 } else if (idx == SUB_CALLWAIT) { 06218 /* Ditch the holding callwait call, and immediately make it availabe */ 06219 if (p->subs[SUB_CALLWAIT].inthreeway) { 06220 /* This is actually part of a three way, placed on hold. Place the third part 06221 on music on hold now */ 06222 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06223 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06224 S_OR(p->mohsuggest, NULL), 06225 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06226 } 06227 p->subs[SUB_THREEWAY].inthreeway = 0; 06228 /* Make it the call wait now */ 06229 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06230 unalloc_sub(p, SUB_THREEWAY); 06231 } else 06232 unalloc_sub(p, SUB_CALLWAIT); 06233 } else if (idx == SUB_THREEWAY) { 06234 if (p->subs[SUB_CALLWAIT].inthreeway) { 06235 /* The other party of the three way call is currently in a call-wait state. 06236 Start music on hold for them, and take the main guy out of the third call */ 06237 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06238 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06239 S_OR(p->mohsuggest, NULL), 06240 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06241 } 06242 p->subs[SUB_CALLWAIT].inthreeway = 0; 06243 } 06244 p->subs[SUB_REAL].inthreeway = 0; 06245 /* If this was part of a three way call index, let us make 06246 another three way call */ 06247 unalloc_sub(p, SUB_THREEWAY); 06248 } else { 06249 /* This wasn't any sort of call, but how are we an index? */ 06250 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 06251 } 06252 } 06253 06254 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 06255 p->owner = NULL; 06256 p->ringt = 0; 06257 p->distinctivering = 0; 06258 p->confirmanswer = 0; 06259 p->outgoing = 0; 06260 p->digital = 0; 06261 p->faxhandled = 0; 06262 p->pulsedial = 0; 06263 if (p->dsp) { 06264 ast_dsp_free(p->dsp); 06265 p->dsp = NULL; 06266 } 06267 06268 revert_fax_buffers(p, ast); 06269 06270 p->law = p->law_default; 06271 law = p->law_default; 06272 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 06273 if (res < 0) 06274 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 06275 /* Perform low level hangup if no owner left */ 06276 #ifdef HAVE_OPENR2 06277 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 06278 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 06279 /* If it's an incoming call, check the mfcr2_forced_release setting */ 06280 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 06281 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 06282 } else { 06283 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 06284 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 06285 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 06286 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 06287 dahdi_r2_disconnect_call(p, r2cause); 06288 } 06289 } else if (p->mfcr2call) { 06290 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 06291 /* since ast_request() was called but not ast_call() we have not yet dialed 06292 and the openr2 stack will not call on_call_end callback, we need to unset 06293 the mfcr2call flag and bump the monitor count so the monitor thread can take 06294 care of this channel events from now on */ 06295 p->mfcr2call = 0; 06296 } 06297 #endif 06298 switch (p->sig) { 06299 case SIG_SS7: 06300 case SIG_MFCR2: 06301 case SIG_PRI_LIB_HANDLE_CASES: 06302 case 0: 06303 break; 06304 default: 06305 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06306 break; 06307 } 06308 if (res < 0) { 06309 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 06310 } 06311 switch (p->sig) { 06312 case SIG_FXOGS: 06313 case SIG_FXOLS: 06314 case SIG_FXOKS: 06315 memset(&par, 0, sizeof(par)); 06316 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 06317 if (!res) { 06318 struct analog_pvt *analog_p = p->sig_pvt; 06319 #if 0 06320 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 06321 #endif 06322 /* If they're off hook, try playing congestion */ 06323 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 06324 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06325 else 06326 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06327 analog_p->fxsoffhookstate = par.rxisoffhook; 06328 } 06329 break; 06330 case SIG_FXSGS: 06331 case SIG_FXSLS: 06332 case SIG_FXSKS: 06333 /* Make sure we're not made available for at least two seconds assuming 06334 we were actually used for an inbound or outbound call. */ 06335 if (ast->_state != AST_STATE_RESERVED) { 06336 time(&p->guardtime); 06337 p->guardtime += 2; 06338 } 06339 break; 06340 default: 06341 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06342 } 06343 if (p->sig) 06344 dahdi_disable_ec(p); 06345 x = 0; 06346 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 06347 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 06348 p->didtdd = 0; 06349 p->callwaitcas = 0; 06350 p->callwaiting = p->permcallwaiting; 06351 p->hidecallerid = p->permhidecallerid; 06352 p->waitingfordt.tv_sec = 0; 06353 p->dialing = 0; 06354 p->rdnis[0] = '\0'; 06355 update_conf(p); 06356 reset_conf(p); 06357 /* Restore data mode */ 06358 switch (p->sig) { 06359 case SIG_PRI_LIB_HANDLE_CASES: 06360 case SIG_SS7: 06361 x = 0; 06362 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 06363 break; 06364 default: 06365 break; 06366 } 06367 if (num_restart_pending == 0) 06368 restart_monitor(); 06369 } 06370 06371 p->callwaitingrepeat = 0; 06372 p->cidcwexpire = 0; 06373 p->cid_suppress_expire = 0; 06374 p->oprmode = 0; 06375 ast->tech_pvt = NULL; 06376 hangup_out: 06377 ast_free(p->cidspill); 06378 p->cidspill = NULL; 06379 06380 ast_mutex_unlock(&p->lock); 06381 ast_module_unref(ast_module_info->self); 06382 ast_verb(3, "Hungup '%s'\n", ast->name); 06383 06384 ast_mutex_lock(&iflock); 06385 06386 if (p->restartpending) { 06387 num_restart_pending--; 06388 } 06389 06390 if (p->destroy) { 06391 destroy_channel(p, 0); 06392 } 06393 ast_mutex_unlock(&iflock); 06394 return 0; 06395 }
static void dahdi_iflist_extract | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5405 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().
05406 { 05407 /* Extract from the forward chain. */ 05408 if (pvt->prev) { 05409 pvt->prev->next = pvt->next; 05410 } else if (iflist == pvt) { 05411 /* Node is at the head of the list. */ 05412 iflist = pvt->next; 05413 } 05414 05415 /* Extract from the reverse chain. */ 05416 if (pvt->next) { 05417 pvt->next->prev = pvt->prev; 05418 } else if (ifend == pvt) { 05419 /* Node is at the end of the list. */ 05420 ifend = pvt->prev; 05421 } 05422 05423 /* Node is no longer in the list. */ 05424 pvt->which_iflist = DAHDI_IFLIST_NONE; 05425 pvt->prev = NULL; 05426 pvt->next = NULL; 05427 }
static void dahdi_iflist_insert | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5355 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().
05356 { 05357 struct dahdi_pvt *cur; 05358 05359 pvt->which_iflist = DAHDI_IFLIST_MAIN; 05360 05361 /* Find place in middle of list for the new interface. */ 05362 for (cur = iflist; cur; cur = cur->next) { 05363 if (pvt->channel < cur->channel) { 05364 /* New interface goes before the current interface. */ 05365 pvt->prev = cur->prev; 05366 pvt->next = cur; 05367 if (cur->prev) { 05368 /* Insert into the middle of the list. */ 05369 cur->prev->next = pvt; 05370 } else { 05371 /* Insert at head of list. */ 05372 iflist = pvt; 05373 } 05374 cur->prev = pvt; 05375 return; 05376 } 05377 } 05378 05379 /* New interface goes onto the end of the list */ 05380 pvt->prev = ifend; 05381 pvt->next = NULL; 05382 if (ifend) { 05383 ifend->next = pvt; 05384 } 05385 ifend = pvt; 05386 if (!iflist) { 05387 /* List was empty */ 05388 iflist = pvt; 05389 } 05390 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 9127 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_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.
09128 { 09129 struct dahdi_pvt *p = chan->tech_pvt; 09130 int res=-1; 09131 int idx; 09132 int func = DAHDI_FLASH; 09133 09134 ast_mutex_lock(&p->lock); 09135 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 09136 switch (p->sig) { 09137 #if defined(HAVE_PRI) 09138 case SIG_PRI_LIB_HANDLE_CASES: 09139 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen); 09140 ast_mutex_unlock(&p->lock); 09141 return res; 09142 #endif /* defined(HAVE_PRI) */ 09143 #if defined(HAVE_SS7) 09144 case SIG_SS7: 09145 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen); 09146 ast_mutex_unlock(&p->lock); 09147 return res; 09148 #endif /* defined(HAVE_SS7) */ 09149 default: 09150 break; 09151 } 09152 #ifdef HAVE_OPENR2 09153 if (p->mfcr2 && !p->mfcr2_call_accepted) { 09154 ast_mutex_unlock(&p->lock); 09155 /* if this is an R2 call and the call is not yet accepted, we don't want the 09156 tone indications to mess up with the MF tones */ 09157 return 0; 09158 } 09159 #endif 09160 idx = dahdi_get_index(chan, p, 0); 09161 if (idx == SUB_REAL) { 09162 switch (condition) { 09163 case AST_CONTROL_BUSY: 09164 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 09165 break; 09166 case AST_CONTROL_RINGING: 09167 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 09168 09169 if (chan->_state != AST_STATE_UP) { 09170 if ((chan->_state != AST_STATE_RING) || 09171 ((p->sig != SIG_FXSKS) && 09172 (p->sig != SIG_FXSLS) && 09173 (p->sig != SIG_FXSGS))) 09174 ast_setstate(chan, AST_STATE_RINGING); 09175 } 09176 break; 09177 case AST_CONTROL_PROCEEDING: 09178 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 09179 /* don't continue in ast_indicate */ 09180 res = 0; 09181 break; 09182 case AST_CONTROL_PROGRESS: 09183 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 09184 /* don't continue in ast_indicate */ 09185 res = 0; 09186 break; 09187 case AST_CONTROL_CONGESTION: 09188 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 09189 switch (chan->hangupcause) { 09190 case AST_CAUSE_USER_BUSY: 09191 case AST_CAUSE_NORMAL_CLEARING: 09192 case 0:/* Cause has not been set. */ 09193 /* Supply a more appropriate cause. */ 09194 chan->hangupcause = AST_CAUSE_CONGESTION; 09195 break; 09196 default: 09197 break; 09198 } 09199 break; 09200 case AST_CONTROL_HOLD: 09201 ast_moh_start(chan, data, p->mohinterpret); 09202 break; 09203 case AST_CONTROL_UNHOLD: 09204 ast_moh_stop(chan); 09205 break; 09206 case AST_CONTROL_RADIO_KEY: 09207 if (p->radio) 09208 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 09209 res = 0; 09210 break; 09211 case AST_CONTROL_RADIO_UNKEY: 09212 if (p->radio) 09213 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 09214 res = 0; 09215 break; 09216 case AST_CONTROL_FLASH: 09217 /* flash hookswitch */ 09218 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 09219 /* Clear out the dial buffer */ 09220 p->dop.dialstr[0] = '\0'; 09221 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 09222 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 09223 chan->name, strerror(errno)); 09224 } else 09225 res = 0; 09226 } else 09227 res = 0; 09228 break; 09229 case AST_CONTROL_SRCUPDATE: 09230 res = 0; 09231 break; 09232 case -1: 09233 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 09234 break; 09235 } 09236 } else { 09237 res = 0; 09238 } 09239 ast_mutex_unlock(&p->lock); 09240 return res; 09241 }
Definition at line 6975 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and dahdi_pvt::slaves.
Referenced by dahdi_bridge().
06975 { 06976 int x; 06977 if (!slave || !master) { 06978 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 06979 return; 06980 } 06981 for (x = 0; x < MAX_SLAVES; x++) { 06982 if (!master->slaves[x]) { 06983 master->slaves[x] = slave; 06984 break; 06985 } 06986 } 06987 if (x >= MAX_SLAVES) { 06988 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 06989 master->slaves[MAX_SLAVES - 1] = slave; 06990 } 06991 if (slave->master) 06992 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 06993 slave->master = master; 06994 06995 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 06996 }
static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
int | sub_idx | |||
) | [static] |
Definition at line 3635 of file chan_dahdi.c.
References ast_channel_trylock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by wakeup_sub().
03636 { 03637 for (;;) { 03638 if (!pvt->subs[sub_idx].owner) { 03639 /* No subchannel owner pointer */ 03640 break; 03641 } 03642 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) { 03643 /* Got subchannel owner lock */ 03644 break; 03645 } 03646 /* We must unlock the private to avoid the possibility of a deadlock */ 03647 DEADLOCK_AVOIDANCE(&pvt->lock); 03648 } 03649 }
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 9291 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_set_fd(), ast_copy_string(), ast_debug, 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_chan2dev(), 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_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().
09292 { 09293 struct ast_channel *tmp; 09294 format_t deflaw; 09295 int x; 09296 int features; 09297 struct ast_str *chan_name; 09298 struct ast_variable *v; 09299 09300 if (i->subs[idx].owner) { 09301 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 09302 return NULL; 09303 } 09304 09305 #if defined(HAVE_PRI) 09306 /* 09307 * The dnid has been stuffed with the called-number[:subaddress] 09308 * by dahdi_request() for outgoing calls. 09309 */ 09310 chan_name = create_channel_name(i, i->outgoing, i->dnid); 09311 #else 09312 chan_name = create_channel_name(i); 09313 #endif /* defined(HAVE_PRI) */ 09314 if (!chan_name) { 09315 return NULL; 09316 } 09317 09318 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)); 09319 ast_free(chan_name); 09320 if (!tmp) 09321 return NULL; 09322 tmp->tech = &dahdi_tech; 09323 #if defined(HAVE_PRI) 09324 if (i->pri) { 09325 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params); 09326 } 09327 #endif /* defined(HAVE_PRI) */ 09328 ast_channel_cc_params_init(tmp, i->cc_params); 09329 if (law) { 09330 i->law = law; 09331 if (law == DAHDI_LAW_ALAW) { 09332 deflaw = AST_FORMAT_ALAW; 09333 } else { 09334 deflaw = AST_FORMAT_ULAW; 09335 } 09336 } else { 09337 switch (i->sig) { 09338 case SIG_PRI_LIB_HANDLE_CASES: 09339 /* Make sure companding law is known. */ 09340 i->law = (i->law_default == DAHDI_LAW_ALAW) 09341 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW; 09342 break; 09343 default: 09344 i->law = i->law_default; 09345 break; 09346 } 09347 if (i->law_default == DAHDI_LAW_ALAW) { 09348 deflaw = AST_FORMAT_ALAW; 09349 } else { 09350 deflaw = AST_FORMAT_ULAW; 09351 } 09352 } 09353 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 09354 tmp->nativeformats = deflaw; 09355 /* Start out assuming ulaw since it's smaller :) */ 09356 tmp->rawreadformat = deflaw; 09357 tmp->readformat = deflaw; 09358 tmp->rawwriteformat = deflaw; 09359 tmp->writeformat = deflaw; 09360 i->subs[idx].linear = 0; 09361 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 09362 features = 0; 09363 if (idx == SUB_REAL) { 09364 if (i->busydetect && CANBUSYDETECT(i)) 09365 features |= DSP_FEATURE_BUSY_DETECT; 09366 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 09367 features |= DSP_FEATURE_CALL_PROGRESS; 09368 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 09369 features |= DSP_FEATURE_WAITDIALTONE; 09370 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 09371 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 09372 features |= DSP_FEATURE_FAX_DETECT; 09373 } 09374 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 09375 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 09376 i->hardwaredtmf = 0; 09377 features |= DSP_FEATURE_DIGIT_DETECT; 09378 } else if (NEED_MFDETECT(i)) { 09379 i->hardwaredtmf = 1; 09380 features |= DSP_FEATURE_DIGIT_DETECT; 09381 } 09382 } 09383 if (features) { 09384 if (i->dsp) { 09385 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 09386 } else { 09387 if (i->channel != CHAN_PSEUDO) 09388 i->dsp = ast_dsp_new(); 09389 else 09390 i->dsp = NULL; 09391 if (i->dsp) { 09392 i->dsp_features = features; 09393 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09394 /* We cannot do progress detection until receive PROGRESS message */ 09395 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) { 09396 /* Remember requested DSP features, don't treat 09397 talking as ANSWER */ 09398 i->dsp_features = features & ~DSP_PROGRESS_TALK; 09399 features = 0; 09400 } 09401 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09402 ast_dsp_set_features(i->dsp, features); 09403 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 09404 if (!ast_strlen_zero(progzone)) 09405 ast_dsp_set_call_progress_zone(i->dsp, progzone); 09406 if (i->busydetect && CANBUSYDETECT(i)) { 09407 if(i->silencethreshold > 0) 09408 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 09409 ast_dsp_set_busy_count(i->dsp, i->busycount); 09410 if(i->busytonelength > 0) 09411 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 09412 if((i->busytonelength == i->busyquietlength) && i->busycompare) 09413 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 09414 } 09415 } 09416 } 09417 } 09418 09419 if (state == AST_STATE_RING) 09420 tmp->rings = 1; 09421 tmp->tech_pvt = i; 09422 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 09423 /* Only FXO signalled stuff can be picked up */ 09424 tmp->callgroup = i->callgroup; 09425 tmp->pickupgroup = i->pickupgroup; 09426 } 09427 if (!ast_strlen_zero(i->parkinglot)) 09428 ast_string_field_set(tmp, parkinglot, i->parkinglot); 09429 if (!ast_strlen_zero(i->language)) 09430 ast_string_field_set(tmp, language, i->language); 09431 if (!i->owner) 09432 i->owner = tmp; 09433 if (!ast_strlen_zero(i->accountcode)) 09434 ast_string_field_set(tmp, accountcode, i->accountcode); 09435 if (i->amaflags) 09436 tmp->amaflags = i->amaflags; 09437 i->subs[idx].owner = tmp; 09438 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 09439 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) { 09440 ast_string_field_set(tmp, call_forward, i->call_forward); 09441 } 09442 /* If we've been told "no ADSI" then enforce it */ 09443 if (!i->adsi) 09444 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 09445 if (!ast_strlen_zero(i->exten)) 09446 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 09447 if (!ast_strlen_zero(i->rdnis)) { 09448 tmp->redirecting.from.number.valid = 1; 09449 tmp->redirecting.from.number.str = ast_strdup(i->rdnis); 09450 } 09451 if (!ast_strlen_zero(i->dnid)) { 09452 tmp->dialed.number.str = ast_strdup(i->dnid); 09453 } 09454 09455 /* Don't use ast_set_callerid() here because it will 09456 * generate a needless NewCallerID event */ 09457 #if defined(HAVE_PRI) || defined(HAVE_SS7) 09458 if (!ast_strlen_zero(i->cid_ani)) { 09459 tmp->caller.ani.number.valid = 1; 09460 tmp->caller.ani.number.str = ast_strdup(i->cid_ani); 09461 } else if (!ast_strlen_zero(i->cid_num)) { 09462 tmp->caller.ani.number.valid = 1; 09463 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09464 } 09465 #else 09466 if (!ast_strlen_zero(i->cid_num)) { 09467 tmp->caller.ani.number.valid = 1; 09468 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 09469 } 09470 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 09471 tmp->caller.id.name.presentation = i->callingpres; 09472 tmp->caller.id.number.presentation = i->callingpres; 09473 tmp->caller.id.number.plan = i->cid_ton; 09474 tmp->caller.ani2 = i->cid_ani2; 09475 tmp->caller.id.tag = ast_strdup(i->cid_tag); 09476 /* clear the fake event in case we posted one before we had ast_channel */ 09477 i->fake_event = 0; 09478 /* Assure there is no confmute on this channel */ 09479 dahdi_confmute(i, 0); 09480 i->muting = 0; 09481 /* Configure the new channel jb */ 09482 ast_jb_configure(tmp, &global_jbconf); 09483 09484 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 09485 09486 for (v = i->vars ; v ; v = v->next) 09487 pbx_builtin_setvar_helper(tmp, v->name, v->value); 09488 09489 ast_module_ref(ast_module_info->self); 09490 09491 if (startpbx) { 09492 #ifdef HAVE_OPENR2 09493 if (i->mfcr2call) { 09494 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 09495 } 09496 #endif 09497 if (ast_pbx_start(tmp)) { 09498 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 09499 ast_hangup(tmp); 09500 return NULL; 09501 } 09502 } 09503 return tmp; 09504 }
static int dahdi_new_pri_nobch_channel | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 12938 of file chan_dahdi.c.
References CHAN_PSEUDO, sig_pri_span::numchans, and sig_pri_span::pvts.
12939 { 12940 int pvt_idx; 12941 int res; 12942 unsigned idx; 12943 struct dahdi_pvt *pvt; 12944 struct sig_pri_chan *chan; 12945 struct dahdi_bufferinfo bi; 12946 12947 static int nobch_channel = CHAN_PSEUDO; 12948 12949 /* Find spot in the private pointer array for new interface. */ 12950 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) { 12951 if (!pri->pvts[pvt_idx]) { 12952 break; 12953 } 12954 } 12955 if (pri->numchans == pvt_idx) { 12956 if (ARRAY_LEN(pri->pvts) <= pvt_idx) { 12957 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n"); 12958 return -1; 12959 } 12960 12961 /* Add new spot to the private pointer array. */ 12962 pri->pvts[pvt_idx] = NULL; 12963 ++pri->numchans; 12964 } 12965 12966 pvt = ast_calloc(1, sizeof(*pvt)); 12967 if (!pvt) { 12968 return -1; 12969 } 12970 pvt->cc_params = ast_cc_config_params_init(); 12971 if (!pvt->cc_params) { 12972 ast_free(pvt); 12973 return -1; 12974 } 12975 ast_mutex_init(&pvt->lock); 12976 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) { 12977 pvt->subs[idx].dfd = -1; 12978 } 12979 pvt->buf_no = dahdi_pseudo_parms.buf_no; 12980 pvt->buf_policy = dahdi_pseudo_parms.buf_policy; 12981 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no; 12982 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy; 12983 12984 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0); 12985 if (!chan) { 12986 destroy_dahdi_pvt(pvt); 12987 return -1; 12988 } 12989 chan->no_b_channel = 1; 12990 12991 /* 12992 * Pseudo channel companding law. 12993 * Needed for outgoing call waiting calls. 12994 * XXX May need to make this determined by switchtype or user option. 12995 */ 12996 pvt->law_default = DAHDI_LAW_ALAW; 12997 12998 pvt->sig = pri->sig; 12999 pvt->outsigmod = -1; 13000 pvt->pri = pri; 13001 pvt->sig_pvt = chan; 13002 pri->pvts[pvt_idx] = chan; 13003 13004 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13005 if (pvt->subs[SUB_REAL].dfd < 0) { 13006 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n", 13007 strerror(errno)); 13008 destroy_dahdi_pvt(pvt); 13009 return -1; 13010 } 13011 memset(&bi, 0, sizeof(bi)); 13012 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13013 if (!res) { 13014 pvt->bufsize = bi.bufsize; 13015 bi.txbufpolicy = pvt->buf_policy; 13016 bi.rxbufpolicy = pvt->buf_policy; 13017 bi.numbufs = pvt->buf_no; 13018 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13019 if (res < 0) { 13020 ast_log(LOG_WARNING, 13021 "Unable to set buffer policy on no B channel interface: %s\n", 13022 strerror(errno)); 13023 } 13024 } else 13025 ast_log(LOG_WARNING, 13026 "Unable to check buffer policy on no B channel interface: %s\n", 13027 strerror(errno)); 13028 13029 --nobch_channel; 13030 if (CHAN_PSEUDO < nobch_channel) { 13031 nobch_channel = CHAN_PSEUDO - 1; 13032 } 13033 pvt->channel = nobch_channel; 13034 chan->channel = pvt->channel; 13035 13036 dahdi_nobch_insert(pri, pvt); 13037 13038 return pvt_idx; 13039 }
static void dahdi_nobch_extract | ( | struct sig_pri_span * | pri, | |
struct dahdi_pvt * | pvt | |||
) | [static] |
Definition at line 5499 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().
05500 { 05501 /* Extract from the forward chain. */ 05502 if (pvt->prev) { 05503 pvt->prev->next = pvt->next; 05504 } else if (pri->no_b_chan_iflist == pvt) { 05505 /* Node is at the head of the list. */ 05506 pri->no_b_chan_iflist = pvt->next; 05507 } 05508 05509 /* Extract from the reverse chain. */ 05510 if (pvt->next) { 05511 pvt->next->prev = pvt->prev; 05512 } else if (pri->no_b_chan_end == pvt) { 05513 /* Node is at the end of the list. */ 05514 pri->no_b_chan_end = pvt->prev; 05515 } 05516 05517 /* Node is no longer in the list. */ 05518 pvt->which_iflist = DAHDI_IFLIST_NONE; 05519 pvt->prev = NULL; 05520 pvt->next = NULL; 05521 }
static void dahdi_nobch_insert | ( | struct sig_pri_span * | pri, | |
struct dahdi_pvt * | pvt | |||
) | [static] |
Definition at line 5446 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.
05447 { 05448 struct dahdi_pvt *cur; 05449 05450 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN; 05451 05452 /* Find place in middle of list for the new interface. */ 05453 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) { 05454 if (pvt->channel < cur->channel) { 05455 /* New interface goes before the current interface. */ 05456 pvt->prev = cur->prev; 05457 pvt->next = cur; 05458 if (cur->prev) { 05459 /* Insert into the middle of the list. */ 05460 cur->prev->next = pvt; 05461 } else { 05462 /* Insert at head of list. */ 05463 pri->no_b_chan_iflist = pvt; 05464 } 05465 cur->prev = pvt; 05466 return; 05467 } 05468 } 05469 05470 /* New interface goes onto the end of the list */ 05471 pvt->prev = pri->no_b_chan_end; 05472 pvt->next = NULL; 05473 if (pri->no_b_chan_end) { 05474 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt; 05475 } 05476 pri->no_b_chan_end = pvt; 05477 if (!pri->no_b_chan_iflist) { 05478 /* List was empty */ 05479 pri->no_b_chan_iflist = pvt; 05480 } 05481 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 4166 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), and duplicate_pseudo().
04167 { 04168 int fd; 04169 int isnum; 04170 int chan = 0; 04171 int bs; 04172 int x; 04173 isnum = 1; 04174 for (x = 0; x < strlen(fn); x++) { 04175 if (!isdigit(fn[x])) { 04176 isnum = 0; 04177 break; 04178 } 04179 } 04180 if (isnum) { 04181 chan = atoi(fn); 04182 if (chan < 1) { 04183 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 04184 return -1; 04185 } 04186 fn = "/dev/dahdi/channel"; 04187 } 04188 fd = open(fn, O_RDWR | O_NONBLOCK); 04189 if (fd < 0) { 04190 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 04191 return -1; 04192 } 04193 if (chan) { 04194 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 04195 x = errno; 04196 close(fd); 04197 errno = x; 04198 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 04199 return -1; 04200 } 04201 } 04202 bs = READ_SIZE; 04203 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 04204 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 04205 x = errno; 04206 close(fd); 04207 errno = x; 04208 return -1; 04209 } 04210 return fd; 04211 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 13734 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, errno, pridebugfd, pridebugfdlock, and pris.
Referenced by load_module().
13735 { 13736 int x, y; 13737 int dchan = -1, span = -1; 13738 int dchancount = 0; 13739 13740 if (pri) { 13741 for (x = 0; x < NUM_SPANS; x++) { 13742 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 13743 if (pris[x].pri.dchans[y]) 13744 dchancount++; 13745 13746 if (pris[x].pri.dchans[y] == pri) 13747 dchan = y; 13748 } 13749 if (dchan >= 0) { 13750 span = x; 13751 break; 13752 } 13753 dchancount = 0; 13754 } 13755 if ((dchancount > 1) && (span > -1)) 13756 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 13757 else if (span > -1) 13758 ast_log(LOG_ERROR, "%d %s", span+1, s); 13759 else 13760 ast_log(LOG_ERROR, "%s", s); 13761 } else 13762 ast_log(LOG_ERROR, "%s", s); 13763 13764 ast_mutex_lock(&pridebugfdlock); 13765 13766 if (pridebugfd >= 0) { 13767 if (write(pridebugfd, s, strlen(s)) < 0) { 13768 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 13769 } 13770 } 13771 13772 ast_mutex_unlock(&pridebugfdlock); 13773 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 13692 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose, errno, pridebugfd, pridebugfdlock, and pris.
Referenced by load_module().
13693 { 13694 int x, y; 13695 int dchan = -1, span = -1, dchancount = 0; 13696 13697 if (pri) { 13698 for (x = 0; x < NUM_SPANS; x++) { 13699 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 13700 if (pris[x].pri.dchans[y]) 13701 dchancount++; 13702 13703 if (pris[x].pri.dchans[y] == pri) 13704 dchan = y; 13705 } 13706 if (dchan >= 0) { 13707 span = x; 13708 break; 13709 } 13710 dchancount = 0; 13711 } 13712 if (dchancount > 1 && (span > -1)) 13713 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 13714 else if (span > -1) 13715 ast_verbose("%d %s", span+1, s); 13716 else 13717 ast_verbose("%s", s); 13718 } else 13719 ast_verbose("%s", s); 13720 13721 ast_mutex_lock(&pridebugfdlock); 13722 13723 if (pridebugfd >= 0) { 13724 if (write(pridebugfd, s, strlen(s)) < 0) { 13725 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 13726 } 13727 } 13728 13729 ast_mutex_unlock(&pridebugfdlock); 13730 }
static void dahdi_pri_update_span_devstate | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 3174 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, HAVE_PRI_SERVICE_MESSAGES, sig_pri_chan::inalarm, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::owner, dahdi_pvt::pri, sig_pri_span::pvts, sig_pri_chan::service_status, and sig_pri_span::span.
03175 { 03176 unsigned idx; 03177 unsigned num_b_chans; /* Number of B channels provisioned on the span. */ 03178 unsigned in_use; /* Number of B channels in use on the span. */ 03179 unsigned in_alarm; /* TRUE if the span is in alarm condition. */ 03180 enum ast_device_state new_state; 03181 03182 /* Count the number of B channels and the number of B channels in use. */ 03183 num_b_chans = 0; 03184 in_use = 0; 03185 in_alarm = 1; 03186 for (idx = pri->numchans; idx--;) { 03187 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) { 03188 /* This is a B channel interface. */ 03189 ++num_b_chans; 03190 if (pri->pvts[idx]->owner 03191 #if defined(HAVE_PRI_SERVICE_MESSAGES) 03192 /* Out-of-service B channels are "in-use". */ 03193 || pri->pvts[idx]->service_status 03194 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 03195 ) { 03196 ++in_use; 03197 } 03198 if (!pri->pvts[idx]->inalarm) { 03199 /* There is a channel that is not in alarm. */ 03200 in_alarm = 0; 03201 } 03202 } 03203 } 03204 03205 /* Update the span congestion device state and report any change. */ 03206 if (in_alarm) { 03207 new_state = AST_DEVICE_UNAVAILABLE; 03208 } else { 03209 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE; 03210 } 03211 if (pri->congestion_devstate != new_state) { 03212 pri->congestion_devstate = new_state; 03213 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span); 03214 } 03215 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) 03216 /* Update the span threshold device state and report any change. */ 03217 if (in_alarm) { 03218 new_state = AST_DEVICE_UNAVAILABLE; 03219 } else if (!in_use) { 03220 new_state = AST_DEVICE_NOT_INUSE; 03221 } else if (!pri->user_busy_threshold) { 03222 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY; 03223 } else { 03224 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE 03225 : AST_DEVICE_BUSY; 03226 } 03227 if (pri->threshold_devstate != new_state) { 03228 pri->threshold_devstate = new_state; 03229 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span); 03230 } 03231 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ 03232 }
static int dahdi_queryoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int * | datalen | |||
) | [static] |
Definition at line 6492 of file chan_dahdi.c.
References ast_copy_string(), ast_debug, AST_OPTION_CC_AGENT_TYPE, AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, dahdi_sig_pri_lib_handles(), DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, errno, dahdi_pvt::ignoredtmf, ast_channel::name, dahdi_pvt::sig, and ast_channel::tech_pvt.
06493 { 06494 char *cp; 06495 struct dahdi_pvt *p = chan->tech_pvt; 06496 06497 /* all supported options require data */ 06498 if (!data || (*datalen < 1)) { 06499 errno = EINVAL; 06500 return -1; 06501 } 06502 06503 switch (option) { 06504 case AST_OPTION_DIGIT_DETECT: 06505 cp = (char *) data; 06506 *cp = p->ignoredtmf ? 0 : 1; 06507 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06508 break; 06509 case AST_OPTION_FAX_DETECT: 06510 cp = (char *) data; 06511 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1; 06512 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name); 06513 break; 06514 case AST_OPTION_CC_AGENT_TYPE: 06515 #if defined(HAVE_PRI) 06516 #if defined(HAVE_PRI_CCSS) 06517 if (dahdi_sig_pri_lib_handles(p->sig)) { 06518 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen); 06519 break; 06520 } 06521 #endif /* defined(HAVE_PRI_CCSS) */ 06522 #endif /* defined(HAVE_PRI) */ 06523 return -1; 06524 default: 06525 return -1; 06526 } 06527 06528 errno = 0; 06529 06530 return 0; 06531 }
Definition at line 3660 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().
03661 { 03662 for (;;) { 03663 if (p->owner) { 03664 if (ast_channel_trylock(p->owner)) { 03665 DEADLOCK_AVOIDANCE(&p->lock); 03666 } else { 03667 ast_queue_frame(p->owner, f); 03668 ast_channel_unlock(p->owner); 03669 break; 03670 } 03671 } else 03672 break; 03673 } 03674 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 4121 of file chan_dahdi.c.
References AST_ALAW.
04122 { 04123 return AST_ALAW(sample); 04124 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3690 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().
03691 { 03692 int res = 0; 03693 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 03694 * and does not has support for openr2_chan_answer_call_with_mode 03695 * */ 03696 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 03697 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 03698 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 03699 if (!double_answer) { 03700 /* this still can result in double answer if the channel context 03701 * was configured that way */ 03702 res = openr2_chan_answer_call(p->r2chan); 03703 } else if (wants_double_answer) { 03704 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 03705 } else { 03706 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 03707 } 03708 #else 03709 res = openr2_chan_answer_call(p->r2chan); 03710 #endif 03711 return res; 03712 }
static int dahdi_r2_cause_to_ast_cause | ( | openr2_call_disconnect_cause_t | cause | ) | [static] |
Definition at line 3931 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().
03932 { 03933 switch (cause) { 03934 case OR2_CAUSE_BUSY_NUMBER: 03935 return AST_CAUSE_BUSY; 03936 case OR2_CAUSE_NETWORK_CONGESTION: 03937 return AST_CAUSE_CONGESTION; 03938 case OR2_CAUSE_OUT_OF_ORDER: 03939 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 03940 case OR2_CAUSE_UNALLOCATED_NUMBER: 03941 return AST_CAUSE_UNREGISTERED; 03942 case OR2_CAUSE_NO_ANSWER: 03943 return AST_CAUSE_NO_ANSWER; 03944 case OR2_CAUSE_NORMAL_CLEARING: 03945 return AST_CAUSE_NORMAL_CLEARING; 03946 case OR2_CAUSE_UNSPECIFIED: 03947 default: 03948 return AST_CAUSE_NOTDEFINED; 03949 } 03950 }
static void dahdi_r2_destroy_links | ( | void | ) | [static] |
Definition at line 11776 of file chan_dahdi.c.
References ast_free, AST_PTHREADT_NULL, r2links, and r2links_count.
Referenced by __unload_module(), and dahdi_restart().
11777 { 11778 int i = 0; 11779 if (!r2links) { 11780 return; 11781 } 11782 for (; i < r2links_count; i++) { 11783 if (r2links[i]->r2master != AST_PTHREADT_NULL) { 11784 pthread_cancel(r2links[i]->r2master); 11785 pthread_join(r2links[i]->r2master, NULL); 11786 openr2_context_delete(r2links[i]->protocol_context); 11787 } 11788 ast_free(r2links[i]); 11789 } 11790 ast_free(r2links); 11791 r2links = NULL; 11792 r2links_count = 0; 11793 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 3799 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().
03800 { 03801 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 03802 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 03803 p->channel, openr2_proto_get_disconnect_string(cause)); 03804 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 03805 openr2_chan_set_idle(p->r2chan); 03806 ast_mutex_lock(&p->lock); 03807 p->mfcr2call = 0; 03808 ast_mutex_unlock(&p->lock); 03809 } 03810 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3717 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().
03718 { 03719 openr2_calling_party_category_t cat; 03720 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 03721 struct dahdi_pvt *p = c->tech_pvt; 03722 if (ast_strlen_zero(catstr)) { 03723 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n", 03724 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 03725 return p->mfcr2_category; 03726 } 03727 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 03728 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 03729 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 03730 return p->mfcr2_category; 03731 } 03732 ast_debug(1, "Using category %s\n", catstr); 03733 return cat; 03734 }
static struct dahdi_mfcr2* dahdi_r2_get_link | ( | void | ) | [static] |
Definition at line 11796 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.
11797 { 11798 struct dahdi_mfcr2 *new_r2link = NULL; 11799 struct dahdi_mfcr2 **new_r2links = NULL; 11800 /* this function is called just when starting up and no monitor threads have been launched, 11801 no need to lock monitored_count member */ 11802 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) { 11803 new_r2link = ast_calloc(1, sizeof(**r2links)); 11804 if (!new_r2link) { 11805 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n"); 11806 return NULL; 11807 } 11808 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links))); 11809 if (!new_r2links) { 11810 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n"); 11811 ast_free(new_r2link); 11812 return NULL; 11813 } 11814 r2links = new_r2links; 11815 new_r2link->r2master = AST_PTHREADT_NULL; 11816 r2links[r2links_count] = new_r2link; 11817 r2links_count++; 11818 ast_log(LOG_DEBUG, "Created new R2 link!\n"); 11819 } 11820 return r2links[r2links_count - 1]; 11821 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 4126 of file chan_dahdi.c.
References AST_LIN2A.
04127 { 04128 return AST_LIN2A(sample); 04129 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 4085 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
04086 { 04087 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04088 p->cid_num[p->mfcr2_ani_index] = digit; 04089 p->cid_name[p->mfcr2_ani_index] = digit; 04090 p->mfcr2_ani_index++; 04091 p->cid_num[p->mfcr2_ani_index] = 0; 04092 p->cid_name[p->mfcr2_ani_index] = 0; 04093 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4095 of file chan_dahdi.c.
References ast_verbose.
04096 { 04097 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 04098 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 3877 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.
03878 { 03879 struct dahdi_pvt *p = NULL; 03880 struct ast_channel *c = NULL; 03881 p = openr2_chan_get_client_data(r2chan); 03882 dahdi_enable_ec(p); 03883 p->mfcr2_call_accepted = 1; 03884 /* if it's an incoming call ... */ 03885 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 03886 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 03887 /* If accept on offer is not set, it means at this point the PBX thread is already 03888 launched (was launched in the 'on call offered' handler) and therefore this callback 03889 is being executed already in the PBX thread rather than the monitor thread, don't launch 03890 any other thread, just disable the openr2 reading and answer the call if needed */ 03891 if (!p->mfcr2_accept_on_offer) { 03892 openr2_chan_disable_read(r2chan); 03893 if (p->mfcr2_answer_pending) { 03894 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 03895 dahdi_r2_answer(p); 03896 } 03897 return; 03898 } 03899 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL); 03900 if (c) { 03901 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the 03902 library to forget about it */ 03903 openr2_chan_disable_read(r2chan); 03904 return; 03905 } 03906 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel); 03907 /* failed to create the channel, bail out and report it as an out of order line */ 03908 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 03909 return; 03910 } 03911 /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */ 03912 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel); 03913 p->subs[SUB_REAL].needringing = 1; 03914 p->dialing = 0; 03915 /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */ 03916 openr2_chan_disable_read(r2chan); 03917 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 3919 of file chan_dahdi.c.
References ast_verbose, dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
03920 { 03921 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03922 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan)); 03923 p->subs[SUB_REAL].needanswer = 1; 03924 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 3952 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.
03953 { 03954 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03955 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan)); 03956 ast_mutex_lock(&p->lock); 03957 if (!p->owner) { 03958 ast_mutex_unlock(&p->lock); 03959 /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */ 03960 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 03961 return; 03962 } 03963 /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will 03964 be done in dahdi_hangup */ 03965 if (p->owner->_state == AST_STATE_UP) { 03966 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03967 ast_mutex_unlock(&p->lock); 03968 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 03969 /* being the forward side we must report what happened to the call to whoever requested it */ 03970 switch (cause) { 03971 case OR2_CAUSE_BUSY_NUMBER: 03972 p->subs[SUB_REAL].needbusy = 1; 03973 break; 03974 case OR2_CAUSE_NETWORK_CONGESTION: 03975 case OR2_CAUSE_OUT_OF_ORDER: 03976 case OR2_CAUSE_UNALLOCATED_NUMBER: 03977 case OR2_CAUSE_NO_ANSWER: 03978 case OR2_CAUSE_UNSPECIFIED: 03979 case OR2_CAUSE_NORMAL_CLEARING: 03980 p->subs[SUB_REAL].needcongestion = 1; 03981 break; 03982 default: 03983 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03984 } 03985 ast_mutex_unlock(&p->lock); 03986 } else { 03987 ast_mutex_unlock(&p->lock); 03988 /* being the backward side and not UP yet, we only need to request hangup */ 03989 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 03990 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause)); 03991 } 03992 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 3867 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, ast_verbose, dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
03868 { 03869 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03870 ast_verbose("MFC/R2 call end on channel %d\n", p->channel); 03871 ast_mutex_lock(&p->lock); 03872 p->mfcr2call = 0; 03873 ast_mutex_unlock(&p->lock); 03874 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 3736 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.
03737 { 03738 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03739 ast_mutex_lock(&p->lock); 03740 if (p->mfcr2call) { 03741 ast_mutex_unlock(&p->lock); 03742 /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same 03743 interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line, 03744 can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since 03745 the other end will see our seize as a forced release and drop the call, we will see an invalid 03746 pattern that will be seen and treated as protocol error. */ 03747 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 03748 return; 03749 } 03750 p->mfcr2call = 1; 03751 /* better safe than sorry ... */ 03752 p->cid_name[0] = '\0'; 03753 p->cid_num[0] = '\0'; 03754 p->cid_subaddr[0] = '\0'; 03755 p->rdnis[0] = '\0'; 03756 p->exten[0] = '\0'; 03757 p->mfcr2_ani_index = '\0'; 03758 p->mfcr2_dnis_index = '\0'; 03759 p->mfcr2_dnis_matched = 0; 03760 p->mfcr2_answer_pending = 0; 03761 p->mfcr2_call_accepted = 0; 03762 ast_mutex_unlock(&p->lock); 03763 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 03764 }
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 3812 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.
03813 { 03814 struct dahdi_pvt *p; 03815 struct ast_channel *c; 03816 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 03817 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, 03818 openr2_proto_get_category_string(category)); 03819 p = openr2_chan_get_client_data(r2chan); 03820 /* if collect calls are not allowed and this is a collect call, reject it! */ 03821 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 03822 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n"); 03823 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 03824 return; 03825 } 03826 ast_mutex_lock(&p->lock); 03827 p->mfcr2_recvd_category = category; 03828 /* if we're not supposed to use CID, clear whatever we have */ 03829 if (!p->use_callerid) { 03830 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 03831 p->cid_num[0] = 0; 03832 p->cid_name[0] = 0; 03833 } 03834 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 03835 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 03836 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 03837 p->exten[0] = 's'; 03838 p->exten[1] = 0; 03839 } 03840 ast_mutex_unlock(&p->lock); 03841 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 03842 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 03843 p->channel, p->exten, p->context); 03844 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 03845 return; 03846 } 03847 if (!p->mfcr2_accept_on_offer) { 03848 /* The user wants us to start the PBX thread right away without accepting the call first */ 03849 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL); 03850 if (c) { 03851 /* Done here, don't disable reading now since we still need to generate MF tones to accept 03852 the call or reject it and detect the tone off condition of the other end, all of this 03853 will be done in the PBX thread now */ 03854 return; 03855 } 03856 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel); 03857 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 03858 } else if (p->mfcr2_charge_calls) { 03859 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel); 03860 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 03861 } else { 03862 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel); 03863 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 03864 } 03865 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 3926 of file chan_dahdi.c.
03927 { 03928 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 03929 }
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 4053 of file chan_dahdi.c.
References CHAN_TAG, and dahdi_r2_write_log().
04054 { 04055 #define CHAN_TAG "Chan " 04056 char logmsg[256]; 04057 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1]; 04058 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 04059 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg); 04060 dahdi_r2_write_log(level, completemsg); 04061 }
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 4040 of file chan_dahdi.c.
References CONTEXT_TAG, and dahdi_r2_write_log().
04041 { 04042 #define CONTEXT_TAG "Context - " 04043 char logmsg[256]; 04044 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1]; 04045 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 04046 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg); 04047 dahdi_r2_write_log(level, completemsg); 04048 #undef CONTEXT_TAG 04049 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 4063 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.
04064 { 04065 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04066 /* if 'immediate' is set, let's stop requesting DNIS */ 04067 if (p->immediate) { 04068 return 0; 04069 } 04070 p->exten[p->mfcr2_dnis_index] = digit; 04071 p->rdnis[p->mfcr2_dnis_index] = digit; 04072 p->mfcr2_dnis_index++; 04073 p->exten[p->mfcr2_dnis_index] = 0; 04074 p->rdnis[p->mfcr2_dnis_index] = 0; 04075 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 04076 if ((p->mfcr2_dnis_matched || 04077 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 04078 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 04079 return 0; 04080 } 04081 /* otherwise keep going */ 04082 return 1; 04083 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 3766 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.
03767 { 03768 int res; 03769 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03770 ast_mutex_lock(&p->lock); 03771 p->inalarm = alarm ? 1 : 0; 03772 if (p->inalarm) { 03773 res = get_alarms(p); 03774 handle_alarms(p, res); 03775 } else { 03776 handle_clear_alarms(p); 03777 } 03778 ast_mutex_unlock(&p->lock); 03779 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4020 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.
04021 { 04022 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04023 ast_mutex_lock(&p->lock); 04024 p->remotelyblocked = 1; 04025 ast_mutex_unlock(&p->lock); 04026 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan)); 04027 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 4029 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::remotelyblocked.
04030 { 04031 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 04032 ast_mutex_lock(&p->lock); 04033 p->remotelyblocked = 0; 04034 ast_mutex_unlock(&p->lock); 04035 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 04036 }
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 3786 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.
03787 { 03788 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 03789 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 03790 if (p->owner) { 03791 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 03792 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03793 } 03794 ast_mutex_lock(&p->lock); 03795 p->mfcr2call = 0; 03796 ast_mutex_unlock(&p->lock); 03797 }
static int dahdi_r2_set_context | ( | struct dahdi_mfcr2 * | r2_link, | |
const struct dahdi_chan_conf * | conf | |||
) | [static] |
Definition at line 11823 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.
11824 { 11825 char tmplogdir[] = "/tmp"; 11826 char logdir[OR2_MAX_PATH]; 11827 int threshold = 0; 11828 int snres = 0; 11829 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 11830 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani, 11831 conf->mfcr2.max_dnis); 11832 if (!r2_link->protocol_context) { 11833 return -1; 11834 } 11835 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel); 11836 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first); 11837 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 11838 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request); 11839 #endif 11840 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold); 11841 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout); 11842 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout); 11843 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer); 11844 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept); 11845 if (ast_strlen_zero(conf->mfcr2.logdir)) { 11846 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) { 11847 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 11848 } 11849 } else { 11850 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir); 11851 if (snres >= sizeof(logdir)) { 11852 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 11853 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) { 11854 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 11855 } 11856 } else { 11857 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) { 11858 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 11859 } 11860 } 11861 } 11862 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) { 11863 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) { 11864 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file); 11865 } 11866 } 11867 r2_link->monitored_count = 0; 11868 return 0; 11869 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 3994 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().
03995 { 03996 switch (level) { 03997 case OR2_LOG_NOTICE: 03998 ast_verbose("%s", logmessage); 03999 break; 04000 case OR2_LOG_WARNING: 04001 ast_log(LOG_WARNING, "%s", logmessage); 04002 break; 04003 case OR2_LOG_ERROR: 04004 ast_log(LOG_ERROR, "%s", logmessage); 04005 break; 04006 case OR2_LOG_STACK_TRACE: 04007 case OR2_LOG_MF_TRACE: 04008 case OR2_LOG_CAS_TRACE: 04009 case OR2_LOG_DEBUG: 04010 case OR2_LOG_EX_DEBUG: 04011 ast_log(LOG_DEBUG, "%s", logmessage); 04012 break; 04013 default: 04014 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 04015 ast_log(LOG_DEBUG, "%s", logmessage); 04016 break; 04017 } 04018 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 8641 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_FLAG_EXCEPTION, 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_set_flag, 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.
08642 { 08643 struct dahdi_pvt *p = ast->tech_pvt; 08644 int res; 08645 int idx; 08646 void *readbuf; 08647 struct ast_frame *f; 08648 08649 while (ast_mutex_trylock(&p->lock)) { 08650 CHANNEL_DEADLOCK_AVOIDANCE(ast); 08651 } 08652 08653 idx = dahdi_get_index(ast, p, 0); 08654 08655 /* Hang up if we don't really exist */ 08656 if (idx < 0) { 08657 ast_log(LOG_WARNING, "We don't exist?\n"); 08658 ast_mutex_unlock(&p->lock); 08659 return NULL; 08660 } 08661 08662 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 08663 ast_mutex_unlock(&p->lock); 08664 return NULL; 08665 } 08666 08667 p->subs[idx].f.frametype = AST_FRAME_NULL; 08668 p->subs[idx].f.datalen = 0; 08669 p->subs[idx].f.samples = 0; 08670 p->subs[idx].f.mallocd = 0; 08671 p->subs[idx].f.offset = 0; 08672 p->subs[idx].f.subclass.integer = 0; 08673 p->subs[idx].f.delivery = ast_tv(0,0); 08674 p->subs[idx].f.src = "dahdi_read"; 08675 p->subs[idx].f.data.ptr = NULL; 08676 08677 /* make sure it sends initial key state as first frame */ 08678 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 08679 { 08680 struct dahdi_params ps; 08681 08682 memset(&ps, 0, sizeof(ps)); 08683 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 08684 ast_mutex_unlock(&p->lock); 08685 return NULL; 08686 } 08687 p->firstradio = 1; 08688 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08689 if (ps.rxisoffhook) 08690 { 08691 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY; 08692 } 08693 else 08694 { 08695 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY; 08696 } 08697 ast_mutex_unlock(&p->lock); 08698 return &p->subs[idx].f; 08699 } 08700 if (p->ringt > 0) { 08701 if (!(--p->ringt)) { 08702 ast_mutex_unlock(&p->lock); 08703 return NULL; 08704 } 08705 } 08706 08707 #ifdef HAVE_OPENR2 08708 if (p->mfcr2) { 08709 openr2_chan_process_event(p->r2chan); 08710 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) { 08711 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, }; 08712 /* if the call is already accepted and we already delivered AST_CONTROL_RINGING 08713 * now enqueue a progress frame to bridge the media up */ 08714 if (p->mfcr2_call_accepted && 08715 !p->mfcr2_progress && 08716 ast->_state == AST_STATE_RINGING) { 08717 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel); 08718 ast_queue_frame(p->owner, &f); 08719 p->mfcr2_progress = 1; 08720 } 08721 } 08722 } 08723 #endif 08724 08725 if (p->subs[idx].needringing) { 08726 /* Send ringing frame if requested */ 08727 p->subs[idx].needringing = 0; 08728 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08729 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING; 08730 ast_setstate(ast, AST_STATE_RINGING); 08731 ast_mutex_unlock(&p->lock); 08732 return &p->subs[idx].f; 08733 } 08734 08735 if (p->subs[idx].needbusy) { 08736 /* Send busy frame if requested */ 08737 p->subs[idx].needbusy = 0; 08738 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08739 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY; 08740 ast_mutex_unlock(&p->lock); 08741 return &p->subs[idx].f; 08742 } 08743 08744 if (p->subs[idx].needcongestion) { 08745 /* Send congestion frame if requested */ 08746 p->subs[idx].needcongestion = 0; 08747 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08748 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION; 08749 ast_mutex_unlock(&p->lock); 08750 return &p->subs[idx].f; 08751 } 08752 08753 if (p->subs[idx].needanswer) { 08754 /* Send answer frame if requested */ 08755 p->subs[idx].needanswer = 0; 08756 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08757 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER; 08758 ast_mutex_unlock(&p->lock); 08759 return &p->subs[idx].f; 08760 } 08761 #ifdef HAVE_OPENR2 08762 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 08763 /* openr2 took care of reading and handling any event 08764 (needanswer, needbusy etc), if we continue we will read() 08765 twice, lets just return a null frame. This should only 08766 happen when openr2 is dialing out */ 08767 ast_mutex_unlock(&p->lock); 08768 return &ast_null_frame; 08769 } 08770 #endif 08771 08772 if (p->subs[idx].needflash) { 08773 /* Send answer frame if requested */ 08774 p->subs[idx].needflash = 0; 08775 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08776 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH; 08777 ast_mutex_unlock(&p->lock); 08778 return &p->subs[idx].f; 08779 } 08780 08781 if (p->subs[idx].needhold) { 08782 /* Send answer frame if requested */ 08783 p->subs[idx].needhold = 0; 08784 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08785 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD; 08786 ast_mutex_unlock(&p->lock); 08787 ast_debug(1, "Sending hold on '%s'\n", ast->name); 08788 return &p->subs[idx].f; 08789 } 08790 08791 if (p->subs[idx].needunhold) { 08792 /* Send answer frame if requested */ 08793 p->subs[idx].needunhold = 0; 08794 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 08795 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD; 08796 ast_mutex_unlock(&p->lock); 08797 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 08798 return &p->subs[idx].f; 08799 } 08800 08801 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 08802 if (!p->subs[idx].linear) { 08803 p->subs[idx].linear = 1; 08804 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08805 if (res) 08806 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 08807 } 08808 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 08809 (ast->rawreadformat == AST_FORMAT_ALAW)) { 08810 if (p->subs[idx].linear) { 08811 p->subs[idx].linear = 0; 08812 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08813 if (res) 08814 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 08815 } 08816 } else { 08817 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 08818 ast_mutex_unlock(&p->lock); 08819 return NULL; 08820 } 08821 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 08822 CHECK_BLOCKING(ast); 08823 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 08824 ast_clear_flag(ast, AST_FLAG_BLOCKING); 08825 /* Check for hangup */ 08826 if (res < 0) { 08827 f = NULL; 08828 if (res == -1) { 08829 if (errno == EAGAIN) { 08830 /* Return "NULL" frame if there is nobody there */ 08831 ast_mutex_unlock(&p->lock); 08832 return &p->subs[idx].f; 08833 } else if (errno == ELAST) { 08834 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08835 struct analog_pvt *analog_p = p->sig_pvt; 08836 f = analog_exception(analog_p, ast); 08837 } else { 08838 f = __dahdi_exception(ast); 08839 } 08840 } else 08841 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 08842 } 08843 ast_mutex_unlock(&p->lock); 08844 return f; 08845 } 08846 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 08847 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 08848 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 08849 struct analog_pvt *analog_p = p->sig_pvt; 08850 f = analog_exception(analog_p, ast); 08851 } else { 08852 f = __dahdi_exception(ast); 08853 } 08854 ast_mutex_unlock(&p->lock); 08855 return f; 08856 } 08857 if (p->tdd) { /* if in TDD mode, see if we receive that */ 08858 int c; 08859 08860 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 08861 if (c < 0) { 08862 ast_debug(1,"tdd_feed failed\n"); 08863 ast_mutex_unlock(&p->lock); 08864 return NULL; 08865 } 08866 if (c) { /* if a char to return */ 08867 p->subs[idx].f.subclass.integer = 0; 08868 p->subs[idx].f.frametype = AST_FRAME_TEXT; 08869 p->subs[idx].f.mallocd = 0; 08870 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 08871 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 08872 p->subs[idx].f.datalen = 1; 08873 *((char *) p->subs[idx].f.data.ptr) = c; 08874 ast_mutex_unlock(&p->lock); 08875 return &p->subs[idx].f; 08876 } 08877 } 08878 if (idx == SUB_REAL) { 08879 /* Ensure the CW timers decrement only on a single subchannel */ 08880 if (p->cidcwexpire) { 08881 if (!--p->cidcwexpire) { 08882 /* Expired CID/CW */ 08883 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 08884 restore_conference(p); 08885 } 08886 } 08887 if (p->cid_suppress_expire) { 08888 --p->cid_suppress_expire; 08889 } 08890 if (p->callwaitingrepeat) { 08891 if (!--p->callwaitingrepeat) { 08892 /* Expired, Repeat callwaiting tone */ 08893 ++p->callwaitrings; 08894 dahdi_callwait(ast); 08895 } 08896 } 08897 } 08898 if (p->subs[idx].linear) { 08899 p->subs[idx].f.datalen = READ_SIZE * 2; 08900 } else 08901 p->subs[idx].f.datalen = READ_SIZE; 08902 08903 /* Handle CallerID Transmission */ 08904 if ((p->owner == ast) && p->cidspill) { 08905 send_callerid(p); 08906 } 08907 08908 p->subs[idx].f.frametype = AST_FRAME_VOICE; 08909 p->subs[idx].f.subclass.codec = ast->rawreadformat; 08910 p->subs[idx].f.samples = READ_SIZE; 08911 p->subs[idx].f.mallocd = 0; 08912 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 08913 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 08914 #if 0 08915 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 08916 #endif 08917 if (p->dialing || p->radio || /* Transmitting something */ 08918 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 08919 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 08920 ) { 08921 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 08922 don't send anything */ 08923 p->subs[idx].f.frametype = AST_FRAME_NULL; 08924 p->subs[idx].f.subclass.integer = 0; 08925 p->subs[idx].f.samples = 0; 08926 p->subs[idx].f.mallocd = 0; 08927 p->subs[idx].f.offset = 0; 08928 p->subs[idx].f.data.ptr = NULL; 08929 p->subs[idx].f.datalen= 0; 08930 } 08931 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 08932 /* Perform busy detection etc on the dahdi line */ 08933 int mute; 08934 08935 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 08936 08937 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 08938 mute = ast_dsp_was_muted(p->dsp); 08939 if (p->muting != mute) { 08940 p->muting = mute; 08941 dahdi_confmute(p, mute); 08942 } 08943 08944 if (f) { 08945 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) { 08946 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 08947 /* Treat this as a "hangup" instead of a "busy" on the assumption that 08948 a busy */ 08949 f = NULL; 08950 } 08951 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 08952 || f->frametype == AST_FRAME_DTMF_END) { 08953 #ifdef HAVE_PRI 08954 if (dahdi_sig_pri_lib_handles(p->sig) 08955 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING 08956 && p->pri 08957 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 08958 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 08959 /* Don't accept in-band DTMF when in overlap dial mode */ 08960 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 08961 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 08962 f->subclass.integer, f->subclass.integer, ast->name); 08963 08964 f->frametype = AST_FRAME_NULL; 08965 f->subclass.integer = 0; 08966 } 08967 #endif 08968 /* DSP clears us of being pulse */ 08969 p->pulsedial = 0; 08970 } else if (p->waitingfordt.tv_sec) { 08971 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 08972 p->waitingfordt.tv_sec = 0; 08973 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 08974 f=NULL; 08975 } else if (f->frametype == AST_FRAME_VOICE) { 08976 f->frametype = AST_FRAME_NULL; 08977 f->subclass.integer = 0; 08978 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) { 08979 p->waitingfordt.tv_sec = 0; 08980 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 08981 ast_dsp_set_features(p->dsp, p->dsp_features); 08982 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 08983 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 08984 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 08985 if (res < 0) { 08986 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 08987 p->dop.dialstr[0] = '\0'; 08988 ast_mutex_unlock(&p->lock); 08989 return NULL; 08990 } else { 08991 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 08992 p->dialing = 1; 08993 p->dop.dialstr[0] = '\0'; 08994 p->dop.op = DAHDI_DIAL_OP_REPLACE; 08995 ast_setstate(ast, AST_STATE_DIALING); 08996 } 08997 } 08998 } 08999 } 09000 } 09001 } 09002 } else 09003 f = &p->subs[idx].f; 09004 09005 if (f) { 09006 switch (f->frametype) { 09007 case AST_FRAME_DTMF_BEGIN: 09008 case AST_FRAME_DTMF_END: 09009 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 09010 analog_handle_dtmf(p->sig_pvt, ast, idx, &f); 09011 } else { 09012 dahdi_handle_dtmf(ast, idx, &f); 09013 } 09014 break; 09015 case AST_FRAME_VOICE: 09016 if (p->cidspill || p->cid_suppress_expire) { 09017 /* We are/were sending a caller id spill. Suppress any echo. */ 09018 p->subs[idx].f.frametype = AST_FRAME_NULL; 09019 p->subs[idx].f.subclass.integer = 0; 09020 p->subs[idx].f.samples = 0; 09021 p->subs[idx].f.mallocd = 0; 09022 p->subs[idx].f.offset = 0; 09023 p->subs[idx].f.data.ptr = NULL; 09024 p->subs[idx].f.datalen= 0; 09025 } 09026 break; 09027 default: 09028 break; 09029 } 09030 } 09031 09032 /* If we have a fake_event, trigger exception to handle it */ 09033 if (p->fake_event) 09034 ast_set_flag(ast, AST_FLAG_EXCEPTION); 09035 09036 ast_mutex_unlock(&p->lock); 09037 return f; 09038 }
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 13272 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, 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.
13273 { 13274 int callwait = 0; 13275 struct dahdi_pvt *p; 13276 struct ast_channel *tmp = NULL; 13277 struct dahdi_pvt *exitpvt; 13278 int channelmatched = 0; 13279 int groupmatched = 0; 13280 int transcapdigital = 0; 13281 struct dahdi_starting_point start; 13282 13283 ast_mutex_lock(&iflock); 13284 p = determine_starting_point(data, &start); 13285 if (!p) { 13286 /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */ 13287 ast_mutex_unlock(&iflock); 13288 return NULL; 13289 } 13290 13291 /* Search for an unowned channel */ 13292 exitpvt = p; 13293 while (p && !tmp) { 13294 if (start.roundrobin) 13295 round_robin[start.rr_starting_point] = p; 13296 13297 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched) 13298 && available(&p, channelmatched)) { 13299 ast_debug(1, "Using channel %d\n", p->channel); 13300 13301 callwait = (p->owner != NULL); 13302 #ifdef HAVE_OPENR2 13303 if (p->mfcr2) { 13304 ast_mutex_lock(&p->lock); 13305 if (p->mfcr2call) { 13306 ast_mutex_unlock(&p->lock); 13307 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 13308 goto next; 13309 } 13310 p->mfcr2call = 1; 13311 ast_mutex_unlock(&p->lock); 13312 } 13313 #endif 13314 if (p->channel == CHAN_PSEUDO) { 13315 p = duplicate_pseudo(p); 13316 if (!p) { 13317 break; 13318 } 13319 } 13320 13321 /* Make special notes */ 13322 switch (start.opt) { 13323 case '\0': 13324 /* No option present. */ 13325 break; 13326 case 'c': 13327 /* Confirm answer */ 13328 p->confirmanswer = 1; 13329 break; 13330 case 'r': 13331 /* Distinctive ring */ 13332 p->distinctivering = start.cadance; 13333 break; 13334 case 'd': 13335 /* If this is an ISDN call, make it digital */ 13336 transcapdigital = AST_TRANS_CAP_DIGITAL; 13337 break; 13338 default: 13339 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data); 13340 break; 13341 } 13342 13343 p->outgoing = 1; 13344 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { 13345 tmp = analog_request(p->sig_pvt, &callwait, requestor); 13346 #ifdef HAVE_PRI 13347 } else if (dahdi_sig_pri_lib_handles(p->sig)) { 13348 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid, 13349 sizeof(p->dnid)); 13350 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital); 13351 #endif 13352 #if defined(HAVE_SS7) 13353 } else if (p->sig == SIG_SS7) { 13354 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital); 13355 #endif /* defined(HAVE_SS7) */ 13356 } else { 13357 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : ""); 13358 } 13359 if (!tmp) { 13360 p->outgoing = 0; 13361 #if defined(HAVE_PRI) 13362 #if defined(HAVE_PRI_CALL_WAITING) 13363 switch (p->sig) { 13364 case SIG_PRI_LIB_HANDLE_CASES: 13365 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) { 13366 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0; 13367 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); 13368 } 13369 break; 13370 default: 13371 break; 13372 } 13373 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 13374 #endif /* defined(HAVE_PRI) */ 13375 } else { 13376 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data); 13377 } 13378 break; 13379 } 13380 #ifdef HAVE_OPENR2 13381 next: 13382 #endif 13383 if (start.backwards) { 13384 p = p->prev; 13385 if (!p) 13386 p = ifend; 13387 } else { 13388 p = p->next; 13389 if (!p) 13390 p = iflist; 13391 } 13392 /* stop when you roll to the one that we started from */ 13393 if (p == exitpvt) 13394 break; 13395 } 13396 ast_mutex_unlock(&iflock); 13397 restart_monitor(); 13398 if (cause && !tmp) { 13399 if (callwait || channelmatched) { 13400 *cause = AST_CAUSE_BUSY; 13401 } else if (groupmatched) { 13402 *cause = AST_CAUSE_CONGESTION; 13403 } else { 13404 /* 13405 * We did not match any channel requested. 13406 * Dialplan error requesting non-existant channel? 13407 */ 13408 } 13409 } 13410 13411 return tmp; 13412 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 14637 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().
14638 { 14639 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14640 int i, j; 14641 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 14642 int cancel_code; 14643 struct dahdi_pvt *p; 14644 14645 ast_mutex_lock(&restart_lock); 14646 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 14647 dahdi_softhangup_all(); 14648 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 14649 #ifdef HAVE_OPENR2 14650 dahdi_r2_destroy_links(); 14651 #endif 14652 14653 #if defined(HAVE_PRI) 14654 for (i = 0; i < NUM_SPANS; i++) { 14655 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) { 14656 cancel_code = pthread_cancel(pris[i].pri.master); 14657 pthread_kill(pris[i].pri.master, SIGURG); 14658 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); 14659 pthread_join(pris[i].pri.master, NULL); 14660 ast_debug(4, "Joined thread of span %d\n", i); 14661 } 14662 } 14663 #endif 14664 14665 #if defined(HAVE_SS7) 14666 for (i = 0; i < NUM_SPANS; i++) { 14667 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) { 14668 cancel_code = pthread_cancel(linksets[i].ss7.master); 14669 pthread_kill(linksets[i].ss7.master, SIGURG); 14670 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); 14671 pthread_join(linksets[i].ss7.master, NULL); 14672 ast_debug(4, "Joined thread of span %d\n", i); 14673 } 14674 } 14675 #endif /* defined(HAVE_SS7) */ 14676 14677 ast_mutex_lock(&monlock); 14678 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14679 cancel_code = pthread_cancel(monitor_thread); 14680 pthread_kill(monitor_thread, SIGURG); 14681 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 14682 pthread_join(monitor_thread, NULL); 14683 ast_debug(4, "Joined monitor thread\n"); 14684 } 14685 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 14686 14687 ast_mutex_lock(&ss_thread_lock); 14688 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 14689 int x = DAHDI_FLASH; 14690 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count); 14691 14692 ast_mutex_lock(&iflock); 14693 for (p = iflist; p; p = p->next) { 14694 if (p->owner) { 14695 /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */ 14696 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 14697 } 14698 } 14699 ast_mutex_unlock(&iflock); 14700 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 14701 } 14702 14703 /* ensure any created channels before monitor threads were stopped are hungup */ 14704 dahdi_softhangup_all(); 14705 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 14706 destroy_all_channels(); 14707 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 14708 14709 ast_mutex_unlock(&monlock); 14710 14711 #ifdef HAVE_PRI 14712 for (i = 0; i < NUM_SPANS; i++) { 14713 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) 14714 dahdi_close_pri_fd(&(pris[i]), j); 14715 } 14716 14717 memset(pris, 0, sizeof(pris)); 14718 for (i = 0; i < NUM_SPANS; i++) { 14719 sig_pri_init_pri(&pris[i].pri); 14720 } 14721 pri_set_error(dahdi_pri_error); 14722 pri_set_message(dahdi_pri_message); 14723 #endif 14724 #if defined(HAVE_SS7) 14725 for (i = 0; i < NUM_SPANS; i++) { 14726 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) 14727 dahdi_close_ss7_fd(&(linksets[i]), j); 14728 } 14729 14730 memset(linksets, 0, sizeof(linksets)); 14731 for (i = 0; i < NUM_SPANS; i++) { 14732 sig_ss7_init_linkset(&linksets[i].ss7); 14733 } 14734 ss7_set_error(dahdi_ss7_error); 14735 ss7_set_message(dahdi_ss7_message); 14736 #endif /* defined(HAVE_SS7) */ 14737 14738 if (setup_dahdi(2) != 0) { 14739 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 14740 ast_mutex_unlock(&ss_thread_lock); 14741 return 1; 14742 } 14743 ast_mutex_unlock(&ss_thread_lock); 14744 ast_mutex_unlock(&restart_lock); 14745 return 0; 14746 }
static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14748 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.
14749 { 14750 switch (cmd) { 14751 case CLI_INIT: 14752 e->command = "dahdi restart"; 14753 e->usage = 14754 "Usage: dahdi restart\n" 14755 " Restarts the DAHDI channels: destroys them all and then\n" 14756 " re-reads them from chan_dahdi.conf.\n" 14757 " Note that this will STOP any running CALL on DAHDI channels.\n" 14758 ""; 14759 return NULL; 14760 case CLI_GENERATE: 14761 return NULL; 14762 } 14763 if (a->argc != 2) 14764 return CLI_SHOWUSAGE; 14765 14766 if (dahdi_restart() != 0) 14767 return CLI_FAILURE; 14768 return CLI_SUCCESS; 14769 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 7389 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().
07390 { 07391 int x; 07392 int res; 07393 /* Make sure our transmit state is on hook */ 07394 x = 0; 07395 x = DAHDI_ONHOOK; 07396 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07397 do { 07398 x = DAHDI_RING; 07399 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 07400 if (res) { 07401 switch (errno) { 07402 case EBUSY: 07403 case EINTR: 07404 /* Wait just in case */ 07405 usleep(10000); 07406 continue; 07407 case EINPROGRESS: 07408 res = 0; 07409 break; 07410 default: 07411 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 07412 res = 0; 07413 } 07414 } 07415 } while (res); 07416 return res; 07417 }
static int dahdi_send_callrerouting_facility_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 5779 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().
05780 { 05781 /* Data will be our digit string */ 05782 struct dahdi_pvt *pvt; 05783 char *parse; 05784 int res = -1; 05785 AST_DECLARE_APP_ARGS(args, 05786 AST_APP_ARG(destination); 05787 AST_APP_ARG(original); 05788 AST_APP_ARG(reason); 05789 ); 05790 05791 if (ast_strlen_zero(data)) { 05792 ast_log(LOG_DEBUG, "No data sent to application!\n"); 05793 return -1; 05794 } 05795 if (chan->tech != &dahdi_tech) { 05796 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 05797 return -1; 05798 } 05799 pvt = (struct dahdi_pvt *) chan->tech_pvt; 05800 if (!pvt) { 05801 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 05802 return -1; 05803 } 05804 switch (pvt->sig) { 05805 case SIG_PRI_LIB_HANDLE_CASES: 05806 break; 05807 default: 05808 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n", 05809 chan->name); 05810 return -1; 05811 } 05812 05813 parse = ast_strdupa(data); 05814 AST_STANDARD_APP_ARGS(args, parse); 05815 05816 if (ast_strlen_zero(args.destination)) { 05817 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n"); 05818 return -1; 05819 } 05820 05821 if (ast_strlen_zero(args.original)) { 05822 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n"); 05823 args.original = NULL; 05824 } 05825 05826 if (ast_strlen_zero(args.reason)) { 05827 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n"); 05828 args.reason = NULL; 05829 } 05830 05831 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination, 05832 args.original, args.reason); 05833 05834 return res; 05835 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
const char * | digits | |||
) | [static] |
Definition at line 5752 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().
05753 { 05754 /* Data will be our digit string */ 05755 struct dahdi_pvt *p; 05756 05757 if (ast_strlen_zero(digits)) { 05758 ast_debug(1, "No digit string sent to application!\n"); 05759 return -1; 05760 } 05761 05762 p = (struct dahdi_pvt *)chan->tech_pvt; 05763 05764 if (!p) { 05765 ast_debug(1, "Unable to find technology private\n"); 05766 return -1; 05767 } 05768 05769 pri_send_keypad_facility_exec(p->sig_pvt, digits); 05770 05771 return 0; 05772 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 18066 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.
18067 { 18068 #define END_SILENCE_LEN 400 18069 #define HEADER_MS 50 18070 #define TRAILER_MS 5 18071 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 18072 #define ASCII_BYTES_PER_CHAR 80 18073 18074 unsigned char *buf,*mybuf; 18075 struct dahdi_pvt *p = c->tech_pvt; 18076 struct pollfd fds[1]; 18077 int size,res,fd,len,x; 18078 int bytes=0; 18079 /* Initial carrier (imaginary) */ 18080 float cr = 1.0; 18081 float ci = 0.0; 18082 float scont = 0.0; 18083 int idx; 18084 18085 idx = dahdi_get_index(c, p, 0); 18086 if (idx < 0) { 18087 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 18088 return -1; 18089 } 18090 if (!text[0]) return(0); /* if nothing to send, don't */ 18091 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 18092 if (p->mate) 18093 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 18094 else 18095 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 18096 if (!buf) 18097 return -1; 18098 mybuf = buf; 18099 if (p->mate) { 18100 int codec = AST_LAW(p); 18101 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 18102 PUT_CLID_MARKMS; 18103 } 18104 /* Put actual message */ 18105 for (x = 0; text[x]; x++) { 18106 PUT_CLID(text[x]); 18107 } 18108 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 18109 PUT_CLID_MARKMS; 18110 } 18111 len = bytes; 18112 buf = mybuf; 18113 } else { 18114 len = tdd_generate(p->tdd, buf, text); 18115 if (len < 1) { 18116 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 18117 ast_free(mybuf); 18118 return -1; 18119 } 18120 } 18121 memset(buf + len, 0x7f, END_SILENCE_LEN); 18122 len += END_SILENCE_LEN; 18123 fd = p->subs[idx].dfd; 18124 while (len) { 18125 if (ast_check_hangup(c)) { 18126 ast_free(mybuf); 18127 return -1; 18128 } 18129 size = len; 18130 if (size > READ_SIZE) 18131 size = READ_SIZE; 18132 fds[0].fd = fd; 18133 fds[0].events = POLLOUT | POLLPRI; 18134 fds[0].revents = 0; 18135 res = poll(fds, 1, -1); 18136 if (!res) { 18137 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 18138 continue; 18139 } 18140 /* if got exception */ 18141 if (fds[0].revents & POLLPRI) { 18142 ast_free(mybuf); 18143 return -1; 18144 } 18145 if (!(fds[0].revents & POLLOUT)) { 18146 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 18147 continue; 18148 } 18149 res = write(fd, buf, size); 18150 if (res != size) { 18151 if (res == -1) { 18152 ast_free(mybuf); 18153 return -1; 18154 } 18155 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 18156 break; 18157 } 18158 len -= size; 18159 buf += size; 18160 } 18161 ast_free(mybuf); 18162 return(0); 18163 }
static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15360 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.
15361 { 15362 int channel; 15363 int on; 15364 struct dahdi_pvt *dahdi_chan = NULL; 15365 15366 switch (cmd) { 15367 case CLI_INIT: 15368 e->command = "dahdi set dnd"; 15369 e->usage = 15370 "Usage: dahdi set dnd <chan#> <on|off>\n" 15371 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15372 " Changes take effect immediately.\n" 15373 " <chan num> is the channel number\n" 15374 " <on|off> Enable or disable DND mode?\n" 15375 ; 15376 return NULL; 15377 case CLI_GENERATE: 15378 return NULL; 15379 } 15380 15381 if (a->argc != 5) 15382 return CLI_SHOWUSAGE; 15383 15384 if ((channel = atoi(a->argv[3])) <= 0) { 15385 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 15386 return CLI_SHOWUSAGE; 15387 } 15388 15389 if (ast_true(a->argv[4])) 15390 on = 1; 15391 else if (ast_false(a->argv[4])) 15392 on = 0; 15393 else { 15394 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 15395 return CLI_SHOWUSAGE; 15396 } 15397 15398 ast_mutex_lock(&iflock); 15399 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 15400 if (dahdi_chan->channel != channel) 15401 continue; 15402 15403 /* Found the channel. Actually set it */ 15404 dahdi_dnd(dahdi_chan, on); 15405 break; 15406 } 15407 ast_mutex_unlock(&iflock); 15408 15409 if (!dahdi_chan) { 15410 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15411 return CLI_FAILURE; 15412 } 15413 15414 return CLI_SUCCESS; 15415 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 5012 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().
05013 { 05014 int x, res; 05015 05016 x = hs; 05017 res = ioctl(fd, DAHDI_HOOK, &x); 05018 05019 if (res < 0) { 05020 if (errno == EINPROGRESS) 05021 return 0; 05022 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 05023 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 05024 } 05025 05026 return res; 05027 }
static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15220 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.
15221 { 15222 int channel; 15223 int gain; 15224 int tx; 15225 struct dahdi_hwgain hwgain; 15226 struct dahdi_pvt *tmp = NULL; 15227 15228 switch (cmd) { 15229 case CLI_INIT: 15230 e->command = "dahdi set hwgain"; 15231 e->usage = 15232 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 15233 " Sets the hardware gain on a a given channel, overriding the\n" 15234 " value provided at module loadtime, whether the channel is in\n" 15235 " use or not. Changes take effect immediately.\n" 15236 " <rx|tx> which direction do you want to change (relative to our module)\n" 15237 " <chan num> is the channel number relative to the device\n" 15238 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15239 return NULL; 15240 case CLI_GENERATE: 15241 return NULL; 15242 } 15243 15244 if (a->argc != 6) 15245 return CLI_SHOWUSAGE; 15246 15247 if (!strcasecmp("rx", a->argv[3])) 15248 tx = 0; /* rx */ 15249 else if (!strcasecmp("tx", a->argv[3])) 15250 tx = 1; /* tx */ 15251 else 15252 return CLI_SHOWUSAGE; 15253 15254 channel = atoi(a->argv[4]); 15255 gain = atof(a->argv[5])*10.0; 15256 15257 ast_mutex_lock(&iflock); 15258 15259 for (tmp = iflist; tmp; tmp = tmp->next) { 15260 15261 if (tmp->channel != channel) 15262 continue; 15263 15264 if (tmp->subs[SUB_REAL].dfd == -1) 15265 break; 15266 15267 hwgain.newgain = gain; 15268 hwgain.tx = tx; 15269 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15270 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15271 ast_mutex_unlock(&iflock); 15272 return CLI_FAILURE; 15273 } 15274 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15275 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15276 break; 15277 } 15278 15279 ast_mutex_unlock(&iflock); 15280 15281 if (tmp) 15282 return CLI_SUCCESS; 15283 15284 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15285 return CLI_FAILURE; 15286 15287 }
static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15289 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.
15290 { 15291 int channel; 15292 float gain; 15293 int tx; 15294 int res; 15295 struct dahdi_pvt *tmp = NULL; 15296 15297 switch (cmd) { 15298 case CLI_INIT: 15299 e->command = "dahdi set swgain"; 15300 e->usage = 15301 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15302 " Sets the software gain on a a given channel, overriding the\n" 15303 " value provided at module loadtime, whether the channel is in\n" 15304 " use or not. Changes take effect immediately.\n" 15305 " <rx|tx> which direction do you want to change (relative to our module)\n" 15306 " <chan num> is the channel number relative to the device\n" 15307 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15308 return NULL; 15309 case CLI_GENERATE: 15310 return NULL; 15311 } 15312 15313 if (a->argc != 6) 15314 return CLI_SHOWUSAGE; 15315 15316 if (!strcasecmp("rx", a->argv[3])) 15317 tx = 0; /* rx */ 15318 else if (!strcasecmp("tx", a->argv[3])) 15319 tx = 1; /* tx */ 15320 else 15321 return CLI_SHOWUSAGE; 15322 15323 channel = atoi(a->argv[4]); 15324 gain = atof(a->argv[5]); 15325 15326 ast_mutex_lock(&iflock); 15327 for (tmp = iflist; tmp; tmp = tmp->next) { 15328 15329 if (tmp->channel != channel) 15330 continue; 15331 15332 if (tmp->subs[SUB_REAL].dfd == -1) 15333 break; 15334 15335 if (tx) 15336 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law); 15337 else 15338 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law); 15339 15340 if (res) { 15341 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15342 ast_mutex_unlock(&iflock); 15343 return CLI_FAILURE; 15344 } 15345 15346 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15347 tx ? "tx" : "rx", gain, channel); 15348 break; 15349 } 15350 ast_mutex_unlock(&iflock); 15351 15352 if (tmp) 15353 return CLI_SUCCESS; 15354 15355 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15356 return CLI_FAILURE; 15357 15358 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 2486 of file chan_dahdi.c.
Referenced by my_new_pri_ast_channel(), and my_pri_open_media().
02487 { 02488 int res; 02489 res = ioctl(dfd, DAHDI_SETLAW, &law); 02490 if (res) 02491 return res; 02492 return 0; 02493 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 4241 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 6533 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.
06534 { 06535 char *cp; 06536 signed char *scp; 06537 int x; 06538 int idx; 06539 struct dahdi_pvt *p = chan->tech_pvt, *pp; 06540 struct oprmode *oprmode; 06541 06542 06543 /* all supported options require data */ 06544 if (!data || (datalen < 1)) { 06545 errno = EINVAL; 06546 return -1; 06547 } 06548 06549 switch (option) { 06550 case AST_OPTION_TXGAIN: 06551 scp = (signed char *) data; 06552 idx = dahdi_get_index(chan, p, 0); 06553 if (idx < 0) { 06554 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 06555 return -1; 06556 } 06557 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 06558 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law); 06559 case AST_OPTION_RXGAIN: 06560 scp = (signed char *) data; 06561 idx = dahdi_get_index(chan, p, 0); 06562 if (idx < 0) { 06563 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 06564 return -1; 06565 } 06566 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 06567 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law); 06568 case AST_OPTION_TONE_VERIFY: 06569 if (!p->dsp) 06570 break; 06571 cp = (char *) data; 06572 switch (*cp) { 06573 case 1: 06574 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 06575 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 06576 break; 06577 case 2: 06578 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 06579 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 06580 break; 06581 default: 06582 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 06583 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 06584 break; 06585 } 06586 break; 06587 case AST_OPTION_TDD: 06588 /* turn on or off TDD */ 06589 cp = (char *) data; 06590 p->mate = 0; 06591 if (!*cp) { /* turn it off */ 06592 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 06593 if (p->tdd) 06594 tdd_free(p->tdd); 06595 p->tdd = 0; 06596 break; 06597 } 06598 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 06599 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 06600 dahdi_disable_ec(p); 06601 /* otherwise, turn it on */ 06602 if (!p->didtdd) { /* if havent done it yet */ 06603 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 06604 unsigned char *buf; 06605 int size, res, fd, len; 06606 struct pollfd fds[1]; 06607 06608 buf = mybuf; 06609 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 06610 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 06611 len = 40000; 06612 idx = dahdi_get_index(chan, p, 0); 06613 if (idx < 0) { 06614 ast_log(LOG_WARNING, "No index in TDD?\n"); 06615 return -1; 06616 } 06617 fd = p->subs[idx].dfd; 06618 while (len) { 06619 if (ast_check_hangup(chan)) 06620 return -1; 06621 size = len; 06622 if (size > READ_SIZE) 06623 size = READ_SIZE; 06624 fds[0].fd = fd; 06625 fds[0].events = POLLPRI | POLLOUT; 06626 fds[0].revents = 0; 06627 res = poll(fds, 1, -1); 06628 if (!res) { 06629 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 06630 continue; 06631 } 06632 /* if got exception */ 06633 if (fds[0].revents & POLLPRI) 06634 return -1; 06635 if (!(fds[0].revents & POLLOUT)) { 06636 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 06637 continue; 06638 } 06639 res = write(fd, buf, size); 06640 if (res != size) { 06641 if (res == -1) return -1; 06642 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06643 break; 06644 } 06645 len -= size; 06646 buf += size; 06647 } 06648 p->didtdd = 1; /* set to have done it now */ 06649 } 06650 if (*cp == 2) { /* Mate mode */ 06651 if (p->tdd) 06652 tdd_free(p->tdd); 06653 p->tdd = 0; 06654 p->mate = 1; 06655 break; 06656 } 06657 if (!p->tdd) { /* if we don't have one yet */ 06658 p->tdd = tdd_new(); /* allocate one */ 06659 } 06660 break; 06661 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 06662 if (!p->dsp) 06663 break; 06664 cp = (char *) data; 06665 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 06666 *cp ? "ON" : "OFF", (int) *cp, chan->name); 06667 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 06668 break; 06669 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 06670 #if defined(HAVE_PRI) 06671 if (dahdi_sig_pri_lib_handles(p->sig) 06672 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 06673 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 06674 break; 06675 } 06676 #endif /* defined(HAVE_PRI) */ 06677 06678 cp = (char *) data; 06679 if (!*cp) { 06680 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 06681 x = 0; 06682 dahdi_disable_ec(p); 06683 } else { 06684 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 06685 x = 1; 06686 } 06687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 06688 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 06689 break; 06690 case AST_OPTION_OPRMODE: /* Operator services mode */ 06691 oprmode = (struct oprmode *) data; 06692 /* We don't support operator mode across technologies */ 06693 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 06694 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 06695 chan->tech->type, oprmode->peer->tech->type); 06696 errno = EINVAL; 06697 return -1; 06698 } 06699 pp = oprmode->peer->tech_pvt; 06700 p->oprmode = pp->oprmode = 0; 06701 /* setup peers */ 06702 p->oprpeer = pp; 06703 pp->oprpeer = p; 06704 /* setup modes, if any */ 06705 if (oprmode->mode) 06706 { 06707 pp->oprmode = oprmode->mode; 06708 p->oprmode = -oprmode->mode; 06709 } 06710 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 06711 oprmode->mode, chan->name,oprmode->peer->name); 06712 break; 06713 case AST_OPTION_ECHOCAN: 06714 cp = (char *) data; 06715 if (*cp) { 06716 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name); 06717 dahdi_enable_ec(p); 06718 } else { 06719 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name); 06720 dahdi_disable_ec(p); 06721 } 06722 break; 06723 case AST_OPTION_DIGIT_DETECT: 06724 cp = (char *) data; 06725 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); 06726 if (*cp) { 06727 enable_dtmf_detect(p); 06728 } else { 06729 disable_dtmf_detect(p); 06730 } 06731 break; 06732 case AST_OPTION_FAX_DETECT: 06733 cp = (char *) data; 06734 if (p->dsp) { 06735 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name); 06736 if (*cp) { 06737 p->dsp_features |= DSP_FEATURE_FAX_DETECT; 06738 } else { 06739 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 06740 } 06741 ast_dsp_set_features(p->dsp, p->dsp_features); 06742 } 06743 break; 06744 default: 06745 return -1; 06746 } 06747 errno = 0; 06748 06749 return 0; 06750 }
static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14867 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.
14868 { 14869 int channel; 14870 struct dahdi_pvt *tmp = NULL; 14871 struct dahdi_confinfo ci; 14872 struct dahdi_params ps; 14873 int x; 14874 14875 switch (cmd) { 14876 case CLI_INIT: 14877 e->command = "dahdi show channel"; 14878 e->usage = 14879 "Usage: dahdi show channel <chan num>\n" 14880 " Detailed information about a given channel\n"; 14881 return NULL; 14882 case CLI_GENERATE: 14883 return NULL; 14884 } 14885 14886 if (a->argc != 4) 14887 return CLI_SHOWUSAGE; 14888 14889 channel = atoi(a->argv[3]); 14890 14891 ast_mutex_lock(&iflock); 14892 for (tmp = iflist; tmp; tmp = tmp->next) { 14893 if (tmp->channel == channel) { 14894 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 14895 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 14896 ast_cli(a->fd, "Span: %d\n", tmp->span); 14897 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 14898 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 14899 ast_cli(a->fd, "Context: %s\n", tmp->context); 14900 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 14901 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 14902 #if defined(HAVE_PRI) 14903 #if defined(HAVE_PRI_SUBADDR) 14904 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr); 14905 #endif /* defined(HAVE_PRI_SUBADDR) */ 14906 #endif /* defined(HAVE_PRI) */ 14907 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 14908 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 14909 if (tmp->vars) { 14910 struct ast_variable *v; 14911 ast_cli(a->fd, "Variables:\n"); 14912 for (v = tmp->vars ; v ; v = v->next) 14913 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 14914 } 14915 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 14916 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 14917 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 14918 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 14919 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 14920 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)" : ""); 14921 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)" : ""); 14922 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)" : ""); 14923 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 14924 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 14925 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 14926 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 14927 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 14928 if (tmp->busydetect) { 14929 #if defined(BUSYDETECT_TONEONLY) 14930 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 14931 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 14932 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 14933 #endif 14934 #ifdef BUSYDETECT_DEBUG 14935 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 14936 #endif 14937 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 14938 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength); 14939 } 14940 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 14941 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 14942 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 14943 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 14944 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 14945 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 14946 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain); 14947 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc); 14948 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no"); 14949 ast_cli(a->fd, "Echo Cancellation:\n"); 14950 14951 if (tmp->echocancel.head.tap_length) { 14952 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 14953 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 14954 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 14955 } 14956 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 14957 } else { 14958 ast_cli(a->fd, "\tnone\n"); 14959 } 14960 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 14961 if (tmp->master) 14962 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 14963 for (x = 0; x < MAX_SLAVES; x++) { 14964 if (tmp->slaves[x]) 14965 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 14966 } 14967 #ifdef HAVE_OPENR2 14968 if (tmp->mfcr2) { 14969 char calldir[OR2_MAX_PATH]; 14970 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 14971 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 14972 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 14973 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 14974 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 14975 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 14976 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 14977 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 14978 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 14979 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 14980 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 14981 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 14982 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 14983 #endif 14984 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 14985 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 14986 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 14987 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 14988 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 14989 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 14990 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 14991 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 14992 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 14993 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 14994 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 14995 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 14996 } 14997 #endif 14998 #if defined(HAVE_SS7) 14999 if (tmp->ss7) { 15000 struct sig_ss7_chan *chan = tmp->sig_pvt; 15001 15002 ast_cli(a->fd, "CIC: %d\n", chan->cic); 15003 } 15004 #endif /* defined(HAVE_SS7) */ 15005 #ifdef HAVE_PRI 15006 if (tmp->pri) { 15007 struct sig_pri_chan *chan = tmp->sig_pvt; 15008 15009 ast_cli(a->fd, "PRI Flags: "); 15010 if (chan->resetting) 15011 ast_cli(a->fd, "Resetting "); 15012 if (chan->call) 15013 ast_cli(a->fd, "Call "); 15014 ast_cli(a->fd, "\n"); 15015 if (tmp->logicalspan) 15016 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 15017 else 15018 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 15019 } 15020 #endif 15021 memset(&ci, 0, sizeof(ci)); 15022 ps.channo = tmp->channel; 15023 if (tmp->subs[SUB_REAL].dfd > -1) { 15024 memset(&ci, 0, sizeof(ci)); 15025 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 15026 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 15027 } 15028 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 15029 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 15030 } 15031 memset(&ps, 0, sizeof(ps)); 15032 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 15033 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 15034 } else { 15035 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 15036 } 15037 } 15038 if (ISTRUNK(tmp)) { 15039 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 15040 if (!ast_strlen_zero(progzone)) 15041 ast_cli(a->fd, "Progress Zone: %s\n", progzone); 15042 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 15043 if(tmp->busydetect) { 15044 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount); 15045 if(tmp->busytonelength > 0) { 15046 ast_cli(a->fd, "Busy Pattern:\n"); 15047 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 15048 if (tmp->busyquietlength > 0) 15049 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 15050 else 15051 ast_cli(a->fd, " -- Detect Tone Only\n"); 15052 if(tmp->busyfuzziness > 0) 15053 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 15054 } 15055 } 15056 } 15057 ast_mutex_unlock(&iflock); 15058 return CLI_SUCCESS; 15059 } 15060 } 15061 ast_mutex_unlock(&iflock); 15062 15063 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15064 return CLI_FAILURE; 15065 }
static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14781 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.
14782 { 14783 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 14784 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 14785 unsigned int targetnum = 0; 14786 int filtertype = 0; 14787 struct dahdi_pvt *tmp = NULL; 14788 char tmps[20] = ""; 14789 char statestr[20] = ""; 14790 char blockstr[20] = ""; 14791 14792 switch (cmd) { 14793 case CLI_INIT: 14794 e->command = "dahdi show channels [group|context]"; 14795 e->usage = 14796 "Usage: dahdi show channels [ group <group> | context <context> ]\n" 14797 " Shows a list of available channels with optional filtering\n" 14798 " <group> must be a number between 0 and 63\n"; 14799 return NULL; 14800 case CLI_GENERATE: 14801 return NULL; 14802 } 14803 14804 /* syntax: dahdi show channels [ group <group> | context <context> ] */ 14805 14806 if (!((a->argc == 3) || (a->argc == 5))) 14807 return CLI_SHOWUSAGE; 14808 14809 if (a->argc == 5) { 14810 if (!strcasecmp(a->argv[3], "group")) { 14811 targetnum = atoi(a->argv[4]); 14812 if ((targetnum < 0) || (targetnum > 63)) 14813 return CLI_SHOWUSAGE; 14814 targetnum = 1 << targetnum; 14815 filtertype = 1; 14816 } else if (!strcasecmp(a->argv[3], "context")) { 14817 filtertype = 2; 14818 } 14819 } 14820 14821 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 14822 ast_mutex_lock(&iflock); 14823 for (tmp = iflist; tmp; tmp = tmp->next) { 14824 if (filtertype) { 14825 switch(filtertype) { 14826 case 1: /* dahdi show channels group <group> */ 14827 if (!(tmp->group & targetnum)) { 14828 continue; 14829 } 14830 break; 14831 case 2: /* dahdi show channels context <context> */ 14832 if (strcasecmp(tmp->context, a->argv[4])) { 14833 continue; 14834 } 14835 break; 14836 default: 14837 ; 14838 } 14839 } 14840 if (tmp->channel > 0) { 14841 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 14842 } else 14843 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 14844 14845 if (tmp->locallyblocked) 14846 blockstr[0] = 'L'; 14847 else 14848 blockstr[0] = ' '; 14849 14850 if (tmp->remotelyblocked) 14851 blockstr[1] = 'R'; 14852 else 14853 blockstr[1] = ' '; 14854 14855 blockstr[2] = '\0'; 14856 14857 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 14858 14859 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 14860 } 14861 ast_mutex_unlock(&iflock); 14862 return CLI_SUCCESS; 14863 #undef FORMAT 14864 #undef FORMAT2 14865 }
static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15104 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.
15105 { 15106 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 15107 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 15108 int span; 15109 int res; 15110 char alarmstr[50]; 15111 15112 int ctl; 15113 struct dahdi_spaninfo s; 15114 15115 switch (cmd) { 15116 case CLI_INIT: 15117 e->command = "dahdi show status"; 15118 e->usage = 15119 "Usage: dahdi show status\n" 15120 " Shows a list of DAHDI cards with status\n"; 15121 return NULL; 15122 case CLI_GENERATE: 15123 return NULL; 15124 } 15125 ctl = open("/dev/dahdi/ctl", O_RDWR); 15126 if (ctl < 0) { 15127 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 15128 return CLI_FAILURE; 15129 } 15130 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 15131 15132 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 15133 s.spanno = span; 15134 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 15135 if (res) { 15136 continue; 15137 } 15138 alarmstr[0] = '\0'; 15139 if (s.alarms > 0) { 15140 if (s.alarms & DAHDI_ALARM_BLUE) 15141 strcat(alarmstr, "BLU/"); 15142 if (s.alarms & DAHDI_ALARM_YELLOW) 15143 strcat(alarmstr, "YEL/"); 15144 if (s.alarms & DAHDI_ALARM_RED) 15145 strcat(alarmstr, "RED/"); 15146 if (s.alarms & DAHDI_ALARM_LOOPBACK) 15147 strcat(alarmstr, "LB/"); 15148 if (s.alarms & DAHDI_ALARM_RECOVER) 15149 strcat(alarmstr, "REC/"); 15150 if (s.alarms & DAHDI_ALARM_NOTOPEN) 15151 strcat(alarmstr, "NOP/"); 15152 if (!strlen(alarmstr)) 15153 strcat(alarmstr, "UUU/"); 15154 if (strlen(alarmstr)) { 15155 /* Strip trailing / */ 15156 alarmstr[strlen(alarmstr) - 1] = '\0'; 15157 } 15158 } else { 15159 if (s.numchans) 15160 strcpy(alarmstr, "OK"); 15161 else 15162 strcpy(alarmstr, "UNCONFIGURED"); 15163 } 15164 15165 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 15166 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 15167 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 15168 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 15169 "CAS", 15170 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 15171 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 15172 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 15173 "Unk", 15174 s.lineconfig & DAHDI_CONFIG_CRC4 ? 15175 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 15176 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "", 15177 lbostr[s.lbo] 15178 ); 15179 } 15180 close(ctl); 15181 15182 return CLI_SUCCESS; 15183 #undef FORMAT 15184 #undef FORMAT2 15185 }
static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15187 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.
15188 { 15189 int pseudo_fd = -1; 15190 struct dahdi_versioninfo vi; 15191 15192 switch (cmd) { 15193 case CLI_INIT: 15194 e->command = "dahdi show version"; 15195 e->usage = 15196 "Usage: dahdi show version\n" 15197 " Shows the DAHDI version in use\n"; 15198 return NULL; 15199 case CLI_GENERATE: 15200 return NULL; 15201 } 15202 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 15203 ast_cli(a->fd, "Failed to open control file to get version.\n"); 15204 return CLI_SUCCESS; 15205 } 15206 15207 strcpy(vi.version, "Unknown"); 15208 strcpy(vi.echo_canceller, "Unknown"); 15209 15210 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 15211 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 15212 else 15213 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 15214 15215 close(pseudo_fd); 15216 15217 return CLI_SUCCESS; 15218 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 4462 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.
04463 { 04464 static char buf[256]; 04465 switch (sig) { 04466 case SIG_EM: 04467 return "E & M Immediate"; 04468 case SIG_EMWINK: 04469 return "E & M Wink"; 04470 case SIG_EM_E1: 04471 return "E & M E1"; 04472 case SIG_FEATD: 04473 return "Feature Group D (DTMF)"; 04474 case SIG_FEATDMF: 04475 return "Feature Group D (MF)"; 04476 case SIG_FEATDMF_TA: 04477 return "Feature Groud D (MF) Tandem Access"; 04478 case SIG_FEATB: 04479 return "Feature Group B (MF)"; 04480 case SIG_E911: 04481 return "E911 (MF)"; 04482 case SIG_FGC_CAMA: 04483 return "FGC/CAMA (Dialpulse)"; 04484 case SIG_FGC_CAMAMF: 04485 return "FGC/CAMA (MF)"; 04486 case SIG_FXSLS: 04487 return "FXS Loopstart"; 04488 case SIG_FXSGS: 04489 return "FXS Groundstart"; 04490 case SIG_FXSKS: 04491 return "FXS Kewlstart"; 04492 case SIG_FXOLS: 04493 return "FXO Loopstart"; 04494 case SIG_FXOGS: 04495 return "FXO Groundstart"; 04496 case SIG_FXOKS: 04497 return "FXO Kewlstart"; 04498 case SIG_PRI: 04499 return "ISDN PRI"; 04500 case SIG_BRI: 04501 return "ISDN BRI Point to Point"; 04502 case SIG_BRI_PTMP: 04503 return "ISDN BRI Point to MultiPoint"; 04504 case SIG_SS7: 04505 return "SS7"; 04506 case SIG_MFCR2: 04507 return "MFC/R2"; 04508 case SIG_SF: 04509 return "SF (Tone) Immediate"; 04510 case SIG_SFWINK: 04511 return "SF (Tone) Wink"; 04512 case SIG_SF_FEATD: 04513 return "SF (Tone) with Feature Group D (DTMF)"; 04514 case SIG_SF_FEATDMF: 04515 return "SF (Tone) with Feature Group D (MF)"; 04516 case SIG_SF_FEATB: 04517 return "SF (Tone) with Feature Group B (MF)"; 04518 case 0: 04519 return "Pseudo"; 04520 default: 04521 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 04522 return buf; 04523 } 04524 }
static int dahdi_sig_pri_lib_handles | ( | int | signaling | ) | [inline, static] |
Definition at line 1534 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_queryoption(), dahdi_read(), dahdi_request(), and dahdi_setoption().
01535 { 01536 int handles; 01537 01538 switch (signaling) { 01539 case SIG_PRI_LIB_HANDLE_CASES: 01540 handles = 1; 01541 break; 01542 default: 01543 handles = 0; 01544 break; 01545 } 01546 01547 return handles; 01548 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 14608 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().
14609 { 14610 struct dahdi_pvt *p; 14611 retry: 14612 ast_mutex_lock(&iflock); 14613 for (p = iflist; p; p = p->next) { 14614 ast_mutex_lock(&p->lock); 14615 if (p->owner && !p->restartpending) { 14616 if (ast_channel_trylock(p->owner)) { 14617 if (option_debug > 2) 14618 ast_verbose("Avoiding deadlock\n"); 14619 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 14620 ast_mutex_unlock(&p->lock); 14621 ast_mutex_unlock(&iflock); 14622 goto retry; 14623 } 14624 if (option_debug > 2) 14625 ast_verbose("Softhanging up on %s\n", p->owner->name); 14626 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 14627 p->restartpending = 1; 14628 num_restart_pending++; 14629 ast_channel_unlock(p->owner); 14630 } 14631 ast_mutex_unlock(&p->lock); 14632 } 14633 ast_mutex_unlock(&iflock); 14634 }
static int dahdi_status_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 17835 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.
17837 { 17838 int ctl, res, span; 17839 struct ast_data *data_span, *data_alarms; 17840 struct dahdi_spaninfo s; 17841 17842 ctl = open("/dev/dahdi/ctl", O_RDWR); 17843 if (ctl < 0) { 17844 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 17845 return -1; 17846 } 17847 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 17848 s.spanno = span; 17849 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 17850 if (res) { 17851 continue; 17852 } 17853 17854 data_span = ast_data_add_node(data_root, "span"); 17855 if (!data_span) { 17856 continue; 17857 } 17858 ast_data_add_str(data_span, "description", s.desc); 17859 17860 /* insert the alarms status */ 17861 data_alarms = ast_data_add_node(data_span, "alarms"); 17862 if (!data_alarms) { 17863 continue; 17864 } 17865 17866 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE); 17867 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW); 17868 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED); 17869 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK); 17870 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER); 17871 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN); 17872 17873 ast_data_add_int(data_span, "irqmisses", s.irqmisses); 17874 ast_data_add_int(data_span, "bpviol", s.bpvcount); 17875 ast_data_add_int(data_span, "crc4", s.crc4count); 17876 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 17877 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 17878 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 17879 "CAS"); 17880 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 17881 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 17882 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 17883 "Unknown"); 17884 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ? 17885 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : 17886 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : ""); 17887 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]); 17888 17889 /* if this span doesn't match remove it. */ 17890 if (!ast_data_search_match(search, data_span)) { 17891 ast_data_remove_node(data_root, data_span); 17892 } 17893 } 17894 close(ctl); 17895 17896 return 0; 17897 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4804 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().
04805 { 04806 int x; 04807 int res; 04808 04809 if (p && p->echocanon && p->echotraining) { 04810 x = p->echotraining; 04811 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 04812 if (res) 04813 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 04814 else 04815 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 04816 } else { 04817 ast_debug(1, "No echo training requested\n"); 04818 } 04819 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 6919 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().
06920 { 06921 /* Unlink a specific slave or all slaves/masters from a given master */ 06922 int x; 06923 int hasslaves; 06924 if (!master) 06925 return; 06926 if (needlock) { 06927 ast_mutex_lock(&master->lock); 06928 if (slave) { 06929 while (ast_mutex_trylock(&slave->lock)) { 06930 DEADLOCK_AVOIDANCE(&master->lock); 06931 } 06932 } 06933 } 06934 hasslaves = 0; 06935 for (x = 0; x < MAX_SLAVES; x++) { 06936 if (master->slaves[x]) { 06937 if (!slave || (master->slaves[x] == slave)) { 06938 /* Take slave out of the conference */ 06939 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 06940 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 06941 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 06942 master->slaves[x]->master = NULL; 06943 master->slaves[x] = NULL; 06944 } else 06945 hasslaves = 1; 06946 } 06947 if (!hasslaves) 06948 master->inconference = 0; 06949 } 06950 if (!slave) { 06951 if (master->master) { 06952 /* Take master out of the conference */ 06953 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 06954 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 06955 hasslaves = 0; 06956 for (x = 0; x < MAX_SLAVES; x++) { 06957 if (master->master->slaves[x] == master) 06958 master->master->slaves[x] = NULL; 06959 else if (master->master->slaves[x]) 06960 hasslaves = 1; 06961 } 06962 if (!hasslaves) 06963 master->master->inconference = 0; 06964 } 06965 master->master = NULL; 06966 } 06967 update_conf(master); 06968 if (needlock) { 06969 if (slave) 06970 ast_mutex_unlock(&slave->lock); 06971 ast_mutex_unlock(&master->lock); 06972 } 06973 }
static void dahdi_unlink_pri_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5534 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().
05535 { 05536 unsigned idx; 05537 struct sig_pri_span *pri; 05538 05539 pri = pvt->pri; 05540 if (!pri) { 05541 /* Not PRI signaling so cannot be in a PRI private pointer array. */ 05542 return; 05543 } 05544 ast_mutex_lock(&pri->lock); 05545 for (idx = 0; idx < pri->numchans; ++idx) { 05546 if (pri->pvts[idx] == pvt->sig_pvt) { 05547 pri->pvts[idx] = NULL; 05548 ast_mutex_unlock(&pri->lock); 05549 return; 05550 } 05551 } 05552 ast_mutex_unlock(&pri->lock); 05553 }
static int dahdi_version_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 17938 of file chan_dahdi.c.
References ast_data_add_str(), ast_log(), and errno.
17940 { 17941 int pseudo_fd = -1; 17942 struct dahdi_versioninfo vi = { 17943 .version = "Unknown", 17944 .echo_canceller = "Unknown" 17945 }; 17946 17947 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 17948 ast_log(LOG_ERROR, "Failed to open control file to get version.\n"); 17949 return -1; 17950 } 17951 17952 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) { 17953 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno)); 17954 } 17955 17956 close(pseudo_fd); 17957 17958 ast_data_add_str(data_root, "value", vi.version); 17959 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller); 17960 17961 return 0; 17962 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 479 of file chan_dahdi.c.
00480 { 00481 int i, j = 0; 00482 i = DAHDI_IOMUX_SIGEVENT; 00483 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00484 return -1; 00485 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00486 return -1; 00487 return j; 00488 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 9526 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by analog_ss_thread(), and my_wink().
09527 { 09528 int j; 09529 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 09530 for (;;) 09531 { 09532 /* set bits of interest */ 09533 j = DAHDI_IOMUX_SIGEVENT; 09534 /* wait for some happening */ 09535 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 09536 /* exit loop if we have it */ 09537 if (j & DAHDI_IOMUX_SIGEVENT) break; 09538 } 09539 /* get the event info */ 09540 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 09541 return 0; 09542 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 9062 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.
09063 { 09064 struct dahdi_pvt *p = ast->tech_pvt; 09065 int res; 09066 int idx; 09067 idx = dahdi_get_index(ast, p, 0); 09068 if (idx < 0) { 09069 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 09070 return -1; 09071 } 09072 09073 /* Write a frame of (presumably voice) data */ 09074 if (frame->frametype != AST_FRAME_VOICE) { 09075 if (frame->frametype != AST_FRAME_IMAGE) 09076 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 09077 return 0; 09078 } 09079 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) && 09080 (frame->subclass.codec != AST_FORMAT_ULAW) && 09081 (frame->subclass.codec != AST_FORMAT_ALAW)) { 09082 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 09083 return -1; 09084 } 09085 if (p->dialing) { 09086 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 09087 return 0; 09088 } 09089 if (!p->owner) { 09090 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 09091 return 0; 09092 } 09093 if (p->cidspill) { 09094 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n", 09095 ast->name); 09096 return 0; 09097 } 09098 /* Return if it's not valid data */ 09099 if (!frame->data.ptr || !frame->datalen) 09100 return 0; 09101 09102 if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 09103 if (!p->subs[idx].linear) { 09104 p->subs[idx].linear = 1; 09105 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09106 if (res) 09107 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 09108 } 09109 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 09110 } else { 09111 /* x-law already */ 09112 if (p->subs[idx].linear) { 09113 p->subs[idx].linear = 0; 09114 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 09115 if (res) 09116 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 09117 } 09118 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 09119 } 09120 if (res < 0) { 09121 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 09122 return -1; 09123 } 09124 return 0; 09125 }
static enum analog_event dahdievent_to_analogevent | ( | int | event | ) | [static] |
Definition at line 2631 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().
02632 { 02633 enum analog_event res; 02634 02635 switch (event) { 02636 case DAHDI_EVENT_ONHOOK: 02637 res = ANALOG_EVENT_ONHOOK; 02638 break; 02639 case DAHDI_EVENT_RINGOFFHOOK: 02640 res = ANALOG_EVENT_RINGOFFHOOK; 02641 break; 02642 case DAHDI_EVENT_WINKFLASH: 02643 res = ANALOG_EVENT_WINKFLASH; 02644 break; 02645 case DAHDI_EVENT_ALARM: 02646 res = ANALOG_EVENT_ALARM; 02647 break; 02648 case DAHDI_EVENT_NOALARM: 02649 res = ANALOG_EVENT_NOALARM; 02650 break; 02651 case DAHDI_EVENT_DIALCOMPLETE: 02652 res = ANALOG_EVENT_DIALCOMPLETE; 02653 break; 02654 case DAHDI_EVENT_RINGERON: 02655 res = ANALOG_EVENT_RINGERON; 02656 break; 02657 case DAHDI_EVENT_RINGEROFF: 02658 res = ANALOG_EVENT_RINGEROFF; 02659 break; 02660 case DAHDI_EVENT_HOOKCOMPLETE: 02661 res = ANALOG_EVENT_HOOKCOMPLETE; 02662 break; 02663 case DAHDI_EVENT_PULSE_START: 02664 res = ANALOG_EVENT_PULSE_START; 02665 break; 02666 case DAHDI_EVENT_POLARITY: 02667 res = ANALOG_EVENT_POLARITY; 02668 break; 02669 case DAHDI_EVENT_RINGBEGIN: 02670 res = ANALOG_EVENT_RINGBEGIN; 02671 break; 02672 case DAHDI_EVENT_EC_DISABLED: 02673 res = ANALOG_EVENT_EC_DISABLED; 02674 break; 02675 case DAHDI_EVENT_REMOVED: 02676 res = ANALOG_EVENT_REMOVED; 02677 break; 02678 case DAHDI_EVENT_NEONMWI_ACTIVE: 02679 res = ANALOG_EVENT_NEONMWI_ACTIVE; 02680 break; 02681 case DAHDI_EVENT_NEONMWI_INACTIVE: 02682 res = ANALOG_EVENT_NEONMWI_INACTIVE; 02683 break; 02684 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE 02685 case DAHDI_EVENT_TX_CED_DETECTED: 02686 res = ANALOG_EVENT_TX_CED_DETECTED; 02687 break; 02688 case DAHDI_EVENT_RX_CED_DETECTED: 02689 res = ANALOG_EVENT_RX_CED_DETECTED; 02690 break; 02691 case DAHDI_EVENT_EC_NLP_DISABLED: 02692 res = ANALOG_EVENT_EC_NLP_DISABLED; 02693 break; 02694 case DAHDI_EVENT_EC_NLP_ENABLED: 02695 res = ANALOG_EVENT_EC_NLP_ENABLED; 02696 break; 02697 #endif 02698 case DAHDI_EVENT_PULSEDIGIT: 02699 res = ANALOG_EVENT_PULSEDIGIT; 02700 break; 02701 case DAHDI_EVENT_DTMFDOWN: 02702 res = ANALOG_EVENT_DTMFDOWN; 02703 break; 02704 case DAHDI_EVENT_DTMFUP: 02705 res = ANALOG_EVENT_DTMFUP; 02706 break; 02707 default: 02708 switch(event & 0xFFFF0000) { 02709 case DAHDI_EVENT_PULSEDIGIT: 02710 case DAHDI_EVENT_DTMFDOWN: 02711 case DAHDI_EVENT_DTMFUP: 02712 /* The event includes a digit number in the low word. 02713 * Converting it to a 'enum analog_event' would remove 02714 * that information. Thus it is returned as-is. 02715 */ 02716 return event; 02717 } 02718 02719 res = ANALOG_EVENT_ERROR; 02720 break; 02721 } 02722 02723 return res; 02724 }
static enum analog_sigtype dahdisig_to_analogsig | ( | int | sig | ) | [static] |
Definition at line 1550 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.
01551 { 01552 switch (sig) { 01553 case SIG_FXOLS: 01554 return ANALOG_SIG_FXOLS; 01555 case SIG_FXOGS: 01556 return ANALOG_SIG_FXOGS; 01557 case SIG_FXOKS: 01558 return ANALOG_SIG_FXOKS; 01559 case SIG_FXSLS: 01560 return ANALOG_SIG_FXSLS; 01561 case SIG_FXSGS: 01562 return ANALOG_SIG_FXSGS; 01563 case SIG_FXSKS: 01564 return ANALOG_SIG_FXSKS; 01565 case SIG_EMWINK: 01566 return ANALOG_SIG_EMWINK; 01567 case SIG_EM: 01568 return ANALOG_SIG_EM; 01569 case SIG_EM_E1: 01570 return ANALOG_SIG_EM_E1; 01571 case SIG_FEATD: 01572 return ANALOG_SIG_FEATD; 01573 case SIG_FEATDMF: 01574 return ANALOG_SIG_FEATDMF; 01575 case SIG_E911: 01576 return SIG_E911; 01577 case SIG_FGC_CAMA: 01578 return ANALOG_SIG_FGC_CAMA; 01579 case SIG_FGC_CAMAMF: 01580 return ANALOG_SIG_FGC_CAMAMF; 01581 case SIG_FEATB: 01582 return ANALOG_SIG_FEATB; 01583 case SIG_SFWINK: 01584 return ANALOG_SIG_SFWINK; 01585 case SIG_SF: 01586 return ANALOG_SIG_SF; 01587 case SIG_SF_FEATD: 01588 return ANALOG_SIG_SF_FEATD; 01589 case SIG_SF_FEATDMF: 01590 return ANALOG_SIG_SF_FEATDMF; 01591 case SIG_FEATDMF_TA: 01592 return ANALOG_SIG_FEATDMF_TA; 01593 case SIG_SF_FEATB: 01594 return ANALOG_SIG_FEATB; 01595 default: 01596 return -1; 01597 } 01598 }
static void deep_copy_dahdi_chan_conf | ( | struct dahdi_chan_conf * | dest, | |
const struct dahdi_chan_conf * | src | |||
) | [static] |
Definition at line 17545 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().
17546 { 17547 struct ast_cc_config_params *cc_params; 17548 17549 cc_params = dest->chan.cc_params; 17550 *dest = *src; 17551 dest->chan.cc_params = cc_params; 17552 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params); 17553 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 5687 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().
05688 { 05689 int chan; 05690 #if defined(HAVE_PRI) 05691 unsigned span; 05692 struct sig_pri_span *pri; 05693 #endif /* defined(HAVE_PRI) */ 05694 struct dahdi_pvt *p; 05695 05696 while (num_restart_pending) { 05697 usleep(1); 05698 } 05699 05700 ast_mutex_lock(&iflock); 05701 /* Destroy all the interfaces and free their memory */ 05702 while (iflist) { 05703 p = iflist; 05704 05705 chan = p->channel; 05706 #if defined(HAVE_PRI_SERVICE_MESSAGES) 05707 { 05708 char db_chan_name[20]; 05709 char db_answer[5]; 05710 char state; 05711 int why = -1; 05712 05713 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan); 05714 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 05715 sscanf(db_answer, "%1c:%30d", &state, &why); 05716 } 05717 if (!why) { 05718 /* SRVST persistence is not required */ 05719 ast_db_del(db_chan_name, SRVST_DBKEY); 05720 } 05721 } 05722 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 05723 /* Free associated memory */ 05724 destroy_dahdi_pvt(p); 05725 ast_verb(3, "Unregistered channel %d\n", chan); 05726 } 05727 ifcount = 0; 05728 ast_mutex_unlock(&iflock); 05729 05730 #if defined(HAVE_PRI) 05731 /* Destroy all of the no B channel interface lists */ 05732 for (span = 0; span < NUM_SPANS; ++span) { 05733 if (!pris[span].dchannels[0]) { 05734 break; 05735 } 05736 pri = &pris[span].pri; 05737 ast_mutex_lock(&pri->lock); 05738 while (pri->no_b_chan_iflist) { 05739 p = pri->no_b_chan_iflist; 05740 05741 /* Free associated memory */ 05742 destroy_dahdi_pvt(p); 05743 } 05744 ast_mutex_unlock(&pri->lock); 05745 } 05746 #endif /* defined(HAVE_PRI) */ 05747 }
static void destroy_channel | ( | struct dahdi_pvt * | cur, | |
int | now | |||
) | [static] |
Definition at line 5669 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().
05670 { 05671 int i; 05672 05673 if (!now) { 05674 /* Do not destroy the channel now if it is owned by someone. */ 05675 if (cur->owner) { 05676 return; 05677 } 05678 for (i = 0; i < 3; i++) { 05679 if (cur->subs[i].owner) { 05680 return; 05681 } 05682 } 05683 } 05684 destroy_dahdi_pvt(cur); 05685 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 5599 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().
05600 { 05601 struct dahdi_pvt *p = pvt; 05602 05603 if (p->manages_span_alarms) { 05604 struct dahdi_pvt *next = find_next_iface_in_span(p); 05605 if (next) { 05606 next->manages_span_alarms = 1; 05607 } 05608 } 05609 05610 /* Remove channel from the list */ 05611 #if defined(HAVE_PRI) 05612 dahdi_unlink_pri_pvt(p); 05613 #endif /* defined(HAVE_PRI) */ 05614 #if defined(HAVE_SS7) 05615 dahdi_unlink_ss7_pvt(p); 05616 #endif /* defined(HAVE_SS7) */ 05617 switch (pvt->which_iflist) { 05618 case DAHDI_IFLIST_NONE: 05619 break; 05620 case DAHDI_IFLIST_MAIN: 05621 dahdi_iflist_extract(p); 05622 break; 05623 #if defined(HAVE_PRI) 05624 case DAHDI_IFLIST_NO_B_CHAN: 05625 if (p->pri) { 05626 dahdi_nobch_extract(p->pri, p); 05627 } 05628 break; 05629 #endif /* defined(HAVE_PRI) */ 05630 } 05631 05632 if (p->sig_pvt) { 05633 if (analog_lib_handles(p->sig, 0, 0)) { 05634 analog_delete(p->sig_pvt); 05635 } 05636 switch (p->sig) { 05637 #if defined(HAVE_PRI) 05638 case SIG_PRI_LIB_HANDLE_CASES: 05639 sig_pri_chan_delete(p->sig_pvt); 05640 break; 05641 #endif /* defined(HAVE_PRI) */ 05642 #if defined(HAVE_SS7) 05643 case SIG_SS7: 05644 sig_ss7_chan_delete(p->sig_pvt); 05645 break; 05646 #endif /* defined(HAVE_SS7) */ 05647 default: 05648 break; 05649 } 05650 } 05651 ast_free(p->cidspill); 05652 if (p->use_smdi) 05653 ast_smdi_interface_unref(p->smdi_iface); 05654 if (p->mwi_event_sub) 05655 ast_event_unsubscribe(p->mwi_event_sub); 05656 if (p->vars) { 05657 ast_variables_destroy(p->vars); 05658 } 05659 if (p->cc_params) { 05660 ast_cc_config_params_destroy(p->cc_params); 05661 } 05662 ast_mutex_destroy(&p->lock); 05663 dahdi_close_sub(p, SUB_REAL); 05664 if (p->owner) 05665 p->owner->tech_pvt = NULL; 05666 ast_free(p); 05667 }
static struct dahdi_pvt* determine_starting_point | ( | const char * | data, | |
struct dahdi_starting_point * | param | |||
) | [static] |
Definition at line 13111 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().
13112 { 13113 char *dest; 13114 char *s; 13115 int x; 13116 int res = 0; 13117 struct dahdi_pvt *p; 13118 char *subdir = NULL; 13119 AST_DECLARE_APP_ARGS(args, 13120 AST_APP_ARG(group); /* channel/group token */ 13121 //AST_APP_ARG(ext); /* extension token */ 13122 //AST_APP_ARG(opts); /* options token */ 13123 AST_APP_ARG(other); /* Any remining unused arguments */ 13124 ); 13125 13126 /* 13127 * data is ---v 13128 * Dial(DAHDI/pseudo[/extension[/options]]) 13129 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]]) 13130 * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]]) 13131 * Dial(DAHDI/i<span>[/extension[/options]]) 13132 * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]) 13133 * 13134 * i - ISDN span channel restriction. 13135 * Used by CC to ensure that the CC recall goes out the same span. 13136 * Also to make ISDN channel names dialable when the sequence number 13137 * is stripped off. (Used by DTMF attended transfer feature.) 13138 * 13139 * g - channel group allocation search forward 13140 * G - channel group allocation search backward 13141 * r - channel group allocation round robin search forward 13142 * R - channel group allocation round robin search backward 13143 * 13144 * c - Wait for DTMF digit to confirm answer 13145 * r<cadance#> - Set distintive ring cadance number 13146 * d - Force bearer capability for ISDN/SS7 call to digital. 13147 */ 13148 13149 if (data) { 13150 dest = ast_strdupa(data); 13151 } else { 13152 ast_log(LOG_WARNING, "Channel requested with no data\n"); 13153 return NULL; 13154 } 13155 AST_NONSTANDARD_APP_ARGS(args, dest, '/'); 13156 if (!args.argc || ast_strlen_zero(args.group)) { 13157 ast_log(LOG_WARNING, "No channel/group specified\n"); 13158 return NULL; 13159 } 13160 13161 /* Initialize the output parameters */ 13162 memset(param, 0, sizeof(*param)); 13163 param->channelmatch = -1; 13164 13165 if (strchr(args.group, '!') != NULL) { 13166 char *prev = args.group; 13167 while ((s = strchr(prev, '!')) != NULL) { 13168 *s++ = '/'; 13169 prev = s; 13170 } 13171 *(prev - 1) = '\0'; 13172 subdir = args.group; 13173 args.group = prev; 13174 } else if (args.group[0] == 'i') { 13175 /* Extract the ISDN span channel restriction specifier. */ 13176 res = sscanf(args.group + 1, "%30d", &x); 13177 if (res < 1) { 13178 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data); 13179 return NULL; 13180 } 13181 param->span = x; 13182 13183 /* Remove the ISDN span channel restriction specifier. */ 13184 s = strchr(args.group, '-'); 13185 if (!s) { 13186 /* Search all groups since we are ISDN span restricted. */ 13187 return iflist; 13188 } 13189 args.group = s + 1; 13190 res = 0; 13191 } 13192 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { 13193 /* Retrieve the group number */ 13194 s = args.group + 1; 13195 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13196 if (res < 1) { 13197 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data); 13198 return NULL; 13199 } 13200 param->groupmatch = ((ast_group_t) 1 << x); 13201 13202 if (toupper(args.group[0]) == 'G') { 13203 if (args.group[0] == 'G') { 13204 param->backwards = 1; 13205 p = ifend; 13206 } else 13207 p = iflist; 13208 } else { 13209 if (ARRAY_LEN(round_robin) <= x) { 13210 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n", 13211 x, data); 13212 return NULL; 13213 } 13214 if (args.group[0] == 'R') { 13215 param->backwards = 1; 13216 p = round_robin[x] ? round_robin[x]->prev : ifend; 13217 if (!p) 13218 p = ifend; 13219 } else { 13220 p = round_robin[x] ? round_robin[x]->next : iflist; 13221 if (!p) 13222 p = iflist; 13223 } 13224 param->roundrobin = 1; 13225 param->rr_starting_point = x; 13226 } 13227 } else { 13228 s = args.group; 13229 if (!strcasecmp(s, "pseudo")) { 13230 /* Special case for pseudo */ 13231 x = CHAN_PSEUDO; 13232 param->channelmatch = x; 13233 } else { 13234 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance); 13235 if (res < 1) { 13236 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data); 13237 return NULL; 13238 } else { 13239 param->channelmatch = x; 13240 } 13241 } 13242 if (subdir) { 13243 char path[PATH_MAX]; 13244 struct stat stbuf; 13245 13246 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d", 13247 subdir, param->channelmatch); 13248 if (stat(path, &stbuf) < 0) { 13249 ast_log(LOG_WARNING, "stat(%s) failed: %s\n", 13250 path, strerror(errno)); 13251 return NULL; 13252 } 13253 if (!S_ISCHR(stbuf.st_mode)) { 13254 ast_log(LOG_ERROR, "%s: Not a character device file\n", 13255 path); 13256 return NULL; 13257 } 13258 param->channelmatch = minor(stbuf.st_rdev); 13259 } 13260 13261 p = iflist; 13262 } 13263 13264 if (param->opt == 'r' && res < 3) { 13265 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data); 13266 param->opt = '\0'; 13267 } 13268 13269 return p; 13270 }
static int device2chan | ( | const char * | subdir, | |
int | channel, | |||
char * | path, | |||
int | pathlen | |||
) | [static] |
Definition at line 11894 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, and LOG_ERROR.
Referenced by build_channels().
11895 { 11896 struct stat stbuf; 11897 int num; 11898 11899 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel); 11900 if (stat(path, &stbuf) < 0) { 11901 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno)); 11902 return -errno; 11903 } 11904 if (!S_ISCHR(stbuf.st_mode)) { 11905 ast_log(LOG_ERROR, "%s: Not a character device file\n", path); 11906 return -EINVAL; 11907 } 11908 num = minor(stbuf.st_rdev); 11909 ast_log(LOG_DEBUG, "%s -> %d\n", path, num); 11910 return num; 11911 11912 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 4301 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
04302 { 04303 if (isdigit(digit)) 04304 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 04305 else if (digit >= 'A' && digit <= 'D') 04306 return DAHDI_TONE_DTMF_A + (digit - 'A'); 04307 else if (digit >= 'a' && digit <= 'd') 04308 return DAHDI_TONE_DTMF_A + (digit - 'a'); 04309 else if (digit == '*') 04310 return DAHDI_TONE_DTMF_s; 04311 else if (digit == '#') 04312 return DAHDI_TONE_DTMF_p; 04313 else 04314 return -1; 04315 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6461 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().
06462 { 06463 int val = 0; 06464 06465 p->ignoredtmf = 1; 06466 06467 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06468 06469 if (!p->hardwaredtmf && p->dsp) { 06470 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 06471 ast_dsp_set_features(p->dsp, p->dsp_features); 06472 } 06473 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 11319 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().
11320 { 11321 int count, res, res2, spoint, pollres=0; 11322 struct dahdi_pvt *i; 11323 struct dahdi_pvt *last = NULL; 11324 struct dahdi_pvt *doomed; 11325 time_t thispass = 0, lastpass = 0; 11326 int found; 11327 char buf[1024]; 11328 struct pollfd *pfds=NULL; 11329 int lastalloc = -1; 11330 /* This thread monitors all the frame relay interfaces which are not yet in use 11331 (and thus do not have a separate thread) indefinitely */ 11332 /* From here on out, we die whenever asked */ 11333 #if 0 11334 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 11335 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 11336 return NULL; 11337 } 11338 ast_debug(1, "Monitor starting...\n"); 11339 #endif 11340 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11341 11342 for (;;) { 11343 /* Lock the interface list */ 11344 ast_mutex_lock(&iflock); 11345 if (!pfds || (lastalloc != ifcount)) { 11346 if (pfds) { 11347 ast_free(pfds); 11348 pfds = NULL; 11349 } 11350 if (ifcount) { 11351 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 11352 ast_mutex_unlock(&iflock); 11353 return NULL; 11354 } 11355 } 11356 lastalloc = ifcount; 11357 } 11358 /* Build the stuff we're going to poll on, that is the socket of every 11359 dahdi_pvt that does not have an associated owner channel */ 11360 count = 0; 11361 for (i = iflist; i; i = i->next) { 11362 ast_mutex_lock(&i->lock); 11363 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 11364 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11365 struct analog_pvt *p = i->sig_pvt; 11366 11367 if (!p) 11368 ast_log(LOG_ERROR, "No sig_pvt?\n"); 11369 11370 if (!p->owner && !p->subs[SUB_REAL].owner) { 11371 /* This needs to be watched, as it lacks an owner */ 11372 pfds[count].fd = i->subs[SUB_REAL].dfd; 11373 pfds[count].events = POLLPRI; 11374 pfds[count].revents = 0; 11375 /* Message waiting or r2 channels also get watched for reading */ 11376 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11377 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11378 pfds[count].events |= POLLIN; 11379 } 11380 count++; 11381 } 11382 } else { 11383 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 11384 /* This needs to be watched, as it lacks an owner */ 11385 pfds[count].fd = i->subs[SUB_REAL].dfd; 11386 pfds[count].events = POLLPRI; 11387 pfds[count].revents = 0; 11388 /* If we are monitoring for VMWI or sending CID, we need to 11389 read from the channel as well */ 11390 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 11391 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 11392 pfds[count].events |= POLLIN; 11393 } 11394 count++; 11395 } 11396 } 11397 } 11398 ast_mutex_unlock(&i->lock); 11399 } 11400 /* Okay, now that we know what to do, release the interface lock */ 11401 ast_mutex_unlock(&iflock); 11402 11403 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11404 pthread_testcancel(); 11405 /* Wait at least a second for something to happen */ 11406 res = poll(pfds, count, 1000); 11407 pthread_testcancel(); 11408 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11409 11410 /* Okay, poll has finished. Let's see what happened. */ 11411 if (res < 0) { 11412 if ((errno != EAGAIN) && (errno != EINTR)) 11413 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 11414 continue; 11415 } 11416 /* Alright, lock the interface list again, and let's look and see what has 11417 happened */ 11418 ast_mutex_lock(&iflock); 11419 found = 0; 11420 spoint = 0; 11421 lastpass = thispass; 11422 thispass = time(NULL); 11423 doomed = NULL; 11424 for (i = iflist;; i = i->next) { 11425 if (doomed) { 11426 int res; 11427 res = dahdi_destroy_channel_bynum(doomed->channel); 11428 if (res != RESULT_SUCCESS) { 11429 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 11430 } 11431 doomed = NULL; 11432 } 11433 if (!i) { 11434 break; 11435 } 11436 11437 if (thispass != lastpass) { 11438 if (!found && ((i == last) || ((i == iflist) && !last))) { 11439 last = i; 11440 if (last) { 11441 struct analog_pvt *analog_p = last->sig_pvt; 11442 /* Only allow MWI to be initiated on a quiescent fxs port */ 11443 if (analog_p 11444 && !last->mwisendactive 11445 && (last->sig & __DAHDI_SIG_FXO) 11446 && !analog_p->fxsoffhookstate 11447 && !last->owner 11448 && !ast_strlen_zero(last->mailbox) 11449 && (thispass - analog_p->onhooktime > 3)) { 11450 res = has_voicemail(last); 11451 if (analog_p->msgstate != res) { 11452 /* Set driver resources for signalling VMWI */ 11453 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 11454 if (res2) { 11455 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 11456 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 11457 } 11458 /* If enabled for FSK spill then initiate it */ 11459 if (mwi_send_init(last)) { 11460 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 11461 } 11462 analog_p->msgstate = res; 11463 found ++; 11464 } 11465 } 11466 last = last->next; 11467 } 11468 } 11469 } 11470 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 11471 if (i->radio && !i->owner) 11472 { 11473 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11474 if (res) 11475 { 11476 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 11477 /* Don't hold iflock while handling init events */ 11478 ast_mutex_unlock(&iflock); 11479 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11480 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11481 else 11482 doomed = handle_init_event(i, res); 11483 ast_mutex_lock(&iflock); 11484 } 11485 continue; 11486 } 11487 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 11488 if (pollres & POLLIN) { 11489 if (i->owner || i->subs[SUB_REAL].owner) { 11490 #ifdef HAVE_PRI 11491 if (!i->pri) 11492 #endif 11493 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 11494 continue; 11495 } 11496 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) { 11497 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 11498 continue; 11499 } 11500 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 11501 if (res > 0) { 11502 if (i->mwimonitor_fsk) { 11503 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 11504 pthread_attr_t attr; 11505 pthread_t threadid; 11506 struct mwi_thread_data *mtd; 11507 11508 pthread_attr_init(&attr); 11509 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11510 11511 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 11512 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 11513 mtd->pvt = i; 11514 memcpy(mtd->buf, buf, res); 11515 mtd->len = res; 11516 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 11517 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 11518 ast_free(mtd); 11519 } 11520 i->mwimonitoractive = 1; 11521 } 11522 } 11523 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 11524 } else if (i->cid_start == CID_START_DTMF_NOALERT) { 11525 int energy; 11526 struct timeval now; 11527 /* State machine dtmfcid_holdoff_state allows for the line to settle 11528 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 11529 */ 11530 if (1 == i->dtmfcid_holdoff_state) { 11531 gettimeofday(&i->dtmfcid_delay, NULL); 11532 i->dtmfcid_holdoff_state = 2; 11533 } else if (2 == i->dtmfcid_holdoff_state) { 11534 gettimeofday(&now, NULL); 11535 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 11536 i->dtmfcid_holdoff_state = 0; 11537 } 11538 } else { 11539 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 11540 if (!i->mwisendactive && energy > dtmfcid_level) { 11541 pthread_t threadid; 11542 struct ast_channel *chan; 11543 ast_mutex_unlock(&iflock); 11544 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) { 11545 /* just in case this event changes or somehow destroys a channel, set doomed here too */ 11546 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID); 11547 i->dtmfcid_holdoff_state = 1; 11548 } else { 11549 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11550 if (!chan) { 11551 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11552 } else { 11553 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 11554 if (res) { 11555 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11556 } else { 11557 i->dtmfcid_holdoff_state = 1; 11558 } 11559 } 11560 } 11561 ast_mutex_lock(&iflock); 11562 } 11563 } 11564 } 11565 if (i->mwisendactive) { 11566 mwi_send_process_buffer(i, res); 11567 } 11568 } else { 11569 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 11570 } 11571 } 11572 if (pollres & POLLPRI) { 11573 if (i->owner || i->subs[SUB_REAL].owner) { 11574 #ifdef HAVE_PRI 11575 if (!i->pri) 11576 #endif 11577 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 11578 continue; 11579 } 11580 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 11581 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 11582 /* Don't hold iflock while handling init events */ 11583 ast_mutex_unlock(&iflock); 11584 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 11585 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) 11586 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); 11587 else 11588 doomed = handle_init_event(i, res); 11589 } 11590 ast_mutex_lock(&iflock); 11591 } 11592 } 11593 } 11594 ast_mutex_unlock(&iflock); 11595 } 11596 /* Never reached */ 11597 return NULL; 11598 11599 }
static int drc_sample | ( | int | sample, | |
float | drc | |||
) | [static] |
Definition at line 4840 of file chan_dahdi.c.
Referenced by fill_rxgain(), and fill_txgain().
04841 { 04842 float neg; 04843 float shallow, steep; 04844 float max = SHRT_MAX; 04845 04846 neg = (sample < 0 ? -1 : 1); 04847 steep = drc*sample; 04848 shallow = neg*(max-max/drc)+(float)sample/drc; 04849 if (abs(steep) < abs(shallow)) { 04850 sample = steep; 04851 } 04852 else { 04853 sample = shallow; 04854 } 04855 04856 return sample; 04857 }
Definition at line 13047 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().
13048 { 13049 struct dahdi_pvt *p; 13050 struct dahdi_bufferinfo bi; 13051 int res; 13052 13053 p = ast_malloc(sizeof(*p)); 13054 if (!p) { 13055 return NULL; 13056 } 13057 *p = *src; 13058 13059 /* Must deep copy the cc_params. */ 13060 p->cc_params = ast_cc_config_params_init(); 13061 if (!p->cc_params) { 13062 ast_free(p); 13063 return NULL; 13064 } 13065 ast_cc_copy_config_params(p->cc_params, src->cc_params); 13066 13067 p->which_iflist = DAHDI_IFLIST_NONE; 13068 p->next = NULL; 13069 p->prev = NULL; 13070 ast_mutex_init(&p->lock); 13071 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 13072 if (p->subs[SUB_REAL].dfd < 0) { 13073 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 13074 destroy_dahdi_pvt(p); 13075 return NULL; 13076 } 13077 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 13078 if (!res) { 13079 bi.txbufpolicy = src->buf_policy; 13080 bi.rxbufpolicy = src->buf_policy; 13081 bi.numbufs = src->buf_no; 13082 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 13083 if (res < 0) { 13084 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 13085 } 13086 } else 13087 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 13088 p->destroy = 1; 13089 dahdi_iflist_insert(p); 13090 return p; 13091 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 6475 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().
06476 { 06477 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06478 06479 if (p->channel == CHAN_PSEUDO) 06480 return; 06481 06482 p->ignoredtmf = 0; 06483 06484 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 06485 06486 if (!p->hardwaredtmf && p->dsp) { 06487 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 06488 ast_dsp_set_features(p->dsp, p->dsp_features); 06489 } 06490 }
static const char * event2str | ( | int | event | ) | [static] |
Definition at line 4453 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().
04454 { 04455 static char buf[256]; 04456 if ((event < (ARRAY_LEN(events))) && (event > -1)) 04457 return events[event]; 04458 sprintf(buf, "Event %d", event); /* safe */ 04459 return buf; 04460 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4904 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_rxgain().
04905 { 04906 int j; 04907 int k; 04908 float linear_gain = pow(10.0, gain / 20.0); 04909 04910 switch (law) { 04911 case DAHDI_LAW_ALAW: 04912 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 04913 if (gain || drc) { 04914 k = AST_ALAW(j); 04915 if (drc) { 04916 k = drc_sample(k, drc); 04917 } 04918 k = (float)k*linear_gain; 04919 if (k > 32767) k = 32767; 04920 if (k < -32767) k = -32767; 04921 g->rxgain[j] = AST_LIN2A(k); 04922 } else { 04923 g->rxgain[j] = j; 04924 } 04925 } 04926 break; 04927 case DAHDI_LAW_MULAW: 04928 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 04929 if (gain || drc) { 04930 k = AST_MULAW(j); 04931 if (drc) { 04932 k = drc_sample(k, drc); 04933 } 04934 k = (float)k*linear_gain; 04935 if (k > 32767) k = 32767; 04936 if (k < -32767) k = -32767; 04937 g->rxgain[j] = AST_LIN2MU(k); 04938 } else { 04939 g->rxgain[j] = j; 04940 } 04941 } 04942 break; 04943 } 04944 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4860 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, AST_MULAW, and drc_sample().
Referenced by set_actual_txgain().
04861 { 04862 int j; 04863 int k; 04864 04865 float linear_gain = pow(10.0, gain / 20.0); 04866 04867 switch (law) { 04868 case DAHDI_LAW_ALAW: 04869 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 04870 if (gain || drc) { 04871 k = AST_ALAW(j); 04872 if (drc) { 04873 k = drc_sample(k, drc); 04874 } 04875 k = (float)k*linear_gain; 04876 if (k > 32767) k = 32767; 04877 if (k < -32767) k = -32767; 04878 g->txgain[j] = AST_LIN2A(k); 04879 } else { 04880 g->txgain[j] = j; 04881 } 04882 } 04883 break; 04884 case DAHDI_LAW_MULAW: 04885 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 04886 if (gain || drc) { 04887 k = AST_MULAW(j); 04888 if (drc) { 04889 k = drc_sample(k, drc); 04890 } 04891 k = (float)k*linear_gain; 04892 if (k > 32767) k = 32767; 04893 if (k < -32767) k = -32767; 04894 g->txgain[j] = AST_LIN2MU(k); 04895 04896 } else { 04897 g->txgain[j] = j; 04898 } 04899 } 04900 break; 04901 } 04902 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 15449 of file chan_dahdi.c.
References ast_mutex_lock, dahdi_pvt::channel, iflist, and dahdi_pvt::next.
Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().
15450 { 15451 struct dahdi_pvt *p; 15452 15453 ast_mutex_lock(&iflock); 15454 for (p = iflist; p; p = p->next) { 15455 if (p->channel == channel) { 15456 break; 15457 } 15458 } 15459 ast_mutex_unlock(&iflock); 15460 return p; 15461 }
Definition at line 5588 of file chan_dahdi.c.
References dahdi_pvt::next, dahdi_pvt::prev, and dahdi_pvt::span.
Referenced by destroy_dahdi_pvt().
05589 { 05590 if (cur->next && cur->next->span == cur->span) { 05591 return cur->next; 05592 } else if (cur->prev && cur->prev->span == cur->span) { 05593 return cur->prev; 05594 } 05595 05596 return NULL; 05597 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Checks channel for alarms
p | a channel to check for alarms. |
Definition at line 7499 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().
07500 { 07501 int res; 07502 struct dahdi_spaninfo zi; 07503 struct dahdi_params params; 07504 07505 memset(&zi, 0, sizeof(zi)); 07506 zi.spanno = p->span; 07507 07508 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 07509 if (zi.alarms != DAHDI_ALARM_NONE) 07510 return zi.alarms; 07511 } else { 07512 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 07513 return 0; 07514 } 07515 07516 /* No alarms on the span. Check for channel alarms. */ 07517 memset(¶ms, 0, sizeof(params)); 07518 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 07519 return params.chan_alarms; 07520 07521 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 07522 07523 return DAHDI_ALARM_NONE; 07524 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alms | |||
) | [static] |
Definition at line 7624 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().
07625 { 07626 const char *alarm_str = alarm2str(alms); 07627 07628 if (report_alarms & REPORT_CHANNEL_ALARMS) { 07629 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 07630 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 07631 "Alarm: %s\r\n" 07632 "Channel: %d\r\n", 07633 alarm_str, p->channel); 07634 } 07635 07636 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 07637 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); 07638 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", 07639 "Alarm: %s\r\n" 07640 "Span: %d\r\n", 07641 alarm_str, p->span); 07642 } 07643 }
static void handle_clear_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3676 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().
03677 { 03678 if (report_alarms & REPORT_CHANNEL_ALARMS) { 03679 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 03680 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 03681 } 03682 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { 03683 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); 03684 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); 03685 } 03686 }
static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 15067 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.
15068 { 15069 int i, j; 15070 switch (cmd) { 15071 case CLI_INIT: 15072 e->command = "dahdi show cadences"; 15073 e->usage = 15074 "Usage: dahdi show cadences\n" 15075 " Shows all cadences currently defined\n"; 15076 return NULL; 15077 case CLI_GENERATE: 15078 return NULL; 15079 } 15080 for (i = 0; i < num_cadence; i++) { 15081 char output[1024]; 15082 char tmp[16], tmp2[64]; 15083 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 15084 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 15085 15086 for (j = 0; j < 16; j++) { 15087 if (cadences[i].ringcadence[j] == 0) 15088 break; 15089 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 15090 if (cidrings[i] * 2 - 1 == j) 15091 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 15092 else 15093 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 15094 if (j != 0) 15095 strncat(output, ",", sizeof(output) - strlen(output) - 1); 15096 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 15097 } 15098 ast_cli(a->fd,"%s\n",output); 15099 } 15100 return CLI_SUCCESS; 15101 }
Definition at line 11077 of file chan_dahdi.c.
References analog_ss_thread(), ast_free, ast_hangup(), ast_log(), 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, 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.
11078 { 11079 int res; 11080 pthread_t threadid; 11081 struct ast_channel *chan; 11082 11083 /* Handle an event on a given channel for the monitor thread. */ 11084 11085 switch (event) { 11086 case DAHDI_EVENT_NONE: 11087 case DAHDI_EVENT_BITSCHANGED: 11088 break; 11089 case DAHDI_EVENT_WINKFLASH: 11090 case DAHDI_EVENT_RINGOFFHOOK: 11091 if (i->inalarm) break; 11092 if (i->radio) break; 11093 /* Got a ring/answer. What kind of channel are we? */ 11094 switch (i->sig) { 11095 case SIG_FXOLS: 11096 case SIG_FXOGS: 11097 case SIG_FXOKS: 11098 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11099 if (res && (errno == EBUSY)) 11100 break; 11101 11102 /* Cancel VMWI spill */ 11103 ast_free(i->cidspill); 11104 i->cidspill = NULL; 11105 restore_conference(i); 11106 11107 if (i->immediate) { 11108 dahdi_enable_ec(i); 11109 /* The channel is immediately up. Start right away */ 11110 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 11111 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL); 11112 if (!chan) { 11113 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 11114 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11115 if (res < 0) 11116 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11117 } 11118 } else { 11119 /* Check for callerid, digits, etc */ 11120 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL); 11121 if (chan) { 11122 if (has_voicemail(i)) 11123 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 11124 else 11125 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 11126 if (res < 0) 11127 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 11128 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11129 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11130 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11131 if (res < 0) 11132 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11133 ast_hangup(chan); 11134 } 11135 } else 11136 ast_log(LOG_WARNING, "Unable to create channel\n"); 11137 } 11138 break; 11139 case SIG_FXSLS: 11140 case SIG_FXSGS: 11141 case SIG_FXSKS: 11142 i->ringt = i->ringt_base; 11143 /* Fall through */ 11144 case SIG_EMWINK: 11145 case SIG_FEATD: 11146 case SIG_FEATDMF: 11147 case SIG_FEATDMF_TA: 11148 case SIG_E911: 11149 case SIG_FGC_CAMA: 11150 case SIG_FGC_CAMAMF: 11151 case SIG_FEATB: 11152 case SIG_EM: 11153 case SIG_EM_E1: 11154 case SIG_SFWINK: 11155 case SIG_SF_FEATD: 11156 case SIG_SF_FEATDMF: 11157 case SIG_SF_FEATB: 11158 case SIG_SF: 11159 /* Check for callerid, digits, etc */ 11160 if (i->cid_start == CID_START_POLARITY_IN) { 11161 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11162 } else { 11163 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL); 11164 } 11165 11166 if (!chan) { 11167 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11168 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11169 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11171 if (res < 0) { 11172 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11173 } 11174 ast_hangup(chan); 11175 } 11176 break; 11177 default: 11178 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11179 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 11180 if (res < 0) 11181 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 11182 return NULL; 11183 } 11184 break; 11185 case DAHDI_EVENT_NOALARM: 11186 switch (i->sig) { 11187 #if defined(HAVE_PRI) 11188 case SIG_PRI_LIB_HANDLE_CASES: 11189 sig_pri_chan_alarm_notify(i->sig_pvt, 1); 11190 break; 11191 #endif /* defined(HAVE_PRI) */ 11192 #if defined(HAVE_SS7) 11193 case SIG_SS7: 11194 sig_ss7_set_alarm(i->sig_pvt, 0); 11195 break; 11196 #endif /* defined(HAVE_SS7) */ 11197 default: 11198 i->inalarm = 0; 11199 break; 11200 } 11201 handle_clear_alarms(i); 11202 break; 11203 case DAHDI_EVENT_ALARM: 11204 switch (i->sig) { 11205 #if defined(HAVE_PRI) 11206 case SIG_PRI_LIB_HANDLE_CASES: 11207 sig_pri_chan_alarm_notify(i->sig_pvt, 0); 11208 break; 11209 #endif /* defined(HAVE_PRI) */ 11210 #if defined(HAVE_SS7) 11211 case SIG_SS7: 11212 sig_ss7_set_alarm(i->sig_pvt, 1); 11213 break; 11214 #endif /* defined(HAVE_SS7) */ 11215 default: 11216 i->inalarm = 1; 11217 break; 11218 } 11219 res = get_alarms(i); 11220 handle_alarms(i, res); 11221 /* fall thru intentionally */ 11222 case DAHDI_EVENT_ONHOOK: 11223 if (i->radio) 11224 break; 11225 /* Back on hook. Hang up. */ 11226 switch (i->sig) { 11227 case SIG_FXOLS: 11228 case SIG_FXOGS: 11229 case SIG_FEATD: 11230 case SIG_FEATDMF: 11231 case SIG_FEATDMF_TA: 11232 case SIG_E911: 11233 case SIG_FGC_CAMA: 11234 case SIG_FGC_CAMAMF: 11235 case SIG_FEATB: 11236 case SIG_EM: 11237 case SIG_EM_E1: 11238 case SIG_EMWINK: 11239 case SIG_SF_FEATD: 11240 case SIG_SF_FEATDMF: 11241 case SIG_SF_FEATB: 11242 case SIG_SF: 11243 case SIG_SFWINK: 11244 case SIG_FXSLS: 11245 case SIG_FXSGS: 11246 case SIG_FXSKS: 11247 case SIG_FXOKS: 11248 dahdi_disable_ec(i); 11249 /* Diddle the battery for the zhone */ 11250 #ifdef ZHONE_HACK 11251 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 11252 usleep(1); 11253 #endif 11254 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11255 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 11256 break; 11257 case SIG_SS7: 11258 case SIG_PRI_LIB_HANDLE_CASES: 11259 dahdi_disable_ec(i); 11260 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11261 break; 11262 default: 11263 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 11264 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 11265 return NULL; 11266 } 11267 break; 11268 case DAHDI_EVENT_POLARITY: 11269 switch (i->sig) { 11270 case SIG_FXSLS: 11271 case SIG_FXSKS: 11272 case SIG_FXSGS: 11273 /* We have already got a PR before the channel was 11274 created, but it wasn't handled. We need polarity 11275 to be REV for remote hangup detection to work. 11276 At least in Spain */ 11277 if (i->hanguponpolarityswitch) 11278 i->polarity = POLARITY_REV; 11279 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 11280 i->polarity = POLARITY_REV; 11281 ast_verb(2, "Starting post polarity " 11282 "CID detection on channel %d\n", 11283 i->channel); 11284 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL); 11285 if (!chan) { 11286 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 11287 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) { 11288 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 11289 } 11290 } 11291 break; 11292 default: 11293 ast_log(LOG_WARNING, "handle_init_event detected " 11294 "polarity reversal on non-FXO (SIG_FXS) " 11295 "interface %d\n", i->channel); 11296 } 11297 break; 11298 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 11299 ast_log(LOG_NOTICE, 11300 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 11301 i->channel); 11302 return i; 11303 case DAHDI_EVENT_NEONMWI_ACTIVE: 11304 if (i->mwimonitor_neon) { 11305 notify_message(i->mailbox, 1); 11306 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 11307 } 11308 break; 11309 case DAHDI_EVENT_NEONMWI_INACTIVE: 11310 if (i->mwimonitor_neon) { 11311 notify_message(i->mailbox, 0); 11312 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 11313 } 11314 break; 11315 } 11316 return NULL; 11317 }
static char* handle_mfcr2_call_files | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14438 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.
14439 { 14440 struct dahdi_pvt *p = NULL; 14441 int channo = 0; 14442 switch (cmd) { 14443 case CLI_INIT: 14444 e->command = "mfcr2 call files [on|off]"; 14445 e->usage = 14446 "Usage: mfcr2 call files [on|off] <channel>\n" 14447 " Enable call files creation on the specified channel.\n" 14448 " If no channel is specified call files creation policy will be applied to all channels.\n"; 14449 return NULL; 14450 case CLI_GENERATE: 14451 return NULL; 14452 } 14453 if (a->argc < 4) { 14454 return CLI_SHOWUSAGE; 14455 } 14456 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1; 14457 ast_mutex_lock(&iflock); 14458 for (p = iflist; p; p = p->next) { 14459 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14460 continue; 14461 } 14462 if ((channo != -1) && (p->channel != channo )) { 14463 continue; 14464 } 14465 if (ast_true(a->argv[3])) { 14466 openr2_chan_enable_call_files(p->r2chan); 14467 } else { 14468 openr2_chan_disable_call_files(p->r2chan); 14469 } 14470 if (channo != -1) { 14471 if (ast_true(a->argv[3])) { 14472 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 14473 } else { 14474 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 14475 } 14476 break; 14477 } 14478 } 14479 if ((channo != -1) && !p) { 14480 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14481 } 14482 if (channo == -1) { 14483 if (ast_true(a->argv[3])) { 14484 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n"); 14485 } else { 14486 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n"); 14487 } 14488 } 14489 ast_mutex_unlock(&iflock); 14490 return CLI_SUCCESS; 14491 }
static char* handle_mfcr2_set_blocked | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14534 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.
14535 { 14536 struct dahdi_pvt *p = NULL; 14537 int channo = 0; 14538 switch (cmd) { 14539 case CLI_INIT: 14540 e->command = "mfcr2 set blocked"; 14541 e->usage = 14542 "Usage: mfcr2 set blocked <channel>\n" 14543 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" 14544 " Force the given channel into BLOCKED state.\n" 14545 " If no channel is specified, all channels will be set to BLOCKED.\n"; 14546 return NULL; 14547 case CLI_GENERATE: 14548 return NULL; 14549 } 14550 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1; 14551 ast_mutex_lock(&iflock); 14552 for (p = iflist; p; p = p->next) { 14553 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14554 continue; 14555 } 14556 if ((channo != -1) && (p->channel != channo )) { 14557 continue; 14558 } 14559 openr2_chan_set_blocked(p->r2chan); 14560 ast_mutex_lock(&p->lock); 14561 p->locallyblocked = 1; 14562 ast_mutex_unlock(&p->lock); 14563 if (channo != -1) { 14564 break; 14565 } 14566 } 14567 if ((channo != -1) && !p) { 14568 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14569 } 14570 ast_mutex_unlock(&iflock); 14571 return CLI_SUCCESS; 14572 }
static char* handle_mfcr2_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14373 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.
14374 { 14375 struct dahdi_pvt *p = NULL; 14376 int channo = 0; 14377 char *toklevel = NULL; 14378 char *saveptr = NULL; 14379 char *logval = NULL; 14380 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 14381 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 14382 switch (cmd) { 14383 case CLI_INIT: 14384 e->command = "mfcr2 set debug"; 14385 e->usage = 14386 "Usage: mfcr2 set debug <loglevel> <channel>\n" 14387 " Set a new logging level for the specified channel.\n" 14388 " If no channel is specified the logging level will be applied to all channels.\n"; 14389 return NULL; 14390 case CLI_GENERATE: 14391 return NULL; 14392 } 14393 if (a->argc < 4) { 14394 return CLI_SHOWUSAGE; 14395 } 14396 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1; 14397 logval = ast_strdupa(a->argv[3]); 14398 toklevel = strtok_r(logval, ",", &saveptr); 14399 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14400 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]); 14401 return CLI_FAILURE; 14402 } else if (OR2_LOG_NOTHING == tmplevel) { 14403 loglevel = tmplevel; 14404 } else { 14405 loglevel |= tmplevel; 14406 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 14407 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14408 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 14409 continue; 14410 } 14411 loglevel |= tmplevel; 14412 } 14413 } 14414 ast_mutex_lock(&iflock); 14415 for (p = iflist; p; p = p->next) { 14416 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14417 continue; 14418 } 14419 if ((channo != -1) && (p->channel != channo )) { 14420 continue; 14421 } 14422 openr2_chan_set_log_level(p->r2chan, loglevel); 14423 if (channo != -1) { 14424 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel); 14425 break; 14426 } 14427 } 14428 if ((channo != -1) && !p) { 14429 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14430 } 14431 if (channo == -1) { 14432 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]); 14433 } 14434 ast_mutex_unlock(&iflock); 14435 return CLI_SUCCESS; 14436 }
static char* handle_mfcr2_set_idle | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14493 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.
14494 { 14495 struct dahdi_pvt *p = NULL; 14496 int channo = 0; 14497 switch (cmd) { 14498 case CLI_INIT: 14499 e->command = "mfcr2 set idle"; 14500 e->usage = 14501 "Usage: mfcr2 set idle <channel>\n" 14502 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" 14503 " Force the given channel into IDLE state.\n" 14504 " If no channel is specified, all channels will be set to IDLE.\n"; 14505 return NULL; 14506 case CLI_GENERATE: 14507 return NULL; 14508 } 14509 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1; 14510 ast_mutex_lock(&iflock); 14511 for (p = iflist; p; p = p->next) { 14512 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14513 continue; 14514 } 14515 if ((channo != -1) && (p->channel != channo )) { 14516 continue; 14517 } 14518 openr2_chan_set_idle(p->r2chan); 14519 ast_mutex_lock(&p->lock); 14520 p->locallyblocked = 0; 14521 p->mfcr2call = 0; 14522 ast_mutex_unlock(&p->lock); 14523 if (channo != -1) { 14524 break; 14525 } 14526 } 14527 if ((channo != -1) && !p) { 14528 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo); 14529 } 14530 ast_mutex_unlock(&iflock); 14531 return CLI_SUCCESS; 14532 }
static char* handle_mfcr2_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14299 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.
14300 { 14301 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 14302 int filtertype = 0; 14303 int targetnum = 0; 14304 char channo[5]; 14305 char anino[5]; 14306 char dnisno[5]; 14307 struct dahdi_pvt *p; 14308 openr2_context_t *r2context; 14309 openr2_variant_t r2variant; 14310 switch (cmd) { 14311 case CLI_INIT: 14312 e->command = "mfcr2 show channels [group|context]"; 14313 e->usage = 14314 "Usage: mfcr2 show channels [group <group> | context <context>]\n" 14315 " Shows the DAHDI channels configured with MFC/R2 signaling.\n"; 14316 return NULL; 14317 case CLI_GENERATE: 14318 return NULL; 14319 } 14320 if (!((a->argc == 3) || (a->argc == 5))) { 14321 return CLI_SHOWUSAGE; 14322 } 14323 if (a->argc == 5) { 14324 if (!strcasecmp(a->argv[3], "group")) { 14325 targetnum = atoi(a->argv[4]); 14326 if ((targetnum < 0) || (targetnum > 63)) 14327 return CLI_SHOWUSAGE; 14328 targetnum = 1 << targetnum; 14329 filtertype = 1; 14330 } else if (!strcasecmp(a->argv[3], "context")) { 14331 filtertype = 2; 14332 } else { 14333 return CLI_SHOWUSAGE; 14334 } 14335 } 14336 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 14337 ast_mutex_lock(&iflock); 14338 for (p = iflist; p; p = p->next) { 14339 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 14340 continue; 14341 } 14342 if (filtertype) { 14343 switch(filtertype) { 14344 case 1: /* mfcr2 show channels group <group> */ 14345 if (p->group != targetnum) { 14346 continue; 14347 } 14348 break; 14349 case 2: /* mfcr2 show channels context <context> */ 14350 if (strcasecmp(p->context, a->argv[4])) { 14351 continue; 14352 } 14353 break; 14354 default: 14355 ; 14356 } 14357 } 14358 r2context = openr2_chan_get_context(p->r2chan); 14359 r2variant = openr2_context_get_variant(r2context); 14360 snprintf(channo, sizeof(channo), "%d", p->channel); 14361 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 14362 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 14363 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 14364 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 14365 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 14366 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 14367 } 14368 ast_mutex_unlock(&iflock); 14369 return CLI_SUCCESS; 14370 #undef FORMAT 14371 }
static char* handle_mfcr2_show_variants | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14271 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.
14272 { 14273 #define FORMAT "%4s %40s\n" 14274 int i = 0; 14275 int numvariants = 0; 14276 const openr2_variant_entry_t *variants; 14277 switch (cmd) { 14278 case CLI_INIT: 14279 e->command = "mfcr2 show variants"; 14280 e->usage = 14281 "Usage: mfcr2 show variants\n" 14282 " Shows the list of MFC/R2 variants supported.\n"; 14283 return NULL; 14284 case CLI_GENERATE: 14285 return NULL; 14286 } 14287 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 14288 ast_cli(a->fd, "Failed to get list of variants.\n"); 14289 return CLI_FAILURE; 14290 } 14291 ast_cli(a->fd, FORMAT, "Variant Code", "Country"); 14292 for (i = 0; i < numvariants; i++) { 14293 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country); 14294 } 14295 return CLI_SUCCESS; 14296 #undef FORMAT 14297 }
static char* handle_mfcr2_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14255 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.
14256 { 14257 switch (cmd) { 14258 case CLI_INIT: 14259 e->command = "mfcr2 show version"; 14260 e->usage = 14261 "Usage: mfcr2 show version\n" 14262 " Shows the version of the OpenR2 library being used.\n"; 14263 return NULL; 14264 case CLI_GENERATE: 14265 return NULL; 14266 } 14267 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 14268 return CLI_SUCCESS; 14269 }
static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13901 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.
13902 { 13903 int span; 13904 int x; 13905 int level = 0; 13906 switch (cmd) { 13907 case CLI_INIT: 13908 e->command = "pri set debug {on|off|0|1|2} span"; 13909 e->usage = 13910 "Usage: pri set debug {<level>|on|off} span <span>\n" 13911 " Enables debugging on a given PRI span\n"; 13912 return NULL; 13913 case CLI_GENERATE: 13914 return complete_span_4(a->line, a->word, a->pos, a->n); 13915 } 13916 if (a->argc < 6) { 13917 return CLI_SHOWUSAGE; 13918 } 13919 13920 if (!strcasecmp(a->argv[3], "on")) { 13921 level = 1; 13922 } else if (!strcasecmp(a->argv[3], "off")) { 13923 level = 0; 13924 } else { 13925 level = atoi(a->argv[3]); 13926 } 13927 span = atoi(a->argv[5]); 13928 if ((span < 1) || (span > NUM_SPANS)) { 13929 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS); 13930 return CLI_SUCCESS; 13931 } 13932 if (!pris[span-1].pri.pri) { 13933 ast_cli(a->fd, "No PRI running on span %d\n", span); 13934 return CLI_SUCCESS; 13935 } 13936 13937 /* Set debug level in libpri */ 13938 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) { 13939 if (pris[span - 1].pri.dchans[x]) { 13940 switch (level) { 13941 case 0: 13942 pri_set_debug(pris[span - 1].pri.dchans[x], 0); 13943 break; 13944 case 1: 13945 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL); 13946 break; 13947 default: 13948 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE); 13949 break; 13950 } 13951 } 13952 } 13953 if (level == 0) { 13954 /* Close the debugging file if it's set */ 13955 ast_mutex_lock(&pridebugfdlock); 13956 if (0 <= pridebugfd) { 13957 close(pridebugfd); 13958 pridebugfd = -1; 13959 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n", 13960 pridebugfilename); 13961 } 13962 ast_mutex_unlock(&pridebugfdlock); 13963 } 13964 pris[span - 1].pri.debug = (level) ? 1 : 0; 13965 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span); 13966 return CLI_SUCCESS; 13967 }
static char* handle_pri_service_disable_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14096 of file chan_dahdi.c.
References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.
14097 { 14098 switch (cmd) { 14099 case CLI_INIT: 14100 e->command = "pri service disable channel"; 14101 e->usage = 14102 "Usage: pri service disable channel <chan num> [<interface id>]\n" 14103 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" 14104 " to remove a channel from service, with optional interface id\n" 14105 " as agreed upon with remote switch operator\n"; 14106 return NULL; 14107 case CLI_GENERATE: 14108 return NULL; 14109 } 14110 return handle_pri_service_generic(e, cmd, a, 2); 14111 }
static char* handle_pri_service_enable_channel | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14079 of file chan_dahdi.c.
References CLI_GENERATE, CLI_INIT, ast_cli_entry::command, handle_pri_service_generic(), and ast_cli_entry::usage.
14080 { 14081 switch (cmd) { 14082 case CLI_INIT: 14083 e->command = "pri service enable channel"; 14084 e->usage = 14085 "Usage: pri service enable channel <channel> [<interface id>]\n" 14086 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" 14087 " to restore a channel to service, with optional interface id\n" 14088 " as agreed upon with remote switch operator\n"; 14089 return NULL; 14090 case CLI_GENERATE: 14091 return NULL; 14092 } 14093 return handle_pri_service_generic(e, cmd, a, 0); 14094 }
static char* handle_pri_service_generic | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a, | |||
int | changestatus | |||
) | [static] |
Definition at line 13971 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().
13972 { 13973 unsigned *why; 13974 int channel; 13975 int trunkgroup; 13976 int x, y, fd = a->fd; 13977 int interfaceid = 0; 13978 char *c; 13979 char db_chan_name[20], db_answer[5]; 13980 struct dahdi_pvt *tmp; 13981 struct dahdi_pri *pri; 13982 13983 if (a->argc < 5 || a->argc > 6) 13984 return CLI_SHOWUSAGE; 13985 if ((c = strchr(a->argv[4], ':'))) { 13986 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2) 13987 return CLI_SHOWUSAGE; 13988 if ((trunkgroup < 1) || (channel < 1)) 13989 return CLI_SHOWUSAGE; 13990 pri = NULL; 13991 for (x=0;x<NUM_SPANS;x++) { 13992 if (pris[x].pri.trunkgroup == trunkgroup) { 13993 pri = pris + x; 13994 break; 13995 } 13996 } 13997 if (!pri) { 13998 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 13999 return CLI_FAILURE; 14000 } 14001 } else 14002 channel = atoi(a->argv[4]); 14003 14004 if (a->argc == 6) 14005 interfaceid = atoi(a->argv[5]); 14006 14007 /* either servicing a D-Channel */ 14008 for (x = 0; x < NUM_SPANS; x++) { 14009 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 14010 if (pris[x].dchannels[y] == channel) { 14011 pri = pris + x; 14012 if (pri->pri.enable_service_message_support) { 14013 ast_mutex_lock(&pri->pri.lock); 14014 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus); 14015 ast_mutex_unlock(&pri->pri.lock); 14016 } else { 14017 ast_cli(fd, 14018 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n" 14019 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n"); 14020 } 14021 return CLI_SUCCESS; 14022 } 14023 } 14024 } 14025 14026 /* or servicing a B-Channel */ 14027 ast_mutex_lock(&iflock); 14028 for (tmp = iflist; tmp; tmp = tmp->next) { 14029 if (tmp->pri && tmp->channel == channel) { 14030 ast_mutex_unlock(&iflock); 14031 ast_mutex_lock(&tmp->pri->lock); 14032 if (!tmp->pri->enable_service_message_support) { 14033 ast_mutex_unlock(&tmp->pri->lock); 14034 ast_cli(fd, 14035 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n" 14036 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n"); 14037 return CLI_SUCCESS; 14038 } 14039 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel); 14040 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 14041 switch(changestatus) { 14042 case 0: /* enable */ 14043 /* Near end wants to be in service now. */ 14044 ast_db_del(db_chan_name, SRVST_DBKEY); 14045 *why &= ~SRVST_NEAREND; 14046 if (*why) { 14047 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why); 14048 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); 14049 } else { 14050 dahdi_pri_update_span_devstate(tmp->pri); 14051 } 14052 break; 14053 /* case 1: -- loop */ 14054 case 2: /* disable */ 14055 /* Near end wants to be out-of-service now. */ 14056 ast_db_del(db_chan_name, SRVST_DBKEY); 14057 *why |= SRVST_NEAREND; 14058 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why); 14059 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); 14060 dahdi_pri_update_span_devstate(tmp->pri); 14061 break; 14062 /* case 3: -- continuity */ 14063 /* case 4: -- shutdown */ 14064 default: 14065 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus); 14066 break; 14067 } 14068 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus); 14069 ast_mutex_unlock(&tmp->pri->lock); 14070 return CLI_SUCCESS; 14071 } 14072 } 14073 ast_mutex_unlock(&iflock); 14074 14075 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel); 14076 return CLI_FAILURE; 14077 }
static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 13863 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.
13864 { 13865 int myfd; 13866 switch (cmd) { 13867 case CLI_INIT: 13868 e->command = "pri set debug file"; 13869 e->usage = "Usage: pri set debug file [output-file]\n" 13870 " Sends PRI debug output to the specified output file\n"; 13871 return NULL; 13872 case CLI_GENERATE: 13873 return NULL; 13874 } 13875 if (a->argc < 5) 13876 return CLI_SHOWUSAGE; 13877 13878 if (ast_strlen_zero(a->argv[4])) 13879 return CLI_SHOWUSAGE; 13880 13881 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 13882 if (myfd < 0) { 13883 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 13884 return CLI_SUCCESS; 13885 } 13886 13887 ast_mutex_lock(&pridebugfdlock); 13888 13889 if (pridebugfd >= 0) 13890 close(pridebugfd); 13891 13892 pridebugfd = myfd; 13893 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 13894 ast_mutex_unlock(&pridebugfdlock); 13895 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 13896 return CLI_SUCCESS; 13897 }
static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14177 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.
14178 { 14179 int x; 14180 int span; 14181 int count=0; 14182 int debug; 14183 14184 switch (cmd) { 14185 case CLI_INIT: 14186 e->command = "pri show debug"; 14187 e->usage = 14188 "Usage: pri show debug\n" 14189 " Show the debug state of pri spans\n"; 14190 return NULL; 14191 case CLI_GENERATE: 14192 return NULL; 14193 } 14194 14195 for (span = 0; span < NUM_SPANS; span++) { 14196 if (pris[span].pri.pri) { 14197 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) { 14198 if (pris[span].pri.dchans[x]) { 14199 debug = pri_get_debug(pris[span].pri.dchans[x]); 14200 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" ); 14201 count++; 14202 } 14203 } 14204 } 14205 14206 } 14207 ast_mutex_lock(&pridebugfdlock); 14208 if (pridebugfd >= 0) 14209 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 14210 ast_mutex_unlock(&pridebugfdlock); 14211 14212 if (!count) 14213 ast_cli(a->fd, "No PRI running\n"); 14214 return CLI_SUCCESS; 14215 }
static char* handle_pri_show_span | ( | 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(), 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.
14144 { 14145 int span; 14146 14147 switch (cmd) { 14148 case CLI_INIT: 14149 e->command = "pri show span"; 14150 e->usage = 14151 "Usage: pri show span <span>\n" 14152 " Displays PRI Information on a given PRI span\n"; 14153 return NULL; 14154 case CLI_GENERATE: 14155 return complete_span_4(a->line, a->word, a->pos, a->n); 14156 } 14157 14158 if (a->argc < 4) 14159 return CLI_SHOWUSAGE; 14160 span = atoi(a->argv[3]); 14161 if ((span < 1) || (span > NUM_SPANS)) { 14162 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 14163 return CLI_SUCCESS; 14164 } 14165 if (!pris[span-1].pri.pri) { 14166 ast_cli(a->fd, "No PRI running on span %d\n", span); 14167 return CLI_SUCCESS; 14168 } 14169 14170 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri); 14171 14172 return CLI_SUCCESS; 14173 }
static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14115 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.
14116 { 14117 int span; 14118 14119 switch (cmd) { 14120 case CLI_INIT: 14121 e->command = "pri show spans"; 14122 e->usage = 14123 "Usage: pri show spans\n" 14124 " Displays PRI Information\n"; 14125 return NULL; 14126 case CLI_GENERATE: 14127 return NULL; 14128 } 14129 14130 if (a->argc != 3) 14131 return CLI_SHOWUSAGE; 14132 14133 for (span = 0; span < NUM_SPANS; span++) { 14134 if (pris[span].pri.pri) { 14135 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri); 14136 } 14137 } 14138 return CLI_SUCCESS; 14139 }
static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14219 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.
14220 { 14221 switch (cmd) { 14222 case CLI_INIT: 14223 e->command = "pri show version"; 14224 e->usage = 14225 "Usage: pri show version\n" 14226 "Show libpri version information\n"; 14227 return NULL; 14228 case CLI_GENERATE: 14229 return NULL; 14230 } 14231 14232 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 14233 14234 return CLI_SUCCESS; 14235 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5123 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().
05124 { 05125 int new_msgs; 05126 struct ast_event *event; 05127 char *mailbox, *context; 05128 05129 mailbox = context = ast_strdupa(p->mailbox); 05130 strsep(&context, "@"); 05131 if (ast_strlen_zero(context)) 05132 context = "default"; 05133 05134 event = ast_event_get_cached(AST_EVENT_MWI, 05135 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 05136 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 05137 AST_EVENT_IE_END); 05138 05139 if (event) { 05140 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 05141 ast_event_destroy(event); 05142 } else 05143 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 05144 05145 return new_msgs; 05146 }
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 12807 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().
12808 { 12809 #if defined(HAVE_PRI) 12810 if (0 < span) { 12811 /* The channel must be on the specified PRI span. */ 12812 if (!p->pri || p->pri->span != span) { 12813 return 0; 12814 } 12815 if (!groupmatch && channelmatch == -1) { 12816 /* Match any group since it only needs to be on the PRI span. */ 12817 *groupmatched = 1; 12818 return 1; 12819 } 12820 } 12821 #endif /* defined(HAVE_PRI) */ 12822 /* check group matching */ 12823 if (groupmatch) { 12824 if ((p->group & groupmatch) != groupmatch) 12825 /* Doesn't match the specified group, try the next one */ 12826 return 0; 12827 *groupmatched = 1; 12828 } 12829 /* Check to see if we have a channel match */ 12830 if (channelmatch != -1) { 12831 if (p->channel != channelmatch) 12832 /* Doesn't match the specified channel, try the next one */ 12833 return 0; 12834 *channelmatched = 1; 12835 } 12836 12837 return 1; 12838 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 4605 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
04606 { 04607 /* If they're listening to our channel, they're ours */ 04608 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 04609 return 1; 04610 /* If they're a talker on our (allocated) conference, they're ours */ 04611 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 04612 return 1; 04613 return 0; 04614 }
Definition at line 4635 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().
04636 { 04637 int x; 04638 int useslavenative; 04639 struct dahdi_pvt *slave = NULL; 04640 /* Start out optimistic */ 04641 useslavenative = 1; 04642 /* Update conference state in a stateless fashion */ 04643 for (x = 0; x < 3; x++) { 04644 /* Any three-way calling makes slave native mode *definitely* out 04645 of the question */ 04646 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 04647 useslavenative = 0; 04648 } 04649 /* If we don't have any 3-way calls, check to see if we have 04650 precisely one slave */ 04651 if (useslavenative) { 04652 for (x = 0; x < MAX_SLAVES; x++) { 04653 if (p->slaves[x]) { 04654 if (slave) { 04655 /* Whoops already have a slave! No 04656 slave native and stop right away */ 04657 slave = NULL; 04658 useslavenative = 0; 04659 break; 04660 } else { 04661 /* We have one slave so far */ 04662 slave = p->slaves[x]; 04663 } 04664 } 04665 } 04666 } 04667 /* If no slave, slave native definitely out */ 04668 if (!slave) 04669 useslavenative = 0; 04670 else if (slave->law != p->law) { 04671 useslavenative = 0; 04672 slave = NULL; 04673 } 04674 if (out) 04675 *out = slave; 04676 return useslavenative; 04677 }
static int load_module | ( | void | ) | [static] |
Definition at line 17985 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_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_callrerouting_facility_exec(), dahdi_send_keypad_facility_exec(), dahdi_tech, round_robin, setup_dahdi(), sig_pri_init_pri(), sig_pri_load(), sig_ss7_init_linkset(), and ss_thread_complete.
17986 { 17987 int res; 17988 #if defined(HAVE_PRI) || defined(HAVE_SS7) 17989 int y; 17990 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 17991 17992 #ifdef HAVE_PRI 17993 memset(pris, 0, sizeof(pris)); 17994 for (y = 0; y < NUM_SPANS; y++) { 17995 sig_pri_init_pri(&pris[y].pri); 17996 } 17997 pri_set_error(dahdi_pri_error); 17998 pri_set_message(dahdi_pri_message); 17999 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 18000 #ifdef HAVE_PRI_PROG_W_CAUSE 18001 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 18002 #endif 18003 #if defined(HAVE_PRI_CCSS) 18004 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks) 18005 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) { 18006 __unload_module(); 18007 return AST_MODULE_LOAD_FAILURE; 18008 } 18009 #endif /* defined(HAVE_PRI_CCSS) */ 18010 if (sig_pri_load( 18011 #if defined(HAVE_PRI_CCSS) 18012 dahdi_pri_cc_type 18013 #else 18014 NULL 18015 #endif /* defined(HAVE_PRI_CCSS) */ 18016 )) { 18017 __unload_module(); 18018 return AST_MODULE_LOAD_FAILURE; 18019 } 18020 #endif 18021 #if defined(HAVE_SS7) 18022 memset(linksets, 0, sizeof(linksets)); 18023 for (y = 0; y < NUM_SPANS; y++) { 18024 sig_ss7_init_linkset(&linksets[y].ss7); 18025 } 18026 ss7_set_error(dahdi_ss7_error); 18027 ss7_set_message(dahdi_ss7_message); 18028 #endif /* defined(HAVE_SS7) */ 18029 res = setup_dahdi(0); 18030 /* Make sure we can register our DAHDI channel type */ 18031 if (res) 18032 return AST_MODULE_LOAD_DECLINE; 18033 if (ast_channel_register(&dahdi_tech)) { 18034 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 18035 __unload_module(); 18036 return AST_MODULE_LOAD_FAILURE; 18037 } 18038 #ifdef HAVE_PRI 18039 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 18040 #endif 18041 #if defined(HAVE_SS7) 18042 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 18043 #endif /* defined(HAVE_SS7) */ 18044 #ifdef HAVE_OPENR2 18045 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 18046 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 18047 #endif 18048 18049 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 18050 /* register all the data providers */ 18051 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers)); 18052 memset(round_robin, 0, sizeof(round_robin)); 18053 ast_manager_register_xml("DAHDITransfer", 0, action_transfer); 18054 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup); 18055 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook); 18056 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon); 18057 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff); 18058 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels); 18059 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart); 18060 18061 ast_cond_init(&ss_thread_complete, NULL); 18062 18063 return res; 18064 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 13611 of file chan_dahdi.c.
References ast_log(), LOG_DEBUG, and SUB_REAL.
13612 { 13613 struct dahdi_mfcr2 *mfcr2 = data; 13614 /* we should be using pthread_key_create 13615 and allocate pollers dynamically. 13616 I think do_monitor() could be leaking, since it 13617 could be cancelled at any time and is not 13618 using thread keys, why?, */ 13619 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)]; 13620 int res = 0; 13621 int i = 0; 13622 int oldstate = 0; 13623 int quit_loop = 0; 13624 int maxsleep = 20; 13625 int was_idle = 0; 13626 int pollsize = 0; 13627 /* now that we're ready to get calls, unblock our side and 13628 get current line state */ 13629 for (i = 0; i < mfcr2->numchans; i++) { 13630 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan); 13631 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 13632 } 13633 while (1) { 13634 /* we trust here that the mfcr2 channel list will not ever change once 13635 the module is loaded */ 13636 pollsize = 0; 13637 for (i = 0; i < mfcr2->numchans; i++) { 13638 pollers[i].revents = 0; 13639 pollers[i].events = 0; 13640 if (mfcr2->pvts[i]->owner) { 13641 continue; 13642 } 13643 if (!mfcr2->pvts[i]->r2chan) { 13644 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 13645 quit_loop = 1; 13646 break; 13647 } 13648 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 13649 pollers[i].events = POLLIN | POLLPRI; 13650 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 13651 pollsize++; 13652 } 13653 if (quit_loop) { 13654 break; 13655 } 13656 if (pollsize == 0) { 13657 if (!was_idle) { 13658 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n"); 13659 was_idle = 1; 13660 } 13661 poll(NULL, 0, maxsleep); 13662 continue; 13663 } 13664 was_idle = 0; 13665 /* probably poll() is a valid cancel point, lets just be on the safe side 13666 by calling pthread_testcancel */ 13667 pthread_testcancel(); 13668 res = poll(pollers, mfcr2->numchans, maxsleep); 13669 pthread_testcancel(); 13670 if ((res < 0) && (errno != EINTR)) { 13671 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 13672 break; 13673 } 13674 /* do we want to allow to cancel while processing events? */ 13675 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 13676 for (i = 0; i < mfcr2->numchans; i++) { 13677 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) { 13678 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 13679 } 13680 } 13681 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 13682 } 13683 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 13684 return 0; 13685 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
int | reloading | |||
) | [static] |
Definition at line 11928 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::destroy, iflist, and dahdi_pvt::next.
Referenced by build_channels().
11929 { 11930 /* Make a dahdi_pvt structure for this interface */ 11931 struct dahdi_pvt *tmp;/*!< Current channel structure initializing */ 11932 char fn[80]; 11933 struct dahdi_bufferinfo bi; 11934 11935 int res; 11936 int span = 0; 11937 int here = 0;/*!< TRUE if the channel interface already exists. */ 11938 int x; 11939 struct analog_pvt *analog_p = NULL; 11940 struct dahdi_params p; 11941 #if defined(HAVE_PRI) 11942 struct dahdi_spaninfo si; 11943 struct sig_pri_chan *pri_chan = NULL; 11944 #endif /* defined(HAVE_PRI) */ 11945 #if defined(HAVE_SS7) 11946 struct sig_ss7_chan *ss7_chan = NULL; 11947 #endif /* defined(HAVE_SS7) */ 11948 11949 /* Search channel interface list to see if it already exists. */ 11950 for (tmp = iflist; tmp; tmp = tmp->next) { 11951 if (!tmp->destroy) { 11952 if (tmp->channel == channel) { 11953 /* The channel interface already exists. */ 11954 here = 1; 11955 break; 11956 } 11957 if (tmp->channel > channel) { 11958 /* No way it can be in the sorted list. */ 11959 tmp = NULL; 11960 break; 11961 } 11962 } 11963 } 11964 11965 if (!here && reloading != 1) { 11966 tmp = ast_calloc(1, sizeof(*tmp)); 11967 if (!tmp) { 11968 return NULL; 11969 } 11970 tmp->cc_params = ast_cc_config_params_init(); 11971 if (!tmp->cc_params) { 11972 ast_free(tmp); 11973 return NULL; 11974 } 11975 ast_mutex_init(&tmp->lock); 11976 ifcount++; 11977 for (x = 0; x < 3; x++) 11978 tmp->subs[x].dfd = -1; 11979 tmp->channel = channel; 11980 tmp->priindication_oob = conf->chan.priindication_oob; 11981 } 11982 11983 if (tmp) { 11984 int chan_sig = conf->chan.sig; 11985 11986 if (!here) { 11987 /* Can only get here if this is a new channel interface being created. */ 11988 if ((channel != CHAN_PSEUDO)) { 11989 int count = 0; 11990 11991 snprintf(fn, sizeof(fn), "%d", channel); 11992 /* Open non-blocking */ 11993 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 11994 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 */ 11995 usleep(1); 11996 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 11997 count++; 11998 } 11999 /* Allocate a DAHDI structure */ 12000 if (tmp->subs[SUB_REAL].dfd < 0) { 12001 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); 12002 destroy_dahdi_pvt(tmp); 12003 return NULL; 12004 } 12005 memset(&p, 0, sizeof(p)); 12006 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12007 if (res < 0) { 12008 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 12009 destroy_dahdi_pvt(tmp); 12010 return NULL; 12011 } 12012 if (conf->is_sig_auto) 12013 chan_sig = sigtype_to_signalling(p.sigtype); 12014 if (p.sigtype != (chan_sig & 0x3ffff)) { 12015 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)); 12016 destroy_dahdi_pvt(tmp); 12017 return NULL; 12018 } 12019 tmp->law_default = p.curlaw; 12020 tmp->law = p.curlaw; 12021 tmp->span = p.spanno; 12022 span = p.spanno - 1; 12023 } else { 12024 chan_sig = 0; 12025 } 12026 tmp->sig = chan_sig; 12027 tmp->outsigmod = conf->chan.outsigmod; 12028 12029 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) { 12030 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp); 12031 if (!analog_p) { 12032 destroy_dahdi_pvt(tmp); 12033 return NULL; 12034 } 12035 tmp->sig_pvt = analog_p; 12036 } 12037 #if defined(HAVE_SS7) 12038 if (chan_sig == SIG_SS7) { 12039 struct dahdi_ss7 *ss7; 12040 int clear = 0; 12041 12042 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 12043 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12044 destroy_dahdi_pvt(tmp); 12045 return NULL; 12046 } 12047 12048 ss7 = ss7_resolve_linkset(cur_linkset); 12049 if (!ss7) { 12050 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 12051 destroy_dahdi_pvt(tmp); 12052 return NULL; 12053 } 12054 ss7->ss7.span = cur_linkset; 12055 if (cur_cicbeginswith < 0) { 12056 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 12057 destroy_dahdi_pvt(tmp); 12058 return NULL; 12059 } 12060 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7); 12061 if (!ss7_chan) { 12062 destroy_dahdi_pvt(tmp); 12063 return NULL; 12064 } 12065 tmp->sig_pvt = ss7_chan; 12066 tmp->ss7 = &ss7->ss7; 12067 12068 ss7_chan->channel = tmp->channel; 12069 ss7_chan->cic = cur_cicbeginswith++; 12070 12071 /* DB: Add CIC's DPC information */ 12072 ss7_chan->dpc = cur_defaultdpc; 12073 12074 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan; 12075 12076 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix)); 12077 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix)); 12078 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix)); 12079 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix)); 12080 12081 ss7->ss7.called_nai = conf->ss7.ss7.called_nai; 12082 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai; 12083 } 12084 #endif /* defined(HAVE_SS7) */ 12085 #ifdef HAVE_OPENR2 12086 if (chan_sig == SIG_MFCR2) { 12087 struct dahdi_mfcr2 *r2_link; 12088 r2_link = dahdi_r2_get_link(); 12089 if (!r2_link) { 12090 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 12091 destroy_dahdi_pvt(tmp); 12092 return NULL; 12093 } 12094 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 12095 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 12096 destroy_dahdi_pvt(tmp); 12097 return NULL; 12098 } 12099 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) { 12100 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 12101 destroy_dahdi_pvt(tmp); 12102 return NULL; 12103 } 12104 r2_link->pvts[r2_link->numchans++] = tmp; 12105 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 12106 tmp->subs[SUB_REAL].dfd, 12107 NULL, NULL); 12108 if (!tmp->r2chan) { 12109 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 12110 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 12111 destroy_dahdi_pvt(tmp); 12112 return NULL; 12113 } 12114 tmp->mfcr2 = r2_link; 12115 if (conf->mfcr2.call_files) { 12116 openr2_chan_enable_call_files(tmp->r2chan); 12117 } 12118 openr2_chan_set_client_data(tmp->r2chan, tmp); 12119 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 12120 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 12121 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 12122 tmp->mfcr2_category = conf->mfcr2.category; 12123 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 12124 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 12125 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 12126 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 12127 tmp->mfcr2call = 0; 12128 tmp->mfcr2_dnis_index = 0; 12129 tmp->mfcr2_ani_index = 0; 12130 r2_link->monitored_count++; 12131 } 12132 #endif 12133 #ifdef HAVE_PRI 12134 if (dahdi_sig_pri_lib_handles(chan_sig)) { 12135 int offset; 12136 int matchesdchan; 12137 int x,y; 12138 int myswitchtype = 0; 12139 12140 offset = 0; 12141 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 12142 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 12143 destroy_dahdi_pvt(tmp); 12144 return NULL; 12145 } 12146 if (span >= NUM_SPANS) { 12147 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 12148 destroy_dahdi_pvt(tmp); 12149 return NULL; 12150 } else { 12151 si.spanno = 0; 12152 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12153 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12154 destroy_dahdi_pvt(tmp); 12155 return NULL; 12156 } 12157 /* Store the logical span first based upon the real span */ 12158 tmp->logicalspan = pris[span].prilogicalspan; 12159 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 12160 if (span < 0) { 12161 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 12162 destroy_dahdi_pvt(tmp); 12163 return NULL; 12164 } 12165 myswitchtype = conf->pri.pri.switchtype; 12166 /* Make sure this isn't a d-channel */ 12167 matchesdchan=0; 12168 for (x = 0; x < NUM_SPANS; x++) { 12169 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 12170 if (pris[x].dchannels[y] == tmp->channel) { 12171 matchesdchan = 1; 12172 break; 12173 } 12174 } 12175 } 12176 if (!matchesdchan) { 12177 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) { 12178 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype)); 12179 destroy_dahdi_pvt(tmp); 12180 return NULL; 12181 } 12182 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) { 12183 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype)); 12184 destroy_dahdi_pvt(tmp); 12185 return NULL; 12186 } 12187 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) { 12188 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)); 12189 destroy_dahdi_pvt(tmp); 12190 return NULL; 12191 } 12192 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) { 12193 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial); 12194 destroy_dahdi_pvt(tmp); 12195 return NULL; 12196 } 12197 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) { 12198 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext); 12199 destroy_dahdi_pvt(tmp); 12200 return NULL; 12201 } 12202 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) { 12203 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused); 12204 destroy_dahdi_pvt(tmp); 12205 return NULL; 12206 } 12207 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) { 12208 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle); 12209 destroy_dahdi_pvt(tmp); 12210 return NULL; 12211 } 12212 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) { 12213 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 12214 pris[span].pri.trunkgroup); 12215 destroy_dahdi_pvt(tmp); 12216 return NULL; 12217 } 12218 12219 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel); 12220 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup); 12221 if (!pri_chan) { 12222 destroy_dahdi_pvt(tmp); 12223 return NULL; 12224 } 12225 tmp->sig_pvt = pri_chan; 12226 tmp->pri = &pris[span].pri; 12227 12228 tmp->priexclusive = conf->chan.priexclusive; 12229 12230 if (!tmp->pri->cc_params) { 12231 tmp->pri->cc_params = ast_cc_config_params_init(); 12232 if (!tmp->pri->cc_params) { 12233 destroy_dahdi_pvt(tmp); 12234 return NULL; 12235 } 12236 } 12237 ast_cc_copy_config_params(tmp->pri->cc_params, 12238 conf->chan.cc_params); 12239 12240 pris[span].pri.sig = chan_sig; 12241 pris[span].pri.nodetype = conf->pri.pri.nodetype; 12242 pris[span].pri.switchtype = myswitchtype; 12243 pris[span].pri.nsf = conf->pri.pri.nsf; 12244 pris[span].pri.dialplan = conf->pri.pri.dialplan; 12245 pris[span].pri.localdialplan = conf->pri.pri.localdialplan; 12246 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt; 12247 pris[span].pri.minunused = conf->pri.pri.minunused; 12248 pris[span].pri.minidle = conf->pri.pri.minidle; 12249 pris[span].pri.overlapdial = conf->pri.pri.overlapdial; 12250 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping; 12251 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval; 12252 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12253 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support; 12254 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12255 #ifdef HAVE_PRI_INBANDDISCONNECT 12256 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect; 12257 #endif 12258 #if defined(HAVE_PRI_CALL_HOLD) 12259 pris[span].pri.hold_disconnect_transfer = 12260 conf->pri.pri.hold_disconnect_transfer; 12261 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 12262 #if defined(HAVE_PRI_CCSS) 12263 pris[span].pri.cc_ptmp_recall_mode = 12264 conf->pri.pri.cc_ptmp_recall_mode; 12265 pris[span].pri.cc_qsig_signaling_link_req = 12266 conf->pri.pri.cc_qsig_signaling_link_req; 12267 pris[span].pri.cc_qsig_signaling_link_rsp = 12268 conf->pri.pri.cc_qsig_signaling_link_rsp; 12269 #endif /* defined(HAVE_PRI_CCSS) */ 12270 #if defined(HAVE_PRI_CALL_WAITING) 12271 pris[span].pri.max_call_waiting_calls = 12272 conf->pri.pri.max_call_waiting_calls; 12273 pris[span].pri.allow_call_waiting_calls = 12274 conf->pri.pri.allow_call_waiting_calls; 12275 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12276 pris[span].pri.transfer = conf->chan.transfer; 12277 pris[span].pri.facilityenable = conf->pri.pri.facilityenable; 12278 #if defined(HAVE_PRI_AOC_EVENTS) 12279 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag; 12280 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup; 12281 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 12282 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag; 12283 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag)); 12284 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list)); 12285 #if defined(HAVE_PRI_MWI) 12286 ast_copy_string(pris[span].pri.mwi_mailboxes, 12287 conf->pri.pri.mwi_mailboxes, 12288 sizeof(pris[span].pri.mwi_mailboxes)); 12289 #endif /* defined(HAVE_PRI_MWI) */ 12290 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial)); 12291 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext)); 12292 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix)); 12293 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix)); 12294 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix)); 12295 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix)); 12296 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix)); 12297 pris[span].pri.resetinterval = conf->pri.pri.resetinterval; 12298 12299 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12300 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x]; 12301 } 12302 12303 #if defined(HAVE_PRI_CALL_WAITING) 12304 /* Channel initial config parameters. */ 12305 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd; 12306 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid; 12307 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname; 12308 pris[span].pri.ch_cfg.immediate = conf->chan.immediate; 12309 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive; 12310 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob; 12311 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid; 12312 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres; 12313 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context)); 12314 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret)); 12315 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 12316 } else { 12317 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos); 12318 destroy_dahdi_pvt(tmp); 12319 return NULL; 12320 } 12321 } 12322 } 12323 #endif 12324 } else { 12325 /* already exists in interface list */ 12326 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)); 12327 chan_sig = tmp->sig; 12328 if (tmp->subs[SUB_REAL].dfd > -1) { 12329 memset(&p, 0, sizeof(p)); 12330 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12331 } 12332 } 12333 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 12334 switch (chan_sig) { 12335 case SIG_FXSKS: 12336 case SIG_FXSLS: 12337 case SIG_EM: 12338 case SIG_EM_E1: 12339 case SIG_EMWINK: 12340 case SIG_FEATD: 12341 case SIG_FEATDMF: 12342 case SIG_FEATDMF_TA: 12343 case SIG_FEATB: 12344 case SIG_E911: 12345 case SIG_SF: 12346 case SIG_SFWINK: 12347 case SIG_FGC_CAMA: 12348 case SIG_FGC_CAMAMF: 12349 case SIG_SF_FEATD: 12350 case SIG_SF_FEATDMF: 12351 case SIG_SF_FEATB: 12352 p.starttime = 250; 12353 break; 12354 } 12355 12356 if (tmp->radio) { 12357 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 12358 p.channo = channel; 12359 p.rxwinktime = 1; 12360 p.rxflashtime = 1; 12361 p.starttime = 1; 12362 p.debouncetime = 5; 12363 } else { 12364 p.channo = channel; 12365 /* Override timing settings based on config file */ 12366 if (conf->timing.prewinktime >= 0) 12367 p.prewinktime = conf->timing.prewinktime; 12368 if (conf->timing.preflashtime >= 0) 12369 p.preflashtime = conf->timing.preflashtime; 12370 if (conf->timing.winktime >= 0) 12371 p.winktime = conf->timing.winktime; 12372 if (conf->timing.flashtime >= 0) 12373 p.flashtime = conf->timing.flashtime; 12374 if (conf->timing.starttime >= 0) 12375 p.starttime = conf->timing.starttime; 12376 if (conf->timing.rxwinktime >= 0) 12377 p.rxwinktime = conf->timing.rxwinktime; 12378 if (conf->timing.rxflashtime >= 0) 12379 p.rxflashtime = conf->timing.rxflashtime; 12380 if (conf->timing.debouncetime >= 0) 12381 p.debouncetime = conf->timing.debouncetime; 12382 } 12383 12384 /* don't set parms on a pseudo-channel */ 12385 if (tmp->subs[SUB_REAL].dfd >= 0) 12386 { 12387 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 12388 if (res < 0) { 12389 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 12390 destroy_dahdi_pvt(tmp); 12391 return NULL; 12392 } 12393 } 12394 #if 1 12395 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 12396 memset(&bi, 0, sizeof(bi)); 12397 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 12398 if (!res) { 12399 bi.txbufpolicy = conf->chan.buf_policy; 12400 bi.rxbufpolicy = conf->chan.buf_policy; 12401 bi.numbufs = conf->chan.buf_no; 12402 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 12403 if (res < 0) { 12404 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 12405 } 12406 } else { 12407 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 12408 } 12409 tmp->buf_policy = conf->chan.buf_policy; 12410 tmp->buf_no = conf->chan.buf_no; 12411 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 12412 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 12413 tmp->faxbuf_no = conf->chan.faxbuf_no; 12414 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 12415 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 12416 * The reason the ioctl call above failed should to be determined before worrying about the 12417 * faxbuffer-related ioctl calls */ 12418 tmp->bufsize = bi.bufsize; 12419 } 12420 #endif 12421 tmp->immediate = conf->chan.immediate; 12422 tmp->transfertobusy = conf->chan.transfertobusy; 12423 if (chan_sig & __DAHDI_SIG_FXS) { 12424 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 12425 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 12426 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 12427 } 12428 tmp->ringt_base = ringt_base; 12429 tmp->firstradio = 0; 12430 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 12431 tmp->permcallwaiting = conf->chan.callwaiting; 12432 else 12433 tmp->permcallwaiting = 0; 12434 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 12435 tmp->destroy = 0; 12436 tmp->drings = conf->chan.drings; 12437 12438 /* 10 is a nice default. */ 12439 if (tmp->drings.ringnum[0].range == 0) 12440 tmp->drings.ringnum[0].range = 10; 12441 if (tmp->drings.ringnum[1].range == 0) 12442 tmp->drings.ringnum[1].range = 10; 12443 if (tmp->drings.ringnum[2].range == 0) 12444 tmp->drings.ringnum[2].range = 10; 12445 12446 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 12447 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 12448 tmp->threewaycalling = conf->chan.threewaycalling; 12449 tmp->adsi = conf->chan.adsi; 12450 tmp->use_smdi = conf->chan.use_smdi; 12451 tmp->permhidecallerid = conf->chan.hidecallerid; 12452 tmp->hidecalleridname = conf->chan.hidecalleridname; 12453 tmp->callreturn = conf->chan.callreturn; 12454 tmp->echocancel = conf->chan.echocancel; 12455 tmp->echotraining = conf->chan.echotraining; 12456 tmp->pulse = conf->chan.pulse; 12457 if (tmp->echocancel.head.tap_length) { 12458 tmp->echocanbridged = conf->chan.echocanbridged; 12459 } else { 12460 if (conf->chan.echocanbridged) 12461 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 12462 tmp->echocanbridged = 0; 12463 } 12464 tmp->busydetect = conf->chan.busydetect; 12465 tmp->busycount = conf->chan.busycount; 12466 tmp->busycompare = conf->chan.busycompare; 12467 tmp->busytonelength = conf->chan.busytonelength; 12468 tmp->busyquietlength = conf->chan.busyquietlength; 12469 tmp->busyfuzziness = conf->chan.busyfuzziness; 12470 tmp->silencethreshold = conf->chan.silencethreshold; 12471 tmp->callprogress = conf->chan.callprogress; 12472 tmp->waitfordialtone = conf->chan.waitfordialtone; 12473 tmp->cancallforward = conf->chan.cancallforward; 12474 tmp->dtmfrelax = conf->chan.dtmfrelax; 12475 tmp->callwaiting = tmp->permcallwaiting; 12476 tmp->hidecallerid = tmp->permhidecallerid; 12477 tmp->channel = channel; 12478 tmp->stripmsd = conf->chan.stripmsd; 12479 tmp->use_callerid = conf->chan.use_callerid; 12480 tmp->cid_signalling = conf->chan.cid_signalling; 12481 tmp->cid_start = conf->chan.cid_start; 12482 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 12483 tmp->restrictcid = conf->chan.restrictcid; 12484 tmp->use_callingpres = conf->chan.use_callingpres; 12485 if (tmp->usedistinctiveringdetection) { 12486 if (!tmp->use_callerid) { 12487 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 12488 tmp->use_callerid = 1; 12489 } 12490 } 12491 12492 if (tmp->cid_signalling == CID_SIG_SMDI) { 12493 if (!tmp->use_smdi) { 12494 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 12495 tmp->use_smdi = 1; 12496 } 12497 } 12498 if (tmp->use_smdi) { 12499 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 12500 if (!(tmp->smdi_iface)) { 12501 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 12502 tmp->use_smdi = 0; 12503 } 12504 } 12505 12506 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 12507 tmp->amaflags = conf->chan.amaflags; 12508 if (!here) { 12509 tmp->confno = -1; 12510 tmp->propconfno = -1; 12511 } 12512 tmp->canpark = conf->chan.canpark; 12513 tmp->transfer = conf->chan.transfer; 12514 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 12515 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 12516 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 12517 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 12518 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 12519 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 12520 tmp->cid_ton = 0; 12521 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) { 12522 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 12523 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 12524 } else { 12525 tmp->cid_num[0] = '\0'; 12526 tmp->cid_name[0] = '\0'; 12527 } 12528 #if defined(HAVE_PRI) 12529 if (dahdi_sig_pri_lib_handles(tmp->sig)) { 12530 tmp->cid_tag[0] = '\0'; 12531 } else 12532 #endif /* defined(HAVE_PRI) */ 12533 { 12534 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); 12535 } 12536 tmp->cid_subaddr[0] = '\0'; 12537 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 12538 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 12539 char *mailbox, *context; 12540 mailbox = context = ast_strdupa(tmp->mailbox); 12541 strsep(&context, "@"); 12542 if (ast_strlen_zero(context)) 12543 context = "default"; 12544 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL, 12545 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 12546 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 12547 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 12548 AST_EVENT_IE_END); 12549 } 12550 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 12551 tmp->mwisend_setting = conf->chan.mwisend_setting; 12552 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 12553 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 12554 #endif 12555 12556 tmp->group = conf->chan.group; 12557 tmp->callgroup = conf->chan.callgroup; 12558 tmp->pickupgroup= conf->chan.pickupgroup; 12559 if (conf->chan.vars) { 12560 struct ast_variable *v, *tmpvar; 12561 for (v = conf->chan.vars ; v ; v = v->next) { 12562 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 12563 tmpvar->next = tmp->vars; 12564 tmp->vars = tmpvar; 12565 } 12566 } 12567 } 12568 tmp->cid_rxgain = conf->chan.cid_rxgain; 12569 tmp->rxgain = conf->chan.rxgain; 12570 tmp->txgain = conf->chan.txgain; 12571 tmp->txdrc = conf->chan.txdrc; 12572 tmp->rxdrc = conf->chan.rxdrc; 12573 tmp->tonezone = conf->chan.tonezone; 12574 if (tmp->subs[SUB_REAL].dfd > -1) { 12575 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law); 12576 if (tmp->dsp) 12577 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 12578 update_conf(tmp); 12579 if (!here) { 12580 switch (chan_sig) { 12581 case SIG_PRI_LIB_HANDLE_CASES: 12582 case SIG_SS7: 12583 case SIG_MFCR2: 12584 break; 12585 default: 12586 /* Hang it up to be sure it's good */ 12587 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 12588 break; 12589 } 12590 } 12591 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 12592 #ifdef HAVE_PRI 12593 memset(&si, 0, sizeof(si)); 12594 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 12595 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 12596 destroy_dahdi_pvt(tmp); 12597 return NULL; 12598 } 12599 #endif 12600 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 12601 /* the dchannel is down so put the channel in alarm */ 12602 switch (tmp->sig) { 12603 #ifdef HAVE_PRI 12604 case SIG_PRI_LIB_HANDLE_CASES: 12605 sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms); 12606 break; 12607 #endif 12608 #if defined(HAVE_SS7) 12609 case SIG_SS7: 12610 sig_ss7_set_alarm(tmp->sig_pvt, 1); 12611 break; 12612 #endif /* defined(HAVE_SS7) */ 12613 default: 12614 /* The only sig submodule left should be sig_analog. */ 12615 analog_p = tmp->sig_pvt; 12616 if (analog_p) { 12617 analog_p->inalarm = 1; 12618 } 12619 tmp->inalarm = 1; 12620 break; 12621 } 12622 handle_alarms(tmp, res); 12623 } 12624 } 12625 12626 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 12627 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 12628 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 12629 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 12630 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); 12631 12632 if (!here) { 12633 tmp->locallyblocked = 0; 12634 tmp->remotelyblocked = 0; 12635 switch (tmp->sig) { 12636 #if defined(HAVE_PRI) 12637 case SIG_PRI_LIB_HANDLE_CASES: 12638 tmp->inservice = 1;/* Inservice until actually implemented. */ 12639 #if defined(HAVE_PRI_SERVICE_MESSAGES) 12640 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0; 12641 if (chan_sig == SIG_PRI) { 12642 char db_chan_name[20]; 12643 char db_answer[5]; 12644 12645 /* 12646 * Initialize the active out-of-service status 12647 * and delete any record if the feature is not enabled. 12648 */ 12649 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); 12650 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { 12651 unsigned *why; 12652 12653 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status; 12654 if (tmp->pri->enable_service_message_support) { 12655 char state; 12656 12657 sscanf(db_answer, "%1c:%30u", &state, why); 12658 12659 /* Ensure that only the implemented bits could be set.*/ 12660 *why &= (SRVST_NEAREND | SRVST_FAREND); 12661 } 12662 if (!*why) { 12663 ast_db_del(db_chan_name, SRVST_DBKEY); 12664 } 12665 } 12666 } 12667 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 12668 break; 12669 #endif /* defined(HAVE_PRI) */ 12670 #if defined(HAVE_SS7) 12671 case SIG_SS7: 12672 tmp->inservice = 0; 12673 break; 12674 #endif /* defined(HAVE_SS7) */ 12675 default: 12676 /* We default to in service on protocols that don't have a reset */ 12677 tmp->inservice = 1; 12678 break; 12679 } 12680 } 12681 12682 switch (tmp->sig) { 12683 #if defined(HAVE_PRI) 12684 case SIG_PRI_LIB_HANDLE_CASES: 12685 if (pri_chan) { 12686 pri_chan->channel = tmp->channel; 12687 pri_chan->hidecallerid = tmp->hidecallerid; 12688 pri_chan->hidecalleridname = tmp->hidecalleridname; 12689 pri_chan->immediate = tmp->immediate; 12690 pri_chan->inalarm = tmp->inalarm; 12691 pri_chan->priexclusive = tmp->priexclusive; 12692 pri_chan->priindication_oob = tmp->priindication_oob; 12693 pri_chan->use_callerid = tmp->use_callerid; 12694 pri_chan->use_callingpres = tmp->use_callingpres; 12695 ast_copy_string(pri_chan->context, tmp->context, 12696 sizeof(pri_chan->context)); 12697 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret, 12698 sizeof(pri_chan->mohinterpret)); 12699 pri_chan->stripmsd = tmp->stripmsd; 12700 } 12701 break; 12702 #endif /* defined(HAVE_PRI) */ 12703 #if defined(HAVE_SS7) 12704 case SIG_SS7: 12705 if (ss7_chan) { 12706 ss7_chan->inalarm = tmp->inalarm; 12707 12708 ss7_chan->stripmsd = tmp->stripmsd; 12709 ss7_chan->hidecallerid = tmp->hidecallerid; 12710 ss7_chan->use_callerid = tmp->use_callerid; 12711 ss7_chan->use_callingpres = tmp->use_callingpres; 12712 ss7_chan->immediate = tmp->immediate; 12713 ss7_chan->locallyblocked = tmp->locallyblocked; 12714 ss7_chan->remotelyblocked = tmp->remotelyblocked; 12715 ast_copy_string(ss7_chan->context, tmp->context, 12716 sizeof(ss7_chan->context)); 12717 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret, 12718 sizeof(ss7_chan->mohinterpret)); 12719 } 12720 break; 12721 #endif /* defined(HAVE_SS7) */ 12722 default: 12723 /* The only sig submodule left should be sig_analog. */ 12724 analog_p = tmp->sig_pvt; 12725 if (analog_p) { 12726 analog_p->channel = tmp->channel; 12727 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 12728 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 12729 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 12730 analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */ 12731 analog_p->callreturn = conf->chan.callreturn; 12732 analog_p->cancallforward = conf->chan.cancallforward; 12733 analog_p->canpark = conf->chan.canpark; 12734 analog_p->dahditrcallerid = conf->chan.dahditrcallerid; 12735 analog_p->immediate = conf->chan.immediate; 12736 analog_p->permhidecallerid = conf->chan.permhidecallerid; 12737 analog_p->pulse = conf->chan.pulse; 12738 analog_p->threewaycalling = conf->chan.threewaycalling; 12739 analog_p->transfer = conf->chan.transfer; 12740 analog_p->transfertobusy = conf->chan.transfertobusy; 12741 analog_p->use_callerid = tmp->use_callerid; 12742 analog_p->use_smdi = tmp->use_smdi; 12743 analog_p->smdi_iface = tmp->smdi_iface; 12744 analog_p->outsigmod = ANALOG_SIG_NONE; 12745 analog_p->echotraining = conf->chan.echotraining; 12746 analog_p->cid_signalling = conf->chan.cid_signalling; 12747 analog_p->stripmsd = conf->chan.stripmsd; 12748 switch (conf->chan.cid_start) { 12749 case CID_START_POLARITY: 12750 analog_p->cid_start = ANALOG_CID_START_POLARITY; 12751 break; 12752 case CID_START_POLARITY_IN: 12753 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN; 12754 break; 12755 case CID_START_DTMF_NOALERT: 12756 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT; 12757 break; 12758 default: 12759 analog_p->cid_start = ANALOG_CID_START_RING; 12760 break; 12761 } 12762 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid; 12763 analog_p->ringt = conf->chan.ringt; 12764 analog_p->ringt_base = ringt_base; 12765 analog_p->chan_tech = &dahdi_tech; 12766 analog_p->onhooktime = time(NULL); 12767 if (chan_sig & __DAHDI_SIG_FXO) { 12768 memset(&p, 0, sizeof(p)); 12769 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 12770 if (!res) { 12771 analog_p->fxsoffhookstate = p.rxisoffhook; 12772 } 12773 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 12774 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 12775 #endif 12776 } 12777 analog_p->msgstate = -1; 12778 12779 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); 12780 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); 12781 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); 12782 12783 analog_config_complete(analog_p); 12784 } 12785 break; 12786 } 12787 #if defined(HAVE_PRI) 12788 if (tmp->channel == CHAN_PSEUDO) { 12789 /* 12790 * Save off pseudo channel buffer policy values for dynamic creation of 12791 * no B channel interfaces. 12792 */ 12793 dahdi_pseudo_parms.buf_no = tmp->buf_no; 12794 dahdi_pseudo_parms.buf_policy = tmp->buf_policy; 12795 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no; 12796 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy; 12797 } 12798 #endif /* defined(HAVE_PRI) */ 12799 } 12800 if (tmp && !here) { 12801 /* Add the new channel interface to the sorted channel interface list. */ 12802 dahdi_iflist_insert(tmp); 12803 } 12804 return tmp; 12805 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 461 of file chan_dahdi.c.
Referenced by add_peer_mwi_subs(), build_peer(), config_line(), and skinny_register().
00462 { 00463 /* This module does not handle MWI in an event-based manner. However, it 00464 * subscribes to MWI for each mailbox that is configured so that the core 00465 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00466 * event cache instead of checking the mailbox directly. */ 00467 }
static int mwi_send_init | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 10871 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.
10872 { 10873 int x, res; 10874 10875 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10876 /* Determine how this spill is to be sent */ 10877 if (pvt->mwisend_rpas) { 10878 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 10879 pvt->mwisendactive = 1; 10880 } else if (pvt->mwisend_fsk) { 10881 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 10882 pvt->mwisendactive = 1; 10883 } else { 10884 pvt->mwisendactive = 0; 10885 return 0; 10886 } 10887 #else 10888 if (mwisend_rpas) { 10889 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 10890 } else { 10891 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 10892 } 10893 pvt->mwisendactive = 1; 10894 #endif 10895 10896 if (pvt->cidspill) { 10897 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 10898 ast_free(pvt->cidspill); 10899 pvt->cidspill = NULL; 10900 pvt->cidpos = 0; 10901 pvt->cidlen = 0; 10902 } 10903 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 10904 if (!pvt->cidspill) { 10905 pvt->mwisendactive = 0; 10906 return -1; 10907 } 10908 x = DAHDI_FLUSH_BOTH; 10909 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 10910 x = 3000; 10911 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 10912 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10913 if (pvt->mwisend_fsk) { 10914 #endif 10915 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 10916 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 10917 pvt->cidpos = 0; 10918 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10919 } 10920 #endif 10921 return 0; 10922 }
static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
int | num_read | |||
) | [static] |
Definition at line 10924 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.
10925 { 10926 struct timeval now; 10927 int res; 10928 10929 /* sanity check to catch if this had been interrupted previously 10930 * i.e. state says there is more to do but there is no spill allocated 10931 */ 10932 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 10933 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 10934 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 10935 /* Normal processing -- Perform mwi send action */ 10936 switch ( pvt->mwisend_data.mwisend_current) { 10937 case MWI_SEND_SA: 10938 /* Send the Ring Pulse Signal Alert */ 10939 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 10940 if (res) { 10941 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 10942 goto quit; 10943 } 10944 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 10945 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 10946 break; 10947 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 10948 break; 10949 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 10950 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10951 if (pvt->mwisend_fsk) { 10952 #endif 10953 gettimeofday(&now, NULL); 10954 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 10955 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 10956 } 10957 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10958 } else { /* support for mwisendtype=nofsk */ 10959 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 10960 } 10961 #endif 10962 break; 10963 case MWI_SEND_SPILL: 10964 /* We read some number of bytes. Write an equal amount of data */ 10965 if(0 < num_read) { 10966 if (num_read > pvt->cidlen - pvt->cidpos) 10967 num_read = pvt->cidlen - pvt->cidpos; 10968 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 10969 if (res > 0) { 10970 pvt->cidpos += res; 10971 if (pvt->cidpos >= pvt->cidlen) { 10972 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 10973 } 10974 } else { 10975 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 10976 goto quit; 10977 } 10978 } 10979 break; 10980 case MWI_SEND_CLEANUP: 10981 /* For now, do nothing */ 10982 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 10983 break; 10984 default: 10985 /* Should not get here, punt*/ 10986 goto quit; 10987 } 10988 } 10989 10990 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 10991 if (pvt->cidspill) { 10992 ast_free(pvt->cidspill); 10993 pvt->cidspill = NULL; 10994 pvt->cidpos = 0; 10995 pvt->cidlen = 0; 10996 } 10997 pvt->mwisendactive = 0; 10998 } 10999 return 0; 11000 quit: 11001 if (pvt->cidspill) { 11002 ast_free(pvt->cidspill); 11003 pvt->cidspill = NULL; 11004 pvt->cidpos = 0; 11005 pvt->cidlen = 0; 11006 } 11007 pvt->mwisendactive = 0; 11008 return -1; 11009 }
static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
int | event | |||
) | [static] |
Definition at line 11011 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.
11012 { 11013 int handled = 0; 11014 11015 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 11016 switch (event) { 11017 case DAHDI_EVENT_RINGEROFF: 11018 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 11019 handled = 1; 11020 11021 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 11022 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno)); 11023 ast_free(pvt->cidspill); 11024 pvt->cidspill = NULL; 11025 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11026 pvt->mwisendactive = 0; 11027 } else { 11028 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 11029 gettimeofday(&pvt->mwisend_data.pause, NULL); 11030 } 11031 } 11032 break; 11033 /* Going off hook, I need to punt this spill */ 11034 case DAHDI_EVENT_RINGOFFHOOK: 11035 if (pvt->cidspill) { 11036 ast_free(pvt->cidspill); 11037 pvt->cidspill = NULL; 11038 pvt->cidpos = 0; 11039 pvt->cidlen = 0; 11040 } 11041 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 11042 pvt->mwisendactive = 0; 11043 break; 11044 case DAHDI_EVENT_RINGERON: 11045 case DAHDI_EVENT_HOOKCOMPLETE: 11046 break; 11047 default: 11048 break; 11049 } 11050 } 11051 return handled; 11052 }
static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 10715 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.
10716 { 10717 struct mwi_thread_data *mtd = data; 10718 struct callerid_state *cs; 10719 pthread_t threadid; 10720 int samples = 0; 10721 char *name, *number; 10722 int flags; 10723 int i, res; 10724 unsigned int spill_done = 0; 10725 int spill_result = -1; 10726 10727 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 10728 mtd->pvt->mwimonitoractive = 0; 10729 10730 return NULL; 10731 } 10732 10733 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 10734 10735 bump_gains(mtd->pvt); 10736 10737 for (;;) { 10738 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 10739 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 10740 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 10741 goto quit; 10742 } 10743 10744 if (i & DAHDI_IOMUX_SIGEVENT) { 10745 struct ast_channel *chan; 10746 10747 /* If we get an event, screen out events that we do not act on. 10748 * Otherwise, cancel and go to the simple switch to let it deal with it. 10749 */ 10750 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 10751 10752 switch (res) { 10753 case DAHDI_EVENT_NEONMWI_ACTIVE: 10754 case DAHDI_EVENT_NEONMWI_INACTIVE: 10755 case DAHDI_EVENT_NONE: 10756 case DAHDI_EVENT_BITSCHANGED: 10757 break; 10758 case DAHDI_EVENT_NOALARM: 10759 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 10760 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 10761 10762 analog_p->inalarm = 0; 10763 } 10764 mtd->pvt->inalarm = 0; 10765 handle_clear_alarms(mtd->pvt); 10766 break; 10767 case DAHDI_EVENT_ALARM: 10768 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 10769 struct analog_pvt *analog_p = mtd->pvt->sig_pvt; 10770 10771 analog_p->inalarm = 1; 10772 } 10773 mtd->pvt->inalarm = 1; 10774 res = get_alarms(mtd->pvt); 10775 handle_alarms(mtd->pvt, res); 10776 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 10777 default: 10778 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res)); 10779 callerid_free(cs); 10780 10781 restore_gains(mtd->pvt); 10782 mtd->pvt->ringt = mtd->pvt->ringt_base; 10783 10784 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) { 10785 int result; 10786 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) { 10787 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan); 10788 } else { 10789 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan); 10790 } 10791 if (result) { 10792 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 10793 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 10794 if (res < 0) 10795 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 10796 ast_hangup(chan); 10797 goto quit; 10798 } 10799 goto quit_no_clean; 10800 10801 } else { 10802 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 10803 } 10804 } 10805 } else if (i & DAHDI_IOMUX_READ) { 10806 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 10807 if (errno != ELAST) { 10808 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 10809 goto quit; 10810 } 10811 break; 10812 } 10813 samples += res; 10814 if (!spill_done) { 10815 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 10816 /* 10817 * The previous diagnostic message output likely 10818 * explains why it failed. 10819 */ 10820 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 10821 break; 10822 } else if (spill_result) { 10823 spill_done = 1; 10824 } 10825 } else { 10826 /* keep reading data until the energy level drops below the threshold 10827 so we don't get another 'trigger' on the remaining carrier signal 10828 */ 10829 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 10830 break; 10831 } 10832 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 10833 break; 10834 } 10835 } 10836 10837 if (spill_result == 1) { 10838 callerid_get(cs, &name, &number, &flags); 10839 if (flags & CID_MSGWAITING) { 10840 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 10841 notify_message(mtd->pvt->mailbox, 1); 10842 } else if (flags & CID_NOMSGWAITING) { 10843 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 10844 notify_message(mtd->pvt->mailbox, 0); 10845 } else { 10846 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 10847 } 10848 } 10849 10850 10851 quit: 10852 callerid_free(cs); 10853 10854 restore_gains(mtd->pvt); 10855 10856 quit_no_clean: 10857 mtd->pvt->mwimonitoractive = 0; 10858 10859 ast_free(mtd); 10860 10861 return NULL; 10862 }
static void my_all_subchannels_hungup | ( | void * | pvt | ) | [static] |
Definition at line 2327 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.
02328 { 02329 struct dahdi_pvt *p = pvt; 02330 int res, law; 02331 02332 p->faxhandled = 0; 02333 p->didtdd = 0; 02334 02335 if (p->dsp) { 02336 ast_dsp_free(p->dsp); 02337 p->dsp = NULL; 02338 } 02339 02340 p->law = p->law_default; 02341 law = p->law_default; 02342 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02343 if (res < 0) 02344 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02345 02346 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02347 02348 #if 1 02349 { 02350 int i; 02351 p->owner = NULL; 02352 /* Cleanup owners here */ 02353 for (i = 0; i < 3; i++) { 02354 p->subs[i].owner = NULL; 02355 } 02356 } 02357 #endif 02358 02359 reset_conf(p); 02360 if (num_restart_pending == 0) { 02361 restart_monitor(); 02362 } 02363 }
static int my_allocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2605 of file chan_dahdi.c.
References alloc_sub(), and analogsub_to_dahdisub().
02606 { 02607 struct dahdi_pvt *p = pvt; 02608 02609 return alloc_sub(p, analogsub_to_dahdisub(analogsub)); 02610 }
static void my_answer_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2843 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, and my_set_polarity().
02844 { 02845 struct dahdi_pvt *p = pvt; 02846 02847 if (!p->answeronpolarityswitch) { 02848 return; 02849 } 02850 02851 my_set_polarity(pvt, 1); 02852 }
static int my_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1885 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().
01886 { 01887 struct dahdi_pvt *p = pvt; 01888 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01889 if (p->cidspill) { 01890 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01891 ast_free(p->cidspill); 01892 } 01893 01894 /* 01895 * SAS: Subscriber Alert Signal, 440Hz for 300ms 01896 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 01897 */ 01898 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01899 return -1; 01900 save_conference(p); 01901 /* Silence */ 01902 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01903 if (!p->callwaitrings && p->callwaitingcallerid) { 01904 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01905 p->callwaitcas = 1; 01906 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01907 } else { 01908 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01909 p->callwaitcas = 0; 01910 p->cidlen = 2400 + READ_SIZE * 4; 01911 } 01912 p->cidpos = 0; 01913 send_callerid(p); 01914 01915 return 0; 01916 }
static void my_cancel_cidspill | ( | void * | pvt | ) | [static] |
Definition at line 2277 of file chan_dahdi.c.
References ast_free, dahdi_pvt::cidspill, and restore_conference().
02278 { 02279 struct dahdi_pvt *p = pvt; 02280 02281 ast_free(p->cidspill); 02282 p->cidspill = NULL; 02283 restore_conference(p); 02284 }
static int my_check_confirmanswer | ( | void * | pvt | ) | [static] |
Definition at line 2260 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02261 { 02262 struct dahdi_pvt *p = pvt; 02263 if (p->confirmanswer) { 02264 return 1; 02265 } 02266 02267 return 0; 02268 }
static int my_check_for_conference | ( | void * | pvt | ) | [static] |
Definition at line 2437 of file chan_dahdi.c.
References check_for_conference().
02438 { 02439 struct dahdi_pvt *p = pvt; 02440 return check_for_conference(p); 02441 }
static int my_check_waitingfordt | ( | void * | pvt | ) | [static] |
Definition at line 2243 of file chan_dahdi.c.
References dahdi_pvt::waitingfordt.
02244 { 02245 struct dahdi_pvt *p = pvt; 02246 02247 if (p->waitingfordt.tv_usec) { 02248 return 1; 02249 } 02250 02251 return 0; 02252 }
static int my_complete_conference_update | ( | void * | pvt, | |
int | needconference | |||
) | [static] |
Definition at line 2387 of file chan_dahdi.c.
References conf_add(), GET_CHANNEL, isslavenative(), MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
02388 { 02389 struct dahdi_pvt *p = pvt; 02390 int needconf = needconference; 02391 int x; 02392 int useslavenative; 02393 struct dahdi_pvt *slave = NULL; 02394 02395 useslavenative = isslavenative(p, &slave); 02396 02397 /* If we have a slave, add him to our conference now. or DAX 02398 if this is slave native */ 02399 for (x = 0; x < MAX_SLAVES; x++) { 02400 if (p->slaves[x]) { 02401 if (useslavenative) 02402 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02403 else { 02404 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02405 needconf++; 02406 } 02407 } 02408 } 02409 /* If we're supposed to be in there, do so now */ 02410 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02411 if (useslavenative) 02412 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02413 else { 02414 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02415 needconf++; 02416 } 02417 } 02418 /* If we have a master, add ourselves to his conference */ 02419 if (p->master) { 02420 if (isslavenative(p->master, NULL)) { 02421 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02422 } else { 02423 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02424 } 02425 } 02426 if (!needconf) { 02427 /* Nobody is left (or should be left) in our conference. 02428 Kill it. */ 02429 p->confno = -1; 02430 } 02431 02432 return 0; 02433 }
static int my_conf_add | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2377 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_add(), and dahdi_pvt::subs.
02378 { 02379 struct dahdi_pvt *p = pvt; 02380 int x = analogsub_to_dahdisub(sub); 02381 02382 return conf_add(p, &p->subs[x], x, 0); 02383 }
static int my_conf_del | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2367 of file chan_dahdi.c.
References analogsub_to_dahdisub(), conf_del(), and dahdi_pvt::subs.
02368 { 02369 struct dahdi_pvt *p = pvt; 02370 int x = analogsub_to_dahdisub(sub); 02371 02372 return conf_del(p, &p->subs[x], x); 02373 }
static int my_confmute | ( | void * | pvt, | |
int | mute | |||
) | [static] |
Definition at line 2286 of file chan_dahdi.c.
References dahdi_confmute().
02287 { 02288 struct dahdi_pvt *p = pvt; 02289 return dahdi_confmute(p, mute); 02290 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | idx, | |||
int | linear | |||
) | [static] |
Definition at line 9040 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().
09041 { 09042 int sent=0; 09043 int size; 09044 int res; 09045 int fd; 09046 fd = p->subs[idx].dfd; 09047 while (len) { 09048 size = len; 09049 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 09050 size = (linear ? READ_SIZE * 2 : READ_SIZE); 09051 res = write(fd, buf, size); 09052 if (res != size) { 09053 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 09054 return sent; 09055 } 09056 len -= size; 09057 buf += size; 09058 } 09059 return sent; 09060 }
static void my_deadlock_avoidance_private | ( | void * | pvt | ) | [static] |
Definition at line 2103 of file chan_dahdi.c.
References DEADLOCK_AVOIDANCE, and dahdi_pvt::lock.
02104 { 02105 struct dahdi_pvt *p = pvt; 02106 02107 DEADLOCK_AVOIDANCE(&p->lock); 02108 }
static void my_decrease_ss_count | ( | void | ) | [static] |
Definition at line 2319 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.
02320 { 02321 ast_mutex_lock(&ss_thread_lock); 02322 ss_thread_count--; 02323 ast_cond_signal(&ss_thread_complete); 02324 ast_mutex_unlock(&ss_thread_lock); 02325 }
static int my_dial_digits | ( | void * | pvt, | |
enum analog_sub | sub, | |||
struct analog_dialoperation * | dop | |||
) | [static] |
Definition at line 2877 of file chan_dahdi.c.
References ANALOG_DIAL_OP_REPLACE, ANALOG_SUB_REAL, analogsub_to_dahdisub(), ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, analog_dialoperation::dialstr, errno, LOG_DEBUG, LOG_ERROR, ast_channel::name, analog_dialoperation::op, dahdi_pvt::owner, and dahdi_pvt::subs.
02878 { 02879 int index = analogsub_to_dahdisub(sub); 02880 int res; 02881 struct dahdi_pvt *p = pvt; 02882 struct dahdi_dialoperation ddop; 02883 02884 if (dop->op != ANALOG_DIAL_OP_REPLACE) { 02885 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n"); 02886 return -1; 02887 } 02888 02889 if (sub != ANALOG_SUB_REAL) 02890 printf("Trying to dial digits on sub %d\n", sub); 02891 02892 ddop.op = DAHDI_DIAL_OP_REPLACE; 02893 strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr)); 02894 02895 printf("Dialing %s on %d\n", ddop.dialstr, p->channel); 02896 02897 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop); 02898 02899 if (res == -1) 02900 ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno)); 02901 02902 return res; 02903 }
static int my_distinctive_ring | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | idx, | |||
int * | ringdata | |||
) | [static] |
Definition at line 1749 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.
01750 { 01751 unsigned char buf[256]; 01752 int distMatches; 01753 int curRingData[RING_PATTERNS]; 01754 int receivedRingT; 01755 int counter1; 01756 int counter; 01757 int i; 01758 int res; 01759 int checkaftercid = 0; 01760 01761 struct dahdi_pvt *p = pvt; 01762 struct analog_pvt *analog_p = p->sig_pvt; 01763 01764 if (ringdata == NULL) { 01765 ringdata = curRingData; 01766 } else { 01767 checkaftercid = 1; 01768 } 01769 01770 /* We must have a ring by now, so, if configured, lets try to listen for 01771 * distinctive ringing */ 01772 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { 01773 /* Clear the current ring data array so we don't have old data in it. */ 01774 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++) 01775 ringdata[receivedRingT] = 0; 01776 receivedRingT = 0; 01777 if (checkaftercid && distinctiveringaftercid) 01778 ast_verb(3, "Detecting post-CID distinctive ring\n"); 01779 /* Check to see if context is what it should be, if not set to be. */ 01780 else if (strcmp(p->context,p->defcontext) != 0) { 01781 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 01782 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 01783 } 01784 01785 for (;;) { 01786 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 01787 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 01788 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 01789 ast_hangup(chan); 01790 return 1; 01791 } 01792 if (i & DAHDI_IOMUX_SIGEVENT) { 01793 res = dahdi_get_event(p->subs[idx].dfd); 01794 if (res == DAHDI_EVENT_NOALARM) { 01795 p->inalarm = 0; 01796 analog_p->inalarm = 0; 01797 } 01798 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 01799 res = 0; 01800 /* Let us detect distinctive ring */ 01801 01802 ringdata[receivedRingT] = analog_p->ringt; 01803 01804 if (analog_p->ringt < analog_p->ringt_base/2) 01805 break; 01806 /* Increment the ringT counter so we can match it against 01807 values in chan_dahdi.conf for distinctive ring */ 01808 if (++receivedRingT == RING_PATTERNS) 01809 break; 01810 } else if (i & DAHDI_IOMUX_READ) { 01811 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 01812 if (res < 0) { 01813 if (errno != ELAST) { 01814 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01815 ast_hangup(chan); 01816 return 1; 01817 } 01818 break; 01819 } 01820 if (analog_p->ringt > 0) { 01821 if (!(--analog_p->ringt)) { 01822 res = -1; 01823 break; 01824 } 01825 } 01826 } 01827 } 01828 } 01829 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { 01830 /* this only shows up if you have n of the dring patterns filled in */ 01831 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); 01832 for (counter = 0; counter < 3; counter++) { 01833 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ 01834 distMatches = 0; 01835 /* this only shows up if you have n of the dring patterns filled in */ 01836 ast_verb(3, "Checking %d,%d,%d\n", 01837 p->drings.ringnum[counter].ring[0], 01838 p->drings.ringnum[counter].ring[1], 01839 p->drings.ringnum[counter].ring[2]); 01840 for (counter1 = 0; counter1 < 3; counter1++) { 01841 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 01842 if (p->drings.ringnum[counter].ring[counter1] == -1) { 01843 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 01844 ringdata[counter1]); 01845 distMatches++; 01846 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 01847 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 01848 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 01849 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 01850 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 01851 distMatches++; 01852 } 01853 } 01854 01855 if (distMatches == 3) { 01856 /* The ring matches, set the context to whatever is for distinctive ring.. */ 01857 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context)); 01858 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context)); 01859 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 01860 break; 01861 } 01862 } 01863 } 01864 /* Restore linear mode (if appropriate) for Caller*ID processing */ 01865 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 01866 restore_gains(p); 01867 01868 return 0; 01869 }
static int my_dsp_reset_and_flush_digits | ( | void * | pvt | ) | [static] |
Definition at line 1953 of file chan_dahdi.c.
References ast_dsp_digitreset(), and dahdi_pvt::dsp.
01954 { 01955 struct dahdi_pvt *p = pvt; 01956 if (p->dsp) 01957 ast_dsp_digitreset(p->dsp); 01958 01959 return 0; 01960 }
static int my_dsp_set_digitmode | ( | void * | pvt, | |
enum analog_dsp_digitmode | mode | |||
) | [static] |
Definition at line 1962 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.
01963 { 01964 struct dahdi_pvt *p = pvt; 01965 01966 if (p->channel == CHAN_PSEUDO) 01967 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n"); 01968 01969 if (mode == ANALOG_DIGITMODE_DTMF) { 01970 /* If we do hardware dtmf, no need for a DSP */ 01971 if (p->hardwaredtmf) { 01972 if (p->dsp) { 01973 ast_dsp_free(p->dsp); 01974 p->dsp = NULL; 01975 } 01976 return 0; 01977 } 01978 01979 if (!p->dsp) { 01980 p->dsp = ast_dsp_new(); 01981 if (!p->dsp) { 01982 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 01983 return -1; 01984 } 01985 } 01986 01987 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 01988 } else if (mode == ANALOG_DIGITMODE_MF) { 01989 if (!p->dsp) { 01990 p->dsp = ast_dsp_new(); 01991 if (!p->dsp) { 01992 ast_log(LOG_ERROR, "Unable to allocate DSP\n"); 01993 return -1; 01994 } 01995 } 01996 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 01997 } 01998 return 0; 01999 }
static int my_flash | ( | void * | pvt | ) | [static] |
Definition at line 2802 of file chan_dahdi.c.
References SUB_REAL, and dahdi_pvt::subs.
02803 { 02804 struct dahdi_pvt *p = pvt; 02805 int func = DAHDI_FLASH; 02806 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func); 02807 }
static void my_get_and_handle_alarms | ( | void * | pvt | ) | [static] |
Definition at line 2135 of file chan_dahdi.c.
References get_alarms(), and handle_alarms().
02136 { 02137 int res; 02138 struct dahdi_pvt *p = pvt; 02139 02140 res = get_alarms(p); 02141 handle_alarms(p, res); 02142 }
static int my_get_callerid | ( | void * | pvt, | |
char * | namebuf, | |||
char * | numbuf, | |||
enum analog_event * | ev, | |||
size_t | timeout | |||
) | [static] |
Definition at line 1672 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.
01673 { 01674 struct dahdi_pvt *p = pvt; 01675 struct analog_pvt *analog_p = p->sig_pvt; 01676 struct pollfd poller; 01677 char *name, *num; 01678 int index = SUB_REAL; 01679 int res; 01680 unsigned char buf[256]; 01681 int flags; 01682 01683 poller.fd = p->subs[SUB_REAL].dfd; 01684 poller.events = POLLPRI | POLLIN; 01685 poller.revents = 0; 01686 01687 res = poll(&poller, 1, timeout); 01688 01689 if (poller.revents & POLLPRI) { 01690 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd)); 01691 return 1; 01692 } 01693 01694 if (poller.revents & POLLIN) { 01695 /*** NOTES ***/ 01696 /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function 01697 * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until 01698 * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be 01699 * a failure and die, and returning 2 means no event was received. */ 01700 res = read(p->subs[index].dfd, buf, sizeof(buf)); 01701 if (res < 0) { 01702 if (errno != ELAST) { 01703 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 01704 callerid_free(p->cs); 01705 return -1; 01706 } 01707 } 01708 01709 if (analog_p->ringt > 0) { 01710 if (!(--analog_p->ringt)) { 01711 /* only return if we timeout from a ring event */ 01712 return -1; 01713 } 01714 } 01715 01716 if (p->cid_signalling == CID_SIG_V23_JP) { 01717 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); 01718 } else { 01719 res = callerid_feed(p->cs, buf, res, AST_LAW(p)); 01720 } 01721 if (res < 0) { 01722 /* 01723 * The previous diagnostic message output likely 01724 * explains why it failed. 01725 */ 01726 ast_log(LOG_WARNING, "Failed to decode CallerID\n"); 01727 return -1; 01728 } 01729 01730 if (res == 1) { 01731 callerid_get(p->cs, &name, &num, &flags); 01732 if (name) 01733 ast_copy_string(namebuf, name, ANALOG_MAX_CID); 01734 if (num) 01735 ast_copy_string(numbuf, num, ANALOG_MAX_CID); 01736 01737 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags); 01738 return 0; 01739 } 01740 } 01741 01742 *ev = ANALOG_EVENT_NONE; 01743 return 2; 01744 }
static int my_get_event | ( | void * | pvt | ) | [static] |
Definition at line 2735 of file chan_dahdi.c.
References dahdi_get_event(), dahdievent_to_analogevent(), dahdi_pvt::fake_event, SUB_REAL, and dahdi_pvt::subs.
02736 { 02737 struct dahdi_pvt *p = pvt; 02738 int res; 02739 02740 if (p->fake_event) { 02741 res = p->fake_event; 02742 p->fake_event = 0; 02743 } else 02744 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 02745 02746 return dahdievent_to_analogevent(res); 02747 }
static const char* my_get_orig_dialstring | ( | void * | pvt | ) | [static] |
Definition at line 2305 of file chan_dahdi.c.
References dahdi_pvt::dialstring.
02306 { 02307 struct dahdi_pvt *p = pvt; 02308 02309 return p->dialstring; 02310 }
static void* my_get_sigpvt_bridged_channel | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 2144 of file chan_dahdi.c.
References ast_bridged_channel(), dahdi_pvt::sig_pvt, and ast_channel::tech_pvt.
02145 { 02146 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt; 02147 if (p) 02148 return p->sig_pvt; 02149 else 02150 return NULL; 02151 }
static int my_get_sub_fd | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2153 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02154 { 02155 struct dahdi_pvt *p = pvt; 02156 int dahdi_sub = analogsub_to_dahdisub(sub); 02157 return p->subs[dahdi_sub].dfd; 02158 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 9507 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by analog_ss_thread().
09508 { 09509 char c; 09510 09511 *str = 0; /* start with empty output buffer */ 09512 for (;;) 09513 { 09514 /* Wait for the first digit (up to specified ms). */ 09515 c = ast_waitfordigit(chan, ms); 09516 /* if timeout, hangup or error, return as such */ 09517 if (c < 1) 09518 return c; 09519 *str++ = c; 09520 *str = 0; 09521 if (strchr(term, c)) 09522 return 1; 09523 } 09524 }
static void my_handle_dchan_exception | ( | struct sig_pri_span * | pri, | |
int | index | |||
) | [static] |
Definition at line 2997 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.
02998 { 02999 int x, res; 03000 03001 res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x); 03002 if (x) { 03003 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span); 03004 } 03005 /* Keep track of alarm state */ 03006 switch (x) { 03007 case DAHDI_EVENT_ALARM: 03008 pri_event_alarm(pri, index, 0); 03009 break; 03010 case DAHDI_EVENT_NOALARM: 03011 pri_event_noalarm(pri, index, 0); 03012 break; 03013 default: 03014 break; 03015 } 03016 }
static void my_handle_dtmf | ( | void * | pvt, | |
struct ast_channel * | ast, | |||
enum analog_sub | analog_index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 2019 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.
02020 { 02021 struct ast_frame *f = *dest; 02022 struct dahdi_pvt *p = pvt; 02023 int idx = analogsub_to_dahdisub(analog_index); 02024 02025 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n", 02026 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 02027 f->subclass.integer, f->subclass.integer, ast->name); 02028 02029 if (f->subclass.integer == 'f') { 02030 if (f->frametype == AST_FRAME_DTMF_END) { 02031 /* Fax tone -- Handle and return NULL */ 02032 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 02033 /* If faxbuffers are configured, use them for the fax transmission */ 02034 if (p->usefaxbuffers && !p->bufferoverrideinuse) { 02035 struct dahdi_bufferinfo bi = { 02036 .txbufpolicy = p->faxbuf_policy, 02037 .bufsize = p->bufsize, 02038 .numbufs = p->faxbuf_no 02039 }; 02040 int res; 02041 02042 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 02043 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno)); 02044 } else { 02045 p->bufferoverrideinuse = 1; 02046 } 02047 } 02048 p->faxhandled = 1; 02049 if (p->dsp) { 02050 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT; 02051 ast_dsp_set_features(p->dsp, p->dsp_features); 02052 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name); 02053 } 02054 if (strcmp(ast->exten, "fax")) { 02055 const char *target_context = S_OR(ast->macrocontext, ast->context); 02056 02057 /* We need to unlock 'ast' here because ast_exists_extension has the 02058 * potential to start autoservice on the channel. Such action is prone 02059 * to deadlock. 02060 */ 02061 ast_mutex_unlock(&p->lock); 02062 ast_channel_unlock(ast); 02063 if (ast_exists_extension(ast, target_context, "fax", 1, 02064 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) { 02065 ast_channel_lock(ast); 02066 ast_mutex_lock(&p->lock); 02067 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 02068 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 02069 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 02070 if (ast_async_goto(ast, target_context, "fax", 1)) 02071 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 02072 } else { 02073 ast_channel_lock(ast); 02074 ast_mutex_lock(&p->lock); 02075 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 02076 } 02077 } else { 02078 ast_debug(1, "Already in a fax extension, not redirecting\n"); 02079 } 02080 } else { 02081 ast_debug(1, "Fax already handled\n"); 02082 } 02083 dahdi_confmute(p, 0); 02084 } 02085 p->subs[idx].f.frametype = AST_FRAME_NULL; 02086 p->subs[idx].f.subclass.integer = 0; 02087 *dest = &p->subs[idx].f; 02088 } 02089 }
static void my_handle_notify_message | ( | struct ast_channel * | chan, | |
void * | pvt, | |||
int | cid_flags, | |||
int | neon_mwievent | |||
) | [static] |
Definition at line 3505 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().
03506 { 03507 struct dahdi_pvt *p = pvt; 03508 03509 if (neon_mwievent > -1 && !p->mwimonitor_neon) 03510 return; 03511 03512 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) { 03513 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox); 03514 notify_message(p->mailbox, 1); 03515 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) { 03516 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox); 03517 notify_message(p->mailbox, 0); 03518 } 03519 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 03520 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 03521 if (neon_mwievent == -1 && p->mwimonitor_rpas) { 03522 ast_hangup(chan); 03523 return; 03524 } 03525 }
static void my_hangup_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2854 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
02855 { 02856 struct dahdi_pvt *p = pvt; 02857 02858 if (!p->hanguponpolarityswitch) { 02859 return; 02860 } 02861 02862 if (p->answeronpolarityswitch) { 02863 my_set_polarity(pvt, 0); 02864 } else { 02865 my_set_polarity(pvt, 1); 02866 } 02867 }
static int my_has_voicemail | ( | void * | pvt | ) | [static] |
Definition at line 2614 of file chan_dahdi.c.
References has_voicemail().
02615 { 02616 struct dahdi_pvt *p = pvt; 02617 02618 return has_voicemail(p); 02619 }
static void my_increase_ss_count | ( | void | ) | [static] |
Definition at line 2312 of file chan_dahdi.c.
References ast_mutex_lock, ast_mutex_unlock, ss_thread_count, and ss_thread_lock.
02313 { 02314 ast_mutex_lock(&ss_thread_lock); 02315 ss_thread_count++; 02316 ast_mutex_unlock(&ss_thread_lock); 02317 }
static int my_is_dialing | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2916 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_subchannel::dfd, LOG_DEBUG, and dahdi_pvt::subs.
02917 { 02918 struct dahdi_pvt *p = pvt; 02919 int index; 02920 int x; 02921 02922 index = analogsub_to_dahdisub(sub); 02923 02924 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) { 02925 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n"); 02926 return -1; 02927 } 02928 02929 return x; 02930 }
static int my_is_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2749 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.
02750 { 02751 struct dahdi_pvt *p = pvt; 02752 int res; 02753 struct dahdi_params par; 02754 02755 memset(&par, 0, sizeof(par)); 02756 02757 if (p->subs[SUB_REAL].dfd > -1) 02758 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02759 else { 02760 /* Assume not off hook on CVRS */ 02761 res = 0; 02762 par.rxisoffhook = 0; 02763 } 02764 if (res) { 02765 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 02766 } 02767 02768 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 02769 /* When "onhook" that means no battery on the line, and thus 02770 it is out of service..., if it's on a TDM card... If it's a channel 02771 bank, there is no telling... */ 02772 return (par.rxbits > -1) || par.rxisoffhook; 02773 } 02774 02775 return par.rxisoffhook; 02776 }
static void my_lock_private | ( | void * | pvt | ) | [static] |
Definition at line 2091 of file chan_dahdi.c.
References ast_mutex_lock, and dahdi_pvt::lock.
02092 { 02093 struct dahdi_pvt *p = pvt; 02094 ast_mutex_lock(&p->lock); 02095 }
static void my_module_ref | ( | void | ) | [static] |
Definition at line 3243 of file chan_dahdi.c.
References ast_module_ref().
03244 { 03245 ast_module_ref(ast_module_info->self); 03246 }
static void my_module_unref | ( | void | ) | [static] |
Definition at line 3257 of file chan_dahdi.c.
References ast_module_unref().
03258 { 03259 ast_module_unref(ast_module_info->self); 03260 }
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 2477 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_new(), and ast_channel::linkedid.
02478 { 02479 struct dahdi_pvt *p = pvt; 02480 int dsub = analogsub_to_dahdisub(sub); 02481 02482 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : ""); 02483 }
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 2497 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.
02498 { 02499 struct dahdi_pvt *p = pvt; 02500 int audio; 02501 int newlaw = -1; 02502 02503 switch (p->sig) { 02504 case SIG_PRI_LIB_HANDLE_CASES: 02505 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) { 02506 /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */ 02507 break; 02508 } 02509 /* Fall through */ 02510 default: 02511 /* Set to audio mode at this point */ 02512 audio = 1; 02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) { 02514 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", 02515 p->channel, audio, strerror(errno)); 02516 } 02517 break; 02518 } 02519 02520 if (law != SIG_PRI_DEFLAW) { 02521 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW); 02522 } 02523 02524 ast_copy_string(p->exten, exten, sizeof(p->exten)); 02525 02526 switch (law) { 02527 case SIG_PRI_DEFLAW: 02528 newlaw = 0; 02529 break; 02530 case SIG_PRI_ALAW: 02531 newlaw = DAHDI_LAW_ALAW; 02532 break; 02533 case SIG_PRI_ULAW: 02534 newlaw = DAHDI_LAW_MULAW; 02535 break; 02536 } 02537 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : ""); 02538 }
static int my_off_hook | ( | void * | pvt | ) | [static] |
Definition at line 2811 of file chan_dahdi.c.
References dahdi_set_hook(), SUB_REAL, and dahdi_pvt::subs.
02812 { 02813 struct dahdi_pvt *p = pvt; 02814 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02815 }
static int my_on_hook | ( | void * | pvt | ) | [static] |
Definition at line 2932 of file chan_dahdi.c.
References ANALOG_SUB_REAL, dahdi_set_hook(), and dahdi_pvt::subs.
02933 { 02934 struct dahdi_pvt *p = pvt; 02935 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK); 02936 }
static int my_play_tone | ( | void * | pvt, | |
enum analog_sub | sub, | |||
enum analog_tone | tone | |||
) | [static] |
Definition at line 2621 of file chan_dahdi.c.
References analog_tone_to_dahditone(), analogsub_to_dahdisub(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
02622 { 02623 struct dahdi_pvt *p = pvt; 02624 int index; 02625 02626 index = analogsub_to_dahdisub(sub); 02627 02628 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone)); 02629 }
static void my_pri_fixup_chans | ( | void * | chan_old, | |
void * | chan_new | |||
) | [static] |
Definition at line 2939 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.
02940 { 02941 struct dahdi_pvt *old_chan = chan_old; 02942 struct dahdi_pvt *new_chan = chan_new; 02943 02944 new_chan->owner = old_chan->owner; 02945 old_chan->owner = NULL; 02946 if (new_chan->owner) { 02947 new_chan->owner->tech_pvt = new_chan; 02948 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd; 02949 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner; 02950 old_chan->subs[SUB_REAL].owner = NULL; 02951 } 02952 /* Copy any DSP that may be present */ 02953 new_chan->dsp = old_chan->dsp; 02954 new_chan->dsp_features = old_chan->dsp_features; 02955 old_chan->dsp = NULL; 02956 old_chan->dsp_features = 0; 02957 02958 /* Transfer flags from the old channel. */ 02959 new_chan->dialing = old_chan->dialing; 02960 new_chan->digital = old_chan->digital; 02961 new_chan->outgoing = old_chan->outgoing; 02962 old_chan->dialing = 0; 02963 old_chan->digital = 0; 02964 old_chan->outgoing = 0; 02965 02966 /* More stuff to transfer to the new channel. */ 02967 new_chan->law = old_chan->law; 02968 strcpy(new_chan->dialstring, old_chan->dialstring); 02969 }
static void my_pri_make_cc_dialstring | ( | void * | priv, | |
char * | buf, | |||
size_t | buf_size | |||
) | [static] |
Definition at line 3127 of file chan_dahdi.c.
References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, and ast_strdupa.
03128 { 03129 char *dial; 03130 struct dahdi_pvt *pvt; 03131 AST_DECLARE_APP_ARGS(args, 03132 AST_APP_ARG(tech); /* channel technology token */ 03133 AST_APP_ARG(group); /* channel/group token */ 03134 //AST_APP_ARG(ext); /* extension token */ 03135 //AST_APP_ARG(opts); /* options token */ 03136 //AST_APP_ARG(other); /* Any remining unused arguments */ 03137 ); 03138 03139 pvt = priv; 03140 dial = ast_strdupa(pvt->dialstring); 03141 AST_NONSTANDARD_APP_ARGS(args, dial, '/'); 03142 if (!args.tech) { 03143 ast_copy_string(buf, pvt->dialstring, buf_size); 03144 return; 03145 } 03146 if (!args.group) { 03147 /* Append the ISDN span channel restriction to the dialstring. */ 03148 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span); 03149 return; 03150 } 03151 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) { 03152 /* The ISDN span channel restriction is not needed or already 03153 * in the dialstring. */ 03154 ast_copy_string(buf, pvt->dialstring, buf_size); 03155 return; 03156 } 03157 /* Insert the ISDN span channel restriction into the dialstring. */ 03158 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group); 03159 }
static void my_pri_open_media | ( | void * | p | ) | [static] |
Definition at line 2553 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.
02554 { 02555 struct dahdi_pvt *pvt = p; 02556 int res; 02557 int dfd; 02558 int set_val; 02559 02560 dfd = pvt->subs[SUB_REAL].dfd; 02561 02562 /* Open the media path. */ 02563 set_val = 1; 02564 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val); 02565 if (res < 0) { 02566 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", 02567 pvt->channel, strerror(errno)); 02568 } 02569 02570 /* Set correct companding law for this call. */ 02571 res = dahdi_setlaw(dfd, pvt->law); 02572 if (res < 0) { 02573 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel); 02574 } 02575 02576 /* Set correct gain for this call. */ 02577 if (pvt->digital) { 02578 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law); 02579 } else { 02580 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc, 02581 pvt->law); 02582 } 02583 if (res < 0) { 02584 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel); 02585 } 02586 02587 if (pvt->dsp_features && pvt->dsp) { 02588 ast_dsp_set_features(pvt->dsp, pvt->dsp_features); 02589 pvt->dsp_features = 0; 02590 } 02591 }
static int my_pri_play_tone | ( | void * | pvt, | |
enum sig_pri_tone | tone | |||
) | [static] |
Definition at line 3020 of file chan_dahdi.c.
References sig_pri_tone_to_dahditone(), SUB_REAL, and dahdi_pvt::subs.
03021 { 03022 struct dahdi_pvt *p = pvt; 03023 03024 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone)); 03025 }
static int my_ring | ( | void * | pvt | ) | [static] |
Definition at line 2795 of file chan_dahdi.c.
References dahdi_ring_phone().
02796 { 02797 struct dahdi_pvt *p = pvt; 02798 02799 return dahdi_ring_phone(p); 02800 }
static int my_send_callerid | ( | void * | pvt, | |
int | cwcid, | |||
struct ast_party_caller * | caller | |||
) | [static] |
Definition at line 1918 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.
01919 { 01920 struct dahdi_pvt *p = pvt; 01921 01922 ast_debug(2, "Starting cid spill\n"); 01923 01924 if (p->cidspill) { 01925 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01926 ast_free(p->cidspill); 01927 } 01928 01929 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01930 if (cwcid == 0) { 01931 p->cidlen = ast_callerid_generate(p->cidspill, 01932 caller->id.name.str, 01933 caller->id.number.str, 01934 AST_LAW(p)); 01935 } else { 01936 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", 01937 caller->id.name.str, caller->id.number.str); 01938 p->callwaitcas = 0; 01939 p->cidcwexpire = 0; 01940 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, 01941 caller->id.name.str, 01942 caller->id.number.str, 01943 AST_LAW(p)); 01944 p->cidlen += READ_SIZE * 4; 01945 } 01946 p->cidpos = 0; 01947 p->cid_suppress_expire = 0; 01948 send_callerid(p); 01949 } 01950 return 0; 01951 }
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 2160 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.
02161 { 02162 struct dahdi_pvt *p = pvt; 02163 02164 /* Choose proper cadence */ 02165 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02166 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02167 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02168 *cidrings = cidrings[p->distinctivering - 1]; 02169 } else { 02170 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02171 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02172 *cidrings = p->sendcalleridafter; 02173 } 02174 }
static void my_set_callerid | ( | void * | pvt, | |
const struct ast_party_caller * | caller | |||
) | [static] |
Definition at line 3039 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.
03040 { 03041 struct dahdi_pvt *p = pvt; 03042 03043 ast_copy_string(p->cid_num, 03044 S_COR(caller->id.number.valid, caller->id.number.str, ""), 03045 sizeof(p->cid_num)); 03046 ast_copy_string(p->cid_name, 03047 S_COR(caller->id.name.valid, caller->id.name.str, ""), 03048 sizeof(p->cid_name)); 03049 ast_copy_string(p->cid_subaddr, 03050 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""), 03051 sizeof(p->cid_subaddr)); 03052 p->cid_ton = caller->id.number.plan; 03053 p->callingpres = ast_party_id_presentation(&caller->id); 03054 if (caller->id.tag) { 03055 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag)); 03056 } 03057 ast_copy_string(p->cid_ani, 03058 S_COR(caller->ani.number.valid, caller->ani.number.str, ""), 03059 sizeof(p->cid_ani)); 03060 p->cid_ani2 = caller->ani2; 03061 }
static void my_set_callwaiting | ( | void * | pvt, | |
int | callwaiting_enable | |||
) | [static] |
Definition at line 2270 of file chan_dahdi.c.
References dahdi_pvt::callwaiting.
02271 { 02272 struct dahdi_pvt *p = pvt; 02273 02274 p->callwaiting = callwaiting_enable; 02275 }
static void my_set_confirmanswer | ( | void * | pvt, | |
int | flag | |||
) | [static] |
Definition at line 2254 of file chan_dahdi.c.
References dahdi_pvt::confirmanswer.
02255 { 02256 struct dahdi_pvt *p = pvt; 02257 p->confirmanswer = flag; 02258 }
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 3075 of file chan_dahdi.c.
References ast_copy_string(), and dahdi_pvt::dnid.
03076 { 03077 struct dahdi_pvt *p = pvt; 03078 03079 ast_copy_string(p->dnid, dnid, sizeof(p->dnid)); 03080 }
static int my_set_echocanceller | ( | void * | pvt, | |
int | enable | |||
) | [static] |
Definition at line 2781 of file chan_dahdi.c.
References dahdi_disable_ec(), and dahdi_enable_ec().
02782 { 02783 struct dahdi_pvt *p = pvt; 02784 02785 if (enable) 02786 dahdi_enable_ec(p); 02787 else 02788 dahdi_disable_ec(p); 02789 02790 return 0; 02791 }
static void my_set_inthreeway | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | inthreeway | |||
) | [static] |
Definition at line 2125 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_subchannel::inthreeway, and dahdi_pvt::subs.
02126 { 02127 struct dahdi_pvt *p = pvt; 02128 int idx = analogsub_to_dahdisub(sub); 02129 02130 p->subs[idx].inthreeway = inthreeway; 02131 }
static int my_set_linear_mode | ( | void * | pvt, | |
enum analog_sub | sub, | |||
int | linear_mode | |||
) | [static] |
Definition at line 2113 of file chan_dahdi.c.
References analogsub_to_dahdisub(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_subchannel::linear, and dahdi_pvt::subs.
02114 { 02115 struct dahdi_pvt *p = pvt; 02116 int oldval; 02117 int idx = analogsub_to_dahdisub(sub); 02118 02119 dahdi_setlinear(p->subs[idx].dfd, linear_mode); 02120 oldval = p->subs[idx].linear; 02121 p->subs[idx].linear = linear_mode ? 1 : 0; 02122 return oldval; 02123 }
static void my_set_needringing | ( | void * | pvt, | |
int | value | |||
) | [static] |
Definition at line 2817 of file chan_dahdi.c.
References dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
02818 { 02819 struct dahdi_pvt *p = pvt; 02820 p->subs[SUB_REAL].needringing = value; 02821 }
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 2823 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().
02824 { 02825 struct dahdi_pvt *p = pvt; 02826 02827 if (p->channel == CHAN_PSEUDO) { 02828 return; 02829 } 02830 p->polarity = value; 02831 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value); 02832 }
static void my_set_pulsedial | ( | void * | pvt, | |
int | flag | |||
) | [static] |
static void my_set_rdnis | ( | void * | pvt, | |
const char * | rdnis | |||
) | [static] |
Definition at line 3094 of file chan_dahdi.c.
References ast_copy_string(), and dahdi_pvt::rdnis.
03095 { 03096 struct dahdi_pvt *p = pvt; 03097 03098 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis)); 03099 }
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 2232 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.
02233 { 02234 struct dahdi_pvt *p = pvt; 02235 02236 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) { 02237 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone); 02238 gettimeofday(&p->waitingfordt, NULL); 02239 ast_setstate(ast, AST_STATE_OFFHOOK); 02240 } 02241 }
static int my_start | ( | void * | pvt | ) | [static] |
Definition at line 2869 of file chan_dahdi.c.
References SUB_REAL, and dahdi_pvt::subs.
02870 { 02871 struct dahdi_pvt *p = pvt; 02872 int x = DAHDI_START; 02873 02874 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02875 }
static int my_start_cid_detect | ( | void * | pvt, | |
int | cid_signalling | |||
) | [static] |
Definition at line 1647 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.
01648 { 01649 struct dahdi_pvt *p = pvt; 01650 int index = SUB_REAL; 01651 p->cs = callerid_new(cid_signalling); 01652 if (!p->cs) { 01653 ast_log(LOG_ERROR, "Unable to alloc callerid\n"); 01654 return -1; 01655 } 01656 bump_gains(p); 01657 dahdi_setlinear(p->subs[index].dfd, 0); 01658 01659 return 0; 01660 }
static void my_start_polarityswitch | ( | void * | pvt | ) | [static] |
Definition at line 2834 of file chan_dahdi.c.
References dahdi_pvt::answeronpolarityswitch, dahdi_pvt::hanguponpolarityswitch, and my_set_polarity().
02835 { 02836 struct dahdi_pvt *p = pvt; 02837 02838 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02839 my_set_polarity(pvt, 0); 02840 } 02841 }
static int my_stop_callwait | ( | void * | pvt | ) | [static] |
Definition at line 1871 of file chan_dahdi.c.
References dahdi_pvt::callwaitingrepeat, dahdi_pvt::cid_suppress_expire, and dahdi_pvt::cidcwexpire.
01872 { 01873 struct dahdi_pvt *p = pvt; 01874 p->callwaitingrepeat = 0; 01875 p->cidcwexpire = 0; 01876 p->cid_suppress_expire = 0; 01877 01878 return 0; 01879 }
static int my_stop_cid_detect | ( | void * | pvt | ) | [static] |
Definition at line 1662 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.
01663 { 01664 struct dahdi_pvt *p = pvt; 01665 int index = SUB_REAL; 01666 if (p->cs) 01667 callerid_free(p->cs); 01668 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 01669 return 0; 01670 }
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 2443 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().
02444 { 02445 struct dahdi_pvt *p = pvt; 02446 int da, db; 02447 int tchan; 02448 int tinthreeway; 02449 02450 da = analogsub_to_dahdisub(a); 02451 db = analogsub_to_dahdisub(b); 02452 02453 tchan = p->subs[da].chan; 02454 p->subs[da].chan = p->subs[db].chan; 02455 p->subs[db].chan = tchan; 02456 02457 tinthreeway = p->subs[da].inthreeway; 02458 p->subs[da].inthreeway = p->subs[db].inthreeway; 02459 p->subs[db].inthreeway = tinthreeway; 02460 02461 p->subs[da].owner = ast_a; 02462 p->subs[db].owner = ast_b; 02463 02464 if (ast_a) 02465 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); 02466 if (ast_b) 02467 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); 02468 02469 wakeup_sub(p, a); 02470 wakeup_sub(p, b); 02471 02472 return; 02473 }
static int my_train_echocanceller | ( | void * | pvt | ) | [static] |
Definition at line 2907 of file chan_dahdi.c.
References dahdi_train_ec().
02908 { 02909 struct dahdi_pvt *p = pvt; 02910 02911 dahdi_train_ec(p); 02912 02913 return 0; 02914 }
static int my_unallocate_sub | ( | void * | pvt, | |
enum analog_sub | analogsub | |||
) | [static] |
Definition at line 2596 of file chan_dahdi.c.
References analogsub_to_dahdisub(), and unalloc_sub().
02597 { 02598 struct dahdi_pvt *p = pvt; 02599 02600 return unalloc_sub(p, analogsub_to_dahdisub(analogsub)); 02601 }
static void my_unlock_private | ( | void * | pvt | ) | [static] |
Definition at line 2097 of file chan_dahdi.c.
References ast_mutex_unlock, and dahdi_pvt::lock.
02098 { 02099 struct dahdi_pvt *p = pvt; 02100 ast_mutex_unlock(&p->lock); 02101 }
static int my_wait_event | ( | void * | pvt | ) | [static] |
Definition at line 2728 of file chan_dahdi.c.
References dahdi_wait_event(), SUB_REAL, and dahdi_pvt::subs.
02729 { 02730 struct dahdi_pvt *p = pvt; 02731 02732 return dahdi_wait_event(p->subs[SUB_REAL].dfd); 02733 }
static int my_wink | ( | void * | pvt, | |
enum analog_sub | sub | |||
) | [static] |
Definition at line 2003 of file chan_dahdi.c.
References analogsub_to_dahdisub(), ast_log(), dahdi_wink(), LOG_ERROR, and SUB_REAL.
02004 { 02005 struct dahdi_pvt *p = pvt; 02006 int index = analogsub_to_dahdisub(sub); 02007 if (index != SUB_REAL) { 02008 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n"); 02009 } 02010 return dahdi_wink(p, index); 02011 }
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 3476 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().
03477 { 03478 char s[sizeof(mwimonitornotify) + 80]; 03479 struct ast_event *event; 03480 char *mailbox, *context; 03481 03482 /* Strip off @default */ 03483 context = mailbox = ast_strdupa(mailbox_full); 03484 strsep(&context, "@"); 03485 if (ast_strlen_zero(context)) 03486 context = "default"; 03487 03488 if (!(event = ast_event_new(AST_EVENT_MWI, 03489 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03490 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03491 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03492 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 03493 AST_EVENT_IE_END))) { 03494 return; 03495 } 03496 03497 ast_event_queue_and_cache(event); 03498 03499 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 03500 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 03501 ast_safe_system(s); 03502 } 03503 }
static int parse_buffers_policy | ( | const char * | parse, | |
int * | num_buffers, | |||
int * | policy | |||
) | [static] |
Definition at line 6821 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write().
06822 { 06823 int res; 06824 char policy_str[21] = ""; 06825 06826 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) { 06827 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 06828 return 1; 06829 } 06830 if (*num_buffers < 0) { 06831 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 06832 return -1; 06833 } 06834 if (!strcasecmp(policy_str, "full")) { 06835 *policy = DAHDI_POLICY_WHEN_FULL; 06836 } else if (!strcasecmp(policy_str, "immediate")) { 06837 *policy = DAHDI_POLICY_IMMEDIATE; 06838 #if defined(HAVE_DAHDI_HALF_FULL) 06839 } else if (!strcasecmp(policy_str, "half")) { 06840 *policy = DAHDI_POLICY_HALF_FULL; 06841 #endif 06842 } else { 06843 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 06844 return -1; 06845 } 06846 06847 return 0; 06848 }
static char* parse_spanchan | ( | char * | chanstr, | |
char ** | subdir | |||
) | [static] |
Definition at line 16305 of file chan_dahdi.c.
References string_replace().
Referenced by build_channels().
16306 { 16307 char *p; 16308 16309 if ((p = strrchr(chanstr, '!')) == NULL) { 16310 *subdir = NULL; 16311 return chanstr; 16312 } 16313 *p++ = '\0'; 16314 string_replace(chanstr, '!', '/'); 16315 *subdir = chanstr; 16316 return p; 16317 }
static int prepare_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 13777 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().
13778 { 13779 int i, res, x; 13780 struct dahdi_params p; 13781 struct dahdi_bufferinfo bi; 13782 struct dahdi_spaninfo si; 13783 13784 pri->pri.calls = &dahdi_pri_callbacks; 13785 13786 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) { 13787 if (!pri->dchannels[i]) 13788 break; 13789 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR); 13790 x = pri->dchannels[i]; 13791 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) { 13792 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 13793 return -1; 13794 } 13795 memset(&p, 0, sizeof(p)); 13796 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p); 13797 if (res) { 13798 dahdi_close_pri_fd(pri, i); 13799 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 13800 return -1; 13801 } 13802 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 13803 dahdi_close_pri_fd(pri, i); 13804 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 13805 return -1; 13806 } 13807 memset(&si, 0, sizeof(si)); 13808 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si); 13809 if (res) { 13810 dahdi_close_pri_fd(pri, i); 13811 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 13812 } 13813 if (!si.alarms) { 13814 pri_event_noalarm(&pri->pri, i, 1); 13815 } else { 13816 pri_event_alarm(&pri->pri, i, 1); 13817 } 13818 memset(&bi, 0, sizeof(bi)); 13819 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 13820 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 13821 bi.numbufs = 32; 13822 bi.bufsize = 1024; 13823 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) { 13824 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 13825 dahdi_close_pri_fd(pri, i); 13826 return -1; 13827 } 13828 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan; 13829 } 13830 return 0; 13831 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 11737 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi_int().
11738 { 11739 if (pris[span].mastertrunkgroup) { 11740 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); 11741 return -1; 11742 } 11743 pris[span].mastertrunkgroup = trunkgroup; 11744 pris[span].prilogicalspan = logicalspan; 11745 return 0; 11746 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 11674 of file chan_dahdi.c.
References ast_log(), NUM_SPANS, and pris.
Referenced by setup_dahdi_int().
11675 { 11676 struct dahdi_spaninfo si; 11677 struct dahdi_params p; 11678 int fd; 11679 int span; 11680 int ospan=0; 11681 int x,y; 11682 for (x = 0; x < NUM_SPANS; x++) { 11683 if (pris[x].pri.trunkgroup == trunkgroup) { 11684 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 11685 return -1; 11686 } 11687 } 11688 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) { 11689 if (!channels[y]) 11690 break; 11691 memset(&si, 0, sizeof(si)); 11692 memset(&p, 0, sizeof(p)); 11693 fd = open("/dev/dahdi/channel", O_RDWR); 11694 if (fd < 0) { 11695 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 11696 return -1; 11697 } 11698 x = channels[y]; 11699 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 11700 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 11701 close(fd); 11702 return -1; 11703 } 11704 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 11705 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 11706 return -1; 11707 } 11708 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 11709 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 11710 close(fd); 11711 return -1; 11712 } 11713 span = p.spanno - 1; 11714 if (pris[span].pri.trunkgroup) { 11715 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup); 11716 close(fd); 11717 return -1; 11718 } 11719 if (pris[span].pri.pvts[0]) { 11720 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 11721 close(fd); 11722 return -1; 11723 } 11724 if (!y) { 11725 pris[span].pri.trunkgroup = trunkgroup; 11726 ospan = span; 11727 } 11728 pris[ospan].dchannels[y] = channels[y]; 11729 pris[span].pri.span = span + 1; 11730 close(fd); 11731 } 11732 return 0; 11733 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 11628 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pvt::pri, pris, and sig_pri_span::trunkgroup.
11629 { 11630 int x; 11631 int trunkgroup; 11632 /* Get appropriate trunk group if there is one */ 11633 trunkgroup = pris[*span].mastertrunkgroup; 11634 if (trunkgroup) { 11635 /* Select a specific trunk group */ 11636 for (x = 0; x < NUM_SPANS; x++) { 11637 if (pris[x].pri.trunkgroup == trunkgroup) { 11638 *span = x; 11639 return 0; 11640 } 11641 } 11642 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 11643 *span = -1; 11644 } else { 11645 if (pris[*span].pri.trunkgroup) { 11646 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); 11647 *span = -1; 11648 } else if (pris[*span].mastertrunkgroup) { 11649 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 11650 *span = -1; 11651 } else { 11652 if (si->totalchans == 31) { 11653 /* E1 */ 11654 pris[*span].dchannels[0] = 16 + offset; 11655 } else if (si->totalchans == 24) { 11656 /* T1 or J1 */ 11657 pris[*span].dchannels[0] = 24 + offset; 11658 } else if (si->totalchans == 3) { 11659 /* BRI */ 11660 pris[*span].dchannels[0] = 3 + offset; 11661 } else { 11662 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); 11663 *span = -1; 11664 return 0; 11665 } 11666 pris[*span].pri.span = *span + 1; 11667 } 11668 } 11669 return 0; 11670 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | options | |||
) | [static] |
Definition at line 16448 of file chan_dahdi.c.
References ast_copy_string(), ast_jb_read_conf(), ast_log(), build_channels(), dahdi_chan_conf::chan, global_jbconf, ast_variable::lineno, MAX_CHANLIST_LEN, ast_variable::name, ast_variable::next, dahdi_pvt::parkinglot, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.
Referenced by setup_dahdi_int().
16449 { 16450 struct dahdi_pvt *tmp; 16451 int y; 16452 int found_pseudo = 0; 16453 char dahdichan[MAX_CHANLIST_LEN] = {}; 16454 16455 for (; v; v = v->next) { 16456 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 16457 continue; 16458 16459 /* must have parkinglot in confp before build_channels is called */ 16460 if (!strcasecmp(v->name, "parkinglot")) { 16461 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 16462 } 16463 16464 /* Create the interface list */ 16465 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) { 16466 if (options & PROC_DAHDI_OPT_NOCHAN) { 16467 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 16468 continue; 16469 } 16470 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) { 16471 if (confp->ignore_failed_channels) { 16472 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value); 16473 continue; 16474 } else { 16475 return -1; 16476 } 16477 } 16478 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 16479 } else if (!strcasecmp(v->name, "ignore_failed_channels")) { 16480 confp->ignore_failed_channels = ast_true(v->value); 16481 } else if (!strcasecmp(v->name, "buffers")) { 16482 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 16483 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 16484 confp->chan.buf_no = numbufs; 16485 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 16486 } 16487 } else if (!strcasecmp(v->name, "faxbuffers")) { 16488 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) { 16489 confp->chan.usefaxbuffers = 1; 16490 } 16491 } else if (!strcasecmp(v->name, "dahdichan")) { 16492 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 16493 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 16494 usedistinctiveringdetection = ast_true(v->value); 16495 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 16496 distinctiveringaftercid = ast_true(v->value); 16497 } else if (!strcasecmp(v->name, "dring1context")) { 16498 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 16499 } else if (!strcasecmp(v->name, "dring2context")) { 16500 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 16501 } else if (!strcasecmp(v->name, "dring3context")) { 16502 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 16503 } else if (!strcasecmp(v->name, "dring1range")) { 16504 confp->chan.drings.ringnum[0].range = atoi(v->value); 16505 } else if (!strcasecmp(v->name, "dring2range")) { 16506 confp->chan.drings.ringnum[1].range = atoi(v->value); 16507 } else if (!strcasecmp(v->name, "dring3range")) { 16508 confp->chan.drings.ringnum[2].range = atoi(v->value); 16509 } else if (!strcasecmp(v->name, "dring1")) { 16510 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]); 16511 } else if (!strcasecmp(v->name, "dring2")) { 16512 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]); 16513 } else if (!strcasecmp(v->name, "dring3")) { 16514 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]); 16515 } else if (!strcasecmp(v->name, "usecallerid")) { 16516 confp->chan.use_callerid = ast_true(v->value); 16517 } else if (!strcasecmp(v->name, "cidsignalling")) { 16518 if (!strcasecmp(v->value, "bell")) 16519 confp->chan.cid_signalling = CID_SIG_BELL; 16520 else if (!strcasecmp(v->value, "v23")) 16521 confp->chan.cid_signalling = CID_SIG_V23; 16522 else if (!strcasecmp(v->value, "dtmf")) 16523 confp->chan.cid_signalling = CID_SIG_DTMF; 16524 else if (!strcasecmp(v->value, "smdi")) 16525 confp->chan.cid_signalling = CID_SIG_SMDI; 16526 else if (!strcasecmp(v->value, "v23_jp")) 16527 confp->chan.cid_signalling = CID_SIG_V23_JP; 16528 else if (ast_true(v->value)) 16529 confp->chan.cid_signalling = CID_SIG_BELL; 16530 } else if (!strcasecmp(v->name, "cidstart")) { 16531 if (!strcasecmp(v->value, "ring")) 16532 confp->chan.cid_start = CID_START_RING; 16533 else if (!strcasecmp(v->value, "polarity_in")) 16534 confp->chan.cid_start = CID_START_POLARITY_IN; 16535 else if (!strcasecmp(v->value, "polarity")) 16536 confp->chan.cid_start = CID_START_POLARITY; 16537 else if (!strcasecmp(v->value, "dtmf")) 16538 confp->chan.cid_start = CID_START_DTMF_NOALERT; 16539 else if (ast_true(v->value)) 16540 confp->chan.cid_start = CID_START_RING; 16541 } else if (!strcasecmp(v->name, "threewaycalling")) { 16542 confp->chan.threewaycalling = ast_true(v->value); 16543 } else if (!strcasecmp(v->name, "cancallforward")) { 16544 confp->chan.cancallforward = ast_true(v->value); 16545 } else if (!strcasecmp(v->name, "relaxdtmf")) { 16546 if (ast_true(v->value)) 16547 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 16548 else 16549 confp->chan.dtmfrelax = 0; 16550 } else if (!strcasecmp(v->name, "mailbox")) { 16551 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 16552 } else if (!strcasecmp(v->name, "hasvoicemail")) { 16553 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 16554 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 16555 } 16556 } else if (!strcasecmp(v->name, "adsi")) { 16557 confp->chan.adsi = ast_true(v->value); 16558 } else if (!strcasecmp(v->name, "usesmdi")) { 16559 confp->chan.use_smdi = ast_true(v->value); 16560 } else if (!strcasecmp(v->name, "smdiport")) { 16561 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 16562 } else if (!strcasecmp(v->name, "transfer")) { 16563 confp->chan.transfer = ast_true(v->value); 16564 } else if (!strcasecmp(v->name, "canpark")) { 16565 confp->chan.canpark = ast_true(v->value); 16566 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 16567 confp->chan.echocanbridged = ast_true(v->value); 16568 } else if (!strcasecmp(v->name, "busydetect")) { 16569 confp->chan.busydetect = ast_true(v->value); 16570 } else if (!strcasecmp(v->name, "busycount")) { 16571 confp->chan.busycount = atoi(v->value); 16572 } else if (!strcasecmp(v->name, "silencethreshold")) { 16573 confp->chan.silencethreshold = atoi(v->value); 16574 } else if (!strcasecmp(v->name, "busycompare")) { 16575 confp->chan.busycompare = ast_true(v->value); 16576 } else if (!strcasecmp(v->name, "busypattern")) { 16577 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) { 16578 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 16579 } 16580 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 16581 if (count == 1) 16582 confp->chan.busyquietlength = 0; 16583 else if (count < 1) 16584 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno); 16585 } else if (!strcasecmp(v->name, "busyfuzziness")) { 16586 confp->chan.busyfuzziness = atoi(v->value); 16587 } else if (!strcasecmp(v->name, "callprogress")) { 16588 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 16589 if (ast_true(v->value)) 16590 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 16591 } else if (!strcasecmp(v->name, "waitfordialtone")) { 16592 confp->chan.waitfordialtone = atoi(v->value); 16593 } else if (!strcasecmp(v->name, "faxdetect")) { 16594 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 16595 if (!strcasecmp(v->value, "incoming")) { 16596 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 16597 } else if (!strcasecmp(v->value, "outgoing")) { 16598 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 16599 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 16600 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 16601 } else if (!strcasecmp(v->name, "echocancel")) { 16602 process_echocancel(confp, v->value, v->lineno); 16603 } else if (!strcasecmp(v->name, "echotraining")) { 16604 if (sscanf(v->value, "%30d", &y) == 1) { 16605 if ((y < 10) || (y > 4000)) { 16606 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 16607 } else { 16608 confp->chan.echotraining = y; 16609 } 16610 } else if (ast_true(v->value)) { 16611 confp->chan.echotraining = 400; 16612 } else 16613 confp->chan.echotraining = 0; 16614 } else if (!strcasecmp(v->name, "hidecallerid")) { 16615 confp->chan.hidecallerid = ast_true(v->value); 16616 } else if (!strcasecmp(v->name, "hidecalleridname")) { 16617 confp->chan.hidecalleridname = ast_true(v->value); 16618 } else if (!strcasecmp(v->name, "pulsedial")) { 16619 confp->chan.pulse = ast_true(v->value); 16620 } else if (!strcasecmp(v->name, "callreturn")) { 16621 confp->chan.callreturn = ast_true(v->value); 16622 } else if (!strcasecmp(v->name, "callwaiting")) { 16623 confp->chan.callwaiting = ast_true(v->value); 16624 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 16625 confp->chan.callwaitingcallerid = ast_true(v->value); 16626 } else if (!strcasecmp(v->name, "context")) { 16627 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 16628 } else if (!strcasecmp(v->name, "language")) { 16629 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 16630 } else if (!strcasecmp(v->name, "progzone")) { 16631 ast_copy_string(progzone, v->value, sizeof(progzone)); 16632 } else if (!strcasecmp(v->name, "mohinterpret") 16633 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 16634 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 16635 } else if (!strcasecmp(v->name, "mohsuggest")) { 16636 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 16637 } else if (!strcasecmp(v->name, "parkinglot")) { 16638 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 16639 } else if (!strcasecmp(v->name, "stripmsd")) { 16640 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 16641 confp->chan.stripmsd = atoi(v->value); 16642 } else if (!strcasecmp(v->name, "jitterbuffers")) { 16643 numbufs = atoi(v->value); 16644 } else if (!strcasecmp(v->name, "group")) { 16645 confp->chan.group = ast_get_group(v->value); 16646 } else if (!strcasecmp(v->name, "callgroup")) { 16647 if (!strcasecmp(v->value, "none")) 16648 confp->chan.callgroup = 0; 16649 else 16650 confp->chan.callgroup = ast_get_group(v->value); 16651 } else if (!strcasecmp(v->name, "pickupgroup")) { 16652 if (!strcasecmp(v->value, "none")) 16653 confp->chan.pickupgroup = 0; 16654 else 16655 confp->chan.pickupgroup = ast_get_group(v->value); 16656 } else if (!strcasecmp(v->name, "setvar")) { 16657 char *varname = ast_strdupa(v->value), *varval = NULL; 16658 struct ast_variable *tmpvar; 16659 if (varname && (varval = strchr(varname, '='))) { 16660 *varval++ = '\0'; 16661 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 16662 tmpvar->next = confp->chan.vars; 16663 confp->chan.vars = tmpvar; 16664 } 16665 } 16666 } else if (!strcasecmp(v->name, "immediate")) { 16667 confp->chan.immediate = ast_true(v->value); 16668 } else if (!strcasecmp(v->name, "transfertobusy")) { 16669 confp->chan.transfertobusy = ast_true(v->value); 16670 } else if (!strcasecmp(v->name, "mwimonitor")) { 16671 confp->chan.mwimonitor_neon = 0; 16672 confp->chan.mwimonitor_fsk = 0; 16673 confp->chan.mwimonitor_rpas = 0; 16674 if (strcasestr(v->value, "fsk")) { 16675 confp->chan.mwimonitor_fsk = 1; 16676 } 16677 if (strcasestr(v->value, "rpas")) { 16678 confp->chan.mwimonitor_rpas = 1; 16679 } 16680 if (strcasestr(v->value, "neon")) { 16681 confp->chan.mwimonitor_neon = 1; 16682 } 16683 /* If set to true or yes, assume that simple fsk is desired */ 16684 if (ast_true(v->value)) { 16685 confp->chan.mwimonitor_fsk = 1; 16686 } 16687 } else if (!strcasecmp(v->name, "cid_rxgain")) { 16688 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 16689 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 16690 } 16691 } else if (!strcasecmp(v->name, "rxgain")) { 16692 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 16693 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 16694 } 16695 } else if (!strcasecmp(v->name, "txgain")) { 16696 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 16697 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 16698 } 16699 } else if (!strcasecmp(v->name, "txdrc")) { 16700 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) { 16701 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value); 16702 } 16703 } else if (!strcasecmp(v->name, "rxdrc")) { 16704 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) { 16705 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value); 16706 } 16707 } else if (!strcasecmp(v->name, "tonezone")) { 16708 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 16709 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 16710 } 16711 } else if (!strcasecmp(v->name, "callerid")) { 16712 if (!strcasecmp(v->value, "asreceived")) { 16713 confp->chan.cid_num[0] = '\0'; 16714 confp->chan.cid_name[0] = '\0'; 16715 } else { 16716 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 16717 } 16718 } else if (!strcasecmp(v->name, "fullname")) { 16719 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 16720 } else if (!strcasecmp(v->name, "cid_number")) { 16721 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 16722 } else if (!strcasecmp(v->name, "cid_tag")) { 16723 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); 16724 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 16725 confp->chan.dahditrcallerid = ast_true(v->value); 16726 } else if (!strcasecmp(v->name, "restrictcid")) { 16727 confp->chan.restrictcid = ast_true(v->value); 16728 } else if (!strcasecmp(v->name, "usecallingpres")) { 16729 confp->chan.use_callingpres = ast_true(v->value); 16730 } else if (!strcasecmp(v->name, "accountcode")) { 16731 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 16732 } else if (!strcasecmp(v->name, "amaflags")) { 16733 y = ast_cdr_amaflags2int(v->value); 16734 if (y < 0) 16735 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 16736 else 16737 confp->chan.amaflags = y; 16738 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 16739 confp->chan.polarityonanswerdelay = atoi(v->value); 16740 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 16741 confp->chan.answeronpolarityswitch = ast_true(v->value); 16742 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 16743 confp->chan.hanguponpolarityswitch = ast_true(v->value); 16744 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 16745 confp->chan.sendcalleridafter = atoi(v->value); 16746 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 16747 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 16748 } else if (ast_cc_is_config_param(v->name)) { 16749 ast_cc_set_param(confp->chan.cc_params, v->name, v->value); 16750 } else if (!strcasecmp(v->name, "mwisendtype")) { 16751 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 16752 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 16753 mwisend_rpas = 1; 16754 } else { 16755 mwisend_rpas = 0; 16756 } 16757 #else 16758 /* Default is fsk, to turn it off you must specify nofsk */ 16759 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 16760 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 16761 confp->chan.mwisend_fsk = 0; 16762 } else { /* Default FSK */ 16763 confp->chan.mwisend_fsk = 1; 16764 } 16765 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 16766 confp->chan.mwisend_rpas = 1; 16767 } else { 16768 confp->chan.mwisend_rpas = 0; 16769 } 16770 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 16771 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 16772 } 16773 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 16774 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 16775 } 16776 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 16777 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 16778 } 16779 #endif 16780 } else if (reload != 1) { 16781 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 16782 int orig_radio = confp->chan.radio; 16783 int orig_outsigmod = confp->chan.outsigmod; 16784 int orig_auto = confp->is_sig_auto; 16785 16786 confp->chan.radio = 0; 16787 confp->chan.outsigmod = -1; 16788 confp->is_sig_auto = 0; 16789 if (!strcasecmp(v->value, "em")) { 16790 confp->chan.sig = SIG_EM; 16791 } else if (!strcasecmp(v->value, "em_e1")) { 16792 confp->chan.sig = SIG_EM_E1; 16793 } else if (!strcasecmp(v->value, "em_w")) { 16794 confp->chan.sig = SIG_EMWINK; 16795 } else if (!strcasecmp(v->value, "fxs_ls")) { 16796 confp->chan.sig = SIG_FXSLS; 16797 } else if (!strcasecmp(v->value, "fxs_gs")) { 16798 confp->chan.sig = SIG_FXSGS; 16799 } else if (!strcasecmp(v->value, "fxs_ks")) { 16800 confp->chan.sig = SIG_FXSKS; 16801 } else if (!strcasecmp(v->value, "fxo_ls")) { 16802 confp->chan.sig = SIG_FXOLS; 16803 } else if (!strcasecmp(v->value, "fxo_gs")) { 16804 confp->chan.sig = SIG_FXOGS; 16805 } else if (!strcasecmp(v->value, "fxo_ks")) { 16806 confp->chan.sig = SIG_FXOKS; 16807 } else if (!strcasecmp(v->value, "fxs_rx")) { 16808 confp->chan.sig = SIG_FXSKS; 16809 confp->chan.radio = 1; 16810 } else if (!strcasecmp(v->value, "fxo_rx")) { 16811 confp->chan.sig = SIG_FXOLS; 16812 confp->chan.radio = 1; 16813 } else if (!strcasecmp(v->value, "fxs_tx")) { 16814 confp->chan.sig = SIG_FXSLS; 16815 confp->chan.radio = 1; 16816 } else if (!strcasecmp(v->value, "fxo_tx")) { 16817 confp->chan.sig = SIG_FXOGS; 16818 confp->chan.radio = 1; 16819 } else if (!strcasecmp(v->value, "em_rx")) { 16820 confp->chan.sig = SIG_EM; 16821 confp->chan.radio = 1; 16822 } else if (!strcasecmp(v->value, "em_tx")) { 16823 confp->chan.sig = SIG_EM; 16824 confp->chan.radio = 1; 16825 } else if (!strcasecmp(v->value, "em_rxtx")) { 16826 confp->chan.sig = SIG_EM; 16827 confp->chan.radio = 2; 16828 } else if (!strcasecmp(v->value, "em_txrx")) { 16829 confp->chan.sig = SIG_EM; 16830 confp->chan.radio = 2; 16831 } else if (!strcasecmp(v->value, "sf")) { 16832 confp->chan.sig = SIG_SF; 16833 } else if (!strcasecmp(v->value, "sf_w")) { 16834 confp->chan.sig = SIG_SFWINK; 16835 } else if (!strcasecmp(v->value, "sf_featd")) { 16836 confp->chan.sig = SIG_FEATD; 16837 } else if (!strcasecmp(v->value, "sf_featdmf")) { 16838 confp->chan.sig = SIG_FEATDMF; 16839 } else if (!strcasecmp(v->value, "sf_featb")) { 16840 confp->chan.sig = SIG_SF_FEATB; 16841 } else if (!strcasecmp(v->value, "sf")) { 16842 confp->chan.sig = SIG_SF; 16843 } else if (!strcasecmp(v->value, "sf_rx")) { 16844 confp->chan.sig = SIG_SF; 16845 confp->chan.radio = 1; 16846 } else if (!strcasecmp(v->value, "sf_tx")) { 16847 confp->chan.sig = SIG_SF; 16848 confp->chan.radio = 1; 16849 } else if (!strcasecmp(v->value, "sf_rxtx")) { 16850 confp->chan.sig = SIG_SF; 16851 confp->chan.radio = 2; 16852 } else if (!strcasecmp(v->value, "sf_txrx")) { 16853 confp->chan.sig = SIG_SF; 16854 confp->chan.radio = 2; 16855 } else if (!strcasecmp(v->value, "featd")) { 16856 confp->chan.sig = SIG_FEATD; 16857 } else if (!strcasecmp(v->value, "featdmf")) { 16858 confp->chan.sig = SIG_FEATDMF; 16859 } else if (!strcasecmp(v->value, "featdmf_ta")) { 16860 confp->chan.sig = SIG_FEATDMF_TA; 16861 } else if (!strcasecmp(v->value, "e911")) { 16862 confp->chan.sig = SIG_E911; 16863 } else if (!strcasecmp(v->value, "fgccama")) { 16864 confp->chan.sig = SIG_FGC_CAMA; 16865 } else if (!strcasecmp(v->value, "fgccamamf")) { 16866 confp->chan.sig = SIG_FGC_CAMAMF; 16867 } else if (!strcasecmp(v->value, "featb")) { 16868 confp->chan.sig = SIG_FEATB; 16869 #ifdef HAVE_PRI 16870 } else if (!strcasecmp(v->value, "pri_net")) { 16871 confp->chan.sig = SIG_PRI; 16872 confp->pri.pri.nodetype = PRI_NETWORK; 16873 } else if (!strcasecmp(v->value, "pri_cpe")) { 16874 confp->chan.sig = SIG_PRI; 16875 confp->pri.pri.nodetype = PRI_CPE; 16876 } else if (!strcasecmp(v->value, "bri_cpe")) { 16877 confp->chan.sig = SIG_BRI; 16878 confp->pri.pri.nodetype = PRI_CPE; 16879 } else if (!strcasecmp(v->value, "bri_net")) { 16880 confp->chan.sig = SIG_BRI; 16881 confp->pri.pri.nodetype = PRI_NETWORK; 16882 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 16883 confp->chan.sig = SIG_BRI_PTMP; 16884 confp->pri.pri.nodetype = PRI_CPE; 16885 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 16886 #if defined(HAVE_PRI_CALL_HOLD) 16887 confp->chan.sig = SIG_BRI_PTMP; 16888 confp->pri.pri.nodetype = PRI_NETWORK; 16889 #else 16890 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 16891 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 16892 #endif 16893 #if defined(HAVE_SS7) 16894 } else if (!strcasecmp(v->value, "ss7")) { 16895 confp->chan.sig = SIG_SS7; 16896 #endif /* defined(HAVE_SS7) */ 16897 #ifdef HAVE_OPENR2 16898 } else if (!strcasecmp(v->value, "mfcr2")) { 16899 confp->chan.sig = SIG_MFCR2; 16900 #endif 16901 } else if (!strcasecmp(v->value, "auto")) { 16902 confp->is_sig_auto = 1; 16903 } else { 16904 confp->chan.outsigmod = orig_outsigmod; 16905 confp->chan.radio = orig_radio; 16906 confp->is_sig_auto = orig_auto; 16907 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 16908 } 16909 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 16910 if (!strcasecmp(v->value, "em")) { 16911 confp->chan.outsigmod = SIG_EM; 16912 } else if (!strcasecmp(v->value, "em_e1")) { 16913 confp->chan.outsigmod = SIG_EM_E1; 16914 } else if (!strcasecmp(v->value, "em_w")) { 16915 confp->chan.outsigmod = SIG_EMWINK; 16916 } else if (!strcasecmp(v->value, "sf")) { 16917 confp->chan.outsigmod = SIG_SF; 16918 } else if (!strcasecmp(v->value, "sf_w")) { 16919 confp->chan.outsigmod = SIG_SFWINK; 16920 } else if (!strcasecmp(v->value, "sf_featd")) { 16921 confp->chan.outsigmod = SIG_FEATD; 16922 } else if (!strcasecmp(v->value, "sf_featdmf")) { 16923 confp->chan.outsigmod = SIG_FEATDMF; 16924 } else if (!strcasecmp(v->value, "sf_featb")) { 16925 confp->chan.outsigmod = SIG_SF_FEATB; 16926 } else if (!strcasecmp(v->value, "sf")) { 16927 confp->chan.outsigmod = SIG_SF; 16928 } else if (!strcasecmp(v->value, "featd")) { 16929 confp->chan.outsigmod = SIG_FEATD; 16930 } else if (!strcasecmp(v->value, "featdmf")) { 16931 confp->chan.outsigmod = SIG_FEATDMF; 16932 } else if (!strcasecmp(v->value, "featdmf_ta")) { 16933 confp->chan.outsigmod = SIG_FEATDMF_TA; 16934 } else if (!strcasecmp(v->value, "e911")) { 16935 confp->chan.outsigmod = SIG_E911; 16936 } else if (!strcasecmp(v->value, "fgccama")) { 16937 confp->chan.outsigmod = SIG_FGC_CAMA; 16938 } else if (!strcasecmp(v->value, "fgccamamf")) { 16939 confp->chan.outsigmod = SIG_FGC_CAMAMF; 16940 } else if (!strcasecmp(v->value, "featb")) { 16941 confp->chan.outsigmod = SIG_FEATB; 16942 } else { 16943 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 16944 } 16945 #ifdef HAVE_PRI 16946 } else if (!strcasecmp(v->name, "pridialplan")) { 16947 if (!strcasecmp(v->value, "national")) { 16948 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1; 16949 } else if (!strcasecmp(v->value, "unknown")) { 16950 confp->pri.pri.dialplan = PRI_UNKNOWN + 1; 16951 } else if (!strcasecmp(v->value, "private")) { 16952 confp->pri.pri.dialplan = PRI_PRIVATE + 1; 16953 } else if (!strcasecmp(v->value, "international")) { 16954 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 16955 } else if (!strcasecmp(v->value, "local")) { 16956 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1; 16957 } else if (!strcasecmp(v->value, "dynamic")) { 16958 confp->pri.pri.dialplan = -1; 16959 } else if (!strcasecmp(v->value, "redundant")) { 16960 confp->pri.pri.dialplan = -2; 16961 } else { 16962 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 16963 } 16964 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 16965 if (!strcasecmp(v->value, "national")) { 16966 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1; 16967 } else if (!strcasecmp(v->value, "unknown")) { 16968 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1; 16969 } else if (!strcasecmp(v->value, "private")) { 16970 confp->pri.pri.localdialplan = PRI_PRIVATE + 1; 16971 } else if (!strcasecmp(v->value, "international")) { 16972 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 16973 } else if (!strcasecmp(v->value, "local")) { 16974 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1; 16975 } else if (!strcasecmp(v->value, "dynamic")) { 16976 confp->pri.pri.localdialplan = -1; 16977 } else if (!strcasecmp(v->value, "redundant")) { 16978 confp->pri.pri.localdialplan = -2; 16979 } else { 16980 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 16981 } 16982 } else if (!strcasecmp(v->name, "switchtype")) { 16983 if (!strcasecmp(v->value, "national")) 16984 confp->pri.pri.switchtype = PRI_SWITCH_NI2; 16985 else if (!strcasecmp(v->value, "ni1")) 16986 confp->pri.pri.switchtype = PRI_SWITCH_NI1; 16987 else if (!strcasecmp(v->value, "dms100")) 16988 confp->pri.pri.switchtype = PRI_SWITCH_DMS100; 16989 else if (!strcasecmp(v->value, "4ess")) 16990 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS; 16991 else if (!strcasecmp(v->value, "5ess")) 16992 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E; 16993 else if (!strcasecmp(v->value, "euroisdn")) 16994 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1; 16995 else if (!strcasecmp(v->value, "qsig")) 16996 confp->pri.pri.switchtype = PRI_SWITCH_QSIG; 16997 else { 16998 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 16999 return -1; 17000 } 17001 } else if (!strcasecmp(v->name, "msn")) { 17002 ast_copy_string(confp->pri.pri.msn_list, v->value, 17003 sizeof(confp->pri.pri.msn_list)); 17004 } else if (!strcasecmp(v->name, "nsf")) { 17005 if (!strcasecmp(v->value, "sdn")) 17006 confp->pri.pri.nsf = PRI_NSF_SDN; 17007 else if (!strcasecmp(v->value, "megacom")) 17008 confp->pri.pri.nsf = PRI_NSF_MEGACOM; 17009 else if (!strcasecmp(v->value, "tollfreemegacom")) 17010 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 17011 else if (!strcasecmp(v->value, "accunet")) 17012 confp->pri.pri.nsf = PRI_NSF_ACCUNET; 17013 else if (!strcasecmp(v->value, "none")) 17014 confp->pri.pri.nsf = PRI_NSF_NONE; 17015 else { 17016 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 17017 confp->pri.pri.nsf = PRI_NSF_NONE; 17018 } 17019 } else if (!strcasecmp(v->name, "priindication")) { 17020 if (!strcasecmp(v->value, "outofband")) 17021 confp->chan.priindication_oob = 1; 17022 else if (!strcasecmp(v->value, "inband")) 17023 confp->chan.priindication_oob = 0; 17024 else 17025 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 17026 v->value, v->lineno); 17027 } else if (!strcasecmp(v->name, "priexclusive")) { 17028 confp->chan.priexclusive = ast_true(v->value); 17029 } else if (!strcasecmp(v->name, "internationalprefix")) { 17030 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix)); 17031 } else if (!strcasecmp(v->name, "nationalprefix")) { 17032 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix)); 17033 } else if (!strcasecmp(v->name, "localprefix")) { 17034 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix)); 17035 } else if (!strcasecmp(v->name, "privateprefix")) { 17036 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix)); 17037 } else if (!strcasecmp(v->name, "unknownprefix")) { 17038 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix)); 17039 } else if (!strcasecmp(v->name, "resetinterval")) { 17040 if (!strcasecmp(v->value, "never")) 17041 confp->pri.pri.resetinterval = -1; 17042 else if (atoi(v->value) >= 60) 17043 confp->pri.pri.resetinterval = atoi(v->value); 17044 else 17045 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 17046 v->value, v->lineno); 17047 } else if (!strcasecmp(v->name, "minunused")) { 17048 confp->pri.pri.minunused = atoi(v->value); 17049 } else if (!strcasecmp(v->name, "minidle")) { 17050 confp->pri.pri.minidle = atoi(v->value); 17051 } else if (!strcasecmp(v->name, "idleext")) { 17052 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext)); 17053 } else if (!strcasecmp(v->name, "idledial")) { 17054 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial)); 17055 } else if (!strcasecmp(v->name, "overlapdial")) { 17056 if (ast_true(v->value)) { 17057 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17058 } else if (!strcasecmp(v->value, "incoming")) { 17059 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 17060 } else if (!strcasecmp(v->value, "outgoing")) { 17061 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 17062 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 17063 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 17064 } else { 17065 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 17066 } 17067 #ifdef HAVE_PRI_PROG_W_CAUSE 17068 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 17069 if (!strcasecmp(v->value, "logical")) { 17070 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 17071 } else if (!strcasecmp(v->value, "physical")) { 17072 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17073 } else { 17074 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 17075 } 17076 #endif 17077 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 17078 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value); 17079 #if defined(HAVE_PRI_SERVICE_MESSAGES) 17080 } else if (!strcasecmp(v->name, "service_message_support")) { 17081 /* assuming switchtype for this channel group has been configured already */ 17082 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 17083 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E 17084 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) { 17085 confp->pri.pri.enable_service_message_support = 1; 17086 } else { 17087 confp->pri.pri.enable_service_message_support = 0; 17088 } 17089 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ 17090 #ifdef HAVE_PRI_INBANDDISCONNECT 17091 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 17092 confp->pri.pri.inbanddisconnect = ast_true(v->value); 17093 #endif 17094 } else if (!strcasecmp(v->name, "pritimer")) { 17095 #ifdef PRI_GETSET_TIMERS 17096 char tmp[20]; 17097 char *timerc; 17098 char *c; 17099 int timer; 17100 int timeridx; 17101 17102 ast_copy_string(tmp, v->value, sizeof(tmp)); 17103 c = tmp; 17104 timerc = strsep(&c, ","); 17105 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 17106 timeridx = pri_timer2idx(timerc); 17107 timer = atoi(c); 17108 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 17109 ast_log(LOG_WARNING, 17110 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 17111 v->lineno); 17112 } else if (!timer) { 17113 ast_log(LOG_WARNING, 17114 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 17115 c, timerc, v->lineno); 17116 } else { 17117 confp->pri.pri.pritimers[timeridx] = timer; 17118 } 17119 } else { 17120 ast_log(LOG_WARNING, 17121 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 17122 v->value, v->lineno); 17123 } 17124 #endif /* PRI_GETSET_TIMERS */ 17125 } else if (!strcasecmp(v->name, "facilityenable")) { 17126 confp->pri.pri.facilityenable = ast_true(v->value); 17127 #if defined(HAVE_PRI_AOC_EVENTS) 17128 } else if (!strcasecmp(v->name, "aoc_enable")) { 17129 confp->pri.pri.aoc_passthrough_flag = 0; 17130 if (strchr(v->value, 's') || strchr(v->value, 'S')) { 17131 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S; 17132 } 17133 if (strchr(v->value, 'd') || strchr(v->value, 'D')) { 17134 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D; 17135 } 17136 if (strchr(v->value, 'e') || strchr(v->value, 'E')) { 17137 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E; 17138 } 17139 } else if (!strcasecmp(v->name, "aoce_delayhangup")) { 17140 confp->pri.pri.aoce_delayhangup = ast_true(v->value); 17141 #endif /* defined(HAVE_PRI_AOC_EVENTS) */ 17142 #if defined(HAVE_PRI_CALL_HOLD) 17143 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) { 17144 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value); 17145 #endif /* defined(HAVE_PRI_CALL_HOLD) */ 17146 #if defined(HAVE_PRI_CCSS) 17147 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) { 17148 if (!strcasecmp(v->value, "global")) { 17149 confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */ 17150 } else if (!strcasecmp(v->value, "specific")) { 17151 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17152 } else { 17153 confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */ 17154 } 17155 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) { 17156 if (!strcasecmp(v->value, "release")) { 17157 confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */ 17158 } else if (!strcasecmp(v->value, "retain")) { 17159 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17160 } else if (!strcasecmp(v->value, "do_not_care")) { 17161 confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */ 17162 } else { 17163 confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */ 17164 } 17165 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) { 17166 if (!strcasecmp(v->value, "release")) { 17167 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */ 17168 } else if (!strcasecmp(v->value, "retain")) { 17169 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17170 } else { 17171 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */ 17172 } 17173 #endif /* defined(HAVE_PRI_CCSS) */ 17174 #if defined(HAVE_PRI_CALL_WAITING) 17175 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) { 17176 confp->pri.pri.max_call_waiting_calls = atoi(v->value); 17177 if (confp->pri.pri.max_call_waiting_calls < 0) { 17178 /* Negative values are not allowed. */ 17179 confp->pri.pri.max_call_waiting_calls = 0; 17180 } 17181 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) { 17182 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value); 17183 #endif /* defined(HAVE_PRI_CALL_WAITING) */ 17184 #if defined(HAVE_PRI_MWI) 17185 } else if (!strcasecmp(v->name, "mwi_mailboxes")) { 17186 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value, 17187 sizeof(confp->pri.pri.mwi_mailboxes)); 17188 #endif /* defined(HAVE_PRI_MWI) */ 17189 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) { 17190 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value); 17191 #endif /* HAVE_PRI */ 17192 #if defined(HAVE_SS7) 17193 } else if (!strcasecmp(v->name, "ss7type")) { 17194 if (!strcasecmp(v->value, "itu")) { 17195 cur_ss7type = SS7_ITU; 17196 } else if (!strcasecmp(v->value, "ansi")) { 17197 cur_ss7type = SS7_ANSI; 17198 } else 17199 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 17200 } else if (!strcasecmp(v->name, "linkset")) { 17201 cur_linkset = atoi(v->value); 17202 } else if (!strcasecmp(v->name, "pointcode")) { 17203 cur_pointcode = parse_pointcode(v->value); 17204 } else if (!strcasecmp(v->name, "adjpointcode")) { 17205 cur_adjpointcode = parse_pointcode(v->value); 17206 } else if (!strcasecmp(v->name, "defaultdpc")) { 17207 cur_defaultdpc = parse_pointcode(v->value); 17208 } else if (!strcasecmp(v->name, "cicbeginswith")) { 17209 cur_cicbeginswith = atoi(v->value); 17210 } else if (!strcasecmp(v->name, "networkindicator")) { 17211 if (!strcasecmp(v->value, "national")) 17212 cur_networkindicator = SS7_NI_NAT; 17213 else if (!strcasecmp(v->value, "national_spare")) 17214 cur_networkindicator = SS7_NI_NAT_SPARE; 17215 else if (!strcasecmp(v->value, "international")) 17216 cur_networkindicator = SS7_NI_INT; 17217 else if (!strcasecmp(v->value, "international_spare")) 17218 cur_networkindicator = SS7_NI_INT_SPARE; 17219 else 17220 cur_networkindicator = -1; 17221 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 17222 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix)); 17223 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 17224 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix)); 17225 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 17226 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix)); 17227 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 17228 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix)); 17229 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 17230 if (!strcasecmp(v->value, "national")) { 17231 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL; 17232 } else if (!strcasecmp(v->value, "international")) { 17233 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL; 17234 } else if (!strcasecmp(v->value, "subscriber")) { 17235 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER; 17236 } else if (!strcasecmp(v->value, "unknown")) { 17237 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN; 17238 } else if (!strcasecmp(v->value, "dynamic")) { 17239 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC; 17240 } else { 17241 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 17242 } 17243 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 17244 if (!strcasecmp(v->value, "national")) { 17245 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL; 17246 } else if (!strcasecmp(v->value, "international")) { 17247 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL; 17248 } else if (!strcasecmp(v->value, "subscriber")) { 17249 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER; 17250 } else if (!strcasecmp(v->value, "unknown")) { 17251 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN; 17252 } else if (!strcasecmp(v->value, "dynamic")) { 17253 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC; 17254 } else { 17255 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 17256 } 17257 } else if (!strcasecmp(v->name, "sigchan")) { 17258 int sigchan, res; 17259 sigchan = atoi(v->value); 17260 res = linkset_addsigchan(sigchan); 17261 if (res < 0) 17262 return -1; 17263 17264 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 17265 struct dahdi_ss7 *link; 17266 link = ss7_resolve_linkset(cur_linkset); 17267 if (!link) { 17268 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 17269 return -1; 17270 } 17271 if (ast_true(v->value)) 17272 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM; 17273 #endif /* defined(HAVE_SS7) */ 17274 #ifdef HAVE_OPENR2 17275 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 17276 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 17277 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); 17278 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 17279 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 17280 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 17281 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 17282 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 17283 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 17284 confp->mfcr2.variant = OR2_VAR_ITU; 17285 } 17286 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 17287 confp->mfcr2.mfback_timeout = atoi(v->value); 17288 if (!confp->mfcr2.mfback_timeout) { 17289 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 17290 confp->mfcr2.mfback_timeout = -1; 17291 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 17292 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 17293 } 17294 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 17295 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 17296 if (confp->mfcr2.metering_pulse_timeout > 500) { 17297 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 17298 } 17299 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 17300 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 17301 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 17302 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 17303 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 17304 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 17305 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 17306 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 17307 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 17308 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 17309 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 17310 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 17311 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 17312 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 17313 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 17314 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 17315 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0; 17316 #endif 17317 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 17318 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 17319 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 17320 confp->mfcr2.max_ani = atoi(v->value); 17321 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 17322 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 17323 } 17324 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 17325 confp->mfcr2.max_dnis = atoi(v->value); 17326 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 17327 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 17328 } 17329 } else if (!strcasecmp(v->name, "mfcr2_category")) { 17330 confp->mfcr2.category = openr2_proto_get_category(v->value); 17331 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 17332 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 17333 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 17334 v->value, v->lineno); 17335 } 17336 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 17337 openr2_log_level_t tmplevel; 17338 char *clevel; 17339 char *logval = ast_strdupa(v->value); 17340 while (logval) { 17341 clevel = strsep(&logval,","); 17342 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 17343 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 17344 continue; 17345 } 17346 confp->mfcr2.loglevel |= tmplevel; 17347 } 17348 #endif /* HAVE_OPENR2 */ 17349 } else if (!strcasecmp(v->name, "cadence")) { 17350 /* setup to scan our argument */ 17351 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 17352 int i; 17353 struct dahdi_ring_cadence new_cadence; 17354 int cid_location = -1; 17355 int firstcadencepos = 0; 17356 char original_args[80]; 17357 int cadence_is_ok = 1; 17358 17359 ast_copy_string(original_args, v->value, sizeof(original_args)); 17360 /* 16 cadences allowed (8 pairs) */ 17361 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]); 17362 17363 /* Cadence must be even (on/off) */ 17364 if (element_count % 2 == 1) { 17365 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 17366 cadence_is_ok = 0; 17367 } 17368 17369 /* Ring cadences cannot be negative */ 17370 for (i = 0; i < element_count; i++) { 17371 if (c[i] == 0) { 17372 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 17373 cadence_is_ok = 0; 17374 break; 17375 } else if (c[i] < 0) { 17376 if (i % 2 == 1) { 17377 /* Silence duration, negative possibly okay */ 17378 if (cid_location == -1) { 17379 cid_location = i; 17380 c[i] *= -1; 17381 } else { 17382 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 17383 cadence_is_ok = 0; 17384 break; 17385 } 17386 } else { 17387 if (firstcadencepos == 0) { 17388 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 17389 /* duration will be passed negative to the DAHDI driver */ 17390 } else { 17391 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 17392 cadence_is_ok = 0; 17393 break; 17394 } 17395 } 17396 } 17397 } 17398 17399 /* Substitute our scanned cadence */ 17400 for (i = 0; i < 16; i++) { 17401 new_cadence.ringcadence[i] = c[i]; 17402 } 17403 17404 if (cadence_is_ok) { 17405 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 17406 if (element_count < 2) { 17407 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 17408 } else { 17409 if (cid_location == -1) { 17410 /* user didn't say; default to first pause */ 17411 cid_location = 1; 17412 } else { 17413 /* convert element_index to cidrings value */ 17414 cid_location = (cid_location + 1) / 2; 17415 } 17416 /* ---we like their cadence; try to install it--- */ 17417 if (!user_has_defined_cadences++) 17418 /* this is the first user-defined cadence; clear the default user cadences */ 17419 num_cadence = 0; 17420 if ((num_cadence+1) >= NUM_CADENCE_MAX) 17421 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 17422 else { 17423 cadences[num_cadence] = new_cadence; 17424 cidrings[num_cadence++] = cid_location; 17425 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 17426 } 17427 } 17428 } 17429 } else if (!strcasecmp(v->name, "ringtimeout")) { 17430 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 17431 } else if (!strcasecmp(v->name, "prewink")) { 17432 confp->timing.prewinktime = atoi(v->value); 17433 } else if (!strcasecmp(v->name, "preflash")) { 17434 confp->timing.preflashtime = atoi(v->value); 17435 } else if (!strcasecmp(v->name, "wink")) { 17436 confp->timing.winktime = atoi(v->value); 17437 } else if (!strcasecmp(v->name, "flash")) { 17438 confp->timing.flashtime = atoi(v->value); 17439 } else if (!strcasecmp(v->name, "start")) { 17440 confp->timing.starttime = atoi(v->value); 17441 } else if (!strcasecmp(v->name, "rxwink")) { 17442 confp->timing.rxwinktime = atoi(v->value); 17443 } else if (!strcasecmp(v->name, "rxflash")) { 17444 confp->timing.rxflashtime = atoi(v->value); 17445 } else if (!strcasecmp(v->name, "debounce")) { 17446 confp->timing.debouncetime = atoi(v->value); 17447 } else if (!strcasecmp(v->name, "toneduration")) { 17448 int toneduration; 17449 int ctlfd; 17450 int res; 17451 struct dahdi_dialparams dps; 17452 17453 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 17454 if (ctlfd == -1) { 17455 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 17456 return -1; 17457 } 17458 17459 toneduration = atoi(v->value); 17460 if (toneduration > -1) { 17461 memset(&dps, 0, sizeof(dps)); 17462 17463 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 17464 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 17465 if (res < 0) { 17466 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 17467 close(ctlfd); 17468 return -1; 17469 } 17470 } 17471 close(ctlfd); 17472 } else if (!strcasecmp(v->name, "defaultcic")) { 17473 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 17474 } else if (!strcasecmp(v->name, "defaultozz")) { 17475 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 17476 } else if (!strcasecmp(v->name, "mwilevel")) { 17477 mwilevel = atoi(v->value); 17478 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 17479 dtmfcid_level = atoi(v->value); 17480 } else if (!strcasecmp(v->name, "reportalarms")) { 17481 if (!strcasecmp(v->value, "all")) 17482 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; 17483 if (!strcasecmp(v->value, "none")) 17484 report_alarms = 0; 17485 else if (!strcasecmp(v->value, "channels")) 17486 report_alarms = REPORT_CHANNEL_ALARMS; 17487 else if (!strcasecmp(v->value, "spans")) 17488 report_alarms = REPORT_SPAN_ALARMS; 17489 } 17490 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 17491 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 17492 } 17493 if (dahdichan[0]) { 17494 /* The user has set 'dahdichan' */ 17495 /*< \todo pass proper line number instead of 0 */ 17496 if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) { 17497 return -1; 17498 } 17499 } 17500 17501 /* mark the first channels of each DAHDI span to watch for their span alarms */ 17502 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { 17503 if (!tmp->destroy && tmp->span != y) { 17504 tmp->manages_span_alarms = 1; 17505 y = tmp->span; 17506 } else { 17507 tmp->manages_span_alarms = 0; 17508 } 17509 } 17510 17511 /*< \todo why check for the pseudo in the per-channel section. 17512 * Any actual use for manual setup of the pseudo channel? */ 17513 if (!found_pseudo && reload != 1) { 17514 /* use the default configuration for a channel, so 17515 that any settings from real configured channels 17516 don't "leak" into the pseudo channel config 17517 */ 17518 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 17519 17520 if (conf.chan.cc_params) { 17521 tmp = mkintf(CHAN_PSEUDO, &conf, reload); 17522 } else { 17523 tmp = NULL; 17524 } 17525 if (tmp) { 17526 ast_verb(3, "Automatically generated pseudo channel\n"); 17527 } else { 17528 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 17529 } 17530 ast_cc_config_params_destroy(conf.chan.cc_params); 17531 } 17532 return 0; 17533 }
static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
const char * | data, | |||
unsigned int | line | |||
) | [static] |
Definition at line 16392 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.
16393 { 16394 char *parse = ast_strdupa(data); 16395 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 16396 unsigned int param_count; 16397 unsigned int x; 16398 16399 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 16400 return; 16401 16402 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 16403 16404 /* first parameter is tap length, process it here */ 16405 16406 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 16407 16408 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 16409 confp->chan.echocancel.head.tap_length = x; 16410 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 16411 confp->chan.echocancel.head.tap_length = 128; 16412 16413 /* now process any remaining parameters */ 16414 16415 for (x = 1; x < param_count; x++) { 16416 struct { 16417 char *name; 16418 char *value; 16419 } param; 16420 16421 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 16422 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 16423 continue; 16424 } 16425 16426 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 16427 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 16428 continue; 16429 } 16430 16431 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 16432 16433 if (param.value) { 16434 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 16435 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 16436 continue; 16437 } 16438 } 16439 confp->chan.echocancel.head.param_count++; 16440 } 16441 }
static int reload | ( | void | ) | [static] |
Definition at line 18166 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
18167 { 18168 int res = 0; 18169 18170 res = setup_dahdi(1); 18171 if (res) { 18172 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 18173 return -1; 18174 } 18175 return 0; 18176 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4679 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().
04680 { 04681 p->confno = -1; 04682 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 04683 if (p->subs[SUB_REAL].dfd > -1) { 04684 struct dahdi_confinfo zi; 04685 04686 memset(&zi, 0, sizeof(zi)); 04687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 04688 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 04689 } 04690 return 0; 04691 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 11601 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().
11602 { 11603 /* If we're supposed to be stopped -- stay stopped */ 11604 if (monitor_thread == AST_PTHREADT_STOP) 11605 return 0; 11606 ast_mutex_lock(&monlock); 11607 if (monitor_thread == pthread_self()) { 11608 ast_mutex_unlock(&monlock); 11609 ast_log(LOG_WARNING, "Cannot kill myself\n"); 11610 return -1; 11611 } 11612 if (monitor_thread != AST_PTHREADT_NULL) { 11613 /* Wake up the thread */ 11614 pthread_kill(monitor_thread, SIGURG); 11615 } else { 11616 /* Start a new monitor */ 11617 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 11618 ast_mutex_unlock(&monlock); 11619 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 11620 return -1; 11621 } 11622 } 11623 ast_mutex_unlock(&monlock); 11624 return 0; 11625 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5092 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().
05093 { 05094 int res; 05095 if (p->saveconf.confmode) { 05096 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 05097 p->saveconf.confmode = 0; 05098 if (res) { 05099 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 05100 return -1; 05101 } 05102 ast_debug(1, "Restored conferencing\n"); 05103 } 05104 return 0; 05105 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4999 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().
05000 { 05001 int res; 05002 05003 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law); 05004 if (res) { 05005 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 05006 return -1; 05007 } 05008 05009 return 0; 05010 }
static int revert_fax_buffers | ( | struct dahdi_pvt * | p, | |
struct ast_channel * | ast | |||
) | [static] |
Definition at line 5982 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().
05983 { 05984 if (p->bufferoverrideinuse) { 05985 /* faxbuffers are in use, revert them */ 05986 struct dahdi_bufferinfo bi = { 05987 .txbufpolicy = p->buf_policy, 05988 .rxbufpolicy = p->buf_policy, 05989 .bufsize = p->bufsize, 05990 .numbufs = p->buf_no 05991 }; 05992 int bpres; 05993 05994 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 05995 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno)); 05996 } 05997 p->bufferoverrideinuse = 0; 05998 return bpres; 05999 } 06000 06001 return -1; 06002 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5066 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().
05067 { 05068 struct dahdi_confinfo c; 05069 int res; 05070 if (p->saveconf.confmode) { 05071 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 05072 return -1; 05073 } 05074 p->saveconf.chan = 0; 05075 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 05076 if (res) { 05077 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 05078 p->saveconf.confmode = 0; 05079 return -1; 05080 } 05081 memset(&c, 0, sizeof(c)); 05082 c.confmode = DAHDI_CONF_NORMAL; 05083 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 05084 if (res) { 05085 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 05086 return -1; 05087 } 05088 ast_debug(1, "Disabled conferencing\n"); 05089 return 0; 05090 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5150 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().
05151 { 05152 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 05153 int res; 05154 /* Take out of linear mode if necessary */ 05155 if (p->subs[SUB_REAL].linear) { 05156 p->subs[SUB_REAL].linear = 0; 05157 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 05158 } 05159 while (p->cidpos < p->cidlen) { 05160 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 05161 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res); 05162 if (res < 0) { 05163 if (errno == EAGAIN) 05164 return 0; 05165 else { 05166 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05167 return -1; 05168 } 05169 } 05170 if (!res) 05171 return 0; 05172 p->cidpos += res; 05173 } 05174 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 05175 ast_free(p->cidspill); 05176 p->cidspill = NULL; 05177 if (p->callwaitcas) { 05178 /* Wait for CID/CW to expire */ 05179 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 05180 p->cid_suppress_expire = p->cidcwexpire; 05181 } else 05182 restore_conference(p); 05183 return 0; 05184 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5107 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().
05108 { 05109 p->callwaitcas = 0; 05110 p->cidcwexpire = 0; 05111 p->cid_suppress_expire = 0; 05112 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 05113 return -1; 05114 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 05115 /* Make sure we account for the end */ 05116 p->cidlen += READ_SIZE * 4; 05117 p->cidpos = 0; 05118 send_callerid(p); 05119 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 05120 return 0; 05121 }
static int set_actual_gain | ( | int | fd, | |
float | rxgain, | |||
float | txgain, | |||
float | rxdrc, | |||
float | txdrc, | |||
int | law | |||
) | [static] |
Definition at line 4980 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().
04981 { 04982 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law); 04983 }
static int set_actual_rxgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4963 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
04964 { 04965 struct dahdi_gains g; 04966 int res; 04967 04968 memset(&g, 0, sizeof(g)); 04969 res = ioctl(fd, DAHDI_GETGAINS, &g); 04970 if (res) { 04971 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 04972 return res; 04973 } 04974 04975 fill_rxgain(&g, gain, drc, law); 04976 04977 return ioctl(fd, DAHDI_SETGAINS, &g); 04978 }
static int set_actual_txgain | ( | int | fd, | |
float | gain, | |||
float | drc, | |||
int | law | |||
) | [static] |
Definition at line 4946 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
04947 { 04948 struct dahdi_gains g; 04949 int res; 04950 04951 memset(&g, 0, sizeof(g)); 04952 res = ioctl(fd, DAHDI_GETGAINS, &g); 04953 if (res) { 04954 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 04955 return res; 04956 } 04957 04958 fill_txgain(&g, gain, drc, law); 04959 04960 return ioctl(fd, DAHDI_SETGAINS, &g); 04961 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 17809 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().
17810 { 17811 int res; 17812 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default(); 17813 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 17814 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 17815 17816 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) { 17817 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf); 17818 } else { 17819 res = -1; 17820 } 17821 ast_cc_config_params_destroy(default_conf.chan.cc_params); 17822 ast_cc_config_params_destroy(base_conf.chan.cc_params); 17823 ast_cc_config_params_destroy(conf.chan.cc_params); 17824 17825 return res; 17826 }
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 17566 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, 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_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), sig_pri_start_pri(), and ast_variable::value.
Referenced by setup_dahdi().
17567 { 17568 struct ast_config *cfg; 17569 struct ast_config *ucfg; 17570 struct ast_variable *v; 17571 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 17572 const char *cat; 17573 int res; 17574 17575 #ifdef HAVE_PRI 17576 char *c; 17577 int spanno; 17578 int i; 17579 int logicalspan; 17580 int trunkgroup; 17581 int dchannels[SIG_PRI_NUM_DCHANS]; 17582 #endif 17583 17584 cfg = ast_config_load(config, config_flags); 17585 17586 /* Error if we have no config file */ 17587 if (!cfg) { 17588 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 17589 return 0; 17590 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 17591 ucfg = ast_config_load("users.conf", config_flags); 17592 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 17593 return 0; 17594 } else if (ucfg == CONFIG_STATUS_FILEINVALID) { 17595 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 17596 return 0; 17597 } 17598 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 17599 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { 17600 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 17601 ast_config_destroy(ucfg); 17602 return 0; 17603 } 17604 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 17605 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 17606 return 0; 17607 } else { 17608 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 17609 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) { 17610 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 17611 ast_config_destroy(cfg); 17612 return 0; 17613 } 17614 } 17615 17616 /* It's a little silly to lock it, but we might as well just to be sure */ 17617 ast_mutex_lock(&iflock); 17618 #ifdef HAVE_PRI 17619 if (reload != 1) { 17620 /* Process trunkgroups first */ 17621 v = ast_variable_browse(cfg, "trunkgroups"); 17622 while (v) { 17623 if (!strcasecmp(v->name, "trunkgroup")) { 17624 trunkgroup = atoi(v->value); 17625 if (trunkgroup > 0) { 17626 if ((c = strchr(v->value, ','))) { 17627 i = 0; 17628 memset(dchannels, 0, sizeof(dchannels)); 17629 while (c && (i < SIG_PRI_NUM_DCHANS)) { 17630 dchannels[i] = atoi(c + 1); 17631 if (dchannels[i] < 0) { 17632 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); 17633 } else 17634 i++; 17635 c = strchr(c + 1, ','); 17636 } 17637 if (i) { 17638 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 17639 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); 17640 } else 17641 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"); 17642 } else 17643 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 17644 } else 17645 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 17646 } else 17647 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 17648 } else if (!strcasecmp(v->name, "spanmap")) { 17649 spanno = atoi(v->value); 17650 if (spanno > 0) { 17651 if ((c = strchr(v->value, ','))) { 17652 trunkgroup = atoi(c + 1); 17653 if (trunkgroup > 0) { 17654 if ((c = strchr(c + 1, ','))) 17655 logicalspan = atoi(c + 1); 17656 else 17657 logicalspan = 0; 17658 if (logicalspan >= 0) { 17659 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 17660 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 17661 } else 17662 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 17663 } else 17664 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); 17665 } else 17666 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 17667 } else 17668 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 17669 } else 17670 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 17671 } else { 17672 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 17673 } 17674 v = v->next; 17675 } 17676 } 17677 #endif 17678 17679 /* Copy the default jb config over global_jbconf */ 17680 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 17681 17682 mwimonitornotify[0] = '\0'; 17683 17684 v = ast_variable_browse(cfg, "channels"); 17685 if ((res = process_dahdi(base_conf, "", v, reload, 0))) { 17686 ast_mutex_unlock(&iflock); 17687 ast_config_destroy(cfg); 17688 if (ucfg) { 17689 ast_config_destroy(ucfg); 17690 } 17691 return res; 17692 } 17693 17694 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 17695 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 17696 /* [channels] and [trunkgroups] are used. Let's also reserve 17697 * [globals] and [general] for future use 17698 */ 17699 if (!strcasecmp(cat, "general") || 17700 !strcasecmp(cat, "trunkgroups") || 17701 !strcasecmp(cat, "globals") || 17702 !strcasecmp(cat, "channels")) { 17703 continue; 17704 } 17705 17706 /* Copy base_conf to conf. */ 17707 deep_copy_dahdi_chan_conf(conf, base_conf); 17708 17709 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 17710 ast_mutex_unlock(&iflock); 17711 ast_config_destroy(cfg); 17712 if (ucfg) { 17713 ast_config_destroy(ucfg); 17714 } 17715 return res; 17716 } 17717 } 17718 17719 ast_config_destroy(cfg); 17720 17721 if (ucfg) { 17722 const char *chans; 17723 17724 /* Reset base_conf, so things dont leak from dahdi_chan.conf */ 17725 deep_copy_dahdi_chan_conf(base_conf, default_conf); 17726 process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 17727 17728 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 17729 if (!strcasecmp(cat, "general")) { 17730 continue; 17731 } 17732 17733 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 17734 17735 if (ast_strlen_zero(chans)) { 17736 continue; 17737 } 17738 17739 /* Copy base_conf to conf. */ 17740 deep_copy_dahdi_chan_conf(conf, base_conf); 17741 17742 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 17743 ast_config_destroy(ucfg); 17744 ast_mutex_unlock(&iflock); 17745 return res; 17746 } 17747 } 17748 ast_config_destroy(ucfg); 17749 } 17750 ast_mutex_unlock(&iflock); 17751 17752 #ifdef HAVE_PRI 17753 if (reload != 1) { 17754 int x; 17755 for (x = 0; x < NUM_SPANS; x++) { 17756 if (pris[x].pri.pvts[0]) { 17757 prepare_pri(pris + x); 17758 if (sig_pri_start_pri(&pris[x].pri)) { 17759 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 17760 return -1; 17761 } else 17762 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 17763 } 17764 } 17765 } 17766 #endif 17767 #if defined(HAVE_SS7) 17768 if (reload != 1) { 17769 int x; 17770 for (x = 0; x < NUM_SPANS; x++) { 17771 if (linksets[x].ss7.ss7) { 17772 linksets[x].ss7.calls = &dahdi_ss7_callbacks; 17773 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) { 17774 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 17775 return -1; 17776 } else 17777 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 17778 } 17779 } 17780 } 17781 #endif /* defined(HAVE_SS7) */ 17782 #ifdef HAVE_OPENR2 17783 if (reload != 1) { 17784 int x; 17785 for (x = 0; x < r2links_count; x++) { 17786 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 17787 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 17788 return -1; 17789 } else { 17790 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 17791 } 17792 } 17793 } 17794 #endif 17795 /* And start the monitor for the first time */ 17796 restart_monitor(); 17797 return 0; 17798 }
static int sig_pri_tone_to_dahditone | ( | enum sig_pri_tone | tone | ) | [static] |
Definition at line 2973 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().
02974 { 02975 switch (tone) { 02976 case SIG_PRI_TONE_RINGTONE: 02977 return DAHDI_TONE_RINGTONE; 02978 case SIG_PRI_TONE_STUTTER: 02979 return DAHDI_TONE_STUTTER; 02980 case SIG_PRI_TONE_CONGESTION: 02981 return DAHDI_TONE_CONGESTION; 02982 case SIG_PRI_TONE_DIALTONE: 02983 return DAHDI_TONE_DIALTONE; 02984 case SIG_PRI_TONE_DIALRECALL: 02985 return DAHDI_TONE_DIALRECALL; 02986 case SIG_PRI_TONE_INFO: 02987 return DAHDI_TONE_INFO; 02988 case SIG_PRI_TONE_BUSY: 02989 return DAHDI_TONE_BUSY; 02990 default: 02991 return -1; 02992 } 02993 }
static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
static void string_replace | ( | char * | str, | |
int | char1, | |||
int | char2 | |||
) | [static] |
Definition at line 16296 of file chan_dahdi.c.
Referenced by parse_spanchan().
16297 { 16298 for (; *str; str++) { 16299 if (*str == char1) { 16300 *str = char2; 16301 } 16302 } 16303 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 4138 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().
04139 { 04140 int tchan; 04141 int tinthreeway; 04142 struct ast_channel *towner; 04143 04144 ast_debug(1, "Swapping %d and %d\n", a, b); 04145 04146 tchan = p->subs[a].chan; 04147 towner = p->subs[a].owner; 04148 tinthreeway = p->subs[a].inthreeway; 04149 04150 p->subs[a].chan = p->subs[b].chan; 04151 p->subs[a].owner = p->subs[b].owner; 04152 p->subs[a].inthreeway = p->subs[b].inthreeway; 04153 04154 p->subs[b].chan = tchan; 04155 p->subs[b].owner = towner; 04156 p->subs[b].inthreeway = tinthreeway; 04157 04158 if (p->subs[a].owner) 04159 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 04160 if (p->subs[b].owner) 04161 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 04162 wakeup_sub(p, a); 04163 wakeup_sub(p, b); 04164 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 4284 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().
04285 { 04286 if (!x) { 04287 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 04288 return -1; 04289 } 04290 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 04291 dahdi_close_sub(p, x); 04292 p->subs[x].linear = 0; 04293 p->subs[x].chan = 0; 04294 p->subs[x].owner = NULL; 04295 p->subs[x].inthreeway = 0; 04296 p->polarity = POLARITY_IDLE; 04297 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 04298 return 0; 04299 }
static int unload_module | ( | void | ) | [static] |
Definition at line 16280 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, sig_ss7_linkset::lock, sig_pri_span::lock, and dahdi_pvt::pri.
16281 { 16282 #if defined(HAVE_PRI) || defined(HAVE_SS7) 16283 int y; 16284 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ 16285 #ifdef HAVE_PRI 16286 for (y = 0; y < NUM_SPANS; y++) 16287 ast_mutex_destroy(&pris[y].pri.lock); 16288 #endif 16289 #if defined(HAVE_SS7) 16290 for (y = 0; y < NUM_SPANS; y++) 16291 ast_mutex_destroy(&linksets[y].ss7.lock); 16292 #endif /* defined(HAVE_SS7) */ 16293 return __unload_module(); 16294 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4693 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().
04694 { 04695 int needconf = 0; 04696 int x; 04697 int useslavenative; 04698 struct dahdi_pvt *slave = NULL; 04699 04700 useslavenative = isslavenative(p, &slave); 04701 /* Start with the obvious, general stuff */ 04702 for (x = 0; x < 3; x++) { 04703 /* Look for three way calls */ 04704 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 04705 conf_add(p, &p->subs[x], x, 0); 04706 needconf++; 04707 } else { 04708 conf_del(p, &p->subs[x], x); 04709 } 04710 } 04711 /* If we have a slave, add him to our conference now. or DAX 04712 if this is slave native */ 04713 for (x = 0; x < MAX_SLAVES; x++) { 04714 if (p->slaves[x]) { 04715 if (useslavenative) 04716 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 04717 else { 04718 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 04719 needconf++; 04720 } 04721 } 04722 } 04723 /* If we're supposed to be in there, do so now */ 04724 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 04725 if (useslavenative) 04726 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 04727 else { 04728 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 04729 needconf++; 04730 } 04731 } 04732 /* If we have a master, add ourselves to his conference */ 04733 if (p->master) { 04734 if (isslavenative(p->master, NULL)) { 04735 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 04736 } else { 04737 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 04738 } 04739 } 04740 if (!needconf) { 04741 /* Nobody is left (or should be left) in our conference. 04742 Kill it. */ 04743 p->confno = -1; 04744 } 04745 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 04746 return 0; 04747 }
static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
int | a | |||
) | [static] |
Definition at line 3651 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().
03652 { 03653 dahdi_lock_sub_owner(p, a); 03654 if (p->subs[a].owner) { 03655 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 03656 ast_channel_unlock(p->subs[a].owner); 03657 } 03658 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_smdi", } [static] |
Definition at line 18188 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 18188 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 366 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 377 of file chan_dahdi.c.
Referenced by handle_dahdi_show_cadences().
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 320 of file chan_dahdi.c.
const char* const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 5840 of file chan_dahdi.c.
struct analog_callback dahdi_analog_callbacks [static] |
Definition at line 3529 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 17969 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 17979 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_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 4100 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 4131 of file chan_dahdi.c.
char* dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility" [static] |
Definition at line 5777 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 5750 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 17964 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1493 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 17974 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 269 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 393 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 394 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 407 of file chan_dahdi.c.
int dtmfcid_level = 256 [static] |
Definition at line 412 of file chan_dahdi.c.
const char* const events[] [static] |
Definition at line 4408 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 424 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 427 of file chan_dahdi.c.
Referenced by analog_ss_thread(), and mgcp_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 277 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 436 of file chan_dahdi.c.
Referenced by destroy_all_channels(), and do_monitor().
Main interface list end
Definition at line 1297 of file chan_dahdi.c.
Referenced by dahdi_iflist_extract(), dahdi_request(), and determine_starting_point().
Main interface list start
Definition at line 1296 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 433 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 257 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 430 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 448 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 444 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 399 of file chan_dahdi.c.
Referenced by notify_message(), and setup_dahdi_int().
char* name |
Definition at line 4432 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 363 of file chan_dahdi.c.
Referenced by handle_dahdi_show_cadences(), and my_set_cadence().
int num_restart_pending = 0 [static] |
Definition at line 453 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 409 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 396 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_parkinglot(), build_peer(), build_user(), builtin_atxfer(), check_access(), check_peer_ok(), copy_parkinglot(), create_addr_from_peer(), dahdi_new(), find_parkinglot(), find_parkinglot_by_exten_cb(), find_parkinglot_by_position_cb(), findparkinglotname(), func_channel_write_real(), gtalk_load_config(), gtalk_new(), park_exec_full(), park_space_reserve(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 419 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().
ast_mutex_t pridebugfdlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 439 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), and handle_pri_set_debug_file().
char pridebugfilename[1024] = "" [static] |
Definition at line 576 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_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 561 of file chan_dahdi.c.
Referenced by dahdi_r2_destroy_links(), and dahdi_r2_get_link().
int r2links_count = 0 [static] |
Definition at line 563 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 416 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 509 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] [static] |
Round robin search locations.
Definition at line 3598 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 449 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 452 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 450 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 609 of file chan_dahdi.c.
Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().
const char tdesc[] [static] |
Definition at line 299 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 406 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 364 of file chan_dahdi.c.