#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <libpri.h>
#include <openr2.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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/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/dahdi_compat.h"
#include "asterisk/tonezone_compat.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_pri |
struct | dahdi_pvt |
struct | dahdi_subchannel |
struct | distRingData |
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 | CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) |
#define | CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) |
#define | CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) |
#define | CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define | CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define | CHAN_PSEUDO -2 |
#define | CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) |
#define | CONF_USER_REAL (1 << 0) |
#define | CONF_USER_THIRDCALL (1 << 1) |
#define | DAHDI_EVENT_DTMFDOWN 0 |
#define | DAHDI_EVENT_DTMFUP 0 |
#define | dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
#define | DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define | DAHDI_OVERLAPDIAL_INCOMING 2 |
#define | DAHDI_OVERLAPDIAL_NONE 0 |
#define | DAHDI_OVERLAPDIAL_OUTGOING 1 |
#define | DAHDI_R2_LOCAL_BLOCK (1 << 1) |
#define | DAHDI_R2_REMOTE_BLOCK (1 << 0) |
#define | DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define | DCHAN_NOTINALARM (1 << 1) |
#define | DCHAN_PROVISIONED (1 << 0) |
#define | DCHAN_UP (1 << 2) |
#define | DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID. | |
#define | DEFAULT_PRI_DEBUG 0 |
#define | DEFAULT_RINGT ((8000 * 8) / READ_SIZE) |
#define | END_SILENCE_LEN 400 |
#define | FORCE_RESTART_UNAVAIL_CHANS 1 |
#define | FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\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 %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define | GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel) |
#define | HANGUP 1 |
#define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
#define | HEADER_MS 50 |
#define | ISTRUNK(p) |
#define | local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
#define | local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr) |
#define | local_astman_register(a, b, c, d) |
#define | local_astman_unregister(a) |
#define | MASK_AVAIL (1 << 0) |
#define | MASK_INUSE (1 << 1) |
#define | MAX_CHANLIST_LEN 80 |
#define | MAX_CHANNELS 672 |
#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_DCHANS 4 |
#define | NUM_SPANS 32 |
#define | POLARITY_IDLE 0 |
#define | POLARITY_REV 1 |
#define | PRI_CHANNEL(p) ((p) & 0xff) |
#define | PRI_EXPLICIT(p) (((p) >> 16) & 0x01) |
#define | PRI_SPAN(p) (((p) >> 8) & 0xff) |
#define | PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
#define | READ_SIZE 160 |
#define | sig2str dahdi_sig2str |
#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_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
#define | SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
#define | SIG_MFCR2 DAHDI_SIG_CAS |
#define | SIG_PRI DAHDI_SIG_CLEAR |
#define | SIG_PRI_LIB_HANDLE_CASES SIG_PRI |
#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 | SMDI_MD_WAIT_TIMEOUT 1500 |
#define | SUB_CALLWAIT 1 |
#define | SUB_REAL 0 |
#define | SUB_THREEWAY 2 |
#define | tdesc "DAHDI Telephony w/PRI" |
#define | TRAILER_MS 5 |
#define | TRANSFER 0 |
Enumerations | |
enum | dahdi_call_level { DAHDI_CALL_LEVEL_IDLE, DAHDI_CALL_LEVEL_SETUP, DAHDI_CALL_LEVEL_OVERLAP, DAHDI_CALL_LEVEL_PROCEEDING, DAHDI_CALL_LEVEL_ALERTING, DAHDI_CALL_LEVEL_CONNECT } |
Functions | |
static int | __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd) |
static int | __action_restart (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_showchannels (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transfer (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode) |
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 char * | alarm2str (int alarm) |
static int | alloc_sub (struct dahdi_pvt *p, int x) |
static void | apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan) |
static int | attempt_transfer (struct dahdi_pvt *p) |
static int | available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched) |
static int | build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo) |
static void | build_status (char *s, size_t len, int status, int active) |
static int | bump_gains (struct dahdi_pvt *p) |
static int | calc_energy (const unsigned char *buf, int len, int law) |
static struct dahdi_pvt * | chandup (struct dahdi_pvt *src) |
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_5 (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 int | dahdi_accept_r2_call_exec (struct ast_channel *chan, void *data) |
static int | dahdi_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndoff (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndon (struct mansession *s, const struct message *m) |
static int | dahdi_action_restart (struct mansession *s, const struct message *m) |
static int | dahdi_action_showchannels (struct mansession *s, const struct message *m) |
static int | dahdi_action_transfer (struct mansession *s, const struct message *m) |
static int | dahdi_action_transferhangup (struct mansession *s, const struct message *m) |
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 struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
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 int | dahdi_destroy_channel (int fd, int argc, char **argv) |
static int | dahdi_destroy_channel_bynum (int channel) |
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 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, char *function, char *data, char *buf, size_t len) |
static int | dahdi_func_write (struct ast_channel *chan, 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 index, struct ast_frame **dest) |
static struct ast_frame * | dahdi_handle_event (struct ast_channel *ast) |
static int | dahdi_hangup (struct ast_channel *ast) |
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 index, int law, int transfercapability) |
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_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri) |
static int16_t | dahdi_r2_alaw_to_linear (uint8_t sample) |
static int | dahdi_r2_answer (struct dahdi_pvt *p) |
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 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 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, int format, void *data, int *cause) |
static int | dahdi_restart (void) |
static int | dahdi_restart_cmd (int fd, int argc, char **argv) |
static int | dahdi_ring_phone (struct dahdi_pvt *p) |
static int | dahdi_send_keypad_facility_exec (struct ast_channel *chan, void *data) |
static int | dahdi_sendtext (struct ast_channel *c, const char *text) |
static int | dahdi_set_hook (int fd, int hs) |
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 int | dahdi_show_channel (int fd, int argc, char **argv) |
static int | dahdi_show_channels (int fd, int argc, char **argv) |
static int | dahdi_show_status (int fd, int argc, char *argv[]) |
static char * | dahdi_sig2str (int sig) |
static void | dahdi_softhangup_all (void) |
static void | dahdi_train_ec (struct dahdi_pvt *p) |
static void | dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock) |
static int | dahdi_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 void | destroy_all_channels (void) |
static int | destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now) |
static void | destroy_dahdi_pvt (struct dahdi_pvt **pvt) |
static char * | dialplan2str (int dialplan) |
static int | digit_to_dtmfindex (char digit) |
static void | disable_dtmf_detect (struct dahdi_pvt *p) |
static void * | do_idle_thread (void *vchan) |
static void * | do_monitor (void *data) |
static void | enable_dtmf_detect (struct dahdi_pvt *p) |
static char * | event2str (int event) |
static void | fill_rxgain (struct dahdi_gains *g, float gain, int law) |
static void | fill_txgain (struct dahdi_gains *g, float gain, int law) |
static struct dahdi_pvt * | find_channel (int channel) |
static int | get_alarms (struct dahdi_pvt *p) |
static void | handle_alarms (struct dahdi_pvt *p, int alarms) |
static int | handle_dahdi_show_cadences (int fd, int argc, char *argv[]) |
static struct dahdi_pvt * | handle_init_event (struct dahdi_pvt *i, int event) |
static int | handle_mfcr2_call_files (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_blocked (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_debug (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_idle (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_show_channels (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_show_variants (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_version (int fd, int argc, char *argv[]) |
static int | handle_pri_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_no_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_really_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_set_debug_file (int fd, int argc, char **argv) |
static int | handle_pri_show_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_show_span (int fd, int argc, char *argv[]) |
static int | handle_pri_show_spans (int fd, int argc, char *argv[]) |
static int | handle_pri_version (int fd, int agc, char *argv[]) |
static int | has_voicemail (struct dahdi_pvt *p) |
static void | init_mfcr2_globals (void) |
static int | isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c) |
static int | isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out) |
static int | load_module (void) |
static struct dahdi_mfcr2 * | mfcr2_get_context (int id) |
static void * | mfcr2_monitor (void *data) |
static struct dahdi_pvt * | mkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading) |
static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear) |
static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
static int | parse_buffers_policy (const char *parse, int *num_buffers, int *policy) |
static int | pri_active_dchan_fd (struct dahdi_pri *pri) |
static int | pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer) |
static void | pri_check_restart (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 void * | pri_dchannel (void *vpri) |
static struct dahdi_pvt * | pri_find_crv (struct dahdi_pri *pri, int crv) |
static int | pri_find_dchan (struct dahdi_pri *pri) |
static int | pri_find_empty_chan (struct dahdi_pri *pri, int backwards) |
static int | pri_find_fixup_principle (struct dahdi_pri *pri, int channel, q931_call *call) |
static int | pri_find_principle (struct dahdi_pri *pri, int channel) |
static int | pri_find_principle_by_call (struct dahdi_pri *pri, q931_call *call) |
static int | pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c) |
static int | pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri) |
static int | pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri) |
static int | pri_is_up (struct dahdi_pri *pri) |
static char * | pri_order (int level) |
static void | pri_queue_control (struct dahdi_pri *pri, int chanpos, int subclass) |
static void | pri_queue_frame (struct dahdi_pri *pri, int chanpos, struct ast_frame *frame) |
static void | pri_rel (struct dahdi_pri *pri) |
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 skipchannels) |
static char * | redirectingreason2str (int redirectingreason) |
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 | save_conference (struct dahdi_pvt *p) |
static int | send_callerid (struct dahdi_pvt *p) |
static int | send_cwcidspill (struct dahdi_pvt *p) |
static int | send_keypad_facility_exec (struct ast_channel *chan, void *data) |
static int | set_actual_gain (int fd, int chan, float rxgain, float txgain, int law) |
static int | set_actual_rxgain (int fd, int chan, float gain, int law) |
static int | set_actual_txgain (int fd, int chan, float gain, int law) |
static int | setup_dahdi (int reload) |
static int | sig_pri_available (struct dahdi_pvt *pvt) |
static int | sig_pri_available_check (struct dahdi_pvt *pvt) |
static int | sig_pri_is_chan_available (struct dahdi_pvt *pvt) |
static int | sig_pri_is_chan_in_use (struct dahdi_pvt *pvt) |
static void | sig_pri_kill_call (struct dahdi_pri *pri, q931_call *call, int cause) |
static void | sig_pri_lock_owner (struct dahdi_pri *pri, int chanpos) |
static void * | ss_thread (void *data) |
static int | start_pri (struct dahdi_pri *pri) |
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, struct dahdi_pri *pri) |
static int | zap_accept_r2_call_exec (struct ast_channel *chan, void *data) |
static int | zap_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | zap_action_dndoff (struct mansession *s, const struct message *m) |
static int | zap_action_dndon (struct mansession *s, const struct message *m) |
static int | zap_action_restart (struct mansession *s, const struct message *m) |
static int | zap_action_showchannels (struct mansession *s, const struct message *m) |
static int | zap_action_transfer (struct mansession *s, const struct message *m) |
static int | zap_action_transferhangup (struct mansession *s, const struct message *m) |
static int | zap_send_keypad_facility_exec (struct ast_channel *chan, void *data) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
static struct ast_channel_tech * | chan_tech |
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 struct ast_cli_entry | cli_zap_destroy_channel_deprecated |
static struct ast_cli_entry | cli_zap_restart_deprecated |
static struct ast_cli_entry | cli_zap_show_cadences_deprecated |
static struct ast_cli_entry | cli_zap_show_channel_deprecated |
static struct ast_cli_entry | cli_zap_show_channels_deprecated |
static struct ast_cli_entry | cli_zap_show_status_deprecated |
static char * | dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" |
static char * | dahdi_accept_r2_call_descrip |
static char * | dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" |
static struct ast_cli_entry | dahdi_cli [] |
static struct ast_cli_entry | dahdi_mfcr2_cli [] |
static struct ast_cli_entry | dahdi_pri_cli [] |
static const char | dahdi_r2_callfiles_help [] |
static openr2_event_interface_t | dahdi_r2_event_iface |
static const char | dahdi_r2_setblocked_help [] |
static const char | dahdi_r2_setdebug_help [] |
static const char | dahdi_r2_setidle_help [] |
static const char | dahdi_r2_showchannels_help [] |
static openr2_transcoder_interface_t | dahdi_r2_transcode_iface |
static const char | dahdi_r2_variants_help [] |
static const char | dahdi_r2_version_help [] |
static char | dahdi_restart_usage [] |
static char * | dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" |
static char * | dahdi_send_keypad_facility_descrip |
static char * | dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" |
static char | dahdi_show_cadences_usage [] |
static char | dahdi_show_status_usage [] |
static struct ast_channel_tech | dahdi_tech |
static struct ast_jb_conf | default_jbconf |
static char | defaultcic [64] = "" |
static char | defaultozz [64] = "" |
static char | destroy_channel_usage [] |
static int | distinctiveringaftercid = 0 |
static struct dahdi_distRings | drings |
static int | dtmfcid_level = 256 |
static char * | 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 |
static struct dahdi_pvt * | iflist |
static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
Protect the interface list (of dahdi_pvt's). | |
static struct ast_channel | inuse |
static int | matchdigittimeout = 3000 |
How long to wait for an extra digit, if there is an ambiguous match. | |
static int | mfcr2_cur_accept_on_offer = 1 |
static int | mfcr2_cur_allow_collect_calls = 0 |
static int | mfcr2_cur_call_files = 0 |
static openr2_calling_party_category_t | mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER |
static int | mfcr2_cur_charge_calls = 1 |
static int | mfcr2_cur_context_index = 0 |
static int | mfcr2_cur_double_answer = 0 |
static int | mfcr2_cur_forced_release = 0 |
static int | mfcr2_cur_get_ani_first = -1 |
static int | mfcr2_cur_immediate_accept = -1 |
static char | mfcr2_cur_logdir [OR2_MAX_PATH] |
static openr2_log_level_t | mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING |
static int | mfcr2_cur_max_ani = 10 |
static int | mfcr2_cur_max_dnis = 4 |
static int | mfcr2_cur_metering_pulse_timeout = -1 |
static int | mfcr2_cur_mfback_timeout = -1 |
static char | mfcr2_cur_r2proto_file [OR2_MAX_PATH] |
static int | mfcr2_cur_skip_category = -1 |
static openr2_variant_t | mfcr2_cur_variant = OR2_VAR_UNKNOWN |
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
static int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static const char | pri_debug_help [] |
static const char | pri_no_debug_help [] |
static const char | pri_really_debug_help [] |
static const char | pri_show_span_help [] |
static const char | pri_show_spans_help [] |
static int | pridebugfd = -1 |
static ast_mutex_t | pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static char | pridebugfilename [1024] = "" |
static struct dahdi_pri | pris [NUM_SPANS] |
static char | progzone [10] = "" |
static struct dahdi_mfcr2 | r2links [NUM_SPANS] |
static ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static int | ringt_base = DEFAULT_RINGT |
Configured ring timeout base. | |
dahdi_pvt * | round_robin [32] |
static char | show_channel_usage [] |
static char | show_channels_usage [] |
static ast_cond_t | ss_thread_complete |
static int | ss_thread_count = 0 |
static ast_mutex_t | ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static char * | subnames [] |
static const char | tdesc [] |
static int | user_has_defined_cadences = 0 |
static char * | zap_accept_r2_call_app = "ZapAcceptR2Call" |
static char * | zap_accept_r2_call_descrip |
static char * | zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" |
static char * | zap_send_keypad_facility_app = "ZapSendKeypadFacility" |
static char * | zap_send_keypad_facility_descrip |
static char * | zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" |
static struct ast_channel_tech | zap_tech |
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 169 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().
#define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) |
#define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) |
300 ms
Definition at line 315 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) */) |
#define CHAN_PSEUDO -2 |
Definition at line 214 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().
#define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 509 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 510 of file chan_dahdi.c.
#define DAHDI_EVENT_DTMFDOWN 0 |
#define DAHDI_EVENT_DTMFUP 0 |
#define dahdi_get_index | ( | ast, | |||
p, | |||||
nullok | ) | _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__) |
Definition at line 1244 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), dahdi_write(), and ss_thread().
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 225 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), handle_pri_show_span(), process_dahdi(), and ss_thread().
#define DAHDI_OVERLAPDIAL_NONE 0 |
#define DAHDI_OVERLAPDIAL_OUTGOING 1 |
#define DAHDI_R2_LOCAL_BLOCK (1 << 1) |
Definition at line 1723 of file chan_dahdi.c.
Referenced by handle_mfcr2_set_blocked(), handle_mfcr2_set_idle(), mfcr2_monitor(), and mkintf().
#define DAHDI_R2_REMOTE_BLOCK (1 << 0) |
Definition at line 1722 of file chan_dahdi.c.
Referenced by dahdi_r2_on_line_blocked(), dahdi_r2_on_line_idle(), and mkintf().
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define DCHAN_NOTINALARM (1 << 1) |
#define DCHAN_PROVISIONED (1 << 0) |
Definition at line 216 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 218 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 167 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_PRI_DEBUG 0 |
#define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 320 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#define FORCE_RESTART_UNAVAIL_CHANS 1 |
Define to force a RESTART on a channel that returns a cause code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because of a stuck channel on the peer and the channel is always the next channel we pick for an outgoing call then this can help.
Definition at line 146 of file chan_dahdi.c.
#define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\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 %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1191 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 13644 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_information(), build_notify(), 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_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().
#define HEADER_MS 50 |
Referenced by dahdi_sendtext().
#define ISTRUNK | ( | p | ) |
Value:
Definition at line 1238 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().
#define local_astman_ack | ( | s, | |||
m, | |||||
msg, | |||||
zap | ) | do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
Definition at line 13674 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_restart(), __action_showchannels(), __action_transfer(), and __action_transferhangup().
#define local_astman_header | ( | m, | |||
hdr, | |||||
zap | ) | astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr) |
Definition at line 13675 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
#define local_astman_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) |
#define local_astman_unregister | ( | a | ) |
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 312 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 313 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14097 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 212 of file chan_dahdi.c.
Referenced by mkintf().
#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.
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 211 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().
#define NUM_SPANS 32 |
Definition at line 210 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), init_mfcr2_globals(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 467 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 468 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and handle_init_event().
#define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
Definition at line 372 of file chan_dahdi.c.
Referenced by pri_find_fixup_principle(), and pri_find_principle().
#define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
#define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 373 of file chan_dahdi.c.
Referenced by pri_find_fixup_principle(), and pri_find_principle().
#define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 371 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), pri_check_restart(), and ss_thread().
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 310 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_setoption(), and send_cwcidspill().
#define sig2str dahdi_sig2str |
Definition at line 2260 of file chan_dahdi.c.
Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 184 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 206 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 185 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 186 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 187 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 190 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 191 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 192 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 197 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 198 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 196 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 194 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), do_monitor(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 195 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), do_monitor(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 193 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), do_monitor(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 207 of file chan_dahdi.c.
Referenced by dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 208 of file chan_dahdi.c.
Referenced by dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 200 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(), handle_mfcr2_show_channels(), mkintf(), and process_dahdi().
#define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 199 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_PRI_LIB_HANDLE_CASES SIG_PRI |
#define SIG_SF DAHDI_SIG_SF |
Definition at line 201 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 205 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 203 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 204 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 202 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 463 of file chan_dahdi.c.
Referenced by _dahdi_get_index(), available(), dahdi_bridge(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define SUB_REAL 0 |
Active call
Definition at line 462 of file chan_dahdi.c.
Referenced by __dahdi_exception(), _dahdi_get_index(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), 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_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mfcr2_monitor(), mkintf(), pri_assign_bearer(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().
#define SUB_THREEWAY 2 |
Three-way call
Definition at line 464 of file chan_dahdi.c.
Referenced by _dahdi_get_index(), attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define tdesc "DAHDI Telephony w/PRI" |
Definition at line 15272 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 13643 of file chan_dahdi.c.
Referenced by __action_transfer(), and dahdi_fake_event().
enum dahdi_call_level |
Call establishment life cycle level for simple comparisons.
Definition at line 377 of file chan_dahdi.c.
00377 { 00378 /*! Call does not exist. */ 00379 DAHDI_CALL_LEVEL_IDLE, 00380 /*! Call is present but has no response yet. (SETUP) */ 00381 DAHDI_CALL_LEVEL_SETUP, 00382 /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */ 00383 DAHDI_CALL_LEVEL_OVERLAP, 00384 /*! Call routing is happening. (PROCEEDING) */ 00385 DAHDI_CALL_LEVEL_PROCEEDING, 00386 /*! Called party is being alerted of the call. (ALERTING) */ 00387 DAHDI_CALL_LEVEL_ALERTING, 00388 /*! Call is connected/answered. (CONNECT) */ 00389 DAHDI_CALL_LEVEL_CONNECT, 00390 };
static int __action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 13773 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), f, find_channel(), local_astman_ack, local_astman_header, dahdi_pvt::owner, and s.
Referenced by dahdi_action_dialoffhook(), and zap_action_dialoffhook().
13774 { 13775 struct dahdi_pvt *p = NULL; 13776 const char *channel = local_astman_header(m, "Channel", zap_mode); 13777 const char *number = astman_get_header(m, "Number"); 13778 int i; 13779 13780 if (ast_strlen_zero(channel)) { 13781 astman_send_error(s, m, "No channel specified"); 13782 return 0; 13783 } 13784 if (ast_strlen_zero(number)) { 13785 astman_send_error(s, m, "No number specified"); 13786 return 0; 13787 } 13788 if (!(p = find_channel(atoi(channel)))) { 13789 astman_send_error(s, m, "No such channel"); 13790 return 0; 13791 } 13792 if (!p->owner) { 13793 astman_send_error(s, m, "Channel does not have an owner"); 13794 return 0; 13795 } 13796 for (i = 0; i < strlen(number); i++) { 13797 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13798 13799 dahdi_queue_frame(p, &f, NULL); 13800 } 13801 local_astman_ack(s, m, "DialOffHook", zap_mode); 13802 13803 return 0; 13804 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 13677 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), local_astman_ack, local_astman_header, and s.
Referenced by dahdi_action_dndoff(), dahdi_action_dndon(), zap_action_dndoff(), and zap_action_dndon().
13678 { 13679 struct dahdi_pvt *p = NULL; 13680 const char *channel = local_astman_header(m, "Channel", zap_mode); 13681 13682 if (ast_strlen_zero(channel)) { 13683 astman_send_error(s, m, "No channel specified"); 13684 return 0; 13685 } 13686 if (!(p = find_channel(atoi(channel)))) { 13687 astman_send_error(s, m, "No such channel"); 13688 return 0; 13689 } 13690 p->dnd = dnd; 13691 local_astman_ack(s, m, "DND", zap_mode); 13692 13693 return 0; 13694 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 13871 of file chan_dahdi.c.
References astman_send_error(), dahdi_restart(), local_astman_ack, and s.
Referenced by dahdi_action_restart(), and zap_action_restart().
13872 { 13873 if (dahdi_restart() != 0) { 13874 if (zap_mode) { 13875 astman_send_error(s, m, "Failed to restart Zap"); 13876 } else { 13877 astman_send_error(s, m, "Failed to restart DAHDI"); 13878 } 13879 return 1; 13880 } 13881 local_astman_ack(s, m, "Restart: Success", zap_mode); 13882 return 0; 13883 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 13816 of file chan_dahdi.c.
References alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_chan_name, dahdi_pvt::dnd, get_alarms(), iflist, iflock, local_astman_ack, dahdi_pvt::next, s, dahdi_pvt::sig, and sig2str.
Referenced by dahdi_action_showchannels(), and zap_action_showchannels().
13817 { 13818 struct dahdi_pvt *tmp = NULL; 13819 const char *id = astman_get_header(m, "ActionID"); 13820 char idText[256] = ""; 13821 13822 local_astman_ack(s, m, " channel status will follow", zap_mode); 13823 if (!ast_strlen_zero(id)) 13824 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 13825 13826 ast_mutex_lock(&iflock); 13827 13828 tmp = iflist; 13829 while (tmp) { 13830 if (tmp->channel > 0) { 13831 int alarm = get_alarms(tmp); 13832 astman_append(s, 13833 "Event: %sShowChannels\r\n" 13834 "Channel: %d\r\n" 13835 "Signalling: %s\r\n" 13836 "Context: %s\r\n" 13837 "DND: %s\r\n" 13838 "Alarm: %s\r\n" 13839 "%s" 13840 "\r\n", 13841 dahdi_chan_name, 13842 tmp->channel, sig2str(tmp->sig), tmp->context, 13843 tmp->dnd ? "Enabled" : "Disabled", 13844 alarm2str(alarm), idText); 13845 } 13846 13847 tmp = tmp->next; 13848 } 13849 13850 ast_mutex_unlock(&iflock); 13851 13852 astman_append(s, 13853 "Event: %sShowChannelsComplete\r\n" 13854 "%s" 13855 "\r\n", 13856 dahdi_chan_name, 13857 idText); 13858 return 0; 13859 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 13716 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), local_astman_ack, local_astman_header, s, and TRANSFER.
Referenced by dahdi_action_transfer(), and zap_action_transfer().
13717 { 13718 struct dahdi_pvt *p = NULL; 13719 const char *channel = local_astman_header(m, "Channel", zap_mode); 13720 13721 if (ast_strlen_zero(channel)) { 13722 astman_send_error(s, m, "No channel specified"); 13723 return 0; 13724 } 13725 if (!(p = find_channel(atoi(channel)))) { 13726 astman_send_error(s, m, "No such channel"); 13727 return 0; 13728 } 13729 dahdi_fake_event(p,TRANSFER); 13730 local_astman_ack(s, m, "Transfer", zap_mode); 13731 13732 return 0; 13733 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 13745 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), HANGUP, local_astman_ack, local_astman_header, and s.
Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().
13746 { 13747 struct dahdi_pvt *p = NULL; 13748 const char *channel = local_astman_header(m, "Channel", zap_mode); 13749 13750 if (ast_strlen_zero(channel)) { 13751 astman_send_error(s, m, "No channel specified"); 13752 return 0; 13753 } 13754 if (!(p = find_channel(atoi(channel)))) { 13755 astman_send_error(s, m, "No such channel"); 13756 return 0; 13757 } 13758 dahdi_fake_event(p, HANGUP); 13759 local_astman_ack(s, m, "Hangup", zap_mode); 13760 return 0; 13761 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6143 of file chan_dahdi.c.
References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), 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, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.
Referenced by dahdi_exception().
06144 { 06145 struct dahdi_pvt *p = ast->tech_pvt; 06146 int res; 06147 int index; 06148 struct ast_frame *f; 06149 06150 06151 index = dahdi_get_index(ast, p, 1); 06152 if (index < 0) { 06153 index = SUB_REAL; 06154 } 06155 06156 p->subs[index].f.frametype = AST_FRAME_NULL; 06157 p->subs[index].f.datalen = 0; 06158 p->subs[index].f.samples = 0; 06159 p->subs[index].f.mallocd = 0; 06160 p->subs[index].f.offset = 0; 06161 p->subs[index].f.subclass = 0; 06162 p->subs[index].f.delivery = ast_tv(0,0); 06163 p->subs[index].f.src = "dahdi_exception"; 06164 p->subs[index].f.data = NULL; 06165 06166 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 06167 /* If nobody owns us, absorb the event appropriately, otherwise 06168 we loop indefinitely. This occurs when, during call waiting, the 06169 other end hangs up our channel so that it no longer exists, but we 06170 have neither FLASH'd nor ONHOOK'd to signify our desire to 06171 change to the other channel. */ 06172 if (p->fake_event) { 06173 res = p->fake_event; 06174 p->fake_event = 0; 06175 } else 06176 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 06177 /* Switch to real if there is one and this isn't something really silly... */ 06178 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 06179 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 06180 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 06181 p->owner = p->subs[SUB_REAL].owner; 06182 if (p->owner && ast != p->owner) { 06183 /* 06184 * Could this even happen? 06185 * Possible deadlock because we do not have the real-call lock. 06186 */ 06187 ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n", 06188 event2str(res), ast->name, p->owner->name); 06189 } 06190 if (p->owner && ast_bridged_channel(p->owner)) 06191 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 06192 p->subs[SUB_REAL].needunhold = 1; 06193 } 06194 switch (res) { 06195 case DAHDI_EVENT_ONHOOK: 06196 dahdi_disable_ec(p); 06197 if (p->owner) { 06198 if (option_verbose > 2) 06199 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 06200 dahdi_ring_phone(p); 06201 p->callwaitingrepeat = 0; 06202 p->cidcwexpire = 0; 06203 p->cid_suppress_expire = 0; 06204 } else { 06205 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n", 06206 event2str(res)); 06207 } 06208 update_conf(p); 06209 break; 06210 case DAHDI_EVENT_RINGOFFHOOK: 06211 dahdi_enable_ec(p); 06212 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06213 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 06214 p->subs[SUB_REAL].needanswer = 1; 06215 p->dialing = 0; 06216 } 06217 break; 06218 case DAHDI_EVENT_HOOKCOMPLETE: 06219 case DAHDI_EVENT_RINGERON: 06220 case DAHDI_EVENT_RINGEROFF: 06221 /* Do nothing */ 06222 break; 06223 case DAHDI_EVENT_WINKFLASH: 06224 gettimeofday(&p->flashtime, NULL); 06225 if (p->owner) { 06226 if (option_verbose > 2) 06227 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 06228 if (p->owner->_state != AST_STATE_UP) { 06229 /* Answer if necessary */ 06230 p->subs[SUB_REAL].needanswer = 1; 06231 ast_setstate(p->owner, AST_STATE_UP); 06232 } 06233 p->callwaitingrepeat = 0; 06234 p->cidcwexpire = 0; 06235 p->cid_suppress_expire = 0; 06236 if (ast_bridged_channel(p->owner)) 06237 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 06238 p->subs[SUB_REAL].needunhold = 1; 06239 } else { 06240 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n", 06241 event2str(res)); 06242 } 06243 update_conf(p); 06244 break; 06245 default: 06246 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 06247 break; 06248 } 06249 f = &p->subs[index].f; 06250 return f; 06251 } 06252 if (!(p->radio || (p->oprmode < 0)) && option_debug) 06253 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 06254 /* If it's not us, return NULL immediately */ 06255 if (ast != p->owner) { 06256 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 06257 f = &p->subs[index].f; 06258 return f; 06259 } 06260 f = dahdi_handle_event(ast); 06261 return f; 06262 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 15281 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 13902 of file chan_dahdi.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_close_pri_fd(), dahdi_mfcr2_cli, dahdi_pri_cli, destroy_all_channels(), iflist, iflock, local_astman_unregister, master, monitor_thread, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, pris, r2links, and ss_thread_complete.
Referenced by load_module(), and unload_module().
13903 { 13904 struct dahdi_pvt *p; 13905 13906 #ifdef HAVE_OPENR2 13907 int r; 13908 #endif 13909 13910 #ifdef HAVE_PRI 13911 int i, j; 13912 for (i = 0; i < NUM_SPANS; i++) { 13913 if (pris[i].master != AST_PTHREADT_NULL) 13914 pthread_cancel(pris[i].master); 13915 } 13916 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 13917 13918 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13919 ast_unregister_application(dahdi_send_keypad_facility_app); 13920 } 13921 ast_unregister_application(zap_send_keypad_facility_app); 13922 #endif 13923 13924 #ifdef HAVE_OPENR2 13925 for (r = 0; r < NUM_SPANS; r++) { 13926 if (r2links[r].master != AST_PTHREADT_NULL) { 13927 pthread_cancel(r2links[r].master); 13928 pthread_join(r2links[r].master, NULL); 13929 } 13930 } 13931 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0])); 13932 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13933 ast_unregister_application(dahdi_accept_r2_call_app); 13934 } 13935 ast_unregister_application(zap_accept_r2_call_app); 13936 #endif 13937 13938 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 13939 local_astman_unregister("DialOffHook"); 13940 local_astman_unregister("Hangup"); 13941 local_astman_unregister("Transfer"); 13942 local_astman_unregister("DNDoff"); 13943 local_astman_unregister("DNDon"); 13944 local_astman_unregister("ShowChannels"); 13945 local_astman_unregister("Restart"); 13946 ast_channel_unregister(chan_tech); 13947 ast_mutex_lock(&iflock); 13948 /* Hangup all interfaces if they have an owner */ 13949 p = iflist; 13950 while (p) { 13951 if (p->owner) 13952 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 13953 p = p->next; 13954 } 13955 ast_mutex_unlock(&iflock); 13956 ast_mutex_lock(&monlock); 13957 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 13958 pthread_cancel(monitor_thread); 13959 pthread_kill(monitor_thread, SIGURG); 13960 pthread_join(monitor_thread, NULL); 13961 } 13962 monitor_thread = AST_PTHREADT_STOP; 13963 ast_mutex_unlock(&monlock); 13964 13965 destroy_all_channels(); 13966 #ifdef HAVE_PRI 13967 for (i = 0; i < NUM_SPANS; i++) { 13968 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 13969 pthread_join(pris[i].master, NULL); 13970 for (j = 0; j < NUM_DCHANS; j++) { 13971 dahdi_close_pri_fd(&(pris[i]), j); 13972 } 13973 } 13974 #endif 13975 13976 #ifdef HAVE_OPENR2 13977 for (r = 0; r < NUM_SPANS; r++) { 13978 if (r2links[r].protocol_context) { 13979 openr2_context_delete(r2links[r].protocol_context); 13980 } 13981 } 13982 #endif 13983 13984 ast_cond_destroy(&ss_thread_complete); 13985 return 0; 13986 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 15281 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 1245 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.
01246 { 01247 int res; 01248 if (p->subs[SUB_REAL].owner == ast) 01249 res = 0; 01250 else if (p->subs[SUB_CALLWAIT].owner == ast) 01251 res = 1; 01252 else if (p->subs[SUB_THREEWAY].owner == ast) 01253 res = 2; 01254 else { 01255 res = -1; 01256 if (!nullok) 01257 ast_log(LOG_WARNING, 01258 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n", 01259 ast ? ast->name : "", p->channel, fname, line); 01260 } 01261 return res; 01262 }
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 2169 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
02170 { 02171 int x; 02172 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 02173 if (alarms[x].alarm & alarm) 02174 return alarms[x].name; 02175 } 02176 return alarm ? "Unknown Alarm" : "No Alarm"; 02177 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1954 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), DAHDI_FILE_PSEUDO, dahdi_open(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, subnames, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
01955 { 01956 struct dahdi_bufferinfo bi; 01957 int res; 01958 if (p->subs[x].dfd < 0) { 01959 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 01960 if (p->subs[x].dfd > -1) { 01961 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01962 if (!res) { 01963 bi.txbufpolicy = p->buf_policy; 01964 bi.rxbufpolicy = p->buf_policy; 01965 bi.numbufs = p->buf_no; 01966 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01967 if (res < 0) { 01968 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01969 } 01970 } else 01971 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01972 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01973 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01974 dahdi_close_sub(p, x); 01975 return -1; 01976 } 01977 if (option_debug) 01978 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01979 return 0; 01980 } else 01981 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01982 return -1; 01983 } 01984 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01985 return -1; 01986 }
static void apply_plan_to_number | ( | char * | buf, | |
size_t | size, | |||
const struct dahdi_pri * | pri, | |||
const char * | number, | |||
const int | plan | |||
) | [static] |
Definition at line 10975 of file chan_dahdi.c.
References ast_strlen_zero(), dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.
10976 { 10977 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10978 if (size) { 10979 *buf = '\0'; 10980 } 10981 return; 10982 } 10983 10984 switch (plan) { 10985 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10986 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10987 break; 10988 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10989 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10990 break; 10991 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10992 snprintf(buf, size, "%s%s", pri->localprefix, number); 10993 break; 10994 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10995 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10996 break; 10997 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10998 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10999 break; 11000 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 11001 snprintf(buf, size, "%s", number); 11002 break; 11003 } 11004 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4981 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().
04982 { 04983 /* In order to transfer, we need at least one of the channels to 04984 actually be in a call bridge. We can't conference two applications 04985 together (but then, why would we want to?) */ 04986 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04987 /* The three-way person we're about to transfer to could still be in MOH, so 04988 stop it now if appropriate */ 04989 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04990 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04991 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04992 /* 04993 * This may not be safe. 04994 * We currently hold the locks on the real-call, private, and 3-way call. 04995 * We could possibly avoid this here by using an ast_queue_control() instead. 04996 * However, the following ast_channel_masquerade() is going to be locking 04997 * the bridged channel again anyway. 04998 */ 04999 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 05000 } 05001 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 05002 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05003 } 05004 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 05005 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 05006 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 05007 return -1; 05008 } 05009 /* Orphan the channel after releasing the lock */ 05010 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05011 unalloc_sub(p, SUB_THREEWAY); 05012 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05013 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05014 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 05015 /* 05016 * This may not be safe. 05017 * We currently hold the locks on the real-call, private, and 3-way call. 05018 * We could possibly avoid this here by using an ast_queue_control() instead. 05019 * However, the following ast_channel_masquerade() is going to be locking 05020 * the bridged channel again anyway. 05021 */ 05022 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 05023 } 05024 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 05025 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05026 } 05027 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 05028 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 05029 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 05030 return -1; 05031 } 05032 /* Three-way is now the REAL */ 05033 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05034 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 05035 unalloc_sub(p, SUB_THREEWAY); 05036 /* Tell the caller not to hangup */ 05037 return 1; 05038 } else { 05039 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 05040 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 05041 return -1; 05042 } 05043 return 0; 05044 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9798 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, sig_pri_available(), SIG_PRI_LIB_HANDLE_CASES, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __ast_string_field_index_build_va(), and dahdi_request().
09799 { 09800 int res; 09801 struct dahdi_params par; 09802 09803 /* First, check group matching */ 09804 if (groupmatch) { 09805 if ((p->group & groupmatch) != groupmatch) 09806 return 0; 09807 *groupmatched = 1; 09808 } 09809 /* Check to see if we have a channel match */ 09810 if (channelmatch != -1) { 09811 if (p->channel != channelmatch) 09812 return 0; 09813 *channelmatched = 1; 09814 } 09815 09816 #if defined(HAVE_PRI) 09817 switch (p->sig) { 09818 case SIG_PRI_LIB_HANDLE_CASES: 09819 return sig_pri_available(p); 09820 default: 09821 break; 09822 } 09823 #endif /* defined(HAVE_PRI) */ 09824 09825 /* We're at least busy at this point */ 09826 if (busy) { 09827 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09828 *busy = 1; 09829 } 09830 /* If do not disturb, definitely not */ 09831 if (p->dnd) 09832 return 0; 09833 /* If guard time, definitely not */ 09834 if (p->guardtime && (time(NULL) < p->guardtime)) 09835 return 0; 09836 09837 /* If no owner definitely available */ 09838 if (!p->owner) { 09839 #ifdef HAVE_PRI 09840 /* Trust PRI */ 09841 if (p->pri) { 09842 /* Likely only GR-303 gets here. */ 09843 return sig_pri_available(p); 09844 } 09845 #endif 09846 09847 #ifdef HAVE_OPENR2 09848 /* Trust MFC/R2 */ 09849 if (p->mfcr2) { 09850 if (p->mfcr2call || p->mfcr2block) 09851 return 0; 09852 else 09853 return 1; 09854 } 09855 #endif 09856 09857 if (!(p->radio || (p->oprmode < 0))) 09858 { 09859 if (!p->sig || (p->sig == SIG_FXSLS)) 09860 return 1; 09861 /* Check hook state */ 09862 if (p->subs[SUB_REAL].dfd > -1) { 09863 memset(&par, 0, sizeof(par)); 09864 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09865 } else { 09866 /* Assume not off hook on CVRS */ 09867 res = 0; 09868 par.rxisoffhook = 0; 09869 } 09870 if (res) { 09871 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09872 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09873 /* When "onhook" that means no battery on the line, and thus 09874 it is out of service..., if it's on a TDM card... If it's a channel 09875 bank, there is no telling... */ 09876 if (par.rxbits > -1) 09877 return 1; 09878 if (par.rxisoffhook) 09879 return 1; 09880 else 09881 #ifdef DAHDI_CHECK_HOOKSTATE 09882 return 0; 09883 #else 09884 return 1; 09885 #endif 09886 } else if (par.rxisoffhook) { 09887 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 09888 /* Not available when the other end is off hook */ 09889 return 0; 09890 } 09891 } 09892 return 1; 09893 } 09894 09895 /* If it's not an FXO, forget about call wait */ 09896 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09897 return 0; 09898 09899 if (!p->callwaiting) { 09900 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09901 return 0; 09902 } 09903 09904 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09905 /* If there is already a call waiting call, then we can't take a second one */ 09906 return 0; 09907 } 09908 09909 if ((p->owner->_state != AST_STATE_UP) && 09910 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09911 /* If the current call is not up, then don't allow the call */ 09912 return 0; 09913 } 09914 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09915 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09916 return 0; 09917 } 09918 /* We're cool */ 09919 return 1; 09920 }
static int build_channels | ( | struct dahdi_chan_conf * | conf, | |
int | iscrv, | |||
const char * | value, | |||
int | reload, | |||
int | lineno, | |||
int * | found_pseudo | |||
) | [static] |
Definition at line 13998 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, mfcr2_cur_context_index, mkintf(), NUM_SPANS, option_verbose, dahdi_pri::pri, pris, r2links, dahdi_pvt::sig, sig2str, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.
Referenced by process_dahdi().
13999 { 14000 char *c, *chan; 14001 int x, start, finish; 14002 struct dahdi_pvt *tmp; 14003 #ifdef HAVE_PRI 14004 struct dahdi_pri *pri; 14005 int trunkgroup, y; 14006 #endif 14007 14008 if ((reload == 0) && (conf->chan.sig < 0)) { 14009 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14010 return -1; 14011 } 14012 14013 c = ast_strdupa(value); 14014 14015 #ifdef HAVE_PRI 14016 pri = NULL; 14017 if (iscrv) { 14018 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 14019 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 14020 return -1; 14021 } 14022 if (trunkgroup < 1) { 14023 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 14024 return -1; 14025 } 14026 c += y; 14027 for (y = 0; y < NUM_SPANS; y++) { 14028 if (pris[y].trunkgroup == trunkgroup) { 14029 pri = pris + y; 14030 break; 14031 } 14032 } 14033 if (!pri) { 14034 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 14035 return -1; 14036 } 14037 } 14038 #endif 14039 14040 while ((chan = strsep(&c, ","))) { 14041 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 14042 /* Range */ 14043 } else if (sscanf(chan, "%30d", &start)) { 14044 /* Just one */ 14045 finish = start; 14046 } else if (!strcasecmp(chan, "pseudo")) { 14047 finish = start = CHAN_PSEUDO; 14048 if (found_pseudo) 14049 *found_pseudo = 1; 14050 } else { 14051 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14052 return -1; 14053 } 14054 if (finish < start) { 14055 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14056 x = finish; 14057 finish = start; 14058 start = x; 14059 } 14060 14061 for (x = start; x <= finish; x++) { 14062 #ifdef HAVE_PRI 14063 tmp = mkintf(x, conf, pri, reload); 14064 #else 14065 tmp = mkintf(x, conf, NULL, reload); 14066 #endif 14067 14068 if (tmp) { 14069 if (option_verbose > 2) { 14070 #ifdef HAVE_PRI 14071 if (pri) 14072 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14073 else 14074 #endif 14075 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14076 } 14077 } else { 14078 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14079 (reload == 1) ? "reconfigure" : "register", value); 14080 return -1; 14081 } 14082 } 14083 14084 #ifdef HAVE_OPENR2 14085 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) { 14086 mfcr2_cur_context_index++; 14087 } 14088 #endif 14089 14090 } 14091 14092 return 0; 14093 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 12554 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12555 { 12556 if (!s || len < 1) { 12557 return; 12558 } 12559 s[0] = '\0'; 12560 if (status & DCHAN_PROVISIONED) 12561 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12562 if (!(status & DCHAN_NOTINALARM)) 12563 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12564 if (status & DCHAN_UP) 12565 strncat(s, "Up", len - strlen(s) - 1); 12566 else 12567 strncat(s, "Down", len - strlen(s) - 1); 12568 if (active) 12569 strncat(s, ", Active", len - strlen(s) - 1); 12570 else 12571 strncat(s, ", Standby", len - strlen(s) - 1); 12572 s[len - 1] = '\0'; 12573 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2620 of file chan_dahdi.c.
References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by ss_thread().
02621 { 02622 int res; 02623 02624 /* Bump receive gain by 5.0db */ 02625 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 02626 if (res) { 02627 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02628 return -1; 02629 } 02630 02631 return 0; 02632 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 8461 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, ast_log(), AST_MULAW, and option_verbose.
08462 { 08463 int x; 08464 int sum = 0; 08465 int ssum = 0, mean = 0; 08466 08467 if (!len) 08468 return 0; 08469 08470 /* First calc mean signal (DC offset) */ 08471 for (x = 0; x < len; x++) 08472 ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 08473 08474 mean = ssum / len; 08475 08476 for (x = 0; x < len; x++) { 08477 sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean); 08478 if (option_verbose > 7) 08479 ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum); 08480 } 08481 08482 if (option_verbose > 5) 08483 ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len); 08484 08485 return sum / len; 08486 }
Definition at line 9922 of file chan_dahdi.c.
References ast_log(), ast_malloc, ast_mutex_init(), DAHDI_FILE_PSEUDO, dahdi_open(), destroy_dahdi_pvt(), errno, iflist, LOG_ERROR, dahdi_pvt::next, dahdi_pvt::prev, and SUB_REAL.
Referenced by dahdi_request().
09923 { 09924 struct dahdi_pvt *p; 09925 struct dahdi_bufferinfo bi; 09926 int res; 09927 09928 if ((p = ast_malloc(sizeof(*p)))) { 09929 memcpy(p, src, sizeof(struct dahdi_pvt)); 09930 ast_mutex_init(&p->lock); 09931 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 09932 /* Allocate a DAHDI structure */ 09933 if (p->subs[SUB_REAL].dfd < 0) { 09934 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09935 destroy_dahdi_pvt(&p); 09936 return NULL; 09937 } 09938 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09939 if (!res) { 09940 bi.txbufpolicy = p->buf_policy; 09941 bi.rxbufpolicy = p->buf_policy; 09942 bi.numbufs = p->buf_no; 09943 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09944 if (res < 0) { 09945 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09946 } 09947 } else 09948 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09949 } 09950 p->destroy = 1; 09951 p->next = iflist; 09952 p->prev = NULL; 09953 iflist = p; 09954 if (iflist->next) 09955 iflist->next->prev = p; 09956 return p; 09957 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5046 of file chan_dahdi.c.
References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event().
05047 { 05048 struct dahdi_confinfo ci; 05049 /* Fine if we already have a master, etc */ 05050 if (p->master || (p->confno > -1)) 05051 return 0; 05052 memset(&ci, 0, sizeof(ci)); 05053 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 05054 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 05055 return 0; 05056 } 05057 /* If we have no master and don't have a confno, then 05058 if we're in a conference, it's probably a MeetMe room or 05059 some such, so don't let us 3-way out! */ 05060 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 05061 if (option_verbose > 2) 05062 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 05063 return 1; 05064 } 05065 return 0; 05066 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12421 of file chan_dahdi.c.
References complete_span_helper().
12422 { 12423 return complete_span_helper(line,word,pos,state,3); 12424 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 12426 of file chan_dahdi.c.
References complete_span_helper().
12427 { 12428 return complete_span_helper(line,word,pos,state,4); 12429 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 12402 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
12403 { 12404 int which, span; 12405 char *ret = NULL; 12406 12407 if (pos != rpos) 12408 return ret; 12409 12410 for (which = span = 0; span < NUM_SPANS; span++) { 12411 if (pris[span].pri && ++which > state) { 12412 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12413 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12414 } 12415 break; 12416 } 12417 } 12418 return ret; 12419 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 2262 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_DEBUG, and LOG_WARNING.
Referenced by update_conf().
02263 { 02264 /* If the conference already exists, and we're already in it 02265 don't bother doing anything */ 02266 struct dahdi_confinfo zi; 02267 02268 memset(&zi, 0, sizeof(zi)); 02269 zi.chan = 0; 02270 02271 if (slavechannel > 0) { 02272 /* If we have only one slave, do a digital mon */ 02273 zi.confmode = DAHDI_CONF_DIGITALMON; 02274 zi.confno = slavechannel; 02275 } else { 02276 if (!index) { 02277 /* Real-side and pseudo-side both participate in conference */ 02278 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 02279 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02280 } else 02281 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02282 zi.confno = p->confno; 02283 } 02284 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 02285 return 0; 02286 if (c->dfd < 0) 02287 return 0; 02288 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02289 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 02290 return -1; 02291 } 02292 if (slavechannel < 1) { 02293 p->confno = zi.confno; 02294 } 02295 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02296 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02297 return 0; 02298 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 2311 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), LOG_DEBUG, and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
02312 { 02313 struct dahdi_confinfo zi; 02314 if (/* Can't delete if there's no dfd */ 02315 (c->dfd < 0) || 02316 /* Don't delete from the conference if it's not our conference */ 02317 !isourconf(p, c) 02318 /* Don't delete if we don't think it's conferenced at all (implied) */ 02319 ) return 0; 02320 memset(&zi, 0, sizeof(zi)); 02321 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02322 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 02323 return -1; 02324 } 02325 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02326 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02327 return 0; 02328 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3556 of file chan_dahdi.c.
References 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(), and zap_accept_r2_call_exec().
03557 { 03558 /* data is whether to accept with charge or no charge */ 03559 openr2_call_mode_t accept_mode; 03560 int res, timeout, maxloops; 03561 struct ast_frame *f; 03562 struct dahdi_pvt *p; 03563 char *parse; 03564 AST_DECLARE_APP_ARGS(args, 03565 AST_APP_ARG(charge); 03566 ); 03567 03568 if (ast_strlen_zero(data)) { 03569 ast_log(LOG_DEBUG, "No data sent to application!\n"); 03570 return -1; 03571 } 03572 03573 if (chan->tech != &dahdi_tech) { 03574 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 03575 return -1; 03576 } 03577 03578 p = (struct dahdi_pvt *)chan->tech_pvt; 03579 if (!p) { 03580 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 03581 return -1; 03582 } 03583 03584 parse = ast_strdupa(data); 03585 AST_STANDARD_APP_ARGS(args, parse); 03586 03587 if (ast_strlen_zero(args.charge)) { 03588 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 03589 return -1; 03590 } 03591 03592 ast_mutex_lock(&p->lock); 03593 if (!p->mfcr2 || !p->mfcr2call) { 03594 ast_mutex_unlock(&p->lock); 03595 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 03596 return -1; 03597 } 03598 03599 if (p->mfcr2_call_accepted) { 03600 ast_mutex_unlock(&p->lock); 03601 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 03602 return 0; 03603 } 03604 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 03605 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 03606 ast_mutex_unlock(&p->lock); 03607 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03608 return -1; 03609 } 03610 ast_mutex_unlock(&p->lock); 03611 03612 res = 0; 03613 timeout = 100; 03614 maxloops = 50; /* wait up to 5 seconds */ 03615 /* we need to read() until the call is accepted */ 03616 while (maxloops > 0) { 03617 maxloops--; 03618 if (ast_check_hangup(chan)) { 03619 break; 03620 } 03621 res = ast_waitfor(chan, timeout); 03622 if (res < 0) { 03623 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 03624 res = -1; 03625 break; 03626 } 03627 if (res == 0) { 03628 continue; 03629 } 03630 f = ast_read(chan); 03631 if (!f) { 03632 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 03633 res = -1; 03634 break; 03635 } 03636 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 03637 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 03638 ast_frfree(f); 03639 res = -1; 03640 break; 03641 } 03642 ast_frfree(f); 03643 ast_mutex_lock(&p->lock); 03644 if (p->mfcr2_call_accepted) { 03645 ast_mutex_unlock(&p->lock); 03646 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 03647 break; 03648 } 03649 ast_mutex_unlock(&p->lock); 03650 } 03651 if (res == -1) { 03652 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03653 } 03654 return res; 03655 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13811 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
13812 { 13813 return __action_dialoffhook(s, m, 0); 13814 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13711 of file chan_dahdi.c.
References __action_dnd(), and s.
13712 { 13713 return __action_dnd(s, m, 0, 0); 13714 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13701 of file chan_dahdi.c.
References __action_dnd(), and s.
13702 { 13703 return __action_dnd(s, m, 0, 1); 13704 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13890 of file chan_dahdi.c.
References __action_restart(), and s.
13891 { 13892 return __action_restart(s, m, 0); 13893 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13866 of file chan_dahdi.c.
References __action_showchannels(), and s.
13867 { 13868 return __action_showchannels(s, m, 0); 13869 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13740 of file chan_dahdi.c.
References __action_transfer(), and s.
13741 { 13742 return __action_transfer(s, m, 0); 13743 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13768 of file chan_dahdi.c.
References __action_transferhangup(), and s.
13769 { 13770 return __action_transferhangup(s, m, 0); 13771 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4101 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::channel, DAHDI_CALL_LEVEL_CONNECT, dahdi_enable_ec(), dahdi_get_index, dahdi_r2_answer(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_charge_calls, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::ringt, 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
04102 { 04103 struct dahdi_pvt *p = ast->tech_pvt; 04104 int res = 0; 04105 int index; 04106 int oldstate = ast->_state; 04107 ast_setstate(ast, AST_STATE_UP); 04108 ast_mutex_lock(&p->lock); 04109 index = dahdi_get_index(ast, p, 0); 04110 if (index < 0) 04111 index = SUB_REAL; 04112 /* nothing to do if a radio channel */ 04113 if ((p->radio || (p->oprmode < 0))) { 04114 ast_mutex_unlock(&p->lock); 04115 return 0; 04116 } 04117 switch (p->sig) { 04118 case SIG_FXSLS: 04119 case SIG_FXSGS: 04120 case SIG_FXSKS: 04121 p->ringt = 0; 04122 /* Fall through */ 04123 case SIG_EM: 04124 case SIG_EM_E1: 04125 case SIG_EMWINK: 04126 case SIG_FEATD: 04127 case SIG_FEATDMF: 04128 case SIG_FEATDMF_TA: 04129 case SIG_E911: 04130 case SIG_FGC_CAMA: 04131 case SIG_FGC_CAMAMF: 04132 case SIG_FEATB: 04133 case SIG_SF: 04134 case SIG_SFWINK: 04135 case SIG_SF_FEATD: 04136 case SIG_SF_FEATDMF: 04137 case SIG_SF_FEATB: 04138 case SIG_FXOLS: 04139 case SIG_FXOGS: 04140 case SIG_FXOKS: 04141 /* Pick up the line */ 04142 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 04143 if (p->hanguponpolarityswitch) { 04144 gettimeofday(&p->polaritydelaytv, NULL); 04145 } 04146 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 04147 tone_zone_play_tone(p->subs[index].dfd, -1); 04148 p->dialing = 0; 04149 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 04150 if (oldstate == AST_STATE_RINGING) { 04151 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 04152 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 04153 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04154 p->owner = p->subs[SUB_REAL].owner; 04155 } 04156 } 04157 if (p->sig & __DAHDI_SIG_FXS) { 04158 dahdi_enable_ec(p); 04159 dahdi_train_ec(p); 04160 } 04161 break; 04162 #ifdef HAVE_PRI 04163 case SIG_PRI: 04164 /* Send a pri acknowledge */ 04165 if (!pri_grab(p, p->pri)) { 04166 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) { 04167 p->call_level = DAHDI_CALL_LEVEL_CONNECT; 04168 } 04169 p->dialing = 0; 04170 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04171 pri_rel(p->pri); 04172 } else { 04173 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04174 res = -1; 04175 } 04176 break; 04177 #endif 04178 04179 #ifdef HAVE_OPENR2 04180 case SIG_MFCR2: 04181 if (!p->mfcr2_accept_on_offer) { 04182 /* the call was not accepted on offer, so it must be accepted now before answering, 04183 the answer will be executed when the callback on_call_accepted is executed */ 04184 if (p->mfcr2_charge_calls) { 04185 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel); 04186 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04187 } else { 04188 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel); 04189 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04190 } 04191 } else { 04192 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04193 res = dahdi_r2_answer(p); 04194 } 04195 break; 04196 #endif 04197 04198 case 0: 04199 ast_mutex_unlock(&p->lock); 04200 return 0; 04201 default: 04202 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04203 res = -1; 04204 } 04205 ast_mutex_unlock(&p->lock); 04206 return res; 04207 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 3662 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().
03663 { 03664 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 03665 switch (cause) { 03666 case AST_CAUSE_USER_BUSY: 03667 case AST_CAUSE_CALL_REJECTED: 03668 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 03669 r2cause = OR2_CAUSE_BUSY_NUMBER; 03670 break; 03671 03672 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 03673 case AST_CAUSE_SWITCH_CONGESTION: 03674 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 03675 break; 03676 03677 case AST_CAUSE_UNALLOCATED: 03678 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 03679 break; 03680 03681 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 03682 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 03683 r2cause = OR2_CAUSE_OUT_OF_ORDER; 03684 break; 03685 03686 case AST_CAUSE_NO_ANSWER: 03687 case AST_CAUSE_NO_USER_RESPONSE: 03688 r2cause = OR2_CAUSE_NO_ANSWER; 03689 break; 03690 03691 default: 03692 r2cause = OR2_CAUSE_NORMAL_CLEARING; 03693 break; 03694 } 03695 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 03696 r2cause, openr2_proto_get_disconnect_string(r2cause), cause); 03697 return r2cause; 03698 }
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 4597 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_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index, dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pri::lock, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, ast_channel::name, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, subnames, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.
04598 { 04599 struct ast_channel *who; 04600 struct dahdi_pvt *p0, *p1, *op0, *op1; 04601 struct dahdi_pvt *master = NULL, *slave = NULL; 04602 struct ast_frame *f; 04603 int inconf = 0; 04604 int nothingok = 1; 04605 int ofd0, ofd1; 04606 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04607 int os0 = -1, os1 = -1; 04608 int priority = 0; 04609 struct ast_channel *oc0, *oc1; 04610 enum ast_bridge_result res; 04611 04612 #ifdef PRI_2BCT 04613 int triedtopribridge = 0; 04614 #endif 04615 04616 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04617 There is code below to handle it properly until DTMF is actually seen, 04618 but due to currently unresolved issues it's ignored... 04619 */ 04620 04621 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04622 return AST_BRIDGE_FAILED_NOWARN; 04623 04624 ast_mutex_lock(&c0->lock); 04625 while (ast_mutex_trylock(&c1->lock)) { 04626 DEADLOCK_AVOIDANCE(&c0->lock); 04627 } 04628 04629 p0 = c0->tech_pvt; 04630 p1 = c1->tech_pvt; 04631 /* cant do pseudo-channels here */ 04632 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04633 ast_mutex_unlock(&c0->lock); 04634 ast_mutex_unlock(&c1->lock); 04635 return AST_BRIDGE_FAILED_NOWARN; 04636 } 04637 04638 oi0 = dahdi_get_index(c0, p0, 0); 04639 oi1 = dahdi_get_index(c1, p1, 0); 04640 if ((oi0 < 0) || (oi1 < 0)) { 04641 ast_mutex_unlock(&c0->lock); 04642 ast_mutex_unlock(&c1->lock); 04643 return AST_BRIDGE_FAILED; 04644 } 04645 04646 op0 = p0 = c0->tech_pvt; 04647 op1 = p1 = c1->tech_pvt; 04648 ofd0 = c0->fds[0]; 04649 ofd1 = c1->fds[0]; 04650 oc0 = p0->owner; 04651 oc1 = p1->owner; 04652 04653 if (ast_mutex_trylock(&p0->lock)) { 04654 /* Don't block, due to potential for deadlock */ 04655 ast_mutex_unlock(&c0->lock); 04656 ast_mutex_unlock(&c1->lock); 04657 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04658 return AST_BRIDGE_RETRY; 04659 } 04660 if (ast_mutex_trylock(&p1->lock)) { 04661 /* Don't block, due to potential for deadlock */ 04662 ast_mutex_unlock(&p0->lock); 04663 ast_mutex_unlock(&c0->lock); 04664 ast_mutex_unlock(&c1->lock); 04665 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04666 return AST_BRIDGE_RETRY; 04667 } 04668 04669 if ((p0->callwaiting && p0->callwaitingcallerid) 04670 || (p1->callwaiting && p1->callwaitingcallerid)) { 04671 /* 04672 * Call Waiting Caller ID requires DTMF detection to know if it 04673 * can send the CID spill. 04674 * 04675 * For now, don't attempt to native bridge if either channel 04676 * needs DTMF detection. There is code below to handle it 04677 * properly until DTMF is actually seen, but due to currently 04678 * unresolved issues it's ignored... 04679 */ 04680 ast_mutex_unlock(&p0->lock); 04681 ast_mutex_unlock(&p1->lock); 04682 ast_mutex_unlock(&c0->lock); 04683 ast_mutex_unlock(&c1->lock); 04684 return AST_BRIDGE_FAILED_NOWARN; 04685 } 04686 04687 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04688 if (p0->owner && p1->owner) { 04689 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04690 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04691 master = p0; 04692 slave = p1; 04693 inconf = 1; 04694 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04695 master = p1; 04696 slave = p0; 04697 inconf = 1; 04698 } else { 04699 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04700 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04701 p0->channel, 04702 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04703 p0->subs[SUB_REAL].inthreeway, p0->channel, 04704 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04705 p1->subs[SUB_REAL].inthreeway); 04706 } 04707 nothingok = 0; 04708 } 04709 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04710 if (p1->subs[SUB_THREEWAY].inthreeway) { 04711 master = p1; 04712 slave = p0; 04713 nothingok = 0; 04714 } 04715 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04716 if (p0->subs[SUB_THREEWAY].inthreeway) { 04717 master = p0; 04718 slave = p1; 04719 nothingok = 0; 04720 } 04721 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04722 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04723 don't put us in anything */ 04724 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04725 master = p1; 04726 slave = p0; 04727 nothingok = 0; 04728 } 04729 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04730 /* Same as previous */ 04731 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04732 master = p0; 04733 slave = p1; 04734 nothingok = 0; 04735 } 04736 } 04737 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 04738 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04739 if (master && slave) { 04740 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04741 in an active threeway call with a channel that is ringing, we should 04742 indicate ringing. */ 04743 if ((oi1 == SUB_THREEWAY) && 04744 p1->subs[SUB_THREEWAY].inthreeway && 04745 p1->subs[SUB_REAL].owner && 04746 p1->subs[SUB_REAL].inthreeway && 04747 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04748 ast_log(LOG_DEBUG, 04749 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 04750 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 04751 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04752 os1 = p1->subs[SUB_REAL].owner->_state; 04753 } else { 04754 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 04755 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name); 04756 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04757 } 04758 if ((oi0 == SUB_THREEWAY) && 04759 p0->subs[SUB_THREEWAY].inthreeway && 04760 p0->subs[SUB_REAL].owner && 04761 p0->subs[SUB_REAL].inthreeway && 04762 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04763 ast_log(LOG_DEBUG, 04764 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n", 04765 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 04766 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04767 os0 = p0->subs[SUB_REAL].owner->_state; 04768 } else { 04769 ast_log(LOG_DEBUG, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n", 04770 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name); 04771 tone_zone_play_tone(p1->subs[oi1].dfd, -1); 04772 } 04773 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04774 if (!p0->echocanbridged || !p1->echocanbridged) { 04775 /* Disable echo cancellation if appropriate */ 04776 dahdi_disable_ec(p0); 04777 dahdi_disable_ec(p1); 04778 } 04779 } 04780 dahdi_link(slave, master); 04781 master->inconference = inconf; 04782 } else if (!nothingok) 04783 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04784 04785 update_conf(p0); 04786 update_conf(p1); 04787 t0 = p0->subs[SUB_REAL].inthreeway; 04788 t1 = p1->subs[SUB_REAL].inthreeway; 04789 04790 ast_mutex_unlock(&p0->lock); 04791 ast_mutex_unlock(&p1->lock); 04792 04793 ast_mutex_unlock(&c0->lock); 04794 ast_mutex_unlock(&c1->lock); 04795 04796 /* Native bridge failed */ 04797 if ((!master || !slave) && !nothingok) { 04798 dahdi_enable_ec(p0); 04799 dahdi_enable_ec(p1); 04800 return AST_BRIDGE_FAILED; 04801 } 04802 04803 if (option_verbose > 2) 04804 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 04805 04806 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04807 disable_dtmf_detect(op0); 04808 04809 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04810 disable_dtmf_detect(op1); 04811 04812 for (;;) { 04813 struct ast_channel *c0_priority[2] = {c0, c1}; 04814 struct ast_channel *c1_priority[2] = {c1, c0}; 04815 04816 /* Here's our main loop... Start by locking things, looking for private parts, 04817 and then balking if anything is wrong */ 04818 ast_mutex_lock(&c0->lock); 04819 while (ast_mutex_trylock(&c1->lock)) { 04820 DEADLOCK_AVOIDANCE(&c0->lock); 04821 } 04822 04823 p0 = c0->tech_pvt; 04824 p1 = c1->tech_pvt; 04825 04826 if (op0 == p0) 04827 i0 = dahdi_get_index(c0, p0, 1); 04828 if (op1 == p1) 04829 i1 = dahdi_get_index(c1, p1, 1); 04830 ast_mutex_unlock(&c0->lock); 04831 ast_mutex_unlock(&c1->lock); 04832 04833 if (!timeoutms || 04834 (op0 != p0) || 04835 (op1 != p1) || 04836 (ofd0 != c0->fds[0]) || 04837 (ofd1 != c1->fds[0]) || 04838 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04839 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04840 (oc0 != p0->owner) || 04841 (oc1 != p1->owner) || 04842 (t0 != p0->subs[SUB_REAL].inthreeway) || 04843 (t1 != p1->subs[SUB_REAL].inthreeway) || 04844 (oi0 != i0) || 04845 (oi1 != i1)) { 04846 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04847 op0->channel, oi0, op1->channel, oi1); 04848 res = AST_BRIDGE_RETRY; 04849 goto return_from_bridge; 04850 } 04851 04852 #ifdef PRI_2BCT 04853 if (!triedtopribridge) { 04854 triedtopribridge = 1; 04855 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) { 04856 ast_mutex_lock(&p0->pri->lock); 04857 if (p0->call && p1->call) { 04858 pri_channel_bridge(p0->call, p1->call); 04859 } 04860 ast_mutex_unlock(&p0->pri->lock); 04861 } 04862 } 04863 #endif 04864 04865 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04866 if (!who) { 04867 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 04868 continue; 04869 } 04870 f = ast_read(who); 04871 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04872 *fo = f; 04873 *rc = who; 04874 res = AST_BRIDGE_COMPLETE; 04875 goto return_from_bridge; 04876 } 04877 if (f->frametype == AST_FRAME_DTMF) { 04878 if ((who == c0) && p0->pulsedial) { 04879 ast_write(c1, f); 04880 } else if ((who == c1) && p1->pulsedial) { 04881 ast_write(c0, f); 04882 } else { 04883 *fo = f; 04884 *rc = who; 04885 res = AST_BRIDGE_COMPLETE; 04886 goto return_from_bridge; 04887 } 04888 } 04889 ast_frfree(f); 04890 04891 /* Swap who gets priority */ 04892 priority = !priority; 04893 } 04894 04895 return_from_bridge: 04896 if (op0 == p0) 04897 dahdi_enable_ec(p0); 04898 04899 if (op1 == p1) 04900 dahdi_enable_ec(p1); 04901 04902 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04903 enable_dtmf_detect(op0); 04904 04905 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04906 enable_dtmf_detect(op1); 04907 04908 dahdi_unlink(slave, master, 1); 04909 04910 return res; 04911 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2816 of file chan_dahdi.c.
References ast_channel::_state, ast_callerid_generate(), ast_copy_string(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), dahdi_pvt::bearer, cadences, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, cidrings, dahdi_pvt::cidrings, dahdi_pvt::cidspill, DAHDI_CALL_LEVEL_SETUP, dahdi_callwait(), dahdi_get_index, dahdi_r2_get_channel_category(), defaultcic, defaultozz, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, dahdi_pvt::mfcr2, ast_channel::name, dahdi_pri::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, num_cadence, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
02817 { 02818 struct dahdi_pvt *p = ast->tech_pvt; 02819 int x, res, index,mysig; 02820 char *c, *n, *l; 02821 #ifdef HAVE_PRI 02822 char *s = NULL; 02823 #endif 02824 char dest[256]; /* must be same length as p->dialdest */ 02825 ast_mutex_lock(&p->lock); 02826 ast_copy_string(dest, rdest, sizeof(dest)); 02827 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02828 if ((ast->_state == AST_STATE_BUSY)) { 02829 p->subs[SUB_REAL].needbusy = 1; 02830 ast_mutex_unlock(&p->lock); 02831 return 0; 02832 } 02833 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02834 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02835 ast_mutex_unlock(&p->lock); 02836 return -1; 02837 } 02838 p->dialednone = 0; 02839 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02840 { 02841 /* Special pseudo -- automatically up */ 02842 ast_setstate(ast, AST_STATE_UP); 02843 ast_mutex_unlock(&p->lock); 02844 return 0; 02845 } 02846 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02847 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02848 if (res) 02849 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02850 p->outgoing = 1; 02851 02852 if (IS_DIGITAL(ast->transfercapability)) { 02853 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02854 } else { 02855 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02856 } 02857 02858 mysig = p->sig; 02859 if (p->outsigmod > -1) 02860 mysig = p->outsigmod; 02861 02862 switch (mysig) { 02863 case SIG_FXOLS: 02864 case SIG_FXOGS: 02865 case SIG_FXOKS: 02866 if (p->owner == ast) { 02867 /* Normal ring, on hook */ 02868 02869 /* Don't send audio while on hook, until the call is answered */ 02870 p->dialing = 1; 02871 if (p->use_callerid) { 02872 /* Generate the Caller-ID spill if desired */ 02873 if (p->cidspill) { 02874 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02875 free(p->cidspill); 02876 } 02877 p->callwaitcas = 0; 02878 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02879 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02880 p->cidpos = 0; 02881 send_callerid(p); 02882 } 02883 } 02884 /* Choose proper cadence */ 02885 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02886 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02887 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02888 p->cidrings = cidrings[p->distinctivering - 1]; 02889 } else { 02890 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02891 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02892 p->cidrings = p->sendcalleridafter; 02893 } 02894 02895 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02896 c = strchr(dest, '/'); 02897 if (c) 02898 c++; 02899 if (c && (strlen(c) < p->stripmsd)) { 02900 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02901 c = NULL; 02902 } 02903 if (c) { 02904 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02906 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02907 } else { 02908 p->dop.dialstr[0] = '\0'; 02909 } 02910 x = DAHDI_RING; 02911 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02912 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02913 ast_mutex_unlock(&p->lock); 02914 return -1; 02915 } 02916 p->dialing = 1; 02917 } else { 02918 /* Call waiting call */ 02919 p->callwaitrings = 0; 02920 if (ast->cid.cid_num) 02921 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02922 else 02923 p->callwait_num[0] = '\0'; 02924 if (ast->cid.cid_name) 02925 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02926 else 02927 p->callwait_name[0] = '\0'; 02928 /* Call waiting tone instead */ 02929 if (dahdi_callwait(ast)) { 02930 ast_mutex_unlock(&p->lock); 02931 return -1; 02932 } 02933 /* Make ring-back */ 02934 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02935 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02936 02937 } 02938 n = ast->cid.cid_name; 02939 l = ast->cid.cid_num; 02940 if (l) 02941 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02942 else 02943 p->lastcid_num[0] = '\0'; 02944 if (n) 02945 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02946 else 02947 p->lastcid_name[0] = '\0'; 02948 ast_setstate(ast, AST_STATE_RINGING); 02949 index = dahdi_get_index(ast, p, 0); 02950 if (index > -1) { 02951 p->subs[index].needringing = 1; 02952 } 02953 break; 02954 case SIG_FXSLS: 02955 case SIG_FXSGS: 02956 case SIG_FXSKS: 02957 case SIG_EMWINK: 02958 case SIG_EM: 02959 case SIG_EM_E1: 02960 case SIG_FEATD: 02961 case SIG_FEATDMF: 02962 case SIG_E911: 02963 case SIG_FGC_CAMA: 02964 case SIG_FGC_CAMAMF: 02965 case SIG_FEATB: 02966 case SIG_SFWINK: 02967 case SIG_SF: 02968 case SIG_SF_FEATD: 02969 case SIG_SF_FEATDMF: 02970 case SIG_FEATDMF_TA: 02971 case SIG_SF_FEATB: 02972 c = strchr(dest, '/'); 02973 if (c) 02974 c++; 02975 else 02976 c = ""; 02977 if (strlen(c) < p->stripmsd) { 02978 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02979 ast_mutex_unlock(&p->lock); 02980 return -1; 02981 } 02982 #ifdef HAVE_PRI 02983 /* Start the trunk, if not GR-303 */ 02984 if (!p->pri) { 02985 #endif 02986 x = DAHDI_START; 02987 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02988 if (res < 0) { 02989 if (errno != EINPROGRESS) { 02990 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02991 ast_mutex_unlock(&p->lock); 02992 return -1; 02993 } 02994 } 02995 #ifdef HAVE_PRI 02996 } 02997 #endif 02998 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02999 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03000 03001 c += p->stripmsd; 03002 03003 switch (mysig) { 03004 case SIG_FEATD: 03005 l = ast->cid.cid_num; 03006 if (l) 03007 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 03008 else 03009 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 03010 break; 03011 case SIG_FEATDMF: 03012 l = ast->cid.cid_num; 03013 if (l) 03014 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 03015 else 03016 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 03017 break; 03018 case SIG_FEATDMF_TA: 03019 { 03020 const char *cic, *ozz; 03021 03022 /* If you have to go through a Tandem Access point you need to use this */ 03023 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 03024 if (!ozz) 03025 ozz = defaultozz; 03026 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 03027 if (!cic) 03028 cic = defaultcic; 03029 if (!ozz || !cic) { 03030 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 03031 ast_mutex_unlock(&p->lock); 03032 return -1; 03033 } 03034 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 03035 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 03036 p->whichwink = 0; 03037 } 03038 break; 03039 case SIG_E911: 03040 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 03041 break; 03042 case SIG_FGC_CAMA: 03043 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 03044 break; 03045 case SIG_FGC_CAMAMF: 03046 case SIG_FEATB: 03047 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 03048 break; 03049 default: 03050 if (p->pulse) 03051 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 03052 else 03053 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 03054 break; 03055 } 03056 03057 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 03058 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 03059 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 03060 p->echorest[sizeof(p->echorest) - 1] = '\0'; 03061 p->echobreak = 1; 03062 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 03063 } else 03064 p->echobreak = 0; 03065 if (!res) { 03066 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 03067 int saveerr = errno; 03068 03069 x = DAHDI_ONHOOK; 03070 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03071 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 03072 ast_mutex_unlock(&p->lock); 03073 return -1; 03074 } 03075 } else 03076 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res); 03077 p->dialing = 1; 03078 if (ast_strlen_zero(c)) 03079 p->dialednone = 1; 03080 ast_setstate(ast, AST_STATE_DIALING); 03081 break; 03082 case 0: 03083 /* Special pseudo -- automatically up*/ 03084 ast_setstate(ast, AST_STATE_UP); 03085 break; 03086 case SIG_PRI: 03087 case SIG_MFCR2: 03088 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 03089 p->dialdest[0] = '\0'; 03090 p->dialing = 1; 03091 break; 03092 default: 03093 ast_log(LOG_DEBUG, "not yet implemented\n"); 03094 ast_mutex_unlock(&p->lock); 03095 return -1; 03096 } 03097 03098 #ifdef HAVE_OPENR2 03099 if (p->mfcr2) { 03100 int strip = p->stripmsd; 03101 int callres = 0; 03102 c = strchr(dest, '/'); 03103 if (c) { 03104 c++; 03105 } else { 03106 c = dest; 03107 } 03108 if (!p->hidecallerid) { 03109 l = ast->cid.cid_num; 03110 } else { 03111 l = NULL; 03112 } 03113 if (strlen(c) < strip) { 03114 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip); 03115 strip = 0; 03116 } 03117 p->dialing = 1; 03118 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast)); 03119 if (-1 == callres) { 03120 ast_mutex_unlock(&p->lock); 03121 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03122 return -1; 03123 } 03124 ast_setstate(ast, AST_STATE_DIALING); 03125 } 03126 #endif /* HAVE_OPENR2 */ 03127 03128 #ifdef HAVE_PRI 03129 if (p->pri) { 03130 struct pri_sr *sr; 03131 #ifdef SUPPORT_USERUSER 03132 const char *useruser; 03133 #endif 03134 int pridialplan; 03135 int dp_strip; 03136 int prilocaldialplan; 03137 int ldp_strip; 03138 int exclusive; 03139 const char *rr_str; 03140 int redirect_reason; 03141 03142 c = strchr(dest, '/'); 03143 if (c) { 03144 c++; 03145 } else { 03146 c = ""; 03147 } 03148 03149 l = NULL; 03150 n = NULL; 03151 if (!p->hidecallerid) { 03152 l = ast->cid.cid_num; 03153 if (!p->hidecalleridname) { 03154 n = ast->cid.cid_name; 03155 } 03156 } 03157 03158 03159 if (strlen(c) < p->stripmsd) { 03160 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03161 ast_mutex_unlock(&p->lock); 03162 return -1; 03163 } 03164 if (mysig != SIG_FXSKS) { 03165 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03166 s = strchr(c + p->stripmsd, 'w'); 03167 if (s) { 03168 if (strlen(s) > 1) 03169 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03170 else 03171 p->dop.dialstr[0] = '\0'; 03172 *s = '\0'; 03173 } else { 03174 p->dop.dialstr[0] = '\0'; 03175 } 03176 } 03177 if (pri_grab(p, p->pri)) { 03178 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03179 ast_mutex_unlock(&p->lock); 03180 return -1; 03181 } 03182 if (!(p->call = pri_new_call(p->pri->pri))) { 03183 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03184 pri_rel(p->pri); 03185 ast_mutex_unlock(&p->lock); 03186 return -1; 03187 } 03188 if (!(sr = pri_sr_new())) { 03189 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03190 pri_destroycall(p->pri->pri, p->call); 03191 p->call = NULL; 03192 pri_rel(p->pri); 03193 ast_mutex_unlock(&p->lock); 03194 return -1; 03195 } 03196 if (p->bearer || (mysig == SIG_FXSKS)) { 03197 if (p->bearer) { 03198 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 03199 p->bearer->call = p->call; 03200 } else 03201 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 03202 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03203 } 03204 p->digital = IS_DIGITAL(ast->transfercapability); 03205 03206 /* Should the picked channel be used exclusively? */ 03207 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03208 exclusive = 1; 03209 } else { 03210 exclusive = 0; 03211 } 03212 03213 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03214 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03215 (p->digital ? -1 : 03216 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03217 if (p->pri->facilityenable) 03218 pri_facility_enable(p->pri->pri); 03219 03220 if (option_verbose > 2) 03221 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03222 dp_strip = 0; 03223 pridialplan = p->pri->dialplan - 1; 03224 if (pridialplan == -2) { /* compute dynamically */ 03225 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03226 dp_strip = strlen(p->pri->internationalprefix); 03227 pridialplan = PRI_INTERNATIONAL_ISDN; 03228 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03229 dp_strip = strlen(p->pri->nationalprefix); 03230 pridialplan = PRI_NATIONAL_ISDN; 03231 } else { 03232 pridialplan = PRI_LOCAL_ISDN; 03233 } 03234 } 03235 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03236 03237 ldp_strip = 0; 03238 prilocaldialplan = p->pri->localdialplan - 1; 03239 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 03240 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03241 ldp_strip = strlen(p->pri->internationalprefix); 03242 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03243 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03244 ldp_strip = strlen(p->pri->nationalprefix); 03245 prilocaldialplan = PRI_NATIONAL_ISDN; 03246 } else { 03247 prilocaldialplan = PRI_LOCAL_ISDN; 03248 } 03249 } 03250 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03251 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03252 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03253 if (!strcasecmp(rr_str, "UNKNOWN")) 03254 redirect_reason = 0; 03255 else if (!strcasecmp(rr_str, "BUSY")) 03256 redirect_reason = 1; 03257 else if (!strcasecmp(rr_str, "NO_REPLY")) 03258 redirect_reason = 2; 03259 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03260 redirect_reason = 15; 03261 else 03262 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03263 } else 03264 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03265 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03266 03267 #ifdef SUPPORT_USERUSER 03268 /* User-user info */ 03269 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03270 03271 if (useruser) 03272 pri_sr_set_useruser(sr, useruser); 03273 #endif 03274 03275 if (pri_setup(p->pri->pri, p->call, sr)) { 03276 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03277 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03278 pri_destroycall(p->pri->pri, p->call); 03279 p->call = NULL; 03280 pri_rel(p->pri); 03281 ast_mutex_unlock(&p->lock); 03282 pri_sr_free(sr); 03283 return -1; 03284 } 03285 p->call_level = DAHDI_CALL_LEVEL_SETUP; 03286 pri_sr_free(sr); 03287 ast_setstate(ast, AST_STATE_DIALING); 03288 pri_rel(p->pri); 03289 } 03290 #endif 03291 ast_mutex_unlock(&p->lock); 03292 return 0; 03293 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2783 of file chan_dahdi.c.
References 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, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call().
02784 { 02785 struct dahdi_pvt *p = ast->tech_pvt; 02786 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02787 if (p->cidspill) { 02788 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02789 free(p->cidspill); 02790 } 02791 02792 /* 02793 * SAS: Subscriber Alert Signal, 440Hz for 300ms 02794 * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves 02795 */ 02796 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02797 return -1; 02798 save_conference(p); 02799 /* Silence */ 02800 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02801 if (!p->callwaitrings && p->callwaitingcallerid) { 02802 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02803 p->callwaitcas = 1; 02804 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02805 } else { 02806 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02807 p->callwaitcas = 0; 02808 p->cidlen = 2400 + READ_SIZE * 4; 02809 } 02810 p->cidpos = 0; 02811 send_callerid(p); 02812 02813 return 0; 02814 }
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 1048 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by setup_dahdi().
01048 { 01049 /* recall that if a field is not included here it is initialized 01050 * to 0 or equivalent 01051 */ 01052 struct dahdi_chan_conf conf = { 01053 #ifdef HAVE_PRI 01054 .pri = { 01055 .nsf = PRI_NSF_NONE, 01056 .switchtype = PRI_SWITCH_NI2, 01057 .dialplan = PRI_NATIONAL_ISDN + 1, 01058 .localdialplan = PRI_NATIONAL_ISDN + 1, 01059 .nodetype = PRI_CPE, 01060 01061 .minunused = 2, 01062 .idleext = "", 01063 .idledial = "", 01064 .internationalprefix = "", 01065 .nationalprefix = "", 01066 .localprefix = "", 01067 .privateprefix = "", 01068 .unknownprefix = "", 01069 01070 .resetinterval = 3600 01071 }, 01072 #endif 01073 .chan = { 01074 .context = "default", 01075 .cid_num = "", 01076 .cid_name = "", 01077 .mohinterpret = "default", 01078 .mohsuggest = "", 01079 .transfertobusy = 1, 01080 01081 .cid_signalling = CID_SIG_BELL, 01082 .cid_start = CID_START_RING, 01083 .dahditrcallerid = 0, 01084 .use_callerid = 1, 01085 .sig = -1, 01086 .outsigmod = -1, 01087 01088 .tonezone = -1, 01089 01090 .echocancel = 1, 01091 01092 .busycount = 3, 01093 .busycompare = 0, 01094 .busytonelength = 0, 01095 .busyquietlength = 0, 01096 .busyfuzziness = 0, 01097 .silencethreshold = 0, 01098 01099 .accountcode = "", 01100 01101 .mailbox = "", 01102 01103 01104 .polarityonanswerdelay = 600, 01105 01106 .sendcalleridafter = DEFAULT_CIDRINGS, 01107 01108 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01109 .buf_no = numbufs, 01110 }, 01111 .timing = { 01112 .prewinktime = -1, 01113 .preflashtime = -1, 01114 .winktime = -1, 01115 .flashtime = -1, 01116 .starttime = -1, 01117 .rxwinktime = -1, 01118 .rxflashtime = -1, 01119 .debouncetime = -1 01120 }, 01121 .smdi_port = "/dev/ttyS0", 01122 }; 01123 01124 return conf; 01125 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1924 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 1937 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01938 { 01939 dahdi_close(pri->fds[fd_num]); 01940 pri->fds[fd_num] = -1; 01941 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1930 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().
01931 { 01932 dahdi_close(chan_pvt->subs[sub_num].dfd); 01933 chan_pvt->subs[sub_num].dfd = -1; 01934 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2664 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmf(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().
02665 { 02666 int x, y, res; 02667 x = muted; 02668 if (p->sig == SIG_PRI) { 02669 y = 1; 02670 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02671 if (res) 02672 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02673 } 02674 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02675 if (res < 0) 02676 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02677 return res; 02678 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 13060 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
13061 { 13062 int channel; 13063 13064 if (argc != 4) 13065 return RESULT_SHOWUSAGE; 13066 13067 channel = atoi(argv[3]); 13068 13069 return dahdi_destroy_channel_bynum(channel); 13070 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8489 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, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel().
08490 { 08491 struct dahdi_pvt *tmp = NULL; 08492 struct dahdi_pvt *prev = NULL; 08493 08494 ast_mutex_lock(&iflock); 08495 tmp = iflist; 08496 while (tmp) { 08497 if (tmp->channel == channel) { 08498 int x = DAHDI_FLASH; 08499 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */ 08500 destroy_channel(prev, tmp, 1); 08501 ast_mutex_unlock(&iflock); 08502 ast_module_unref(ast_module_info->self); 08503 return RESULT_SUCCESS; 08504 } 08505 prev = tmp; 08506 tmp = tmp->next; 08507 } 08508 ast_mutex_unlock(&iflock); 08509 return RESULT_FAILURE; 08510 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 2021 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, dahdi_pvt::call_level, DAHDI_CALL_LEVEL_CONNECT, DAHDI_CALL_LEVEL_OVERLAP, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_get_index, dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, len(), dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
02022 { 02023 struct dahdi_pvt *pvt; 02024 int index; 02025 int dtmf = -1; 02026 02027 pvt = chan->tech_pvt; 02028 02029 ast_mutex_lock(&pvt->lock); 02030 02031 index = dahdi_get_index(chan, pvt, 0); 02032 02033 if ((index != SUB_REAL) || !pvt->owner) 02034 goto out; 02035 02036 #ifdef HAVE_PRI 02037 if (pvt->sig == SIG_PRI 02038 && chan->_state == AST_STATE_DIALING) { 02039 if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) { 02040 unsigned int len; 02041 02042 len = strlen(pvt->dialdest); 02043 if (len < sizeof(pvt->dialdest) - 1) { 02044 ast_log(LOG_DEBUG, 02045 "Queueing digit '%c' since setup_ack not yet received\n", digit); 02046 pvt->dialdest[len++] = digit; 02047 pvt->dialdest[len] = '\0'; 02048 } else { 02049 ast_log(LOG_WARNING, 02050 "Span %d: Deferred digit buffer overflow for digit '%c'.\n", 02051 pvt->span, digit); 02052 } 02053 goto out; 02054 } 02055 if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) { 02056 if (!pri_grab(pvt, pvt->pri)) { 02057 pri_information(pvt->pri->pri, pvt->call, digit); 02058 pri_rel(pvt->pri); 02059 } else { 02060 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 02061 } 02062 goto out; 02063 } 02064 if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) { 02065 ast_log(LOG_WARNING, 02066 "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n", 02067 pvt->span, digit, pvt->call_level); 02068 } 02069 } 02070 #endif 02071 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 02072 goto out; 02073 02074 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 02075 int res; 02076 struct dahdi_dialoperation zo = { 02077 .op = DAHDI_DIAL_OP_APPEND, 02078 .dialstr[0] = 'T', 02079 .dialstr[1] = digit, 02080 .dialstr[2] = 0, 02081 }; 02082 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 02083 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 02084 else 02085 pvt->dialing = 1; 02086 } else { 02087 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 02088 pvt->dialing = 1; 02089 pvt->begindigit = digit; 02090 } 02091 02092 out: 02093 ast_mutex_unlock(&pvt->lock); 02094 02095 return 0; 02096 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2098 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index, dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
02099 { 02100 struct dahdi_pvt *pvt; 02101 int res = 0; 02102 int index; 02103 int x; 02104 02105 pvt = chan->tech_pvt; 02106 02107 ast_mutex_lock(&pvt->lock); 02108 02109 index = dahdi_get_index(chan, pvt, 0); 02110 02111 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 02112 goto out; 02113 02114 #ifdef HAVE_PRI 02115 /* This means that the digit was already sent via PRI signalling */ 02116 if (pvt->sig == SIG_PRI && !pvt->begindigit) 02117 goto out; 02118 #endif 02119 02120 if (pvt->begindigit) { 02121 x = -1; 02122 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 02123 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 02124 pvt->dialing = 0; 02125 pvt->begindigit = 0; 02126 } 02127 02128 out: 02129 ast_mutex_unlock(&pvt->lock); 02130 02131 return res; 02132 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2495 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().
02496 { 02497 int x; 02498 int res; 02499 if (p->echocancel) { 02500 x = 0; 02501 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02502 if (res) 02503 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02504 else if (option_debug) 02505 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 02506 } 02507 p->echocanon = 0; 02508 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2445 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and ss_thread().
02446 { 02447 int x; 02448 int res; 02449 if (!p) 02450 return; 02451 if (p->echocanon) { 02452 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 02453 return; 02454 } 02455 if (p->digital) { 02456 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 02457 return; 02458 } 02459 if (p->echocancel) { 02460 if (p->sig == SIG_PRI) { 02461 x = 1; 02462 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02463 if (res) 02464 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02465 } 02466 x = p->echocancel; 02467 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02468 if (res) 02469 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02470 else { 02471 p->echocanon = 1; 02472 if (option_debug) 02473 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 02474 } 02475 } else if (option_debug) 02476 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 02477 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6264 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
06265 { 06266 struct dahdi_pvt *p = ast->tech_pvt; 06267 struct ast_frame *f; 06268 ast_mutex_lock(&p->lock); 06269 f = __dahdi_exception(ast); 06270 ast_mutex_unlock(&p->lock); 06271 return f; 06272 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 13646 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().
13647 { 13648 if (p) { 13649 switch (mode) { 13650 case TRANSFER: 13651 p->fake_event = DAHDI_EVENT_WINKFLASH; 13652 break; 13653 case HANGUP: 13654 p->fake_event = DAHDI_EVENT_ONHOOK; 13655 break; 13656 default: 13657 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13658 } 13659 } 13660 return 0; 13661 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4913 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.
04914 { 04915 struct dahdi_pvt *p = newchan->tech_pvt; 04916 int x; 04917 ast_mutex_lock(&p->lock); 04918 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 04919 if (p->owner == oldchan) { 04920 p->owner = newchan; 04921 } 04922 for (x = 0; x < 3; x++) 04923 if (p->subs[x].owner == oldchan) { 04924 if (!x) 04925 dahdi_unlink(NULL, p, 0); 04926 p->subs[x].owner = newchan; 04927 } 04928 update_conf(p); 04929 ast_mutex_unlock(&p->lock); 04930 if (newchan->_state == AST_STATE_RINGING) 04931 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04932 return 0; 04933 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4395 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.
04396 { 04397 struct dahdi_pvt *p = chan->tech_pvt; 04398 int res = 0; 04399 04400 if (!strcasecmp(data, "rxgain")) { 04401 ast_mutex_lock(&p->lock); 04402 snprintf(buf, len, "%f", p->rxgain); 04403 ast_mutex_unlock(&p->lock); 04404 } else if (!strcasecmp(data, "txgain")) { 04405 ast_mutex_lock(&p->lock); 04406 snprintf(buf, len, "%f", p->txgain); 04407 ast_mutex_unlock(&p->lock); 04408 } else { 04409 ast_copy_string(buf, "", len); 04410 res = -1; 04411 } 04412 04413 return res; 04414 }
static int dahdi_func_write | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 4447 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::channel, errno, LOG_WARNING, parse_buffers_policy(), SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
04448 { 04449 struct dahdi_pvt *p = chan->tech_pvt; 04450 int res = 0; 04451 04452 if (!strcasecmp(data, "buffers")) { 04453 int num_bufs, policy; 04454 04455 if (!(parse_buffers_policy(value, &num_bufs, &policy))) { 04456 struct dahdi_bufferinfo bi = { 04457 .txbufpolicy = policy, 04458 .rxbufpolicy = policy, 04459 .bufsize = p->bufsize, 04460 .numbufs = num_bufs, 04461 }; 04462 int bpres; 04463 04464 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 04465 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno)); 04466 } else { 04467 p->bufferoverrideinuse = 1; 04468 } 04469 } else { 04470 res = -1; 04471 } 04472 } else { 04473 res = -1; 04474 } 04475 04476 return res; 04477 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 289 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00290 { 00291 int j; 00292 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00293 return -1; 00294 return j; 00295 }
static void dahdi_handle_dtmf | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 5102 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, free, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event().
05103 { 05104 struct dahdi_pvt *p = ast->tech_pvt; 05105 struct ast_frame *f = *dest; 05106 05107 if (option_debug) 05108 ast_log(LOG_DEBUG, "%s DTMF digit: 0x%02X '%c' on %s\n", 05109 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End", 05110 f->subclass, f->subclass, ast->name); 05111 05112 if (p->confirmanswer) { 05113 if (f->frametype == AST_FRAME_DTMF_END) { 05114 if (option_debug) 05115 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 05116 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 05117 of a DTMF digit */ 05118 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05119 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05120 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 05121 p->confirmanswer = 0; 05122 } else { 05123 p->subs[index].f.frametype = AST_FRAME_NULL; 05124 p->subs[index].f.subclass = 0; 05125 } 05126 *dest = &p->subs[index].f; 05127 } else if (p->callwaitcas) { 05128 if (f->frametype == AST_FRAME_DTMF_END) { 05129 if ((f->subclass == 'A') || (f->subclass == 'D')) { 05130 if (option_debug) 05131 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 05132 free(p->cidspill); 05133 p->cidspill = NULL; 05134 send_cwcidspill(p); 05135 } 05136 if ((f->subclass != 'm') && (f->subclass != 'u')) 05137 p->callwaitcas = 0; 05138 } 05139 p->subs[index].f.frametype = AST_FRAME_NULL; 05140 p->subs[index].f.subclass = 0; 05141 *dest = &p->subs[index].f; 05142 } else if (f->subclass == 'f') { 05143 if (f->frametype == AST_FRAME_DTMF_END) { 05144 /* Fax tone -- Handle and return NULL */ 05145 if ((p->callprogress & 0x6) && !p->faxhandled) { 05146 p->faxhandled = 1; 05147 if (strcmp(ast->exten, "fax")) { 05148 const char *target_context = S_OR(ast->macrocontext, ast->context); 05149 05150 /* We need to unlock 'ast' here because ast_exists_extension has the 05151 * potential to start autoservice on the channel. Such action is prone 05152 * to deadlock. 05153 */ 05154 ast_mutex_unlock(&p->lock); 05155 ast_channel_unlock(ast); 05156 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 05157 ast_channel_lock(ast); 05158 ast_mutex_lock(&p->lock); 05159 if (option_verbose > 2) 05160 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 05161 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 05162 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 05163 if (ast_async_goto(ast, target_context, "fax", 1)) 05164 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 05165 } else { 05166 ast_channel_lock(ast); 05167 ast_mutex_lock(&p->lock); 05168 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 05169 } 05170 } else if (option_debug) 05171 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 05172 } else if (option_debug) 05173 ast_log(LOG_DEBUG, "Fax already handled\n"); 05174 dahdi_confmute(p, 0); 05175 } 05176 p->subs[index].f.frametype = AST_FRAME_NULL; 05177 p->subs[index].f.subclass = 0; 05178 *dest = &p->subs[index].f; 05179 } else if (f->subclass == 'm') { 05180 if (f->frametype == AST_FRAME_DTMF_END) { 05181 /* Confmute request */ 05182 dahdi_confmute(p, 1); 05183 } 05184 p->subs[index].f.frametype = AST_FRAME_NULL; 05185 p->subs[index].f.subclass = 0; 05186 *dest = &p->subs[index].f; 05187 } else if (f->subclass == 'u') { 05188 if (f->frametype == AST_FRAME_DTMF_END) { 05189 /* Unmute */ 05190 dahdi_confmute(p, 0); 05191 } 05192 p->subs[index].f.frametype = AST_FRAME_NULL; 05193 p->subs[index].f.subclass = 0; 05194 *dest = &p->subs[index].f; 05195 } else { 05196 if (f->frametype == AST_FRAME_DTMF_END) { 05197 dahdi_confmute(p, 0); 05198 } 05199 } 05200 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5222 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_unlock(), ast_null_frame, ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), 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_verbose(), attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index, dahdi_handle_dtmf(), dahdi_lock_sub_owner(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::resetting, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, 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, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), 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(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
05223 { 05224 int res, x; 05225 int index, mysig; 05226 char *c; 05227 struct dahdi_pvt *p = ast->tech_pvt; 05228 pthread_t threadid; 05229 pthread_attr_t attr; 05230 struct ast_channel *chan; 05231 struct ast_frame *f; 05232 05233 index = dahdi_get_index(ast, p, 0); 05234 if (index < 0) { 05235 return &ast_null_frame; 05236 } 05237 if (index != SUB_REAL) { 05238 ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n"); 05239 } 05240 05241 mysig = p->sig; 05242 if (p->outsigmod > -1) 05243 mysig = p->outsigmod; 05244 05245 p->subs[index].f.frametype = AST_FRAME_NULL; 05246 p->subs[index].f.subclass = 0; 05247 p->subs[index].f.datalen = 0; 05248 p->subs[index].f.samples = 0; 05249 p->subs[index].f.mallocd = 0; 05250 p->subs[index].f.offset = 0; 05251 p->subs[index].f.src = "dahdi_handle_event"; 05252 p->subs[index].f.data = NULL; 05253 f = &p->subs[index].f; 05254 05255 if (p->fake_event) { 05256 res = p->fake_event; 05257 p->fake_event = 0; 05258 } else 05259 res = dahdi_get_event(p->subs[index].dfd); 05260 05261 if (option_debug) 05262 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 05263 05264 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 05265 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 05266 05267 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 05268 #ifdef HAVE_PRI 05269 if (p->sig == SIG_PRI 05270 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING 05271 && p->pri 05272 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 05273 /* absorb event */ 05274 } else 05275 #endif 05276 { 05277 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 05278 p->subs[index].f.subclass = res & 0xff; 05279 dahdi_handle_dtmf(ast, index, &f); 05280 } 05281 return f; 05282 } 05283 05284 if (res & DAHDI_EVENT_DTMFDOWN) { 05285 if (option_debug) 05286 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 05287 #ifdef HAVE_PRI 05288 if (p->sig == SIG_PRI 05289 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING 05290 && p->pri 05291 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 05292 /* absorb event */ 05293 } else 05294 #endif 05295 { 05296 /* Mute conference */ 05297 dahdi_confmute(p, 1); 05298 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 05299 p->subs[index].f.subclass = res & 0xff; 05300 dahdi_handle_dtmf(ast, index, &f); 05301 } 05302 return &p->subs[index].f; 05303 } 05304 05305 switch (res) { 05306 #ifdef DAHDI_EVENT_EC_DISABLED 05307 case DAHDI_EVENT_EC_DISABLED: 05308 if (option_verbose > 2) 05309 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 05310 p->echocanon = 0; 05311 break; 05312 #endif 05313 case DAHDI_EVENT_BITSCHANGED: 05314 #ifdef HAVE_OPENR2 05315 if (p->sig != SIG_MFCR2) { 05316 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05317 } else { 05318 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 05319 openr2_chan_handle_cas(p->r2chan); 05320 } 05321 #else 05322 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 05323 #endif 05324 case DAHDI_EVENT_PULSE_START: 05325 /* Stop tone if there's a pulse start and the PBX isn't started */ 05326 if (!ast->pbx) 05327 tone_zone_play_tone(p->subs[index].dfd, -1); 05328 break; 05329 case DAHDI_EVENT_DIALCOMPLETE: 05330 #ifdef HAVE_OPENR2 05331 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05332 /* we don't need to do anything for this event for R2 signaling 05333 if the call is being setup */ 05334 break; 05335 } 05336 #endif 05337 if (p->inalarm) break; 05338 if ((p->radio || (p->oprmode < 0))) break; 05339 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 05340 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05341 return NULL; 05342 } 05343 if (!x) { /* if not still dialing in driver */ 05344 dahdi_enable_ec(p); 05345 if (p->echobreak) { 05346 dahdi_train_ec(p); 05347 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05348 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05349 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05350 p->echobreak = 0; 05351 } else { 05352 p->dialing = 0; 05353 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05354 /* if thru with dialing after offhook */ 05355 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05356 ast_setstate(ast, AST_STATE_UP); 05357 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05358 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05359 break; 05360 } else { /* if to state wait for offhook to dial rest */ 05361 /* we now wait for off hook */ 05362 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05363 } 05364 } 05365 if (ast->_state == AST_STATE_DIALING) { 05366 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05367 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 05368 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) { 05369 ast_setstate(ast, AST_STATE_RINGING); 05370 } else if (!p->answeronpolarityswitch) { 05371 ast_setstate(ast, AST_STATE_UP); 05372 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05373 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05374 /* If aops=0 and hops=1, this is necessary */ 05375 p->polarity = POLARITY_REV; 05376 } else { 05377 /* Start clean, so we can catch the change to REV polarity when party answers */ 05378 p->polarity = POLARITY_IDLE; 05379 } 05380 } 05381 } 05382 } 05383 break; 05384 case DAHDI_EVENT_ALARM: 05385 #ifdef HAVE_PRI 05386 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05387 /* T309 is not enabled : destroy calls when alarm occurs */ 05388 if (p->call) { 05389 if (p->pri && p->pri->pri) { 05390 pri_grab(p, p->pri); 05391 pri_destroycall(p->pri->pri, p->call); 05392 p->call = NULL; 05393 pri_rel(p->pri); 05394 } else 05395 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05396 } 05397 if (p->owner) 05398 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05399 } 05400 if (p->bearer) { 05401 p->bearer->inalarm = 1; 05402 p->bearer->resetting = 0; 05403 } else 05404 #endif 05405 { 05406 p->inalarm = 1; 05407 #if defined(HAVE_PRI) 05408 p->resetting = 0; 05409 #endif /* defined(HAVE_PRI) */ 05410 } 05411 res = get_alarms(p); 05412 handle_alarms(p, res); 05413 #ifdef HAVE_PRI 05414 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05415 /* fall through intentionally */ 05416 } else { 05417 break; 05418 } 05419 #endif 05420 05421 #ifdef HAVE_OPENR2 05422 if (p->sig == SIG_MFCR2) 05423 break; 05424 #endif 05425 05426 case DAHDI_EVENT_ONHOOK: 05427 if (p->radio) { 05428 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05429 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05430 break; 05431 } 05432 if (p->oprmode < 0) 05433 { 05434 if (p->oprmode != -1) break; 05435 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05436 { 05437 /* Make sure it starts ringing */ 05438 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05439 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05440 save_conference(p->oprpeer); 05441 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05442 } 05443 break; 05444 } 05445 switch (p->sig) { 05446 case SIG_FXOLS: 05447 case SIG_FXOGS: 05448 case SIG_FXOKS: 05449 p->onhooktime = time(NULL); 05450 p->msgstate = -1; 05451 /* Check for some special conditions regarding call waiting */ 05452 if (index == SUB_REAL) { 05453 /* The normal line was hung up */ 05454 if (p->subs[SUB_CALLWAIT].owner) { 05455 /* Need to hold the lock for real-call, private, and call-waiting call */ 05456 dahdi_lock_sub_owner(p, SUB_CALLWAIT); 05457 if (!p->subs[SUB_CALLWAIT].owner) { 05458 /* 05459 * The call waiting call dissappeared. 05460 * This is now a normal hangup. 05461 */ 05462 dahdi_disable_ec(p); 05463 return NULL; 05464 } 05465 05466 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05467 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05468 if (option_verbose > 2) 05469 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05470 unalloc_sub(p, SUB_CALLWAIT); 05471 #if 0 05472 p->subs[index].needanswer = 0; 05473 p->subs[index].needringing = 0; 05474 #endif 05475 p->callwaitingrepeat = 0; 05476 p->cidcwexpire = 0; 05477 p->cid_suppress_expire = 0; 05478 p->owner = NULL; 05479 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05480 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05481 p->dialing = 1; 05482 /* Unlock the call-waiting call that we swapped to real-call. */ 05483 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 05484 dahdi_ring_phone(p); 05485 } else if (p->subs[SUB_THREEWAY].owner) { 05486 unsigned int mssinceflash; 05487 05488 /* Need to hold the lock for real-call, private, and 3-way call */ 05489 dahdi_lock_sub_owner(p, SUB_THREEWAY); 05490 if (!p->subs[SUB_THREEWAY].owner) { 05491 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05492 /* Just hangup */ 05493 return NULL; 05494 } 05495 if (p->owner != ast) { 05496 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05497 ast_log(LOG_WARNING, "This isn't good...\n"); 05498 /* Just hangup */ 05499 return NULL; 05500 } 05501 05502 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05503 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 05504 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05505 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05506 hanging up. Hangup both channels now */ 05507 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05508 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 05509 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05510 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05511 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05512 if (p->transfer) { 05513 /* In any case this isn't a threeway call anymore */ 05514 p->subs[SUB_REAL].inthreeway = 0; 05515 p->subs[SUB_THREEWAY].inthreeway = 0; 05516 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05517 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05518 /* Swap subs and dis-own channel */ 05519 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05520 /* Unlock the 3-way call that we swapped to real-call. */ 05521 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 05522 p->owner = NULL; 05523 /* Ring the phone */ 05524 dahdi_ring_phone(p); 05525 } else { 05526 res = attempt_transfer(p); 05527 if (res < 0) { 05528 /* Transfer attempt failed. */ 05529 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05530 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05531 } else if (res) { 05532 /* Don't actually hang up at this point */ 05533 break; 05534 } 05535 } 05536 } else { 05537 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05538 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05539 } 05540 } else { 05541 /* Swap subs and dis-own channel */ 05542 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05543 /* Unlock the 3-way call that we swapped to real-call. */ 05544 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 05545 p->owner = NULL; 05546 /* Ring the phone */ 05547 dahdi_ring_phone(p); 05548 } 05549 } 05550 } else { 05551 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 05552 } 05553 /* Fall through */ 05554 default: 05555 dahdi_disable_ec(p); 05556 return NULL; 05557 } 05558 break; 05559 case DAHDI_EVENT_RINGOFFHOOK: 05560 if (p->inalarm) break; 05561 if (p->oprmode < 0) 05562 { 05563 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05564 { 05565 /* Make sure it stops ringing */ 05566 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05567 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 05568 restore_conference(p->oprpeer); 05569 } 05570 break; 05571 } 05572 if (p->radio) 05573 { 05574 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05575 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05576 break; 05577 } 05578 /* for E911, its supposed to wait for offhook then dial 05579 the second half of the dial string */ 05580 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05581 c = strchr(p->dialdest, '/'); 05582 if (c) 05583 c++; 05584 else 05585 c = p->dialdest; 05586 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05587 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05588 if (strlen(p->dop.dialstr) > 4) { 05589 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05590 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05591 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05592 p->echobreak = 1; 05593 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05594 } else 05595 p->echobreak = 0; 05596 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05597 int saveerr = errno; 05598 05599 x = DAHDI_ONHOOK; 05600 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05601 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05602 return NULL; 05603 } 05604 p->dialing = 1; 05605 return &p->subs[index].f; 05606 } 05607 switch (p->sig) { 05608 case SIG_FXOLS: 05609 case SIG_FXOGS: 05610 case SIG_FXOKS: 05611 switch (ast->_state) { 05612 case AST_STATE_RINGING: 05613 dahdi_enable_ec(p); 05614 dahdi_train_ec(p); 05615 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05616 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05617 /* Make sure it stops ringing */ 05618 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05619 p->subs[SUB_REAL].needringing = 0; 05620 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 05621 05622 /* Cancel any running CallerID spill */ 05623 free(p->cidspill); 05624 p->cidspill = NULL; 05625 restore_conference(p); 05626 05627 p->dialing = 0; 05628 p->callwaitcas = 0; 05629 if (p->confirmanswer) { 05630 /* Ignore answer if "confirm answer" is enabled */ 05631 p->subs[index].f.frametype = AST_FRAME_NULL; 05632 p->subs[index].f.subclass = 0; 05633 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05634 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05635 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05636 if (res < 0) { 05637 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05638 p->dop.dialstr[0] = '\0'; 05639 return NULL; 05640 } else { 05641 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05642 p->subs[index].f.frametype = AST_FRAME_NULL; 05643 p->subs[index].f.subclass = 0; 05644 p->dialing = 1; 05645 } 05646 p->dop.dialstr[0] = '\0'; 05647 ast_setstate(ast, AST_STATE_DIALING); 05648 } else 05649 ast_setstate(ast, AST_STATE_UP); 05650 return &p->subs[index].f; 05651 case AST_STATE_DOWN: 05652 ast_setstate(ast, AST_STATE_RING); 05653 ast->rings = 1; 05654 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05655 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05656 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 05657 return &p->subs[index].f; 05658 case AST_STATE_UP: 05659 /* Make sure it stops ringing */ 05660 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05661 /* Okay -- probably call waiting*/ 05662 if (ast_bridged_channel(p->owner)) 05663 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05664 p->subs[index].needunhold = 1; 05665 break; 05666 case AST_STATE_RESERVED: 05667 /* Start up dialtone */ 05668 if (has_voicemail(p)) 05669 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05670 else 05671 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05672 break; 05673 default: 05674 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05675 } 05676 break; 05677 case SIG_FXSLS: 05678 case SIG_FXSGS: 05679 case SIG_FXSKS: 05680 if (ast->_state == AST_STATE_RING) { 05681 p->ringt = p->ringt_base; 05682 } 05683 05684 /* Fall through */ 05685 case SIG_EM: 05686 case SIG_EM_E1: 05687 case SIG_EMWINK: 05688 case SIG_FEATD: 05689 case SIG_FEATDMF: 05690 case SIG_FEATDMF_TA: 05691 case SIG_E911: 05692 case SIG_FGC_CAMA: 05693 case SIG_FGC_CAMAMF: 05694 case SIG_FEATB: 05695 case SIG_SF: 05696 case SIG_SFWINK: 05697 case SIG_SF_FEATD: 05698 case SIG_SF_FEATDMF: 05699 case SIG_SF_FEATB: 05700 if (ast->_state == AST_STATE_PRERING) 05701 ast_setstate(ast, AST_STATE_RING); 05702 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05703 if (option_debug) 05704 ast_log(LOG_DEBUG, "Ring detected\n"); 05705 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05706 p->subs[index].f.subclass = AST_CONTROL_RING; 05707 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05708 if (option_debug) 05709 ast_log(LOG_DEBUG, "Line answered\n"); 05710 if (p->confirmanswer) { 05711 p->subs[index].f.frametype = AST_FRAME_NULL; 05712 p->subs[index].f.subclass = 0; 05713 } else { 05714 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05715 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05716 ast_setstate(ast, AST_STATE_UP); 05717 } 05718 } else if (ast->_state != AST_STATE_RING) 05719 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05720 break; 05721 default: 05722 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05723 } 05724 break; 05725 #ifdef DAHDI_EVENT_RINGBEGIN 05726 case DAHDI_EVENT_RINGBEGIN: 05727 switch (p->sig) { 05728 case SIG_FXSLS: 05729 case SIG_FXSGS: 05730 case SIG_FXSKS: 05731 if (ast->_state == AST_STATE_RING) { 05732 p->ringt = p->ringt_base; 05733 } 05734 break; 05735 } 05736 break; 05737 #endif 05738 case DAHDI_EVENT_RINGEROFF: 05739 if (p->inalarm) break; 05740 if ((p->radio || (p->oprmode < 0))) break; 05741 ast->rings++; 05742 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05743 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05744 free(p->cidspill); 05745 p->cidspill = NULL; 05746 p->callwaitcas = 0; 05747 } 05748 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05749 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05750 break; 05751 case DAHDI_EVENT_RINGERON: 05752 break; 05753 case DAHDI_EVENT_NOALARM: 05754 p->inalarm = 0; 05755 #ifdef HAVE_PRI 05756 p->resetting = 0; 05757 /* Extremely unlikely but just in case */ 05758 if (p->bearer) { 05759 p->bearer->inalarm = 0; 05760 p->bearer->resetting = 0; 05761 } 05762 #endif 05763 if (!p->unknown_alarm) { 05764 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05765 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05766 "Channel: %d\r\n", p->channel); 05767 } else { 05768 p->unknown_alarm = 0; 05769 } 05770 break; 05771 case DAHDI_EVENT_WINKFLASH: 05772 if (p->inalarm) break; 05773 if (p->radio) break; 05774 if (p->oprmode < 0) break; 05775 if (p->oprmode > 1) 05776 { 05777 struct dahdi_params par; 05778 05779 memset(&par, 0, sizeof(par)); 05780 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05781 { 05782 if (!par.rxisoffhook) 05783 { 05784 /* Make sure it stops ringing */ 05785 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05786 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05787 save_conference(p); 05788 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05789 } 05790 } 05791 break; 05792 } 05793 /* Remember last time we got a flash-hook */ 05794 gettimeofday(&p->flashtime, NULL); 05795 switch (mysig) { 05796 case SIG_FXOLS: 05797 case SIG_FXOGS: 05798 case SIG_FXOKS: 05799 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05800 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05801 05802 /* Cancel any running CallerID spill */ 05803 free(p->cidspill); 05804 p->cidspill = NULL; 05805 restore_conference(p); 05806 p->callwaitcas = 0; 05807 05808 if (index != SUB_REAL) { 05809 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05810 goto winkflashdone; 05811 } 05812 05813 if (p->subs[SUB_CALLWAIT].owner) { 05814 /* Need to hold the lock for real-call, private, and call-waiting call */ 05815 dahdi_lock_sub_owner(p, SUB_CALLWAIT); 05816 if (!p->subs[SUB_CALLWAIT].owner) { 05817 /* 05818 * The call waiting call dissappeared. 05819 * Let's just ignore this flash-hook. 05820 */ 05821 ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n"); 05822 goto winkflashdone; 05823 } 05824 05825 /* Swap to call-wait */ 05826 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05827 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05828 p->owner = p->subs[SUB_REAL].owner; 05829 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 05830 if (p->owner->_state == AST_STATE_RINGING) { 05831 ast_setstate(p->owner, AST_STATE_UP); 05832 p->subs[SUB_REAL].needanswer = 1; 05833 } 05834 p->callwaitingrepeat = 0; 05835 p->cidcwexpire = 0; 05836 p->cid_suppress_expire = 0; 05837 05838 /* Start music on hold if appropriate */ 05839 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05840 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05841 S_OR(p->mohsuggest, NULL), 05842 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05843 } 05844 p->subs[SUB_CALLWAIT].needhold = 1; 05845 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05846 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05847 S_OR(p->mohsuggest, NULL), 05848 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05849 } 05850 p->subs[SUB_REAL].needunhold = 1; 05851 05852 /* Unlock the call-waiting call that we swapped to real-call. */ 05853 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 05854 } else if (!p->subs[SUB_THREEWAY].owner) { 05855 if (!p->threewaycalling) { 05856 /* Just send a flash if no 3-way calling */ 05857 p->subs[SUB_REAL].needflash = 1; 05858 goto winkflashdone; 05859 } else if (!check_for_conference(p)) { 05860 char cid_num[256]; 05861 char cid_name[256]; 05862 05863 cid_num[0] = 0; 05864 cid_name[0] = 0; 05865 if (p->dahditrcallerid && p->owner) { 05866 if (p->owner->cid.cid_num) 05867 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05868 if (p->owner->cid.cid_name) 05869 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05870 } 05871 /* XXX This section needs much more error checking!!! XXX */ 05872 /* Start a 3-way call if feasible */ 05873 if (!((ast->pbx) || 05874 (ast->_state == AST_STATE_UP) || 05875 (ast->_state == AST_STATE_RING))) { 05876 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 05877 goto winkflashdone; 05878 } 05879 if (alloc_sub(p, SUB_THREEWAY)) { 05880 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05881 goto winkflashdone; 05882 } 05883 /* Make new channel */ 05884 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05885 if (!chan) { 05886 ast_log(LOG_WARNING, 05887 "Cannot allocate new call structure on channel %d\n", 05888 p->channel); 05889 unalloc_sub(p, SUB_THREEWAY); 05890 goto winkflashdone; 05891 } 05892 if (p->dahditrcallerid) { 05893 if (!p->origcid_num) 05894 p->origcid_num = ast_strdup(p->cid_num); 05895 if (!p->origcid_name) 05896 p->origcid_name = ast_strdup(p->cid_name); 05897 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05898 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05899 } 05900 /* Swap things around between the three-way and real call */ 05901 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05902 /* Disable echo canceller for better dialing */ 05903 dahdi_disable_ec(p); 05904 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05905 if (res) 05906 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05907 p->owner = chan; 05908 pthread_attr_init(&attr); 05909 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05910 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 05911 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05912 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05913 dahdi_enable_ec(p); 05914 ast_hangup(chan); 05915 } else { 05916 if (option_verbose > 2) 05917 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 05918 /* Start music on hold if appropriate */ 05919 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05920 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05921 S_OR(p->mohsuggest, NULL), 05922 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05923 } 05924 p->subs[SUB_THREEWAY].needhold = 1; 05925 } 05926 pthread_attr_destroy(&attr); 05927 } 05928 } else { 05929 /* Already have a 3 way call */ 05930 int orig_3way_sub; 05931 05932 /* Need to hold the lock for real-call, private, and 3-way call */ 05933 dahdi_lock_sub_owner(p, SUB_THREEWAY); 05934 if (!p->subs[SUB_THREEWAY].owner) { 05935 /* 05936 * The 3-way call dissappeared. 05937 * Let's just ignore this flash-hook. 05938 */ 05939 ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n"); 05940 goto winkflashdone; 05941 } 05942 orig_3way_sub = SUB_THREEWAY; 05943 05944 if (p->subs[SUB_THREEWAY].inthreeway) { 05945 /* Call is already up, drop the last person */ 05946 if (option_debug) 05947 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05948 /* If the primary call isn't answered yet, use it */ 05949 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05950 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05951 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05952 orig_3way_sub = SUB_REAL; 05953 p->owner = p->subs[SUB_REAL].owner; 05954 } 05955 /* Drop the last call and stop the conference */ 05956 if (option_verbose > 2) 05957 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05958 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05959 p->subs[SUB_REAL].inthreeway = 0; 05960 p->subs[SUB_THREEWAY].inthreeway = 0; 05961 } else { 05962 /* Lets see what we're up to */ 05963 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05964 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05965 if (option_verbose > 2) { 05966 ast_verbose(VERBOSE_PREFIX_3 "Building conference call with %s and %s\n", 05967 p->subs[SUB_THREEWAY].owner->name, 05968 p->subs[SUB_REAL].owner->name); 05969 } 05970 /* Put them in the threeway, and flip */ 05971 p->subs[SUB_THREEWAY].inthreeway = 1; 05972 p->subs[SUB_REAL].inthreeway = 1; 05973 if (ast->_state == AST_STATE_UP) { 05974 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05975 orig_3way_sub = SUB_REAL; 05976 } 05977 if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) { 05978 ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD); 05979 } 05980 p->subs[orig_3way_sub].needunhold = 1; 05981 p->owner = p->subs[SUB_REAL].owner; 05982 } else { 05983 if (option_verbose > 2) 05984 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05985 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05986 orig_3way_sub = SUB_REAL; 05987 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05988 p->owner = p->subs[SUB_REAL].owner; 05989 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05990 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05991 } 05992 p->subs[SUB_REAL].needunhold = 1; 05993 dahdi_enable_ec(p); 05994 } 05995 05996 } 05997 ast_mutex_unlock(&p->subs[orig_3way_sub].owner->lock); 05998 } 05999 winkflashdone: 06000 update_conf(p); 06001 break; 06002 case SIG_EM: 06003 case SIG_EM_E1: 06004 case SIG_FEATD: 06005 case SIG_SF: 06006 case SIG_SFWINK: 06007 case SIG_SF_FEATD: 06008 case SIG_FXSLS: 06009 case SIG_FXSGS: 06010 if (p->dialing) 06011 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 06012 else 06013 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 06014 break; 06015 case SIG_FEATDMF_TA: 06016 switch (p->whichwink) { 06017 case 0: 06018 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 06019 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 06020 break; 06021 case 1: 06022 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 06023 break; 06024 case 2: 06025 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 06026 return NULL; 06027 } 06028 p->whichwink++; 06029 /* Fall through */ 06030 case SIG_FEATDMF: 06031 case SIG_E911: 06032 case SIG_FGC_CAMAMF: 06033 case SIG_FGC_CAMA: 06034 case SIG_FEATB: 06035 case SIG_SF_FEATDMF: 06036 case SIG_SF_FEATB: 06037 case SIG_EMWINK: 06038 /* FGD MF and EMWINK *Must* wait for wink */ 06039 if (!ast_strlen_zero(p->dop.dialstr)) { 06040 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 06041 if (res < 0) { 06042 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 06043 p->dop.dialstr[0] = '\0'; 06044 return NULL; 06045 } else 06046 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 06047 } 06048 p->dop.dialstr[0] = '\0'; 06049 break; 06050 default: 06051 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 06052 } 06053 break; 06054 case DAHDI_EVENT_HOOKCOMPLETE: 06055 if (p->inalarm) break; 06056 if ((p->radio || (p->oprmode < 0))) break; 06057 switch (mysig) { 06058 case SIG_FXSLS: /* only interesting for FXS */ 06059 case SIG_FXSGS: 06060 case SIG_FXSKS: 06061 case SIG_EM: 06062 case SIG_EM_E1: 06063 case SIG_EMWINK: 06064 case SIG_FEATD: 06065 case SIG_SF: 06066 case SIG_SFWINK: 06067 case SIG_SF_FEATD: 06068 if (!ast_strlen_zero(p->dop.dialstr)) { 06069 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 06070 if (res < 0) { 06071 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 06072 p->dop.dialstr[0] = '\0'; 06073 return NULL; 06074 } else 06075 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 06076 } 06077 p->dop.dialstr[0] = '\0'; 06078 p->dop.op = DAHDI_DIAL_OP_REPLACE; 06079 break; 06080 case SIG_FEATDMF: 06081 case SIG_FEATDMF_TA: 06082 case SIG_E911: 06083 case SIG_FGC_CAMA: 06084 case SIG_FGC_CAMAMF: 06085 case SIG_FEATB: 06086 case SIG_SF_FEATDMF: 06087 case SIG_SF_FEATB: 06088 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 06089 break; 06090 default: 06091 break; 06092 } 06093 break; 06094 case DAHDI_EVENT_POLARITY: 06095 /* 06096 * If we get a Polarity Switch event, check to see 06097 * if we should change the polarity state and 06098 * mark the channel as UP or if this is an indication 06099 * of remote end disconnect. 06100 */ 06101 if (p->polarity == POLARITY_IDLE) { 06102 p->polarity = POLARITY_REV; 06103 if (p->answeronpolarityswitch && 06104 ((ast->_state == AST_STATE_DIALING) || 06105 (ast->_state == AST_STATE_RINGING))) { 06106 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 06107 ast_setstate(p->owner, AST_STATE_UP); 06108 if (p->hanguponpolarityswitch) { 06109 gettimeofday(&p->polaritydelaytv, NULL); 06110 } 06111 } else 06112 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 06113 } 06114 /* Removed else statement from here as it was preventing hangups from ever happening*/ 06115 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 06116 if (p->hanguponpolarityswitch && 06117 (p->polarityonanswerdelay > 0) && 06118 (p->polarity == POLARITY_REV) && 06119 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 06120 /* Added log_debug information below to provide a better indication of what is going on */ 06121 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 06122 06123 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 06124 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 06125 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 06126 p->polarity = POLARITY_IDLE; 06127 } else { 06128 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state); 06129 } 06130 } else { 06131 p->polarity = POLARITY_IDLE; 06132 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 06133 } 06134 /* Added more log_debug information below to provide a better indication of what is going on */ 06135 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 06136 break; 06137 default: 06138 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 06139 } 06140 return &p->subs[index].f; 06141 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3701 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::allocated, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_dsp_digitmode(), ast_dsp_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_verbose(), dahdi_pvt::bearer, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufferoverrideinuse, dahdi_pvt::bufsize, dahdi_pvt::call, dahdi_pvt::call_level, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_suppress_expire, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), DAHDI_CALL_LEVEL_IDLE, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index, dahdi_lock_sub_owner(), dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), 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, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, num_restart_pending, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, option_debug, option_verbose, 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::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.
03702 { 03703 int res; 03704 int index,x, law; 03705 /*static int restore_gains(struct dahdi_pvt *p);*/ 03706 struct dahdi_pvt *p = ast->tech_pvt; 03707 struct dahdi_pvt *tmp = NULL; 03708 struct dahdi_pvt *prev = NULL; 03709 struct dahdi_params par; 03710 03711 if (option_debug) 03712 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 03713 if (!ast->tech_pvt) { 03714 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03715 return 0; 03716 } 03717 03718 ast_mutex_lock(&p->lock); 03719 03720 index = dahdi_get_index(ast, p, 1); 03721 03722 if (p->sig == SIG_PRI) { 03723 x = 1; 03724 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03725 p->cid_num[0] = '\0'; 03726 p->cid_name[0] = '\0'; 03727 } 03728 03729 x = 0; 03730 dahdi_confmute(p, 0); 03731 restore_gains(p); 03732 if (p->origcid_num) { 03733 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03734 free(p->origcid_num); 03735 p->origcid_num = NULL; 03736 } 03737 if (p->origcid_name) { 03738 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03739 free(p->origcid_name); 03740 p->origcid_name = NULL; 03741 } 03742 if (p->dsp) 03743 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 03744 p->exten[0] = '\0'; 03745 03746 if (option_debug) 03747 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03748 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03749 p->ignoredtmf = 0; 03750 03751 if (index > -1) { 03752 /* Real channel, do some fixup */ 03753 p->subs[index].owner = NULL; 03754 p->subs[index].needanswer = 0; 03755 p->subs[index].needflash = 0; 03756 p->subs[index].needringing = 0; 03757 p->subs[index].needbusy = 0; 03758 p->subs[index].needcongestion = 0; 03759 p->subs[index].linear = 0; 03760 p->subs[index].needcallerid = 0; 03761 p->polarity = POLARITY_IDLE; 03762 dahdi_setlinear(p->subs[index].dfd, 0); 03763 switch (index) { 03764 case SUB_REAL: 03765 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03766 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03767 if (p->subs[SUB_CALLWAIT].inthreeway) { 03768 /* We had flipped over to answer a callwait and now it's gone */ 03769 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 03770 /* Move to the call-wait, but un-own us until they flip back. */ 03771 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03772 unalloc_sub(p, SUB_CALLWAIT); 03773 p->owner = NULL; 03774 } else { 03775 /* The three way hung up, but we still have a call wait */ 03776 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03777 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03778 unalloc_sub(p, SUB_THREEWAY); 03779 if (p->subs[SUB_REAL].inthreeway) { 03780 /* This was part of a three way call. Immediately make way for 03781 another call */ 03782 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03783 p->subs[SUB_REAL].inthreeway = 0; 03784 p->owner = p->subs[SUB_REAL].owner; 03785 } else { 03786 /* This call hasn't been completed yet... Set owner to NULL */ 03787 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03788 p->owner = NULL; 03789 } 03790 } 03791 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03792 /* Need to hold the lock for real-call, private, and call-waiting call */ 03793 dahdi_lock_sub_owner(p, SUB_CALLWAIT); 03794 if (!p->subs[SUB_CALLWAIT].owner) { 03795 /* The call waiting call dissappeared. */ 03796 p->owner = NULL; 03797 break; 03798 } 03799 03800 /* Move to the call-wait and switch back to them. */ 03801 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03802 unalloc_sub(p, SUB_CALLWAIT); 03803 p->owner = p->subs[SUB_REAL].owner; 03804 if (p->owner->_state != AST_STATE_UP) 03805 p->subs[SUB_REAL].needanswer = 1; 03806 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03807 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03808 /* Unlock the call-waiting call that we swapped to real-call. */ 03809 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 03810 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03811 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03812 unalloc_sub(p, SUB_THREEWAY); 03813 if (p->subs[SUB_REAL].inthreeway) { 03814 /* This was part of a three way call. Immediately make way for 03815 another call */ 03816 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03817 p->subs[SUB_REAL].inthreeway = 0; 03818 p->owner = p->subs[SUB_REAL].owner; 03819 } else { 03820 /* This call hasn't been completed yet... Set owner to NULL */ 03821 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03822 p->owner = NULL; 03823 } 03824 } 03825 break; 03826 case SUB_CALLWAIT: 03827 /* Ditch the holding callwait call, and immediately make it availabe */ 03828 if (p->subs[SUB_CALLWAIT].inthreeway) { 03829 /* Need to hold the lock for call-waiting call, private, and 3-way call */ 03830 dahdi_lock_sub_owner(p, SUB_THREEWAY); 03831 03832 /* This is actually part of a three way, placed on hold. Place the third part 03833 on music on hold now */ 03834 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03835 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03836 S_OR(p->mohsuggest, NULL), 03837 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03838 } 03839 p->subs[SUB_THREEWAY].inthreeway = 0; 03840 /* Make it the call wait now */ 03841 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03842 unalloc_sub(p, SUB_THREEWAY); 03843 if (p->subs[SUB_CALLWAIT].owner) { 03844 /* Unlock the 3-way call that we swapped to call-waiting call. */ 03845 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock); 03846 } 03847 } else 03848 unalloc_sub(p, SUB_CALLWAIT); 03849 break; 03850 case SUB_THREEWAY: 03851 /* Need to hold the lock for 3-way call, private, and call-waiting call */ 03852 dahdi_lock_sub_owner(p, SUB_CALLWAIT); 03853 if (p->subs[SUB_CALLWAIT].inthreeway) { 03854 /* The other party of the three way call is currently in a call-wait state. 03855 Start music on hold for them, and take the main guy out of the third call */ 03856 p->subs[SUB_CALLWAIT].inthreeway = 0; 03857 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03858 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03859 S_OR(p->mohsuggest, NULL), 03860 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03861 } 03862 } 03863 if (p->subs[SUB_CALLWAIT].owner) { 03864 ast_mutex_unlock(&p->subs[SUB_CALLWAIT].owner->lock); 03865 } 03866 p->subs[SUB_REAL].inthreeway = 0; 03867 /* If this was part of a three way call index, let us make 03868 another three way call */ 03869 unalloc_sub(p, SUB_THREEWAY); 03870 break; 03871 default: 03872 /* 03873 * Should never happen. 03874 * This wasn't any sort of call, so how are we an index? 03875 */ 03876 ast_log(LOG_ERROR, "Index found but not any type of call?\n"); 03877 break; 03878 } 03879 } 03880 03881 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03882 p->ringt = 0; 03883 p->distinctivering = 0; 03884 p->confirmanswer = 0; 03885 p->cidrings = 1; 03886 p->outgoing = 0; 03887 p->digital = 0; 03888 p->faxhandled = 0; 03889 p->pulsedial = 0; 03890 p->onhooktime = time(NULL); 03891 #ifdef HAVE_PRI 03892 p->dialing = 0; 03893 p->progress = 0; 03894 p->call_level = DAHDI_CALL_LEVEL_IDLE; 03895 #endif 03896 if (p->dsp) { 03897 ast_dsp_free(p->dsp); 03898 p->dsp = NULL; 03899 } 03900 03901 if (p->bufferoverrideinuse) { 03902 /* faxbuffers are in use, revert them */ 03903 struct dahdi_bufferinfo bi = { 03904 .txbufpolicy = p->buf_policy, 03905 .rxbufpolicy = p->buf_policy, 03906 .bufsize = p->bufsize, 03907 .numbufs = p->buf_no 03908 }; 03909 int bpres; 03910 03911 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 03912 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno)); 03913 } 03914 p->bufferoverrideinuse = 0; 03915 } 03916 03917 law = DAHDI_LAW_DEFAULT; 03918 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03919 if (res < 0) 03920 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03921 /* Perform low level hangup if no owner left */ 03922 03923 #ifdef HAVE_OPENR2 03924 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 03925 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 03926 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause); 03927 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 03928 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 03929 } else { 03930 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE"); 03931 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 03932 openr2_call_disconnect_cause_t r2cause = r2cause_user 03933 ? dahdi_ast_cause_to_r2_cause(r2cause_user) 03934 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 03935 dahdi_r2_disconnect_call(p, r2cause); 03936 } 03937 } else if (p->mfcr2call) { 03938 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 03939 p->mfcr2call = 0; 03940 } 03941 #endif 03942 03943 #if defined(HAVE_PRI) 03944 if (p->pri) { 03945 #ifdef SUPPORT_USERUSER 03946 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03947 #endif 03948 03949 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03950 pri_grab(p, p->pri); 03951 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03952 if (p->alreadyhungup) { 03953 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03954 03955 #ifdef SUPPORT_USERUSER 03956 pri_call_set_useruser(p->call, useruser); 03957 #endif 03958 03959 pri_hangup(p->pri->pri, p->call, -1); 03960 p->call = NULL; 03961 if (p->bearer) 03962 p->bearer->call = NULL; 03963 } else { 03964 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03965 int icause = ast->hangupcause ? ast->hangupcause : -1; 03966 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03967 03968 #ifdef SUPPORT_USERUSER 03969 pri_call_set_useruser(p->call, useruser); 03970 #endif 03971 03972 p->alreadyhungup = 1; 03973 if (p->bearer) 03974 p->bearer->alreadyhungup = 1; 03975 if (cause) { 03976 if (atoi(cause)) 03977 icause = atoi(cause); 03978 } 03979 pri_hangup(p->pri->pri, p->call, icause); 03980 } 03981 } else { 03982 if (p->bearer) 03983 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03984 p->call = NULL; 03985 } 03986 p->allocated = 0; 03987 p->owner = NULL; 03988 pri_rel(p->pri); 03989 res = 0; 03990 } else 03991 #endif /* defined(HAVE_PRI) */ 03992 { 03993 p->owner = NULL; 03994 } 03995 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2)) 03996 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03997 if (res < 0) { 03998 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03999 } 04000 switch (p->sig) { 04001 case SIG_FXOGS: 04002 case SIG_FXOLS: 04003 case SIG_FXOKS: 04004 memset(&par, 0, sizeof(par)); 04005 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 04006 if (!res) { 04007 #if 0 04008 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 04009 #endif 04010 /* If they're off hook, try playing congestion */ 04011 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 04012 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 04013 else 04014 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04015 } 04016 break; 04017 case SIG_FXSGS: 04018 case SIG_FXSLS: 04019 case SIG_FXSKS: 04020 /* Make sure we're not made available for at least two seconds assuming 04021 we were actually used for an inbound or outbound call. */ 04022 if (ast->_state != AST_STATE_RESERVED) { 04023 time(&p->guardtime); 04024 p->guardtime += 2; 04025 } 04026 break; 04027 default: 04028 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04029 } 04030 free(p->cidspill); 04031 p->cidspill = NULL; 04032 if (p->sig) 04033 dahdi_disable_ec(p); 04034 x = 0; 04035 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 04036 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 04037 p->didtdd = 0; 04038 p->callwaitcas = 0; 04039 p->callwaiting = p->permcallwaiting; 04040 p->hidecallerid = p->permhidecallerid; 04041 p->dialing = 0; 04042 p->rdnis[0] = '\0'; 04043 update_conf(p); 04044 reset_conf(p); 04045 /* Restore data mode */ 04046 if (p->sig == SIG_PRI) { 04047 x = 0; 04048 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 04049 } 04050 #ifdef HAVE_PRI 04051 if (p->bearer) { 04052 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 04053 /* Free up the bearer channel as well, and 04054 don't use its file descriptor anymore */ 04055 update_conf(p->bearer); 04056 reset_conf(p->bearer); 04057 p->bearer->owner = NULL; 04058 p->bearer->realcall = NULL; 04059 p->bearer = NULL; 04060 p->subs[SUB_REAL].dfd = -1; 04061 p->pri = NULL; 04062 } 04063 #endif 04064 if (num_restart_pending == 0) 04065 restart_monitor(); 04066 } 04067 04068 p->callwaitingrepeat = 0; 04069 p->cidcwexpire = 0; 04070 p->cid_suppress_expire = 0; 04071 p->oprmode = 0; 04072 ast->tech_pvt = NULL; 04073 ast_mutex_unlock(&p->lock); 04074 if (option_verbose > 2) 04075 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 04076 04077 ast_mutex_lock(&iflock); 04078 if (p->restartpending) { 04079 num_restart_pending--; 04080 } 04081 04082 tmp = iflist; 04083 prev = NULL; 04084 if (p->destroy) { 04085 while (tmp) { 04086 if (tmp == p) { 04087 destroy_channel(prev, tmp, 0); 04088 break; 04089 } else { 04090 prev = tmp; 04091 tmp = tmp->next; 04092 } 04093 } 04094 } 04095 ast_mutex_unlock(&iflock); 04096 04097 ast_module_unref(ast_module_info->self); 04098 return 0; 04099 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6762 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_SWITCH_CONGESTION, 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_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::call_level, DAHDI_CALL_LEVEL_ALERTING, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_get_index, dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mohinterpret, ast_channel::name, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
06763 { 06764 struct dahdi_pvt *p = chan->tech_pvt; 06765 int res=-1; 06766 int index; 06767 int func = DAHDI_FLASH; 06768 ast_mutex_lock(&p->lock); 06769 index = dahdi_get_index(chan, p, 0); 06770 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 06771 #ifdef HAVE_OPENR2 06772 if (p->mfcr2 && !p->mfcr2_call_accepted) { 06773 ast_mutex_unlock(&p->lock); 06774 /* if this an R2 call and the call is not yet accepted we don't want the 06775 tone indications to mess up with the MF tones */ 06776 return 0; 06777 } 06778 #endif 06779 if (index == SUB_REAL) { 06780 switch (condition) { 06781 case AST_CONTROL_BUSY: 06782 #ifdef HAVE_PRI 06783 if (p->sig == SIG_PRI) { 06784 if (p->priindication_oob) { 06785 chan->hangupcause = AST_CAUSE_USER_BUSY; 06786 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06787 res = 0; 06788 break; 06789 } 06790 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06791 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) { 06792 chan->hangupcause = AST_CAUSE_USER_BUSY; 06793 p->progress = 1;/* No need to send plain PROGRESS after this. */ 06794 if (p->pri && p->pri->pri) { 06795 if (!pri_grab(p, p->pri)) { 06796 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06797 pri_rel(p->pri); 06798 } else { 06799 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06800 } 06801 } 06802 } 06803 break; 06804 } 06805 #endif 06806 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06807 break; 06808 case AST_CONTROL_RINGING: 06809 #ifdef HAVE_PRI 06810 if (p->sig == SIG_PRI 06811 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) { 06812 p->call_level = DAHDI_CALL_LEVEL_ALERTING; 06813 if (p->pri && p->pri->pri) { 06814 if (!pri_grab(p, p->pri)) { 06815 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06816 pri_rel(p->pri); 06817 } else { 06818 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06819 } 06820 } 06821 } 06822 #endif 06823 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06824 if (chan->_state != AST_STATE_UP) { 06825 if ((chan->_state != AST_STATE_RING) || 06826 ((p->sig != SIG_FXSKS) && 06827 (p->sig != SIG_FXSLS) && 06828 (p->sig != SIG_FXSGS))) 06829 ast_setstate(chan, AST_STATE_RINGING); 06830 } 06831 break; 06832 case AST_CONTROL_PROCEEDING: 06833 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06834 #ifdef HAVE_PRI 06835 if (p->sig == SIG_PRI 06836 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) { 06837 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING; 06838 if (p->pri && p->pri->pri) { 06839 if (!pri_grab(p, p->pri)) { 06840 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06841 pri_rel(p->pri); 06842 } else { 06843 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06844 } 06845 } 06846 p->dialing = 0; 06847 } 06848 #endif 06849 /* don't continue in ast_indicate */ 06850 res = 0; 06851 break; 06852 case AST_CONTROL_PROGRESS: 06853 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06854 #ifdef HAVE_PRI 06855 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06856 if (p->sig == SIG_PRI 06857 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING 06858 && !p->outgoing) { 06859 p->progress = 1;/* No need to send plain PROGRESS again. */ 06860 if (p->pri && p->pri->pri) { 06861 if (!pri_grab(p, p->pri)) { 06862 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06863 pri_rel(p->pri); 06864 } else { 06865 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06866 } 06867 } 06868 } 06869 #endif 06870 /* don't continue in ast_indicate */ 06871 res = 0; 06872 break; 06873 case AST_CONTROL_CONGESTION: 06874 #ifdef HAVE_PRI 06875 if (p->sig == SIG_PRI) { 06876 if (p->priindication_oob) { 06877 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 06878 switch (chan->hangupcause) { 06879 case AST_CAUSE_USER_BUSY: 06880 case AST_CAUSE_NORMAL_CLEARING: 06881 case 0:/* Cause has not been set. */ 06882 /* Supply a more appropriate cause. */ 06883 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06884 break; 06885 default: 06886 break; 06887 } 06888 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06889 res = 0; 06890 break; 06891 } 06892 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06893 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) { 06894 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 06895 switch (chan->hangupcause) { 06896 case AST_CAUSE_USER_BUSY: 06897 case AST_CAUSE_NORMAL_CLEARING: 06898 case 0:/* Cause has not been set. */ 06899 /* Supply a more appropriate cause. */ 06900 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06901 break; 06902 default: 06903 break; 06904 } 06905 p->progress = 1;/* No need to send plain PROGRESS after this. */ 06906 if (p->pri && p->pri->pri) { 06907 if (!pri_grab(p, p->pri)) { 06908 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06909 pri_rel(p->pri); 06910 } else { 06911 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06912 } 06913 } 06914 } 06915 break; 06916 } 06917 #endif 06918 /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ 06919 switch (chan->hangupcause) { 06920 case AST_CAUSE_USER_BUSY: 06921 case AST_CAUSE_NORMAL_CLEARING: 06922 case 0:/* Cause has not been set. */ 06923 /* Supply a more appropriate cause. */ 06924 chan->hangupcause = AST_CAUSE_CONGESTION; 06925 break; 06926 default: 06927 break; 06928 } 06929 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06930 break; 06931 case AST_CONTROL_HOLD: 06932 #ifdef HAVE_PRI 06933 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06934 if (!pri_grab(p, p->pri)) { 06935 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06936 pri_rel(p->pri); 06937 } else 06938 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06939 } else 06940 #endif 06941 ast_moh_start(chan, data, p->mohinterpret); 06942 break; 06943 case AST_CONTROL_UNHOLD: 06944 #ifdef HAVE_PRI 06945 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06946 if (!pri_grab(p, p->pri)) { 06947 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06948 pri_rel(p->pri); 06949 } else 06950 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06951 } else 06952 #endif 06953 ast_moh_stop(chan); 06954 break; 06955 case AST_CONTROL_RADIO_KEY: 06956 if (p->radio) 06957 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06958 res = 0; 06959 break; 06960 case AST_CONTROL_RADIO_UNKEY: 06961 if (p->radio) 06962 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06963 res = 0; 06964 break; 06965 case AST_CONTROL_FLASH: 06966 /* flash hookswitch */ 06967 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06968 /* Clear out the dial buffer */ 06969 p->dop.dialstr[0] = '\0'; 06970 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06971 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06972 chan->name, strerror(errno)); 06973 } else 06974 res = 0; 06975 } else 06976 res = 0; 06977 break; 06978 case AST_CONTROL_SRCUPDATE: 06979 res = 0; 06980 break; 06981 case -1: 06982 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06983 break; 06984 } 06985 } else 06986 res = 0; 06987 ast_mutex_unlock(&p->lock); 06988 return res; 06989 }
Definition at line 4535 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04535 { 04536 int x; 04537 if (!slave || !master) { 04538 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04539 return; 04540 } 04541 for (x = 0; x < MAX_SLAVES; x++) { 04542 if (!master->slaves[x]) { 04543 master->slaves[x] = slave; 04544 break; 04545 } 04546 } 04547 if (x >= MAX_SLAVES) { 04548 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04549 master->slaves[MAX_SLAVES - 1] = slave; 04550 } 04551 if (slave->master) 04552 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04553 slave->master = master; 04554 04555 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04556 }
static void dahdi_lock_sub_owner | ( | struct dahdi_pvt * | pvt, | |
int | sub_idx | |||
) | [static] |
Definition at line 1279 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_channel::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_hangup(), and wakeup_sub().
01280 { 01281 for (;;) { 01282 if (!pvt->subs[sub_idx].owner) { 01283 /* No subchannel owner pointer */ 01284 break; 01285 } 01286 if (!ast_mutex_trylock(&pvt->subs[sub_idx].owner->lock)) { 01287 /* Got subchannel owner lock */ 01288 break; 01289 } 01290 /* We must unlock the private to avoid the possibility of a deadlock */ 01291 DEADLOCK_AVOIDANCE(&pvt->lock); 01292 } 01293 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | index, | |||
int | law, | |||
int | transfercapability | |||
) | [static] |
Definition at line 6991 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), ast_dsp_digitmode(), 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_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, dahdi_pvt::mfcr2_recvd_category, dahdi_pvt::mfcr2call, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, PRI_TRANS_CAP_DIGITAL, progzone, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, subnames, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_offered(), dahdi_request(), handle_init_event(), and register_translator().
06992 { 06993 struct ast_channel *tmp; 06994 int deflaw; 06995 int res; 06996 int x,y; 06997 int features; 06998 char *b2 = NULL; 06999 struct dahdi_params ps; 07000 char chanprefix[*dahdi_chan_name_len + 4]; 07001 07002 if (i->subs[index].owner) { 07003 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 07004 return NULL; 07005 } 07006 y = 1; 07007 do { 07008 if (b2) 07009 free(b2); 07010 #ifdef HAVE_PRI 07011 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 07012 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 07013 else 07014 #endif 07015 if (i->channel == CHAN_PSEUDO) 07016 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 07017 else 07018 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 07019 for (x = 0; x < 3; x++) { 07020 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 07021 break; 07022 } 07023 y++; 07024 } while (x < 3); 07025 strcpy(chanprefix, dahdi_chan_name); 07026 strcat(chanprefix, "/%s"); 07027 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 07028 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 07029 free(b2); 07030 if (!tmp) 07031 return NULL; 07032 tmp->tech = chan_tech; 07033 memset(&ps, 0, sizeof(ps)); 07034 ps.channo = i->channel; 07035 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 07036 if (res) { 07037 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 07038 ps.curlaw = DAHDI_LAW_MULAW; 07039 } 07040 if (ps.curlaw == DAHDI_LAW_ALAW) 07041 deflaw = AST_FORMAT_ALAW; 07042 else 07043 deflaw = AST_FORMAT_ULAW; 07044 if (law) { 07045 if (law == DAHDI_LAW_ALAW) 07046 deflaw = AST_FORMAT_ALAW; 07047 else 07048 deflaw = AST_FORMAT_ULAW; 07049 } 07050 tmp->fds[0] = i->subs[index].dfd; 07051 tmp->nativeformats = deflaw; 07052 /* Start out assuming ulaw since it's smaller :) */ 07053 tmp->rawreadformat = deflaw; 07054 tmp->readformat = deflaw; 07055 tmp->rawwriteformat = deflaw; 07056 tmp->writeformat = deflaw; 07057 i->subs[index].linear = 0; 07058 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 07059 features = 0; 07060 if (index == SUB_REAL) { 07061 if (i->busydetect && CANBUSYDETECT(i)) 07062 features |= DSP_FEATURE_BUSY_DETECT; 07063 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 07064 features |= DSP_FEATURE_CALL_PROGRESS; 07065 if ((!i->outgoing && (i->callprogress & 4)) || 07066 (i->outgoing && (i->callprogress & 2))) { 07067 features |= DSP_FEATURE_FAX_DETECT; 07068 } 07069 #ifdef DAHDI_TONEDETECT 07070 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 07071 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 07072 #endif 07073 i->hardwaredtmf = 0; 07074 features |= DSP_FEATURE_DTMF_DETECT; 07075 #ifdef DAHDI_TONEDETECT 07076 } else if (NEED_MFDETECT(i)) { 07077 i->hardwaredtmf = 1; 07078 features |= DSP_FEATURE_DTMF_DETECT; 07079 } 07080 #endif 07081 } 07082 if (features) { 07083 if (i->dsp) { 07084 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 07085 } else { 07086 if (i->channel != CHAN_PSEUDO) 07087 i->dsp = ast_dsp_new(); 07088 else 07089 i->dsp = NULL; 07090 if (i->dsp) { 07091 i->dsp_features = features; 07092 #ifdef HAVE_PRI 07093 /* We cannot do progress detection until receives PROGRESS message */ 07094 if (i->outgoing && (i->sig == SIG_PRI)) { 07095 /* Remember requested DSP features, don't treat 07096 talking as ANSWER */ 07097 i->dsp_features = features & ~DSP_PROGRESS_TALK; 07098 features = 0; 07099 } 07100 #endif 07101 ast_dsp_set_features(i->dsp, features); 07102 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 07103 if (!ast_strlen_zero(progzone)) 07104 ast_dsp_set_call_progress_zone(i->dsp, progzone); 07105 if (i->busydetect && CANBUSYDETECT(i)) { 07106 if(i->silencethreshold > 0) 07107 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 07108 ast_dsp_set_busy_count(i->dsp, i->busycount); 07109 if(i->busytonelength > 0) 07110 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 07111 if((i->busytonelength == i->busyquietlength) && i->busycompare) 07112 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 07113 } 07114 } 07115 } 07116 } 07117 07118 if (state == AST_STATE_RING) 07119 tmp->rings = 1; 07120 tmp->tech_pvt = i; 07121 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 07122 /* Only FXO signalled stuff can be picked up */ 07123 tmp->callgroup = i->callgroup; 07124 tmp->pickupgroup = i->pickupgroup; 07125 } 07126 if (!ast_strlen_zero(i->language)) 07127 ast_string_field_set(tmp, language, i->language); 07128 if (!i->owner) 07129 i->owner = tmp; 07130 if (!ast_strlen_zero(i->accountcode)) 07131 ast_string_field_set(tmp, accountcode, i->accountcode); 07132 if (i->amaflags) 07133 tmp->amaflags = i->amaflags; 07134 i->subs[index].owner = tmp; 07135 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 07136 ast_string_field_set(tmp, call_forward, i->call_forward); 07137 /* If we've been told "no ADSI" then enforce it */ 07138 if (!i->adsi) 07139 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 07140 if (!ast_strlen_zero(i->exten)) 07141 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 07142 if (!ast_strlen_zero(i->rdnis)) 07143 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 07144 if (!ast_strlen_zero(i->dnid)) 07145 tmp->cid.cid_dnid = ast_strdup(i->dnid); 07146 07147 /* Don't use ast_set_callerid() here because it will 07148 * generate a needless NewCallerID event */ 07149 #ifdef PRI_ANI 07150 if (!ast_strlen_zero(i->cid_ani)) 07151 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 07152 else 07153 tmp->cid.cid_ani = ast_strdup(i->cid_num); 07154 #else 07155 tmp->cid.cid_ani = ast_strdup(i->cid_num); 07156 #endif 07157 tmp->cid.cid_pres = i->callingpres; 07158 tmp->cid.cid_ton = i->cid_ton; 07159 #ifdef HAVE_PRI 07160 tmp->transfercapability = transfercapability; 07161 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 07162 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 07163 i->digital = 1; 07164 /* Assume calls are not idle calls unless we're told differently */ 07165 i->isidlecall = 0; 07166 i->alreadyhungup = 0; 07167 #endif 07168 /* clear the fake event in case we posted one before we had ast_channel */ 07169 i->fake_event = 0; 07170 /* Assure there is no confmute on this channel */ 07171 dahdi_confmute(i, 0); 07172 /* Configure the new channel jb */ 07173 ast_jb_configure(tmp, &global_jbconf); 07174 if (startpbx) { 07175 07176 #ifdef HAVE_OPENR2 07177 if (i->mfcr2call) { 07178 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 07179 } 07180 #endif 07181 07182 if (ast_pbx_start(tmp)) { 07183 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 07184 ast_hangup(tmp); 07185 i->owner = NULL; 07186 return NULL; 07187 } 07188 } 07189 07190 ast_module_ref(ast_module_info->self); 07191 07192 return tmp; 07193 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1877 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01878 { 01879 int fd; 01880 int isnum; 01881 int chan = 0; 01882 int bs; 01883 int x; 01884 isnum = 1; 01885 for (x = 0; x < strlen(fn); x++) { 01886 if (!isdigit(fn[x])) { 01887 isnum = 0; 01888 break; 01889 } 01890 } 01891 if (isnum) { 01892 chan = atoi(fn); 01893 if (chan < 1) { 01894 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01895 return -1; 01896 } 01897 fn = DAHDI_FILE_CHANNEL; 01898 } 01899 fd = open(fn, O_RDWR | O_NONBLOCK); 01900 if (fd < 0) { 01901 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01902 return -1; 01903 } 01904 if (chan) { 01905 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01906 x = errno; 01907 close(fd); 01908 errno = x; 01909 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01910 return -1; 01911 } 01912 } 01913 bs = READ_SIZE; 01914 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01915 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01916 x = errno; 01917 close(fd); 01918 errno = x; 01919 return -1; 01920 } 01921 return fd; 01922 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10864 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfd, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10865 { 10866 int x, y; 10867 int dchan = -1, span = -1; 10868 int dchancount = 0; 10869 10870 if (pri) { 10871 for (x = 0; x < NUM_SPANS; x++) { 10872 for (y = 0; y < NUM_DCHANS; y++) { 10873 if (pris[x].dchans[y]) 10874 dchancount++; 10875 10876 if (pris[x].dchans[y] == pri) 10877 dchan = y; 10878 } 10879 if (dchan >= 0) { 10880 span = x; 10881 break; 10882 } 10883 dchancount = 0; 10884 } 10885 if ((dchan >= 0) && (span >= 0)) { 10886 if (dchancount > 1) 10887 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10888 else 10889 ast_log(LOG_ERROR, "%s", s); 10890 } else 10891 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 10892 } else 10893 ast_log(LOG_ERROR, "%s", s); 10894 10895 ast_mutex_lock(&pridebugfdlock); 10896 10897 if (pridebugfd >= 0) { 10898 if (write(pridebugfd, s, strlen(s)) < 0) { 10899 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10900 } 10901 } 10902 10903 ast_mutex_unlock(&pridebugfdlock); 10904 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 10822 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfd, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
10823 { 10824 int x, y; 10825 int dchan = -1, span = -1; 10826 int dchancount = 0; 10827 10828 if (pri) { 10829 for (x = 0; x < NUM_SPANS; x++) { 10830 for (y = 0; y < NUM_DCHANS; y++) { 10831 if (pris[x].dchans[y]) 10832 dchancount++; 10833 10834 if (pris[x].dchans[y] == pri) 10835 dchan = y; 10836 } 10837 if (dchan >= 0) { 10838 span = x; 10839 break; 10840 } 10841 dchancount = 0; 10842 } 10843 if ((dchan >= 0) && (span >= 0)) { 10844 if (dchancount > 1) 10845 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10846 else 10847 ast_verbose("%s", s); 10848 } else 10849 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 10850 } else 10851 ast_verbose("%s", s); 10852 10853 ast_mutex_lock(&pridebugfdlock); 10854 10855 if (pridebugfd >= 0) { 10856 if (write(pridebugfd, s, strlen(s)) < 0) { 10857 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10858 } 10859 } 10860 10861 ast_mutex_unlock(&pridebugfdlock); 10862 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 1313 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
01317 { 01318 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01319 #ifdef HAVE_PRI 01320 if (pri) 01321 ast_mutex_unlock(&pri->lock); 01322 #endif 01323 for (;;) { 01324 if (p->owner) { 01325 if (ast_mutex_trylock(&p->owner->lock)) { 01326 DEADLOCK_AVOIDANCE(&p->lock); 01327 } else { 01328 ast_queue_frame(p->owner, f); 01329 ast_mutex_unlock(&p->owner->lock); 01330 break; 01331 } 01332 } else 01333 break; 01334 } 01335 #ifdef HAVE_PRI 01336 if (pri) 01337 ast_mutex_lock(&pri->lock); 01338 #endif 01339 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 1830 of file chan_dahdi.c.
References AST_ALAW.
01831 { 01832 return AST_ALAW(sample); 01833 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1375 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().
01376 { 01377 int res = 0; 01378 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 01379 * and does not has support for openr2_chan_answer_call_with_mode 01380 * */ 01381 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01382 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 01383 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 01384 if (!double_answer) { 01385 /* this still can result in double answer if the channel context 01386 * was configured that way */ 01387 res = openr2_chan_answer_call(p->r2chan); 01388 } else if (wants_double_answer) { 01389 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 01390 } else { 01391 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 01392 } 01393 #else 01394 res = openr2_chan_answer_call(p->r2chan); 01395 #endif 01396 return res; 01397 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1488 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().
01489 { 01490 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 01491 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 01492 p->channel, openr2_proto_get_disconnect_string(cause)); 01493 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 01494 openr2_chan_set_idle(p->r2chan); 01495 ast_mutex_lock(&p->lock); 01496 p->mfcr2call = 0; 01497 ast_mutex_unlock(&p->lock); 01498 } 01499 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 1399 of file chan_dahdi.c.
References ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_category, ast_channel::name, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.
Referenced by dahdi_call().
01400 { 01401 openr2_calling_party_category_t cat; 01402 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 01403 struct dahdi_pvt *p = c->tech_pvt; 01404 if (ast_strlen_zero(catstr)) { 01405 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 01406 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01407 return p->mfcr2_category; 01408 } 01409 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 01410 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 01411 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01412 return p->mfcr2_category; 01413 } 01414 ast_log(LOG_DEBUG, "Using category %s\n", catstr); 01415 return cat; 01416 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 1835 of file chan_dahdi.c.
References AST_LIN2A.
01836 { 01837 return AST_LIN2A(sample); 01838 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1794 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
01795 { 01796 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01797 p->cid_num[p->mfcr2_ani_index] = digit; 01798 p->cid_name[p->mfcr2_ani_index] = digit; 01799 p->mfcr2_ani_index++; 01800 p->cid_num[p->mfcr2_ani_index] = 0; 01801 p->cid_name[p->mfcr2_ani_index] = 0; 01802 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1804 of file chan_dahdi.c.
References ast_log(), and LOG_NOTICE.
01805 { 01806 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 01807 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 1562 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_ERROR, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
01563 { 01564 struct dahdi_pvt *p = NULL; 01565 struct ast_channel *c = NULL; 01566 p = openr2_chan_get_client_data(r2chan); 01567 dahdi_enable_ec(p); 01568 p->mfcr2_call_accepted = 1; 01569 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 01570 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 01571 /* if accept on offer is not set, it means at this point the PBX thread is already 01572 launched and therefore this callback is being executed in the PBX thread rather than 01573 the monitor thread, don't launch any other thread, just disable the R2 reading and 01574 answer the call */ 01575 if (!p->mfcr2_accept_on_offer) { 01576 openr2_chan_disable_read(r2chan); 01577 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 01578 dahdi_r2_answer(p); 01579 return; 01580 } 01581 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01582 if (c) { 01583 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01584 openr2_chan_disable_read(r2chan); 01585 } else { 01586 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01587 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01588 return; 01589 } 01590 } else { 01591 ast_verbose("Call accepted on forward channel %d\n", p->channel); 01592 p->subs[SUB_REAL].needringing = 1; 01593 p->dialing = 0; 01594 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01595 openr2_chan_disable_read(r2chan); 01596 } 01597 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1599 of file chan_dahdi.c.
References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
01600 { 01601 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01602 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan)); 01603 p->subs[SUB_REAL].needanswer = 1; 01604 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1632 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_BUSY, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose(), dahdi_r2_disconnect_call(), ast_channel::hangupcause, dahdi_pvt::lock, LOG_WARNING, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.
01633 { 01634 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01635 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan)); 01636 ast_mutex_lock(&p->lock); 01637 if (p->owner) { 01638 /* when we have an owner we don't call openr2_chan_disconnect_call here, that will 01639 be done in zt_hangup */ 01640 if (p->owner->_state == AST_STATE_UP) { 01641 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01642 ast_mutex_unlock(&p->lock); 01643 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 01644 /* being the forward side we must report what happened to the call to whoever requested it */ 01645 switch (cause) { 01646 case OR2_CAUSE_BUSY_NUMBER: 01647 p->owner->hangupcause = AST_CAUSE_BUSY; 01648 p->subs[SUB_REAL].needbusy = 1; 01649 break; 01650 case OR2_CAUSE_NUMBER_CHANGED: 01651 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED; 01652 p->subs[SUB_REAL].needcongestion = 1; 01653 break; 01654 case OR2_CAUSE_NETWORK_CONGESTION: 01655 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER; 01656 p->subs[SUB_REAL].needcongestion = 1; 01657 break; 01658 case OR2_CAUSE_OUT_OF_ORDER: 01659 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01660 p->subs[SUB_REAL].needcongestion = 1; 01661 break; 01662 case OR2_CAUSE_UNALLOCATED_NUMBER: 01663 p->owner->hangupcause = AST_CAUSE_UNALLOCATED; 01664 p->subs[SUB_REAL].needcongestion = 1; 01665 break; 01666 case OR2_CAUSE_NO_ANSWER: 01667 p->owner->hangupcause = AST_CAUSE_NO_ANSWER; 01668 p->subs[SUB_REAL].needcongestion = 1; 01669 break; 01670 case OR2_CAUSE_UNSPECIFIED: 01671 p->owner->hangupcause = AST_CAUSE_NOTDEFINED; 01672 p->subs[SUB_REAL].needcongestion = 1; 01673 break; 01674 case OR2_CAUSE_NORMAL_CLEARING: 01675 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01676 p->subs[SUB_REAL].needcongestion = 1; 01677 break; 01678 default: 01679 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause); 01680 } 01681 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01682 ast_mutex_unlock(&p->lock); 01683 } else { 01684 ast_mutex_unlock(&p->lock); 01685 /* being the backward side and not UP yet, we only need to request hangup */ 01686 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 01687 ast_queue_hangup(p->owner); 01688 } 01689 } else { 01690 ast_mutex_unlock(&p->lock); 01691 /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */ 01692 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 01693 } 01694 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1552 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
01553 { 01554 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01555 ast_verbose("MFC/R2 call end on chan %d\n", p->channel); 01556 ast_mutex_lock(&p->lock); 01557 p->mfcr2call = 0; 01558 ast_mutex_unlock(&p->lock); 01559 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1418 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::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.
01419 { 01420 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01421 ast_mutex_lock(&p->lock); 01422 if (p->mfcr2call) { 01423 ast_mutex_unlock(&p->lock); 01424 /* TODO: This can happen when some other thread just finished zt_request requesting this very same 01425 interface but has not yet seized the line (zt_call), and the far end wins and seize the line, 01426 can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since 01427 the other end will see our seize as a forced release and drop the call, we will see an invalid 01428 pattern that will be seen and treated as protocol error. */ 01429 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 01430 return; 01431 } 01432 p->mfcr2call = 1; 01433 /* better safe than sorry ... */ 01434 p->cid_name[0] = 0; 01435 p->cid_num[0] = 0; 01436 p->rdnis[0] = 0; 01437 p->exten[0] = 0; 01438 p->mfcr2_ani_index = 0; 01439 p->mfcr2_dnis_index = 0; 01440 p->mfcr2_dnis_matched = 0; 01441 p->mfcr2_call_accepted = 0; 01442 ast_mutex_unlock(&p->lock); 01443 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 01444 }
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 1501 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_ERROR, LOG_NOTICE, 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.
01502 { 01503 struct dahdi_pvt *p; 01504 struct ast_channel *c; 01505 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 01506 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category)); 01507 p = openr2_chan_get_client_data(r2chan); 01508 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 01509 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel); 01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 01511 return; 01512 } 01513 ast_mutex_lock(&p->lock); 01514 p->mfcr2_recvd_category = category; 01515 /* if we're not supposed to use CID, clear whatever we have */ 01516 if (!p->use_callerid) { 01517 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 01518 p->cid_num[0] = 0; 01519 p->cid_name[0] = 0; 01520 } 01521 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 01522 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 01523 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 01524 p->exten[0] = 's'; 01525 p->exten[1] = 0; 01526 } 01527 ast_mutex_unlock(&p->lock); 01528 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01529 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 01530 p->channel, p->exten, p->context); 01531 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 01532 } else { 01533 /* if the user does not want to accept on offer, then we should launch the PBX thread now */ 01534 if (!p->mfcr2_accept_on_offer) { 01535 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01536 if (!c) { 01537 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01538 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01539 } 01540 /* Don't disable reading since we still need to generate MF tone to accept 01541 the call or reject it and detect the tone off condition of the other end */ 01542 } else if (p->mfcr2_charge_calls) { 01543 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel); 01544 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 01545 } else { 01546 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel); 01547 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 01548 } 01549 } 01550 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 1606 of file chan_dahdi.c.
01607 { 01608 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 01609 }
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 1755 of file chan_dahdi.c.
References dahdi_r2_write_log().
Referenced by mkintf().
01756 { 01757 char logmsg[256]; 01758 char completemsg[sizeof(logmsg)+50]; 01759 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01760 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg); 01761 dahdi_r2_write_log(level, completemsg); 01762 }
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 1744 of file chan_dahdi.c.
References dahdi_r2_write_log().
01745 { 01746 char logmsg[256]; 01747 char completemsg[sizeof(logmsg)+50]; 01748 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01749 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg); 01750 dahdi_r2_write_log(level, completemsg); 01751 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1764 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.
01765 { 01766 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01767 /* if 'immediate' is set, let's stop requesting DNIS */ 01768 if (p->immediate) { 01769 return 0; 01770 } 01771 p->exten[p->mfcr2_dnis_index] = digit; 01772 p->rdnis[p->mfcr2_dnis_index] = digit; 01773 p->mfcr2_dnis_index++; 01774 p->exten[p->mfcr2_dnis_index] = 0; 01775 p->rdnis[p->mfcr2_dnis_index] = 0; 01776 /* 01777 ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten); 01778 int ret; 01779 ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num); 01780 ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01781 ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num); 01782 ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01783 */ 01784 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 01785 if ((p->mfcr2_dnis_matched || 01786 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 01787 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01788 return 0; 01789 } 01790 /* otherwise keep going */ 01791 return 1; 01792 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 1448 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, manager_event(), and dahdi_pvt::unknown_alarm.
01449 { 01450 int res; 01451 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01452 ast_mutex_lock(&p->lock); 01453 p->inalarm = alarm ? 1 : 0; 01454 if (p->inalarm) { 01455 res = get_alarms(p); 01456 /* unknown_alarm may be set here */ 01457 handle_alarms(p, res); 01458 } else { 01459 if (!p->unknown_alarm) { 01460 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 01461 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 01462 } else { 01463 p->unknown_alarm = 0; 01464 } 01465 } 01466 ast_mutex_unlock(&p->lock); 01467 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan)); 01468 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1724 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.
01725 { 01726 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01727 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel); 01728 ast_mutex_lock(&p->lock); 01729 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK; 01730 ast_mutex_unlock(&p->lock); 01731 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1733 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.
01734 { 01735 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01736 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 01737 ast_mutex_lock(&p->lock); 01738 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK; 01739 ast_mutex_unlock(&p->lock); 01740 }
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 1475 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.
01476 { 01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01478 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 01479 if (p->owner) { 01480 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 01481 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01482 } 01483 ast_mutex_lock(&p->lock); 01484 p->mfcr2call = 0; 01485 ast_mutex_unlock(&p->lock); 01486 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 1696 of file chan_dahdi.c.
References ast_log(), ast_verbose(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.
Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().
01697 { 01698 switch (level) { 01699 case OR2_LOG_NOTICE: 01700 ast_verbose("%s", logmessage); 01701 break; 01702 case OR2_LOG_WARNING: 01703 ast_log(LOG_WARNING, "%s", logmessage); 01704 break; 01705 case OR2_LOG_ERROR: 01706 ast_log(LOG_ERROR, "%s", logmessage); 01707 break; 01708 case OR2_LOG_STACK_TRACE: 01709 case OR2_LOG_MF_TRACE: 01710 case OR2_LOG_CAS_TRACE: 01711 case OR2_LOG_DEBUG: 01712 case OR2_LOG_EX_DEBUG: 01713 ast_log(LOG_DEBUG, "%s", logmessage); 01714 break; 01715 default: 01716 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 01717 ast_log(LOG_NOTICE, "%s", logmessage); 01718 break; 01719 } 01720 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6274 of file chan_dahdi.c.
References ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_FLAG_BLOCKING, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRIENDLY_OFFSET, ast_getformatname(), AST_LIN2MU, ast_log(), AST_MULAW, ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_setstate(), AST_STATE_PRERING, AST_STATE_RINGING, ast_tv(), dahdi_subchannel::buffer, dahdi_pvt::channel, CHECK_BLOCKING, ast_channel::cid, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, ast_callerid::cid_tns, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_subchannel::f, f, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, dahdi_pvt::mfcr2, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, dahdi_pvt::ringt, S_OR, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::use_callerid.
06275 { 06276 struct dahdi_pvt *p; 06277 int res; 06278 int index; 06279 void *readbuf; 06280 struct ast_frame *f; 06281 06282 /* 06283 * For analog channels, we must do deadlock avoidance because 06284 * analog ports can have more than one Asterisk channel using 06285 * the same private structure. 06286 */ 06287 p = ast->tech_pvt; 06288 while (ast_mutex_trylock(&p->lock)) { 06289 DEADLOCK_AVOIDANCE(&ast->lock); 06290 06291 /* 06292 * For PRI channels, we must refresh the private pointer because 06293 * the call could move to another B channel while the Asterisk 06294 * channel is unlocked. 06295 */ 06296 p = ast->tech_pvt; 06297 } 06298 06299 index = dahdi_get_index(ast, p, 0); 06300 06301 /* Hang up if we don't really exist */ 06302 if (index < 0) { 06303 ast_log(LOG_WARNING, "We don't exist?\n"); 06304 ast_mutex_unlock(&p->lock); 06305 return NULL; 06306 } 06307 06308 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 06309 ast_mutex_unlock(&p->lock); 06310 return NULL; 06311 } 06312 06313 p->subs[index].f.frametype = AST_FRAME_NULL; 06314 p->subs[index].f.datalen = 0; 06315 p->subs[index].f.samples = 0; 06316 p->subs[index].f.mallocd = 0; 06317 p->subs[index].f.offset = 0; 06318 p->subs[index].f.subclass = 0; 06319 p->subs[index].f.delivery = ast_tv(0,0); 06320 p->subs[index].f.src = "dahdi_read"; 06321 p->subs[index].f.data = NULL; 06322 06323 /* make sure it sends initial key state as first frame */ 06324 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 06325 { 06326 struct dahdi_params ps; 06327 06328 memset(&ps, 0, sizeof(ps)); 06329 ps.channo = p->channel; 06330 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 06331 ast_mutex_unlock(&p->lock); 06332 return NULL; 06333 } 06334 p->firstradio = 1; 06335 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06336 if (ps.rxisoffhook) 06337 { 06338 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 06339 } 06340 else 06341 { 06342 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 06343 } 06344 ast_mutex_unlock(&p->lock); 06345 return &p->subs[index].f; 06346 } 06347 if (p->ringt == 1) { 06348 ast_mutex_unlock(&p->lock); 06349 return NULL; 06350 } 06351 else if (p->ringt > 0) 06352 p->ringt--; 06353 06354 #ifdef HAVE_OPENR2 06355 if (p->mfcr2) { 06356 openr2_chan_process_event(p->r2chan); 06357 } 06358 #endif 06359 06360 if (p->subs[index].needringing) { 06361 /* Send ringing frame if requested */ 06362 p->subs[index].needringing = 0; 06363 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06364 p->subs[index].f.subclass = AST_CONTROL_RINGING; 06365 ast_setstate(ast, AST_STATE_RINGING); 06366 ast_mutex_unlock(&p->lock); 06367 return &p->subs[index].f; 06368 } 06369 06370 if (p->subs[index].needbusy) { 06371 /* Send busy frame if requested */ 06372 p->subs[index].needbusy = 0; 06373 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06374 p->subs[index].f.subclass = AST_CONTROL_BUSY; 06375 ast_mutex_unlock(&p->lock); 06376 return &p->subs[index].f; 06377 } 06378 06379 if (p->subs[index].needcongestion) { 06380 /* Send congestion frame if requested */ 06381 p->subs[index].needcongestion = 0; 06382 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06383 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 06384 ast_mutex_unlock(&p->lock); 06385 return &p->subs[index].f; 06386 } 06387 06388 if (p->subs[index].needcallerid && !ast->cid.cid_tns) { 06389 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06390 S_OR(p->lastcid_name, NULL), 06391 S_OR(p->lastcid_num, NULL) 06392 ); 06393 p->subs[index].needcallerid = 0; 06394 } 06395 06396 if (p->subs[index].needanswer) { 06397 /* Send answer frame if requested */ 06398 p->subs[index].needanswer = 0; 06399 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06400 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 06401 ast_mutex_unlock(&p->lock); 06402 return &p->subs[index].f; 06403 } 06404 06405 #ifdef HAVE_OPENR2 06406 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06407 /* openr2 took care of reading and handling any event 06408 (needanswer, needbusy etc), if we continue we will read() 06409 twice, lets just return a null frame. This should only 06410 happen when openr2 is dialing out */ 06411 p->subs[index].f.frametype = AST_FRAME_NULL; 06412 p->subs[index].f.subclass = 0; 06413 p->subs[index].f.samples = 0; 06414 p->subs[index].f.mallocd = 0; 06415 p->subs[index].f.offset = 0; 06416 p->subs[index].f.data = NULL; 06417 p->subs[index].f.datalen= 0; 06418 ast_mutex_unlock(&p->lock); 06419 return &p->subs[index].f; 06420 } 06421 #endif 06422 06423 if (p->subs[index].needflash) { 06424 /* Send answer frame if requested */ 06425 p->subs[index].needflash = 0; 06426 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06427 p->subs[index].f.subclass = AST_CONTROL_FLASH; 06428 ast_mutex_unlock(&p->lock); 06429 return &p->subs[index].f; 06430 } 06431 06432 if (p->subs[index].needhold) { 06433 /* Send answer frame if requested */ 06434 p->subs[index].needhold = 0; 06435 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06436 p->subs[index].f.subclass = AST_CONTROL_HOLD; 06437 ast_mutex_unlock(&p->lock); 06438 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 06439 return &p->subs[index].f; 06440 } 06441 06442 if (p->subs[index].needunhold) { 06443 /* Send answer frame if requested */ 06444 p->subs[index].needunhold = 0; 06445 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06446 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 06447 ast_mutex_unlock(&p->lock); 06448 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 06449 return &p->subs[index].f; 06450 } 06451 06452 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06453 if (!p->subs[index].linear) { 06454 p->subs[index].linear = 1; 06455 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06456 if (res) 06457 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 06458 } 06459 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06460 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06461 if (p->subs[index].linear) { 06462 p->subs[index].linear = 0; 06463 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06464 if (res) 06465 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 06466 } 06467 } else { 06468 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06469 ast_mutex_unlock(&p->lock); 06470 return NULL; 06471 } 06472 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 06473 CHECK_BLOCKING(ast); 06474 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06475 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06476 06477 if (p->use_callerid && (ast->_state == AST_STATE_PRERING && 06478 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) { 06479 //ast_log(LOG_NOTICE, "use_callerid %u, cid_start %i\n", p->use_callerid, p->cid_start); 06480 if (!p->subs[index].linear) { 06481 int x, samplin; 06482 int mean, ssum; 06483 06484 /* First calc mean signal (DC offset) */ 06485 for (x = 0, ssum = 0; x < READ_SIZE; x++) { 06486 //ssum += (ast->rawreadformat == AST_FORMAT_ULAW ? AST_MULAW((u_char *)readbuf) : AST_ALAW((u_char *)readbuf[x])); 06487 ssum += AST_MULAW(((u_char *)readbuf)[x]); 06488 if (option_verbose > 5 && (x % 10 == 0)) 06489 ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE); 06490 } 06491 mean = ssum / READ_SIZE; 06492 06493 if (option_verbose > 5) 06494 ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean); 06495 if (ast->rawreadformat == AST_FORMAT_ULAW) { 06496 for (x = 0; x < READ_SIZE; x++) { 06497 samplin = AST_MULAW(((u_char *)readbuf)[x]); 06498 if (option_verbose > 6 && (x % 10 == 0)) 06499 ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean)); 06500 ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean); 06501 } 06502 } 06503 } 06504 } 06505 06506 /* Check for hangup */ 06507 if (res < 0) { 06508 f = NULL; 06509 if (res == -1) { 06510 if (errno == EAGAIN) { 06511 /* Return "NULL" frame if there is nobody there */ 06512 ast_mutex_unlock(&p->lock); 06513 return &p->subs[index].f; 06514 } else if (errno == ELAST) { 06515 f = __dahdi_exception(ast); 06516 } else 06517 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06518 } 06519 ast_mutex_unlock(&p->lock); 06520 return f; 06521 } 06522 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 06523 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06524 f = __dahdi_exception(ast); 06525 ast_mutex_unlock(&p->lock); 06526 return f; 06527 } 06528 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06529 int c; 06530 06531 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06532 if (c < 0) { 06533 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 06534 ast_mutex_unlock(&p->lock); 06535 return NULL; 06536 } 06537 if (c) { /* if a char to return */ 06538 p->subs[index].f.subclass = 0; 06539 p->subs[index].f.frametype = AST_FRAME_TEXT; 06540 p->subs[index].f.mallocd = 0; 06541 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06542 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 06543 p->subs[index].f.datalen = 1; 06544 *((char *) p->subs[index].f.data) = c; 06545 ast_mutex_unlock(&p->lock); 06546 return &p->subs[index].f; 06547 } 06548 } 06549 if (index == SUB_REAL) { 06550 /* Ensure the CW timers decrement only on a single subchannel */ 06551 if (p->cidcwexpire) { 06552 if (!--p->cidcwexpire) { 06553 /* Expired CID/CW */ 06554 if (option_verbose > 2) 06555 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 06556 restore_conference(p); 06557 } 06558 } 06559 if (p->cid_suppress_expire) { 06560 --p->cid_suppress_expire; 06561 } 06562 if (p->callwaitingrepeat) { 06563 if (!--p->callwaitingrepeat) { 06564 /* Expired, Repeat callwaiting tone */ 06565 ++p->callwaitrings; 06566 dahdi_callwait(ast); 06567 } 06568 } 06569 } 06570 if (p->subs[index].linear) { 06571 p->subs[index].f.datalen = READ_SIZE * 2; 06572 } else 06573 p->subs[index].f.datalen = READ_SIZE; 06574 06575 /* Handle CallerID Transmission */ 06576 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06577 send_callerid(p); 06578 } 06579 06580 p->subs[index].f.frametype = AST_FRAME_VOICE; 06581 p->subs[index].f.subclass = ast->rawreadformat; 06582 p->subs[index].f.samples = READ_SIZE; 06583 p->subs[index].f.mallocd = 0; 06584 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06585 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 06586 #if 0 06587 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 06588 #endif 06589 if (p->dialing || /* Transmitting something */ 06590 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06591 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06592 ) { 06593 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06594 don't send anything */ 06595 p->subs[index].f.frametype = AST_FRAME_NULL; 06596 p->subs[index].f.subclass = 0; 06597 p->subs[index].f.samples = 0; 06598 p->subs[index].f.mallocd = 0; 06599 p->subs[index].f.offset = 0; 06600 p->subs[index].f.data = NULL; 06601 p->subs[index].f.datalen= 0; 06602 } 06603 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 06604 /* Perform busy detection. etc on the dahdi line */ 06605 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 06606 if (f) { 06607 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 06608 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 06609 /* Treat this as a "hangup" instead of a "busy" on the assumption that 06610 a busy */ 06611 f = NULL; 06612 } 06613 } else if (f->frametype == AST_FRAME_DTMF_BEGIN 06614 || f->frametype == AST_FRAME_DTMF_END) { 06615 #ifdef HAVE_PRI 06616 if (p->sig == SIG_PRI 06617 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING 06618 && p->pri 06619 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) 06620 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 06621 /* Don't accept in-band DTMF when in overlap dial mode */ 06622 ast_log(LOG_DEBUG, 06623 "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n", 06624 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end", 06625 f->subclass, f->subclass, ast->name); 06626 06627 f->frametype = AST_FRAME_NULL; 06628 f->subclass = 0; 06629 } 06630 #endif 06631 /* DSP clears us of being pulse */ 06632 p->pulsedial = 0; 06633 } 06634 } 06635 } else 06636 f = &p->subs[index].f; 06637 06638 if (f) { 06639 switch (f->frametype) { 06640 case AST_FRAME_DTMF_BEGIN: 06641 case AST_FRAME_DTMF_END: 06642 dahdi_handle_dtmf(ast, index, &f); 06643 break; 06644 case AST_FRAME_VOICE: 06645 if (p->cidspill || p->cid_suppress_expire) { 06646 /* We are/were sending a caller id spill. Suppress any echo. */ 06647 p->subs[index].f.frametype = AST_FRAME_NULL; 06648 p->subs[index].f.subclass = 0; 06649 p->subs[index].f.samples = 0; 06650 p->subs[index].f.mallocd = 0; 06651 p->subs[index].f.offset = 0; 06652 p->subs[index].f.data = NULL; 06653 p->subs[index].f.datalen= 0; 06654 } 06655 break; 06656 default: 06657 break; 06658 } 06659 } 06660 06661 /* If we have a fake_event, trigger exception to handle it */ 06662 if (p->fake_event) 06663 ast_set_flag(ast, AST_FLAG_EXCEPTION); 06664 06665 ast_mutex_unlock(&p->lock); 06666 return f; 06667 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 10000 of file chan_dahdi.c.
References alloc_sub(), dahdi_pvt::allocated, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), dahdi_pvt::bearer, busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_pvt::digital, dahdi_pvt::distinctivering, ifend, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, ast_channel::name, dahdi_pvt::next, NUM_SPANS, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), round_robin, s, dahdi_pvt::sig, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI_LIB_HANDLE_CASES, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
10001 { 10002 ast_group_t groupmatch = 0; 10003 int channelmatch = -1; 10004 int roundrobin = 0; 10005 int callwait = 0; 10006 int busy = 0; 10007 struct dahdi_pvt *p; 10008 struct ast_channel *tmp = NULL; 10009 char *dest=NULL; 10010 int x; 10011 char *s; 10012 char opt=0; 10013 int res=0, y=0; 10014 int backwards = 0; 10015 #ifdef HAVE_PRI 10016 int crv; 10017 int bearer = -1; 10018 int trunkgroup; 10019 struct dahdi_pri *pri=NULL; 10020 #endif 10021 struct dahdi_pvt *exit, *start, *end; 10022 ast_mutex_t *lock; 10023 int channelmatched = 0; 10024 int groupmatched = 0; 10025 10026 /* 10027 * data is ---v 10028 * Dial(DAHDI/pseudo[/extension]) 10029 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 10030 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 10031 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 10032 * 10033 * g - channel group allocation search forward 10034 * G - channel group allocation search backward 10035 * r - channel group allocation round robin search forward 10036 * R - channel group allocation round robin search backward 10037 * 10038 * c - Wait for DTMF digit to confirm answer 10039 * r<cadance#> - Set distintive ring cadance number 10040 * d - Force bearer capability for ISDN call to digital. 10041 */ 10042 10043 /* Assume we're locking the iflock */ 10044 lock = &iflock; 10045 start = iflist; 10046 end = ifend; 10047 if (data) { 10048 dest = ast_strdupa((char *)data); 10049 } else { 10050 ast_log(LOG_WARNING, "Channel requested with no data\n"); 10051 return NULL; 10052 } 10053 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 10054 /* Retrieve the group number */ 10055 char *stringp; 10056 10057 stringp = dest + 1; 10058 s = strsep(&stringp, "/"); 10059 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 10060 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 10061 return NULL; 10062 } 10063 groupmatch = ((ast_group_t) 1 << x); 10064 if (toupper(dest[0]) == 'G') { 10065 if (dest[0] == 'G') { 10066 backwards = 1; 10067 p = ifend; 10068 } else 10069 p = iflist; 10070 } else { 10071 if (dest[0] == 'R') { 10072 backwards = 1; 10073 p = round_robin[x]?round_robin[x]->prev:ifend; 10074 if (!p) 10075 p = ifend; 10076 } else { 10077 p = round_robin[x]?round_robin[x]->next:iflist; 10078 if (!p) 10079 p = iflist; 10080 } 10081 roundrobin = 1; 10082 } 10083 } else { 10084 char *stringp; 10085 10086 stringp = dest; 10087 s = strsep(&stringp, "/"); 10088 p = iflist; 10089 if (!strcasecmp(s, "pseudo")) { 10090 /* Special case for pseudo */ 10091 x = CHAN_PSEUDO; 10092 channelmatch = x; 10093 } 10094 #ifdef HAVE_PRI 10095 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 10096 if ((trunkgroup < 1) || (crv < 1)) { 10097 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 10098 return NULL; 10099 } 10100 res--; 10101 for (x = 0; x < NUM_SPANS; x++) { 10102 if (pris[x].trunkgroup == trunkgroup) { 10103 pri = pris + x; 10104 lock = &pri->lock; 10105 start = pri->crvs; 10106 end = pri->crvend; 10107 break; 10108 } 10109 } 10110 if (!pri) { 10111 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 10112 return NULL; 10113 } 10114 channelmatch = crv; 10115 p = pris[x].crvs; 10116 } 10117 #endif 10118 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 10119 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 10120 return NULL; 10121 } else { 10122 channelmatch = x; 10123 } 10124 } 10125 /* Search for an unowned channel */ 10126 ast_mutex_lock(lock); 10127 exit = p; 10128 while (p && !tmp) { 10129 if (roundrobin) 10130 round_robin[x] = p; 10131 #if 0 10132 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 10133 #endif 10134 10135 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 10136 if (option_debug) 10137 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 10138 if (p->inalarm) 10139 goto next; 10140 10141 callwait = (p->owner != NULL); 10142 #ifdef HAVE_PRI 10143 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 10144 if (p->sig != SIG_FXSKS) { 10145 /* Gotta find an actual channel to use for this 10146 CRV if this isn't a callwait */ 10147 bearer = pri_find_empty_chan(pri, 0); 10148 if (bearer < 0) { 10149 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 10150 p = NULL; 10151 break; 10152 } 10153 pri_assign_bearer(p, pri, pri->pvts[bearer]); 10154 } else { 10155 if (alloc_sub(p, 0)) { 10156 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 10157 p = NULL; 10158 break; 10159 } else 10160 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 10161 p->pri = pri; 10162 } 10163 } 10164 #endif 10165 10166 #ifdef HAVE_OPENR2 10167 if (p->mfcr2) { 10168 ast_mutex_lock(&p->lock); 10169 if (p->mfcr2call) { 10170 ast_mutex_unlock(&p->lock); 10171 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 10172 goto next; 10173 } 10174 if (p->mfcr2block) { 10175 ast_mutex_unlock(&p->lock); 10176 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block); 10177 goto next; 10178 } 10179 p->mfcr2call = 1; 10180 ast_mutex_unlock(&p->lock); 10181 } 10182 #endif 10183 10184 if (p->channel == CHAN_PSEUDO) { 10185 p = chandup(p); 10186 if (!p) { 10187 break; 10188 } 10189 } 10190 if (p->owner) { 10191 if (alloc_sub(p, SUB_CALLWAIT)) { 10192 p = NULL; 10193 break; 10194 } 10195 } 10196 #if defined(HAVE_PRI) 10197 switch (p->sig) { 10198 case SIG_GR303FXOKS: 10199 case SIG_GR303FXSKS: 10200 case SIG_PRI_LIB_HANDLE_CASES: 10201 /* 10202 * We already have the B channel reserved for this call. We 10203 * just need to make sure that dahdi_hangup() has completed 10204 * cleaning up before continuing. 10205 */ 10206 ast_mutex_lock(&p->lock); 10207 ast_mutex_unlock(&p->lock); 10208 break; 10209 default: 10210 break; 10211 } 10212 #endif /* defined(HAVE_PRI) */ 10213 p->outgoing = 1; 10214 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 10215 if (!tmp) { 10216 p->outgoing = 0; 10217 #if defined(HAVE_PRI) 10218 /* 10219 * This should be the last thing to clear when we are done with 10220 * the channel. 10221 */ 10222 p->allocated = 0; 10223 #endif /* defined(HAVE_PRI) */ 10224 } 10225 #ifdef HAVE_PRI 10226 if (p->bearer) { 10227 /* Log owner to bearer channel, too */ 10228 p->bearer->owner = tmp; 10229 } 10230 #endif 10231 /* Make special notes */ 10232 if (res > 1) { 10233 if (opt == 'c') { 10234 /* Confirm answer */ 10235 p->confirmanswer = 1; 10236 } else if (opt == 'r') { 10237 /* Distinctive ring */ 10238 if (res < 3) 10239 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 10240 else 10241 p->distinctivering = y; 10242 } else if (opt == 'd') { 10243 /* If this is an ISDN call, make it digital */ 10244 p->digital = 1; 10245 if (tmp) 10246 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 10247 } else { 10248 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 10249 } 10250 } 10251 /* Note if the call is a call waiting call */ 10252 if (tmp && callwait) 10253 tmp->cdrflags |= AST_CDR_CALLWAIT; 10254 break; 10255 } 10256 next: 10257 if (backwards) { 10258 p = p->prev; 10259 if (!p) 10260 p = end; 10261 } else { 10262 p = p->next; 10263 if (!p) 10264 p = start; 10265 } 10266 /* stop when you roll to the one that we started from */ 10267 if (p == exit) 10268 break; 10269 } 10270 ast_mutex_unlock(lock); 10271 restart_monitor(); 10272 if (callwait) 10273 *cause = AST_CAUSE_BUSY; 10274 else if (!tmp) { 10275 if (channelmatched) { 10276 if (busy) 10277 *cause = AST_CAUSE_BUSY; 10278 } else if (groupmatched) { 10279 *cause = AST_CAUSE_CONGESTION; 10280 } 10281 } 10282 10283 return tmp; 10284 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 13101 of file chan_dahdi.c.
References ast_active_channels(), ast_cond_wait(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verbose(), dahdi_close_pri_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, init_mfcr2_globals(), lock, master, monitor_thread, monlock, dahdi_pvt::next, NUM_SPANS, option_debug, option_verbose, dahdi_pvt::owner, pris, r2links, restart_lock, setup_dahdi(), ss_thread_complete, ss_thread_count, ss_thread_lock, and dahdi_pvt::subs.
Referenced by __action_restart(), and dahdi_restart_cmd().
13102 { 13103 13104 #ifdef HAVE_OPENR2 13105 int r; 13106 #endif 13107 13108 #if defined(HAVE_PRI) 13109 int i, j; 13110 #endif 13111 int cancel_code; 13112 struct dahdi_pvt *p; 13113 13114 ast_mutex_lock(&restart_lock); 13115 13116 if (option_verbose) 13117 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 13118 dahdi_softhangup_all(); 13119 if (option_verbose > 3) 13120 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 13121 13122 #ifdef HAVE_OPENR2 13123 for (r = 0; r < NUM_SPANS; r++) { 13124 if (r2links[r].master != AST_PTHREADT_NULL) { 13125 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master); 13126 pthread_cancel(r2links[r].master); 13127 pthread_join(r2links[r].master, NULL); 13128 openr2_context_delete(r2links[r].protocol_context); 13129 } 13130 } 13131 init_mfcr2_globals(); 13132 #endif 13133 13134 #if defined(HAVE_PRI) 13135 for (i = 0; i < NUM_SPANS; i++) { 13136 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 13137 cancel_code = pthread_cancel(pris[i].master); 13138 pthread_kill(pris[i].master, SIGURG); 13139 if (option_debug > 3) 13140 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 13141 pthread_join(pris[i].master, NULL); 13142 if (option_debug > 3) 13143 ast_verbose("Joined thread of span %d\n", i); 13144 } 13145 } 13146 #endif 13147 13148 ast_mutex_lock(&monlock); 13149 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 13150 cancel_code = pthread_cancel(monitor_thread); 13151 pthread_kill(monitor_thread, SIGURG); 13152 if (option_debug > 3) 13153 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 13154 pthread_join(monitor_thread, NULL); 13155 if (option_debug > 3) 13156 ast_verbose("Joined monitor thread\n"); 13157 } 13158 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 13159 13160 ast_mutex_lock(&ss_thread_lock); 13161 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 13162 int x = DAHDI_FLASH; 13163 if (option_debug > 2) 13164 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 13165 13166 for (p = iflist; p; p = p->next) { 13167 if (p->owner) 13168 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */ 13169 } 13170 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 13171 } 13172 13173 /* ensure any created channels before monitor threads were stopped are hungup */ 13174 dahdi_softhangup_all(); 13175 if (option_verbose > 3) 13176 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 13177 destroy_all_channels(); 13178 if (option_debug) 13179 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 13180 13181 ast_mutex_unlock(&monlock); 13182 13183 #ifdef HAVE_PRI 13184 for (i = 0; i < NUM_SPANS; i++) { 13185 for (j = 0; j < NUM_DCHANS; j++) 13186 dahdi_close_pri_fd(&(pris[i]), j); 13187 } 13188 13189 memset(pris, 0, sizeof(pris)); 13190 for (i = 0; i < NUM_SPANS; i++) { 13191 ast_mutex_init(&pris[i].lock); 13192 pris[i].offset = -1; 13193 pris[i].master = AST_PTHREADT_NULL; 13194 for (j = 0; j < NUM_DCHANS; j++) 13195 pris[i].fds[j] = -1; 13196 } 13197 pri_set_error(dahdi_pri_error); 13198 pri_set_message(dahdi_pri_message); 13199 #endif 13200 13201 if (setup_dahdi(2) != 0) { 13202 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 13203 ast_mutex_unlock(&ss_thread_lock); 13204 return 1; 13205 } 13206 ast_mutex_unlock(&ss_thread_lock); 13207 ast_mutex_unlock(&restart_lock); 13208 return 0; 13209 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 13211 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
13212 { 13213 if (argc != 2) { 13214 return RESULT_SHOWUSAGE; 13215 } 13216 13217 if (dahdi_restart() != 0) 13218 return RESULT_FAILURE; 13219 return RESULT_SUCCESS; 13220 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4935 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04936 { 04937 int x; 04938 int res; 04939 /* Make sure our transmit state is on hook */ 04940 x = 0; 04941 x = DAHDI_ONHOOK; 04942 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04943 do { 04944 x = DAHDI_RING; 04945 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04946 if (res) { 04947 switch (errno) { 04948 case EBUSY: 04949 case EINTR: 04950 /* Wait just in case */ 04951 usleep(10000); 04952 continue; 04953 case EINPROGRESS: 04954 res = 0; 04955 break; 04956 default: 04957 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04958 res = 0; 04959 } 04960 } 04961 } while (res); 04962 return res; 04963 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3445 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
03446 { 03447 return send_keypad_facility_exec(chan, data); 03448 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 15154 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index, dahdi_subchannel::dfd, END_SILENCE_LEN, errno, free, HEADER_LEN, HEADER_MS, LOG_ERROR, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
15155 { 15156 #define END_SILENCE_LEN 400 15157 #define HEADER_MS 50 15158 #define TRAILER_MS 5 15159 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15160 #define ASCII_BYTES_PER_CHAR 80 15161 15162 unsigned char *buf,*mybuf; 15163 struct dahdi_pvt *p = c->tech_pvt; 15164 struct pollfd fds[1]; 15165 int size,res,fd,len,x; 15166 int bytes=0; 15167 /* Initial carrier (imaginary) */ 15168 float cr = 1.0; 15169 float ci = 0.0; 15170 float scont = 0.0; 15171 int index; 15172 15173 index = dahdi_get_index(c, p, 0); 15174 if (index < 0) { 15175 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15176 return -1; 15177 } 15178 if (!text[0]) return(0); /* if nothing to send, dont */ 15179 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15180 if (p->mate) 15181 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15182 else 15183 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15184 if (!buf) 15185 return -1; 15186 mybuf = buf; 15187 if (p->mate) { 15188 int codec = AST_LAW(p); 15189 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15190 PUT_CLID_MARKMS; 15191 } 15192 /* Put actual message */ 15193 for (x = 0; text[x]; x++) { 15194 PUT_CLID(text[x]); 15195 } 15196 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15197 PUT_CLID_MARKMS; 15198 } 15199 len = bytes; 15200 buf = mybuf; 15201 } else { 15202 len = tdd_generate(p->tdd, buf, text); 15203 if (len < 1) { 15204 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15205 free(mybuf); 15206 return -1; 15207 } 15208 } 15209 memset(buf + len, 0x7f, END_SILENCE_LEN); 15210 len += END_SILENCE_LEN; 15211 fd = p->subs[index].dfd; 15212 while (len) { 15213 if (ast_check_hangup(c)) { 15214 free(mybuf); 15215 return -1; 15216 } 15217 size = len; 15218 if (size > READ_SIZE) 15219 size = READ_SIZE; 15220 fds[0].fd = fd; 15221 fds[0].events = POLLOUT | POLLPRI; 15222 fds[0].revents = 0; 15223 res = poll(fds, 1, -1); 15224 if (!res) { 15225 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 15226 continue; 15227 } 15228 /* if got exception */ 15229 if (fds[0].revents & POLLPRI) { 15230 ast_free(mybuf); 15231 return -1; 15232 } 15233 if (!(fds[0].revents & POLLOUT)) { 15234 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 15235 continue; 15236 } 15237 res = write(fd, buf, size); 15238 if (res != size) { 15239 if (res == -1) { 15240 free(mybuf); 15241 return -1; 15242 } 15243 if (option_debug) 15244 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15245 break; 15246 } 15247 len -= size; 15248 buf += size; 15249 } 15250 free(mybuf); 15251 return(0); 15252 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2647 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), and ss_thread().
02648 { 02649 int x, res; 02650 02651 x = hs; 02652 res = ioctl(fd, DAHDI_HOOK, &x); 02653 02654 if (res < 0) { 02655 if (errno == EINPROGRESS) 02656 return 0; 02657 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02658 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02659 } 02660 02661 return res; 02662 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 11006 of file chan_dahdi.c.
11007 { 11008 int res; 11009 res = ioctl(dfd, DAHDI_SETLAW, &law); 11010 if (res) 11011 return res; 11012 return 0; 11013 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1944 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01945 { 01946 int res; 01947 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01948 if (res) 01949 return res; 01950 return 0; 01951 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 4209 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, 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_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
04210 { 04211 char *cp; 04212 signed char *scp; 04213 int x; 04214 int index; 04215 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04216 struct oprmode *oprmode; 04217 04218 04219 /* all supported options require data */ 04220 if (!data || (datalen < 1)) { 04221 errno = EINVAL; 04222 return -1; 04223 } 04224 04225 switch (option) { 04226 case AST_OPTION_TXGAIN: 04227 scp = (signed char *) data; 04228 index = dahdi_get_index(chan, p, 0); 04229 if (index < 0) { 04230 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04231 return -1; 04232 } 04233 if (option_debug) 04234 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04235 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 04236 case AST_OPTION_RXGAIN: 04237 scp = (signed char *) data; 04238 index = dahdi_get_index(chan, p, 0); 04239 if (index < 0) { 04240 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04241 return -1; 04242 } 04243 if (option_debug) 04244 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04245 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 04246 case AST_OPTION_TONE_VERIFY: 04247 if (!p->dsp) 04248 break; 04249 cp = (char *) data; 04250 switch (*cp) { 04251 case 1: 04252 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04253 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04254 break; 04255 case 2: 04256 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04257 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04258 break; 04259 default: 04260 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04261 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04262 break; 04263 } 04264 break; 04265 case AST_OPTION_TDD: 04266 /* turn on or off TDD */ 04267 cp = (char *) data; 04268 p->mate = 0; 04269 if (!*cp) { /* turn it off */ 04270 if (option_debug) 04271 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04272 if (p->tdd) 04273 tdd_free(p->tdd); 04274 p->tdd = 0; 04275 break; 04276 } 04277 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 04278 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04279 dahdi_disable_ec(p); 04280 /* otherwise, turn it on */ 04281 if (!p->didtdd) { /* if havent done it yet */ 04282 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04283 unsigned char *buf; 04284 int size, res, fd, len; 04285 struct pollfd fds[1]; 04286 04287 buf = mybuf; 04288 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04289 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04290 len = 40000; 04291 index = dahdi_get_index(chan, p, 0); 04292 if (index < 0) { 04293 ast_log(LOG_WARNING, "No index in TDD?\n"); 04294 return -1; 04295 } 04296 fd = p->subs[index].dfd; 04297 while (len) { 04298 if (ast_check_hangup(chan)) 04299 return -1; 04300 size = len; 04301 if (size > READ_SIZE) 04302 size = READ_SIZE; 04303 fds[0].fd = fd; 04304 fds[0].events = POLLPRI | POLLOUT; 04305 fds[0].revents = 0; 04306 res = poll(fds, 1, -1); 04307 if (!res) { 04308 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 04309 continue; 04310 } 04311 /* if got exception */ 04312 if (fds[0].revents & POLLPRI) 04313 return -1; 04314 if (!(fds[0].revents & POLLOUT)) { 04315 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 04316 continue; 04317 } 04318 res = write(fd, buf, size); 04319 if (res != size) { 04320 if (res == -1) return -1; 04321 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04322 break; 04323 } 04324 len -= size; 04325 buf += size; 04326 } 04327 p->didtdd = 1; /* set to have done it now */ 04328 } 04329 if (*cp == 2) { /* Mate mode */ 04330 if (p->tdd) 04331 tdd_free(p->tdd); 04332 p->tdd = 0; 04333 p->mate = 1; 04334 break; 04335 } 04336 if (!p->tdd) { /* if we dont have one yet */ 04337 p->tdd = tdd_new(); /* allocate one */ 04338 } 04339 break; 04340 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04341 if (!p->dsp) 04342 break; 04343 cp = (char *) data; 04344 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04345 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04346 p->dtmfrelax = 0; 04347 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 04348 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04349 break; 04350 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04351 cp = (char *) data; 04352 if (!*cp) { 04353 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04354 x = 0; 04355 dahdi_disable_ec(p); 04356 } else { 04357 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04358 x = 1; 04359 } 04360 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04361 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04362 break; 04363 case AST_OPTION_OPRMODE: /* Operator services mode */ 04364 oprmode = (struct oprmode *) data; 04365 pp = oprmode->peer->tech_pvt; 04366 p->oprmode = pp->oprmode = 0; 04367 /* setup peers */ 04368 p->oprpeer = pp; 04369 pp->oprpeer = p; 04370 /* setup modes, if any */ 04371 if (oprmode->mode) 04372 { 04373 pp->oprmode = oprmode->mode; 04374 p->oprmode = -oprmode->mode; 04375 } 04376 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 04377 oprmode->mode, chan->name,oprmode->peer->name);; 04378 break; 04379 case AST_OPTION_ECHOCAN: 04380 cp = (char *) data; 04381 if (*cp) { 04382 ast_log(LOG_DEBUG, "Enabling echo cancellation on %s\n", chan->name); 04383 dahdi_enable_ec(p); 04384 } else { 04385 ast_log(LOG_DEBUG, "Disabling echo cancellation on %s\n", chan->name); 04386 dahdi_disable_ec(p); 04387 } 04388 break; 04389 } 04390 errno = 0; 04391 04392 return 0; 04393 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 13283 of file chan_dahdi.c.
References dahdi_pvt::allocated, ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::bearer, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::logicalspan, 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, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, ast_channel::name, dahdi_pvt::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pris, progzone, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::resetting, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, and dahdi_pvt::subs.
13284 { 13285 int channel; 13286 struct dahdi_pvt *tmp = NULL; 13287 struct dahdi_confinfo ci; 13288 struct dahdi_params ps; 13289 int x; 13290 ast_mutex_t *lock; 13291 struct dahdi_pvt *start; 13292 #ifdef HAVE_PRI 13293 char *c; 13294 int trunkgroup; 13295 struct dahdi_pri *pri=NULL; 13296 #endif 13297 13298 lock = &iflock; 13299 start = iflist; 13300 13301 if (argc != 4) 13302 return RESULT_SHOWUSAGE; 13303 #ifdef HAVE_PRI 13304 if ((c = strchr(argv[3], ':'))) { 13305 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 13306 return RESULT_SHOWUSAGE; 13307 if ((trunkgroup < 1) || (channel < 1)) 13308 return RESULT_SHOWUSAGE; 13309 for (x = 0; x < NUM_SPANS; x++) { 13310 if (pris[x].trunkgroup == trunkgroup) { 13311 pri = pris + x; 13312 break; 13313 } 13314 } 13315 if (pri) { 13316 start = pri->crvs; 13317 lock = &pri->lock; 13318 } else { 13319 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 13320 return RESULT_FAILURE; 13321 } 13322 } else 13323 #endif 13324 channel = atoi(argv[3]); 13325 13326 ast_mutex_lock(lock); 13327 tmp = start; 13328 while (tmp) { 13329 if (tmp->channel == channel) { 13330 #ifdef HAVE_PRI 13331 if (pri) 13332 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 13333 else 13334 #endif 13335 ast_cli(fd, "Channel: %d\n", tmp->channel); 13336 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 13337 ast_cli(fd, "Span: %d\n", tmp->span); 13338 ast_cli(fd, "Extension: %s\n", tmp->exten); 13339 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 13340 ast_cli(fd, "Context: %s\n", tmp->context); 13341 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 13342 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 13343 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 13344 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 13345 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 13346 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 13347 ast_cli(fd, "Radio: %d\n", tmp->radio); 13348 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 13349 ast_cli(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)" : ""); 13350 ast_cli(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)" : ""); 13351 ast_cli(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)" : ""); 13352 ast_cli(fd, "Confno: %d\n", tmp->confno); 13353 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 13354 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 13355 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 13356 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 13357 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 13358 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 13359 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 13360 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 13361 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 13362 if (tmp->master) 13363 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 13364 for (x = 0; x < MAX_SLAVES; x++) { 13365 if (tmp->slaves[x]) 13366 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 13367 } 13368 13369 #ifdef HAVE_OPENR2 13370 if (tmp->mfcr2) { 13371 char calldir[OR2_MAX_PATH]; 13372 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 13373 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 13374 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No"); 13375 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No"); 13376 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 13377 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 13378 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 13379 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 13380 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 13381 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 13382 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 13383 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 13384 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 13385 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No"); 13386 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No"); 13387 #endif 13388 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 13389 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 13390 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 13391 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 13392 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 13393 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 13394 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 13395 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 13396 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 13397 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 13398 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 13399 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 13400 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 13401 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 13402 } 13403 #endif 13404 13405 #ifdef HAVE_PRI 13406 if (tmp->pri) { 13407 ast_cli(fd, "PRI Flags: "); 13408 if (tmp->resetting) 13409 ast_cli(fd, "Resetting "); 13410 if (tmp->call) 13411 ast_cli(fd, "Call "); 13412 if (tmp->bearer) 13413 ast_cli(fd, "Bearer "); 13414 if (tmp->allocated) { 13415 ast_cli(fd, "Allocated "); 13416 } 13417 ast_cli(fd, "\n"); 13418 if (tmp->logicalspan) 13419 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 13420 else 13421 ast_cli(fd, "PRI Logical Span: Implicit\n"); 13422 } 13423 #endif 13424 memset(&ci, 0, sizeof(ci)); 13425 ps.channo = tmp->channel; 13426 if (tmp->subs[SUB_REAL].dfd > -1) { 13427 memset(&ci, 0, sizeof(ci)); 13428 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 13429 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 13430 } 13431 #ifdef DAHDI_GETCONFMUTE 13432 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 13433 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 13434 } 13435 #endif 13436 memset(&ps, 0, sizeof(ps)); 13437 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 13438 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 13439 } else { 13440 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 13441 } 13442 } 13443 if (ISTRUNK(tmp)) { 13444 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 13445 if (!ast_strlen_zero(progzone)) 13446 ast_cli(fd, "Progress Zone: %s\n", progzone); 13447 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 13448 if(tmp->busydetect) { 13449 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 13450 if(tmp->busytonelength > 0) { 13451 ast_cli(fd, "Busy Pattern:\n"); 13452 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 13453 if (tmp->busyquietlength > 0) 13454 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 13455 else 13456 ast_cli(fd, " -- Detect Tone Only\n"); 13457 if(tmp->busyfuzziness > 0) 13458 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 13459 } 13460 } 13461 } 13462 ast_mutex_unlock(lock); 13463 return RESULT_SUCCESS; 13464 } 13465 tmp = tmp->next; 13466 } 13467 13468 ast_cli(fd, "Unable to find given channel %d\n", channel); 13469 ast_mutex_unlock(lock); 13470 return RESULT_FAILURE; 13471 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 13222 of file chan_dahdi.c.
References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::exten, FORMAT, FORMAT2, iflist, iflock, dahdi_pvt::language, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, dahdi_pri::pri, pris, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
13223 { 13224 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 13225 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 13226 struct dahdi_pvt *tmp = NULL; 13227 char tmps[20] = ""; 13228 ast_mutex_t *lock; 13229 struct dahdi_pvt *start; 13230 #ifdef HAVE_PRI 13231 int trunkgroup; 13232 struct dahdi_pri *pri = NULL; 13233 int x; 13234 #endif 13235 13236 lock = &iflock; 13237 start = iflist; 13238 13239 #ifdef HAVE_PRI 13240 if (argc == 4) { 13241 if ((trunkgroup = atoi(argv[3])) < 1) 13242 return RESULT_SHOWUSAGE; 13243 for (x = 0; x < NUM_SPANS; x++) { 13244 if (pris[x].trunkgroup == trunkgroup) { 13245 pri = pris + x; 13246 break; 13247 } 13248 } 13249 if (pri) { 13250 start = pri->crvs; 13251 lock = &pri->lock; 13252 } else { 13253 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 13254 return RESULT_FAILURE; 13255 } 13256 } else 13257 #endif 13258 if (argc != 3) 13259 return RESULT_SHOWUSAGE; 13260 13261 ast_mutex_lock(lock); 13262 #ifdef HAVE_PRI 13263 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 13264 #else 13265 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 13266 #endif 13267 13268 tmp = start; 13269 while (tmp) { 13270 if (tmp->channel > 0) { 13271 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 13272 } else 13273 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 13274 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 13275 tmp = tmp->next; 13276 } 13277 ast_mutex_unlock(lock); 13278 return RESULT_SUCCESS; 13279 #undef FORMAT 13280 #undef FORMAT2 13281 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 13504 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
13504 { 13505 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 13506 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 13507 13508 int span; 13509 int res; 13510 char alarms[50]; 13511 13512 int ctl; 13513 struct dahdi_spaninfo s; 13514 13515 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 13516 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 13517 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 13518 return RESULT_FAILURE; 13519 } 13520 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 13521 13522 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13523 s.spanno = span; 13524 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13525 if (res) { 13526 continue; 13527 } 13528 alarms[0] = '\0'; 13529 if (s.alarms > 0) { 13530 if (s.alarms & DAHDI_ALARM_BLUE) 13531 strcat(alarms, "BLU/"); 13532 if (s.alarms & DAHDI_ALARM_YELLOW) 13533 strcat(alarms, "YEL/"); 13534 if (s.alarms & DAHDI_ALARM_RED) 13535 strcat(alarms, "RED/"); 13536 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13537 strcat(alarms, "LB/"); 13538 if (s.alarms & DAHDI_ALARM_RECOVER) 13539 strcat(alarms, "REC/"); 13540 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13541 strcat(alarms, "NOP/"); 13542 if (!strlen(alarms)) 13543 strcat(alarms, "UUU/"); 13544 if (strlen(alarms)) { 13545 /* Strip trailing / */ 13546 alarms[strlen(alarms) - 1] = '\0'; 13547 } 13548 } else { 13549 if (s.numchans) 13550 strcpy(alarms, "OK"); 13551 else 13552 strcpy(alarms, "UNCONFIGURED"); 13553 } 13554 13555 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 13556 } 13557 close(ctl); 13558 13559 return RESULT_SUCCESS; 13560 #undef FORMAT 13561 #undef FORMAT2 13562 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2198 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_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.
02199 { 02200 static char buf[256]; 02201 switch (sig) { 02202 case SIG_EM: 02203 return "E & M Immediate"; 02204 case SIG_EMWINK: 02205 return "E & M Wink"; 02206 case SIG_EM_E1: 02207 return "E & M E1"; 02208 case SIG_FEATD: 02209 return "Feature Group D (DTMF)"; 02210 case SIG_FEATDMF: 02211 return "Feature Group D (MF)"; 02212 case SIG_FEATDMF_TA: 02213 return "Feature Groud D (MF) Tandem Access"; 02214 case SIG_FEATB: 02215 return "Feature Group B (MF)"; 02216 case SIG_E911: 02217 return "E911 (MF)"; 02218 case SIG_FGC_CAMA: 02219 return "FGC/CAMA (Dialpulse)"; 02220 case SIG_FGC_CAMAMF: 02221 return "FGC/CAMA (MF)"; 02222 case SIG_FXSLS: 02223 return "FXS Loopstart"; 02224 case SIG_FXSGS: 02225 return "FXS Groundstart"; 02226 case SIG_FXSKS: 02227 return "FXS Kewlstart"; 02228 case SIG_FXOLS: 02229 return "FXO Loopstart"; 02230 case SIG_FXOGS: 02231 return "FXO Groundstart"; 02232 case SIG_FXOKS: 02233 return "FXO Kewlstart"; 02234 case SIG_PRI: 02235 return "ISDN PRI"; 02236 case SIG_MFCR2: 02237 return "MFC/R2"; 02238 case SIG_SF: 02239 return "SF (Tone) Immediate"; 02240 case SIG_SFWINK: 02241 return "SF (Tone) Wink"; 02242 case SIG_SF_FEATD: 02243 return "SF (Tone) with Feature Group D (DTMF)"; 02244 case SIG_SF_FEATDMF: 02245 return "SF (Tone) with Feature Group D (MF)"; 02246 case SIG_SF_FEATB: 02247 return "SF (Tone) with Feature Group B (MF)"; 02248 case SIG_GR303FXOKS: 02249 return "GR-303 with FXOKS"; 02250 case SIG_GR303FXSKS: 02251 return "GR-303 with FXSKS"; 02252 case 0: 02253 return "Pseudo"; 02254 default: 02255 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 02256 return buf; 02257 } 02258 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 13072 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, iflock, 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().
13073 { 13074 struct dahdi_pvt *p; 13075 retry: 13076 ast_mutex_lock(&iflock); 13077 for (p = iflist; p; p = p->next) { 13078 ast_mutex_lock(&p->lock); 13079 if (p->owner && !p->restartpending) { 13080 if (ast_channel_trylock(p->owner)) { 13081 if (option_debug > 2) 13082 ast_verbose("Avoiding deadlock\n"); 13083 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 13084 ast_mutex_unlock(&p->lock); 13085 ast_mutex_unlock(&iflock); 13086 goto retry; 13087 } 13088 if (option_debug > 2) 13089 ast_verbose("Softhanging up on %s\n", p->owner->name); 13090 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 13091 p->restartpending = 1; 13092 num_restart_pending++; 13093 ast_channel_unlock(p->owner); 13094 } 13095 ast_mutex_unlock(&p->lock); 13096 } 13097 ast_mutex_unlock(&iflock); 13098 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2479 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
02480 { 02481 int x; 02482 int res; 02483 if (p && p->echocancel && p->echotraining) { 02484 x = p->echotraining; 02485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02486 if (res) 02487 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02488 else { 02489 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 02490 } 02491 } else 02492 ast_log(LOG_DEBUG, "No echo training requested\n"); 02493 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4479 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, LOG_DEBUG, master, and SUB_REAL.
Referenced by dahdi_bridge(), and dahdi_fixup().
04480 { 04481 /* Unlink a specific slave or all slaves/masters from a given master */ 04482 int x; 04483 int hasslaves; 04484 if (!master) 04485 return; 04486 if (needlock) { 04487 ast_mutex_lock(&master->lock); 04488 if (slave) { 04489 while (ast_mutex_trylock(&slave->lock)) { 04490 DEADLOCK_AVOIDANCE(&master->lock); 04491 } 04492 } 04493 } 04494 hasslaves = 0; 04495 for (x = 0; x < MAX_SLAVES; x++) { 04496 if (master->slaves[x]) { 04497 if (!slave || (master->slaves[x] == slave)) { 04498 /* Take slave out of the conference */ 04499 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04500 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04501 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04502 master->slaves[x]->master = NULL; 04503 master->slaves[x] = NULL; 04504 } else 04505 hasslaves = 1; 04506 } 04507 if (!hasslaves) 04508 master->inconference = 0; 04509 } 04510 if (!slave) { 04511 if (master->master) { 04512 /* Take master out of the conference */ 04513 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04514 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04515 hasslaves = 0; 04516 for (x = 0; x < MAX_SLAVES; x++) { 04517 if (master->master->slaves[x] == master) 04518 master->master->slaves[x] = NULL; 04519 else if (master->master->slaves[x]) 04520 hasslaves = 1; 04521 } 04522 if (!hasslaves) 04523 master->master->inconference = 0; 04524 } 04525 master->master = NULL; 04526 } 04527 update_conf(master); 04528 if (needlock) { 04529 if (slave) 04530 ast_mutex_unlock(&slave->lock); 04531 ast_mutex_unlock(&master->lock); 04532 } 04533 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 298 of file chan_dahdi.c.
Referenced by ss_thread().
00299 { 00300 int i, j = 0; 00301 i = DAHDI_IOMUX_SIGEVENT; 00302 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00303 return -1; 00304 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00305 return -1; 00306 return j; 00307 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 7215 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
07216 { 07217 int j; 07218 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 07219 for (;;) 07220 { 07221 /* set bits of interest */ 07222 j = DAHDI_IOMUX_SIGEVENT; 07223 /* wait for some happening */ 07224 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 07225 /* exit loop if we have it */ 07226 if (j & DAHDI_IOMUX_SIGEVENT) break; 07227 } 07228 /* get the event info */ 07229 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 07230 return 0; 07231 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6692 of file chan_dahdi.c.
References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, errno, ast_frame::frametype, dahdi_subchannel::linear, LOG_DEBUG, my_dahdi_write(), ast_channel::name, option_debug, dahdi_pvt::owner, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
06693 { 06694 struct dahdi_pvt *p = ast->tech_pvt; 06695 int res; 06696 int index; 06697 index = dahdi_get_index(ast, p, 0); 06698 if (index < 0) { 06699 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06700 return -1; 06701 } 06702 06703 /* Write a frame of (presumably voice) data */ 06704 if (frame->frametype != AST_FRAME_VOICE) { 06705 if (frame->frametype != AST_FRAME_IMAGE) 06706 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06707 return 0; 06708 } 06709 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06710 (frame->subclass != AST_FORMAT_ULAW) && 06711 (frame->subclass != AST_FORMAT_ALAW)) { 06712 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06713 return -1; 06714 } 06715 if (p->dialing) { 06716 if (option_debug) 06717 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06718 return 0; 06719 } 06720 if (!p->owner) { 06721 if (option_debug) 06722 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 06723 return 0; 06724 } 06725 if (p->cidspill) { 06726 if (option_debug) { 06727 ast_log(LOG_DEBUG, 06728 "Dropping frame since I've still got a callerid spill on %s...\n", 06729 ast->name); 06730 } 06731 return 0; 06732 } 06733 /* Return if it's not valid data */ 06734 if (!frame->data || !frame->datalen) 06735 return 0; 06736 06737 if (frame->subclass == AST_FORMAT_SLINEAR) { 06738 if (!p->subs[index].linear) { 06739 p->subs[index].linear = 1; 06740 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06741 if (res) 06742 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06743 } 06744 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06745 } else { 06746 /* x-law already */ 06747 if (p->subs[index].linear) { 06748 p->subs[index].linear = 0; 06749 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06750 if (res) 06751 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06752 } 06753 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06754 } 06755 if (res < 0) { 06756 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06757 return -1; 06758 } 06759 return 0; 06760 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3365 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, destroy_dahdi_pvt(), ifcount, iflist, iflock, dahdi_pvt::next, num_restart_pending, option_verbose, and VERBOSE_PREFIX_2.
Referenced by __unload_module(), and dahdi_restart().
03366 { 03367 int x; 03368 struct dahdi_pvt *p, *pl; 03369 03370 while (num_restart_pending) { 03371 usleep(1); 03372 } 03373 03374 ast_mutex_lock(&iflock); 03375 /* Destroy all the interfaces and free their memory */ 03376 p = iflist; 03377 while (p) { 03378 pl = p; 03379 p = p->next; 03380 x = pl->channel; 03381 /* Free associated memory */ 03382 destroy_dahdi_pvt(&pl); 03383 if (option_verbose > 2) 03384 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03385 } 03386 iflist = NULL; 03387 ifcount = 0; 03388 ast_mutex_unlock(&iflock); 03389 }
Definition at line 3315 of file chan_dahdi.c.
References destroy_dahdi_pvt(), ifend, iflist, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::prev, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().
03316 { 03317 int owned = 0; 03318 int i = 0; 03319 03320 if (!now) { 03321 if (cur->owner) { 03322 owned = 1; 03323 } 03324 03325 for (i = 0; i < 3; i++) { 03326 if (cur->subs[i].owner) { 03327 owned = 1; 03328 } 03329 } 03330 if (!owned) { 03331 if (prev) { 03332 prev->next = cur->next; 03333 if (prev->next) 03334 prev->next->prev = prev; 03335 else 03336 ifend = prev; 03337 } else { 03338 iflist = cur->next; 03339 if (iflist) 03340 iflist->prev = NULL; 03341 else 03342 ifend = NULL; 03343 } 03344 destroy_dahdi_pvt(&cur); 03345 } 03346 } else { 03347 if (prev) { 03348 prev->next = cur->next; 03349 if (prev->next) 03350 prev->next->prev = prev; 03351 else 03352 ifend = prev; 03353 } else { 03354 iflist = cur->next; 03355 if (iflist) 03356 iflist->prev = NULL; 03357 else 03358 ifend = NULL; 03359 } 03360 destroy_dahdi_pvt(&cur); 03361 } 03362 return 0; 03363 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3295 of file chan_dahdi.c.
References ast_mutex_destroy(), ast_smdi_interface_unref(), dahdi_pvt::cidspill, dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.
Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().
03296 { 03297 struct dahdi_pvt *p = *pvt; 03298 /* Remove channel from the list */ 03299 if (p->prev) 03300 p->prev->next = p->next; 03301 if (p->next) 03302 p->next->prev = p->prev; 03303 03304 free(p->cidspill); 03305 if (p->use_smdi) 03306 ast_smdi_interface_unref(p->smdi_iface); 03307 ast_mutex_destroy(&p->lock); 03308 dahdi_close_sub(p, SUB_REAL); 03309 if (p->owner) 03310 p->owner->tech_pvt = NULL; 03311 free(p); 03312 *pvt = NULL; 03313 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2189 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
02190 { 02191 if (dialplan == -1) { 02192 return("Dynamically set dialplan in ISDN"); 02193 } 02194 return (pri_plan2str(dialplan)); 02195 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 2005 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
02006 { 02007 if (isdigit(digit)) 02008 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 02009 else if (digit >= 'A' && digit <= 'D') 02010 return DAHDI_TONE_DTMF_A + (digit - 'A'); 02011 else if (digit >= 'a' && digit <= 'd') 02012 return DAHDI_TONE_DTMF_A + (digit - 'a'); 02013 else if (digit == '*') 02014 return DAHDI_TONE_DTMF_s; 02015 else if (digit == '#') 02016 return DAHDI_TONE_DTMF_p; 02017 else 02018 return -1; 02019 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4558 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04559 { 04560 #ifdef DAHDI_TONEDETECT 04561 int val; 04562 #endif 04563 04564 p->ignoredtmf = 1; 04565 04566 #ifdef DAHDI_TONEDETECT 04567 val = 0; 04568 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04569 #endif 04570 if (!p->hardwaredtmf && p->dsp) { 04571 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04572 ast_dsp_set_features(p->dsp, p->dsp_features); 04573 } 04574 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10767 of file chan_dahdi.c.
References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verbose(), ast_waitfor(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, ast_channel::name, option_verbose, dahdi_pvt::pri, ast_channel::priority, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
Referenced by pri_dchannel().
10768 { 10769 struct ast_channel *chan = vchan; 10770 struct dahdi_pvt *pvt = chan->tech_pvt; 10771 struct ast_frame *f; 10772 char ex[80]; 10773 /* Wait up to 30 seconds for an answer */ 10774 int newms, ms = 30000; 10775 if (option_verbose > 2) 10776 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 10777 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10778 if (ast_call(chan, ex, 0)) { 10779 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10780 ast_hangup(chan); 10781 return NULL; 10782 } 10783 while ((newms = ast_waitfor(chan, ms)) > 0) { 10784 f = ast_read(chan); 10785 if (!f) { 10786 /* Got hangup */ 10787 break; 10788 } 10789 if (f->frametype == AST_FRAME_CONTROL) { 10790 switch (f->subclass) { 10791 case AST_CONTROL_ANSWER: 10792 /* Launch the PBX */ 10793 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10794 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10795 chan->priority = 1; 10796 if (option_verbose > 3) 10797 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10798 ast_pbx_run(chan); 10799 /* It's already hungup, return immediately */ 10800 return NULL; 10801 case AST_CONTROL_BUSY: 10802 if (option_verbose > 3) 10803 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 10804 break; 10805 case AST_CONTROL_CONGESTION: 10806 if (option_verbose > 3) 10807 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 10808 break; 10809 }; 10810 } 10811 ast_frfree(f); 10812 ms = newms; 10813 } 10814 /* Hangup the channel since nothing happend */ 10815 ast_hangup(chan); 10816 return NULL; 10817 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8729 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, free, ifcount, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08730 { 08731 int count, res, res2, spoint, pollres=0; 08732 struct dahdi_pvt *i; 08733 struct dahdi_pvt *last = NULL; 08734 struct dahdi_pvt *doomed; 08735 time_t thispass = 0, lastpass = 0; 08736 int found; 08737 char buf[1024]; 08738 struct pollfd *pfds=NULL; 08739 int lastalloc = -1; 08740 /* This thread monitors all the frame relay interfaces which are not yet in use 08741 (and thus do not have a separate thread) indefinitely */ 08742 /* From here on out, we die whenever asked */ 08743 #if 0 08744 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08745 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08746 return NULL; 08747 } 08748 ast_log(LOG_DEBUG, "Monitor starting...\n"); 08749 #endif 08750 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08751 08752 for (;;) { 08753 /* Lock the interface list */ 08754 ast_mutex_lock(&iflock); 08755 if (!pfds || (lastalloc != ifcount)) { 08756 if (pfds) { 08757 free(pfds); 08758 pfds = NULL; 08759 } 08760 if (ifcount) { 08761 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08762 ast_mutex_unlock(&iflock); 08763 return NULL; 08764 } 08765 } 08766 lastalloc = ifcount; 08767 } 08768 /* Build the stuff we're going to poll on, that is the socket of every 08769 dahdi_pvt that does not have an associated owner channel */ 08770 count = 0; 08771 i = iflist; 08772 while (i) { 08773 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 08774 if (!i->owner && !i->subs[SUB_REAL].owner) { 08775 /* This needs to be watched, as it lacks an owner */ 08776 pfds[count].fd = i->subs[SUB_REAL].dfd; 08777 pfds[count].events = POLLPRI; 08778 pfds[count].revents = 0; 08779 /* Message waiting or r2 channels also get watched for reading */ 08780 if (i->cidspill || 08781 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 08782 pfds[count].events |= POLLIN; 08783 } 08784 count++; 08785 } 08786 } 08787 i = i->next; 08788 } 08789 /* Okay, now that we know what to do, release the interface lock */ 08790 ast_mutex_unlock(&iflock); 08791 08792 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08793 pthread_testcancel(); 08794 /* Wait at least a second for something to happen */ 08795 res = poll(pfds, count, 1000); 08796 pthread_testcancel(); 08797 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08798 08799 /* Okay, poll has finished. Let's see what happened. */ 08800 if (res < 0) { 08801 if ((errno != EAGAIN) && (errno != EINTR)) 08802 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08803 continue; 08804 } 08805 /* Alright, lock the interface list again, and let's look and see what has 08806 happened */ 08807 ast_mutex_lock(&iflock); 08808 found = 0; 08809 spoint = 0; 08810 lastpass = thispass; 08811 thispass = time(NULL); 08812 doomed = NULL; 08813 for (i = iflist;; i = i->next) { 08814 if (doomed) { 08815 int res; 08816 res = dahdi_destroy_channel_bynum(doomed->channel); 08817 if (!res) { 08818 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08819 } 08820 doomed = NULL; 08821 } 08822 if (!i) { 08823 break; 08824 } 08825 if (thispass != lastpass) { 08826 if (!found && ((i == last) || ((i == iflist) && !last))) { 08827 last = i; 08828 if (last) { 08829 if (!last->cidspill 08830 && !last->owner 08831 && !ast_strlen_zero(last->mailbox) 08832 && (thispass - last->onhooktime > 3) 08833 && (last->sig & __DAHDI_SIG_FXO)) { 08834 res = ast_app_has_voicemail(last->mailbox, NULL); 08835 if (last->msgstate != res) { 08836 int x; 08837 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08838 x = DAHDI_FLUSH_BOTH; 08839 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08840 if (res2) 08841 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 08842 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08843 /* Turn on on hook transfer for 4 seconds */ 08844 x = 4000; 08845 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08846 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08847 last->cidpos = 0; 08848 last->msgstate = res; 08849 last->onhooktime = thispass; 08850 } 08851 found ++; 08852 } 08853 } 08854 last = last->next; 08855 } 08856 } 08857 } 08858 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08859 if (i->radio && !i->owner) 08860 { 08861 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08862 if (res) 08863 { 08864 if (option_debug) 08865 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08866 /* Don't hold iflock while handling init events */ 08867 ast_mutex_unlock(&iflock); 08868 doomed = handle_init_event(i, res); 08869 ast_mutex_lock(&iflock); 08870 } 08871 continue; 08872 } 08873 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08874 if (pollres & POLLIN) { 08875 if (i->owner || i->subs[SUB_REAL].owner) { 08876 #ifdef HAVE_PRI 08877 if (!i->pri) 08878 #endif 08879 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08880 continue; 08881 } 08882 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08883 if (res > 0) { 08884 /* We read some number of bytes. Write an equal amount of data */ 08885 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 08886 if (i->cid_start == CID_START_DTMF_NOALERT) { 08887 int energy; 08888 struct timeval now; 08889 /* State machine dtmfcid_holdoff_state allows for the line to settle 08890 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 08891 */ 08892 if (1 == i->dtmfcid_holdoff_state) { 08893 gettimeofday(&i->dtmfcid_delay, NULL); 08894 i->dtmfcid_holdoff_state = 2; 08895 } else if (2 == i->dtmfcid_holdoff_state) { 08896 gettimeofday(&now, NULL); 08897 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 08898 i->dtmfcid_holdoff_state = 0; 08899 } 08900 } else { 08901 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 08902 if (energy > dtmfcid_level) { 08903 pthread_t threadid; 08904 struct ast_channel *chan; 08905 ast_mutex_unlock(&iflock); 08906 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08907 if (!chan) { 08908 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08909 } else { 08910 pthread_attr_t attr; 08911 pthread_attr_init(&attr); 08912 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08913 res = ast_pthread_create(&threadid, &attr, ss_thread, chan); 08914 if (res) { 08915 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08916 } else { 08917 i->dtmfcid_holdoff_state = 1; 08918 } 08919 } 08920 ast_mutex_lock(&iflock); 08921 } 08922 } 08923 } 08924 } else { 08925 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08926 } 08927 } 08928 if (pollres & POLLPRI) { 08929 if (i->owner || i->subs[SUB_REAL].owner) { 08930 #ifdef HAVE_PRI 08931 if (!i->pri) 08932 #endif 08933 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08934 continue; 08935 } 08936 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08937 if (option_debug) 08938 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08939 /* Don't hold iflock while handling init events */ 08940 ast_mutex_unlock(&iflock); 08941 doomed = handle_init_event(i, res); 08942 ast_mutex_lock(&iflock); 08943 } 08944 } 08945 } 08946 ast_mutex_unlock(&iflock); 08947 } 08948 /* Never reached */ 08949 return NULL; 08950 08951 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4576 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04577 { 04578 #ifdef DAHDI_TONEDETECT 04579 int val; 04580 #endif 04581 04582 if (p->channel == CHAN_PSEUDO) 04583 return; 04584 04585 p->ignoredtmf = 0; 04586 04587 #ifdef DAHDI_TONEDETECT 04588 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04589 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04590 #endif 04591 if (!p->hardwaredtmf && p->dsp) { 04592 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04593 ast_dsp_set_features(p->dsp, p->dsp_features); 04594 } 04595 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 2179 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
02180 { 02181 static char buf[256]; 02182 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 02183 return events[event]; 02184 sprintf(buf, "Event %d", event); /* safe */ 02185 return buf; 02186 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2544 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02545 { 02546 int j; 02547 int k; 02548 float linear_gain = pow(10.0, gain / 20.0); 02549 02550 switch (law) { 02551 case DAHDI_LAW_ALAW: 02552 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02553 if (gain) { 02554 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02555 if (k > 32767) k = 32767; 02556 if (k < -32767) k = -32767; 02557 g->rxgain[j] = AST_LIN2A(k); 02558 } else { 02559 g->rxgain[j] = j; 02560 } 02561 } 02562 break; 02563 case DAHDI_LAW_MULAW: 02564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02565 if (gain) { 02566 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02567 if (k > 32767) k = 32767; 02568 if (k < -32767) k = -32767; 02569 g->rxgain[j] = AST_LIN2MU(k); 02570 } else { 02571 g->rxgain[j] = j; 02572 } 02573 } 02574 break; 02575 } 02576 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2510 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02511 { 02512 int j; 02513 int k; 02514 float linear_gain = pow(10.0, gain / 20.0); 02515 02516 switch (law) { 02517 case DAHDI_LAW_ALAW: 02518 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02519 if (gain) { 02520 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02521 if (k > 32767) k = 32767; 02522 if (k < -32767) k = -32767; 02523 g->txgain[j] = AST_LIN2A(k); 02524 } else { 02525 g->txgain[j] = j; 02526 } 02527 } 02528 break; 02529 case DAHDI_LAW_MULAW: 02530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02531 if (gain) { 02532 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02533 if (k > 32767) k = 32767; 02534 if (k < -32767) k = -32767; 02535 g->txgain[j] = AST_LIN2MU(k); 02536 } else { 02537 g->txgain[j] = j; 02538 } 02539 } 02540 break; 02541 } 02542 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 13662 of file chan_dahdi.c.
References dahdi_pvt::channel, iflist, and dahdi_pvt::next.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
13663 { 13664 struct dahdi_pvt *p = iflist; 13665 while (p) { 13666 if (p->channel == channel) { 13667 break; 13668 } 13669 p = p->next; 13670 } 13671 return p; 13672 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5068 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by __action_showchannels(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), and handle_init_event().
05069 { 05070 int res; 05071 struct dahdi_spaninfo zi; 05072 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 05073 /* 05074 * The conditional compilation is needed only in asterisk-1.4 for 05075 * backward compatibility with old zaptel drivers that don't have 05076 * a DAHDI_PARAMS.chan_alarms field. 05077 */ 05078 struct dahdi_params params; 05079 #endif 05080 05081 memset(&zi, 0, sizeof(zi)); 05082 zi.spanno = p->span; 05083 05084 /* First check for span alarms */ 05085 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 05086 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 05087 return 0; 05088 } 05089 if (zi.alarms != DAHDI_ALARM_NONE) 05090 return zi.alarms; 05091 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 05092 /* No alarms on the span. Check for channel alarms. */ 05093 memset(¶ms, 0, sizeof(params)); 05094 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 05095 return params.chan_alarms; 05096 /* ioctl failed */ 05097 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 05098 #endif 05099 return DAHDI_ALARM_NONE; 05100 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 5202 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.
Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), and handle_init_event().
05203 { 05204 const char *alarm_str = alarm2str(alarms); 05205 05206 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 05207 * doesn't know what to do with it. Don't confuse users with log messages. */ 05208 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 05209 p->unknown_alarm = 1; 05210 return; 05211 } else { 05212 p->unknown_alarm = 0; 05213 } 05214 05215 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 05216 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 05217 "Alarm: %s\r\n" 05218 "Channel: %d\r\n", 05219 alarm_str, p->channel); 05220 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 13477 of file chan_dahdi.c.
References ast_cli(), cadences, cidrings, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, num_cadence, and term_color().
13478 { 13479 int i, j; 13480 for (i = 0; i < num_cadence; i++) { 13481 char output[1024]; 13482 char tmp[16], tmp2[64]; 13483 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 13484 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 13485 13486 for (j = 0; j < 16; j++) { 13487 if (cadences[i].ringcadence[j] == 0) 13488 break; 13489 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 13490 if (cidrings[i] * 2 - 1 == j) 13491 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 13492 else 13493 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 13494 if (j != 0) 13495 strncat(output, ",", sizeof(output) - strlen(output) - 1); 13496 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 13497 } 13498 ast_cli(fd,"%s\n",output); 13499 } 13500 return 0; 13501 }
Definition at line 8512 of file chan_dahdi.c.
References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::resetting, 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_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ss_thread(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.
08513 { 08514 int res; 08515 pthread_t threadid; 08516 pthread_attr_t attr; 08517 struct ast_channel *chan; 08518 pthread_attr_init(&attr); 08519 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08520 /* Handle an event on a given channel for the monitor thread. */ 08521 switch (event) { 08522 case DAHDI_EVENT_NONE: 08523 case DAHDI_EVENT_BITSCHANGED: 08524 break; 08525 case DAHDI_EVENT_WINKFLASH: 08526 case DAHDI_EVENT_RINGOFFHOOK: 08527 if (i->inalarm) break; 08528 if (i->radio) break; 08529 /* Got a ring/answer. What kind of channel are we? */ 08530 switch (i->sig) { 08531 case SIG_FXOLS: 08532 case SIG_FXOGS: 08533 case SIG_FXOKS: 08534 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08535 if (res && (errno == EBUSY)) 08536 break; 08537 08538 /* Cancel VMWI spill */ 08539 free(i->cidspill); 08540 i->cidspill = NULL; 08541 restore_conference(i); 08542 08543 if (i->immediate) { 08544 dahdi_enable_ec(i); 08545 /* The channel is immediately up. Start right away */ 08546 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08547 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08548 if (!chan) { 08549 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08550 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08551 if (res < 0) 08552 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08553 } 08554 } else { 08555 /* Check for callerid, digits, etc */ 08556 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08557 if (chan) { 08558 if (has_voicemail(i)) 08559 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08560 else 08561 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08562 if (res < 0) 08563 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08564 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08565 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08566 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08567 if (res < 0) 08568 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08569 ast_hangup(chan); 08570 } 08571 } else 08572 ast_log(LOG_WARNING, "Unable to create channel\n"); 08573 } 08574 break; 08575 case SIG_FXSLS: 08576 case SIG_FXSGS: 08577 case SIG_FXSKS: 08578 i->ringt = i->ringt_base; 08579 /* Fall through */ 08580 case SIG_EMWINK: 08581 case SIG_FEATD: 08582 case SIG_FEATDMF: 08583 case SIG_FEATDMF_TA: 08584 case SIG_E911: 08585 case SIG_FGC_CAMA: 08586 case SIG_FGC_CAMAMF: 08587 case SIG_FEATB: 08588 case SIG_EM: 08589 case SIG_EM_E1: 08590 case SIG_SFWINK: 08591 case SIG_SF_FEATD: 08592 case SIG_SF_FEATDMF: 08593 case SIG_SF_FEATB: 08594 case SIG_SF: 08595 /* Check for callerid, digits, etc */ 08596 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08597 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08598 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08599 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08600 if (res < 0) 08601 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08602 ast_hangup(chan); 08603 } else if (!chan) { 08604 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08605 } 08606 break; 08607 default: 08608 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08609 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08610 if (res < 0) 08611 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08612 pthread_attr_destroy(&attr); 08613 return NULL; 08614 } 08615 break; 08616 case DAHDI_EVENT_NOALARM: 08617 i->inalarm = 0; 08618 #if defined(HAVE_PRI) 08619 i->resetting = 0; 08620 #endif /* defined(HAVE_PRI) */ 08621 if (!i->unknown_alarm) { 08622 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08623 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08624 "Channel: %d\r\n", i->channel); 08625 } else { 08626 i->unknown_alarm = 0; 08627 } 08628 break; 08629 case DAHDI_EVENT_ALARM: 08630 i->inalarm = 1; 08631 #if defined(HAVE_PRI) 08632 i->resetting = 0; 08633 #endif /* defined(HAVE_PRI) */ 08634 res = get_alarms(i); 08635 handle_alarms(i, res); 08636 /* fall thru intentionally */ 08637 case DAHDI_EVENT_ONHOOK: 08638 if (i->radio) 08639 break; 08640 /* Back on hook. Hang up. */ 08641 switch (i->sig) { 08642 case SIG_FXOLS: 08643 case SIG_FXOGS: 08644 case SIG_FEATD: 08645 case SIG_FEATDMF: 08646 case SIG_FEATDMF_TA: 08647 case SIG_E911: 08648 case SIG_FGC_CAMA: 08649 case SIG_FGC_CAMAMF: 08650 case SIG_FEATB: 08651 case SIG_EM: 08652 case SIG_EM_E1: 08653 case SIG_EMWINK: 08654 case SIG_SF_FEATD: 08655 case SIG_SF_FEATDMF: 08656 case SIG_SF_FEATB: 08657 case SIG_SF: 08658 case SIG_SFWINK: 08659 case SIG_FXSLS: 08660 case SIG_FXSGS: 08661 case SIG_FXSKS: 08662 case SIG_GR303FXSKS: 08663 dahdi_disable_ec(i); 08664 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08665 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08666 break; 08667 case SIG_GR303FXOKS: 08668 case SIG_FXOKS: 08669 dahdi_disable_ec(i); 08670 /* Diddle the battery for the zhone */ 08671 #ifdef ZHONE_HACK 08672 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08673 usleep(1); 08674 #endif 08675 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08676 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08677 break; 08678 case SIG_PRI: 08679 dahdi_disable_ec(i); 08680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08681 break; 08682 default: 08683 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08684 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08685 pthread_attr_destroy(&attr); 08686 return NULL; 08687 } 08688 break; 08689 case DAHDI_EVENT_POLARITY: 08690 switch (i->sig) { 08691 case SIG_FXSLS: 08692 case SIG_FXSKS: 08693 case SIG_FXSGS: 08694 /* We have already got a PR before the channel was 08695 created, but it wasn't handled. We need polarity 08696 to be REV for remote hangup detection to work. 08697 At least in Spain */ 08698 if (i->hanguponpolarityswitch) 08699 i->polarity = POLARITY_REV; 08700 08701 if (i->cid_start == CID_START_POLARITY) { 08702 i->polarity = POLARITY_REV; 08703 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 08704 "CID detection on channel %d\n", 08705 i->channel); 08706 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08707 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08708 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08709 } 08710 } 08711 break; 08712 default: 08713 ast_log(LOG_WARNING, "handle_init_event detected " 08714 "polarity reversal on non-FXO (SIG_FXS) " 08715 "interface %d\n", i->channel); 08716 } 08717 break; 08718 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08719 ast_log(LOG_NOTICE, 08720 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08721 i->channel); 08722 pthread_attr_destroy(&attr); 08723 return i; 08724 } 08725 pthread_attr_destroy(&attr); 08726 return NULL; 08727 }
static int handle_mfcr2_call_files | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12879 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.
12880 { 12881 struct dahdi_pvt *p = NULL; 12882 int channo = 0; 12883 if (argc < 4) { 12884 return RESULT_SHOWUSAGE; 12885 } 12886 channo = (argc == 5) ? atoi(argv[4]) : -1; 12887 ast_mutex_lock(&iflock); 12888 p = iflist; 12889 while (p) { 12890 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 12891 p = p->next; 12892 continue; 12893 } 12894 if ((channo != -1) && (p->channel != channo )) { 12895 p = p->next; 12896 continue; 12897 } 12898 if (ast_true(argv[3])) { 12899 openr2_chan_enable_call_files(p->r2chan); 12900 } else { 12901 openr2_chan_disable_call_files(p->r2chan); 12902 } 12903 if (channo != -1) { 12904 if (ast_true(argv[3])) { 12905 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 12906 } else { 12907 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 12908 } 12909 break; 12910 } else { 12911 p = p->next; 12912 } 12913 } 12914 if ((channo != -1) && !p) { 12915 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 12916 } 12917 if (channo == -1) { 12918 if (ast_true(argv[3])) { 12919 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n"); 12920 } else { 12921 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n"); 12922 } 12923 } 12924 ast_mutex_unlock(&iflock); 12925 return RESULT_SUCCESS; 12926 }
static int handle_mfcr2_set_blocked | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12963 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.
12964 { 12965 struct dahdi_pvt *p = NULL; 12966 int channo = 0; 12967 channo = (argc == 4) ? atoi(argv[3]) : -1; 12968 ast_mutex_lock(&iflock); 12969 p = iflist; 12970 while (p) { 12971 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 12972 p = p->next; 12973 continue; 12974 } 12975 if ((channo != -1) && (p->channel != channo )) { 12976 p = p->next; 12977 continue; 12978 } 12979 if (!openr2_chan_set_blocked(p->r2chan)) { 12980 ast_mutex_lock(&p->lock); 12981 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK; 12982 ast_mutex_unlock(&p->lock); 12983 } else { 12984 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel); 12985 } 12986 if (channo != -1) { 12987 break; 12988 } else { 12989 p = p->next; 12990 } 12991 } 12992 if ((channo != -1) && !p) { 12993 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 12994 } 12995 ast_mutex_unlock(&iflock); 12996 return RESULT_SUCCESS; 12997 }
static int handle_mfcr2_set_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12820 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, dahdi_pvt::channel, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.
12821 { 12822 struct dahdi_pvt *p = NULL; 12823 int channo = 0; 12824 char *toklevel = NULL; 12825 char *saveptr = NULL; 12826 char *logval = NULL; 12827 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 12828 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 12829 if (argc < 4) { 12830 return RESULT_SHOWUSAGE; 12831 } 12832 channo = (argc == 5) ? atoi(argv[4]) : -1; 12833 logval = ast_strdupa(argv[3]); 12834 toklevel = strtok_r(logval, ",", &saveptr); 12835 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 12836 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]); 12837 return RESULT_FAILURE; 12838 } else if (OR2_LOG_NOTHING == tmplevel) { 12839 loglevel = tmplevel; 12840 } else { 12841 loglevel |= tmplevel; 12842 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 12843 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 12844 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 12845 continue; 12846 } 12847 loglevel |= tmplevel; 12848 } 12849 } 12850 ast_mutex_lock(&iflock); 12851 p = iflist; 12852 while (p) { 12853 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 12854 p = p->next; 12855 continue; 12856 } 12857 if ((channo != -1) && (p->channel != channo )) { 12858 p = p->next; 12859 continue; 12860 } 12861 openr2_chan_set_log_level(p->r2chan, loglevel); 12862 if (channo != -1) { 12863 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel); 12864 break; 12865 } else { 12866 p = p->next; 12867 } 12868 } 12869 if ((channo != -1) && !p) { 12870 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 12871 } 12872 if (channo == -1) { 12873 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]); 12874 } 12875 ast_mutex_unlock(&iflock); 12876 return RESULT_SUCCESS; 12877 }
static int handle_mfcr2_set_idle | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12928 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, iflist, iflock, dahdi_pvt::lock, dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.
12929 { 12930 struct dahdi_pvt *p = NULL; 12931 int channo = 0; 12932 channo = (argc == 4) ? atoi(argv[3]) : -1; 12933 ast_mutex_lock(&iflock); 12934 p = iflist; 12935 while (p) { 12936 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 12937 p = p->next; 12938 continue; 12939 } 12940 if ((channo != -1) && (p->channel != channo )) { 12941 p = p->next; 12942 continue; 12943 } 12944 if (!openr2_chan_set_idle(p->r2chan)) { 12945 ast_mutex_lock(&p->lock); 12946 p->mfcr2call = 0; 12947 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 12948 ast_mutex_unlock(&p->lock); 12949 } 12950 if (channo != -1) { 12951 break; 12952 } else { 12953 p = p->next; 12954 } 12955 } 12956 if ((channo != -1) && !p) { 12957 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 12958 } 12959 ast_mutex_unlock(&iflock); 12960 return RESULT_SUCCESS; 12961 }
static int handle_mfcr2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12751 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, FORMAT, dahdi_pvt::group, iflist, iflock, dahdi_pvt::next, dahdi_pvt::r2chan, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, and SIG_MFCR2.
12752 { 12753 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 12754 int filtertype = 0; 12755 int targetnum = 0; 12756 char channo[5]; 12757 char anino[5]; 12758 char dnisno[5]; 12759 struct dahdi_pvt *p; 12760 openr2_context_t *r2context; 12761 openr2_variant_t r2variant; 12762 if (!((argc == 3) || (argc == 5))) { 12763 return RESULT_SHOWUSAGE; 12764 } 12765 if (argc == 5) { 12766 if (!strcasecmp(argv[3], "group")) { 12767 targetnum = atoi(argv[4]); 12768 if ((targetnum < 0) || (targetnum > 63)) 12769 return RESULT_SHOWUSAGE; 12770 targetnum = 1 << targetnum; 12771 filtertype = 1; 12772 } else if (!strcasecmp(argv[3], "context")) { 12773 filtertype = 2; 12774 } else { 12775 return RESULT_SHOWUSAGE; 12776 } 12777 } 12778 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 12779 ast_mutex_lock(&iflock); 12780 p = iflist; 12781 while (p) { 12782 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 12783 p = p->next; 12784 continue; 12785 } 12786 if (filtertype) { 12787 switch(filtertype) { 12788 case 1: /* mfcr2 show channels group <group> */ 12789 if (p->group != targetnum) { 12790 p = p->next; 12791 continue; 12792 } 12793 break; 12794 case 2: /* mfcr2 show channels context <context> */ 12795 if (strcasecmp(p->context, argv[4])) { 12796 p= p->next; 12797 continue; 12798 } 12799 break; 12800 default: 12801 ; 12802 } 12803 } 12804 r2context = openr2_chan_get_context(p->r2chan); 12805 r2variant = openr2_context_get_variant(r2context); 12806 snprintf(channo, sizeof(channo), "%d", p->channel); 12807 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 12808 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 12809 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 12810 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 12811 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 12812 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 12813 p = p->next; 12814 } 12815 ast_mutex_unlock(&iflock); 12816 return RESULT_SUCCESS; 12817 #undef FORMAT 12818 }
static int handle_mfcr2_show_variants | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12733 of file chan_dahdi.c.
References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.
12734 { 12735 #define FORMAT "%4s %40s\n" 12736 int numvariants = 0; 12737 int i; 12738 const openr2_variant_entry_t *variants; 12739 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 12740 ast_cli(fd, "Failed to get list of variants.\n"); 12741 return RESULT_FAILURE; 12742 } 12743 ast_cli(fd, FORMAT, "Variant Code", "Country"); 12744 for (i = 0; i < numvariants; i++) { 12745 ast_cli(fd, FORMAT, variants[i].name, variants[i].country); 12746 } 12747 return RESULT_SUCCESS; 12748 #undef FORMAT 12749 }
static int handle_mfcr2_version | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12727 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
12728 { 12729 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 12730 return RESULT_SUCCESS; 12731 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12478 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12479 { 12480 int span; 12481 int x; 12482 if (argc < 4) { 12483 return RESULT_SHOWUSAGE; 12484 } 12485 span = atoi(argv[3]); 12486 if ((span < 1) || (span > NUM_SPANS)) { 12487 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 12488 return RESULT_SUCCESS; 12489 } 12490 if (!pris[span-1].pri) { 12491 ast_cli(fd, "No PRI running on span %d\n", span); 12492 return RESULT_SUCCESS; 12493 } 12494 for (x = 0; x < NUM_DCHANS; x++) { 12495 if (pris[span-1].dchans[x]) 12496 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12497 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12498 PRI_DEBUG_Q921_STATE); 12499 } 12500 ast_cli(fd, "Enabled debugging on span %d\n", span); 12501 return RESULT_SUCCESS; 12502 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12506 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12507 { 12508 int span; 12509 int x; 12510 if (argc < 5) 12511 return RESULT_SHOWUSAGE; 12512 span = atoi(argv[4]); 12513 if ((span < 1) || (span > NUM_SPANS)) { 12514 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 12515 return RESULT_SUCCESS; 12516 } 12517 if (!pris[span-1].pri) { 12518 ast_cli(fd, "No PRI running on span %d\n", span); 12519 return RESULT_SUCCESS; 12520 } 12521 for (x = 0; x < NUM_DCHANS; x++) { 12522 if (pris[span-1].dchans[x]) 12523 pri_set_debug(pris[span-1].dchans[x], 0); 12524 } 12525 ast_cli(fd, "Disabled debugging on span %d\n", span); 12526 return RESULT_SUCCESS; 12527 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12529 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12530 { 12531 int span; 12532 int x; 12533 if (argc < 5) 12534 return RESULT_SHOWUSAGE; 12535 span = atoi(argv[4]); 12536 if ((span < 1) || (span > NUM_SPANS)) { 12537 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 12538 return RESULT_SUCCESS; 12539 } 12540 if (!pris[span-1].pri) { 12541 ast_cli(fd, "No PRI running on span %d\n", span); 12542 return RESULT_SUCCESS; 12543 } 12544 for (x = 0; x < NUM_DCHANS; x++) { 12545 if (pris[span-1].dchans[x]) 12546 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12547 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12548 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12549 } 12550 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12551 return RESULT_SUCCESS; 12552 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12431 of file chan_dahdi.c.
References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), pridebugfd, pridebugfdlock, pridebugfilename, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12432 { 12433 int myfd; 12434 12435 if (!strncasecmp(argv[1], "set", 3)) { 12436 if (argc < 5) 12437 return RESULT_SHOWUSAGE; 12438 12439 if (ast_strlen_zero(argv[4])) 12440 return RESULT_SHOWUSAGE; 12441 12442 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 12443 if (myfd < 0) { 12444 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 12445 return RESULT_SUCCESS; 12446 } 12447 12448 ast_mutex_lock(&pridebugfdlock); 12449 12450 if (pridebugfd >= 0) 12451 close(pridebugfd); 12452 12453 pridebugfd = myfd; 12454 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 12455 12456 ast_mutex_unlock(&pridebugfdlock); 12457 12458 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 12459 } else { 12460 /* Assume it is unset */ 12461 ast_mutex_lock(&pridebugfdlock); 12462 close(pridebugfd); 12463 pridebugfd = -1; 12464 ast_cli(fd, "PRI debug output to file disabled\n"); 12465 ast_mutex_unlock(&pridebugfdlock); 12466 } 12467 12468 return RESULT_SUCCESS; 12469 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12637 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfd, pridebugfdlock, pridebugfilename, pris, and RESULT_SUCCESS.
12638 { 12639 int x; 12640 int span; 12641 int count=0; 12642 int debug=0; 12643 12644 for (span = 0; span < NUM_SPANS; span++) { 12645 if (pris[span].pri) { 12646 for (x = 0; x < NUM_DCHANS; x++) { 12647 debug = 0; 12648 if (pris[span].dchans[x]) { 12649 debug = pri_get_debug(pris[span].dchans[x]); 12650 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" ); 12651 count++; 12652 } 12653 } 12654 } 12655 12656 } 12657 ast_mutex_lock(&pridebugfdlock); 12658 if (pridebugfd >= 0) 12659 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 12660 ast_mutex_unlock(&pridebugfdlock); 12661 12662 if (!count) 12663 ast_cli(fd, "No debug set or no PRI running\n"); 12664 return RESULT_SUCCESS; 12665 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12596 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, lock, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12597 { 12598 int span; 12599 int x; 12600 char status[256]; 12601 if (argc < 4) 12602 return RESULT_SHOWUSAGE; 12603 span = atoi(argv[3]); 12604 if ((span < 1) || (span > NUM_SPANS)) { 12605 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 12606 return RESULT_SUCCESS; 12607 } 12608 if (!pris[span-1].pri) { 12609 ast_cli(fd, "No PRI running on span %d\n", span); 12610 return RESULT_SUCCESS; 12611 } 12612 for (x = 0; x < NUM_DCHANS; x++) { 12613 if (pris[span-1].dchannels[x]) { 12614 #ifdef PRI_DUMP_INFO_STR 12615 char *info_str = NULL; 12616 #endif 12617 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12618 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12619 ast_cli(fd, "Status: %s\n", status); 12620 ast_mutex_lock(&pris[span - 1].lock); 12621 #ifdef PRI_DUMP_INFO_STR 12622 info_str = pri_dump_info_str(pris[span-1].pri); 12623 if (info_str) { 12624 ast_cli(fd, "%s", info_str); 12625 free(info_str); 12626 } 12627 #else 12628 pri_dump_info(pris[span-1].pri); 12629 #endif 12630 ast_mutex_unlock(&pris[span - 1].lock); 12631 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12632 } 12633 } 12634 return RESULT_SUCCESS; 12635 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12575 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12576 { 12577 int span; 12578 int x; 12579 char status[256]; 12580 if (argc != 3) 12581 return RESULT_SHOWUSAGE; 12582 12583 for (span = 0; span < NUM_SPANS; span++) { 12584 if (pris[span].pri) { 12585 for (x = 0; x < NUM_DCHANS; x++) { 12586 if (pris[span].dchannels[x]) { 12587 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12588 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12589 } 12590 } 12591 } 12592 } 12593 return RESULT_SUCCESS; 12594 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12472 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
12472 { 12473 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 12474 return RESULT_SUCCESS; 12475 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2742 of file chan_dahdi.c.
References ast_app_has_voicemail(), and dahdi_pvt::mailbox.
Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().
02743 { 02744 02745 return ast_app_has_voicemail(p->mailbox, NULL); 02746 }
static void init_mfcr2_globals | ( | void | ) | [static] |
Definition at line 1343 of file chan_dahdi.c.
References AST_PTHREADT_NULL, master, mfcr2_cur_allow_collect_calls, mfcr2_cur_call_files, mfcr2_cur_category, mfcr2_cur_context_index, mfcr2_cur_double_answer, mfcr2_cur_forced_release, mfcr2_cur_get_ani_first, mfcr2_cur_immediate_accept, mfcr2_cur_logdir, mfcr2_cur_loglevel, mfcr2_cur_max_ani, mfcr2_cur_max_dnis, mfcr2_cur_metering_pulse_timeout, mfcr2_cur_mfback_timeout, mfcr2_cur_r2proto_file, mfcr2_cur_skip_category, mfcr2_cur_variant, NUM_SPANS, and r2links.
Referenced by dahdi_restart(), and load_module().
01344 { 01345 int r; 01346 mfcr2_cur_context_index = 0; 01347 mfcr2_cur_variant = OR2_VAR_UNKNOWN; 01348 mfcr2_cur_mfback_timeout = -1; 01349 mfcr2_cur_metering_pulse_timeout = -1; 01350 mfcr2_cur_max_ani = 10; 01351 mfcr2_cur_max_dnis = 4; 01352 mfcr2_cur_get_ani_first = -1; 01353 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 01354 mfcr2_cur_dtmf_dialing = -1; 01355 mfcr2_cur_dtmf_detection = -1; 01356 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON; 01357 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF; 01358 #endif 01359 mfcr2_cur_skip_category = -1; 01360 mfcr2_cur_call_files = 0; 01361 mfcr2_cur_allow_collect_calls = 0; 01362 mfcr2_cur_forced_release = 0; 01363 mfcr2_cur_double_answer = 0; 01364 mfcr2_cur_immediate_accept = -1; 01365 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING; 01366 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 01367 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir)); 01368 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file)); 01369 memset(r2links, 0, sizeof(r2links)); 01370 for (r = 0; r < NUM_SPANS; r++) { 01371 r2links[r].master = AST_PTHREADT_NULL; 01372 } 01373 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 2300 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
02301 { 02302 /* If they're listening to our channel, they're ours */ 02303 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 02304 return 1; 02305 /* If they're a talker on our (allocated) conference, they're ours */ 02306 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 02307 return 1; 02308 return 0; 02309 }
Definition at line 2330 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
02331 { 02332 int x; 02333 int useslavenative; 02334 struct dahdi_pvt *slave = NULL; 02335 /* Start out optimistic */ 02336 useslavenative = 1; 02337 /* Update conference state in a stateless fashion */ 02338 for (x = 0; x < 3; x++) { 02339 /* Any three-way calling makes slave native mode *definitely* out 02340 of the question */ 02341 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 02342 useslavenative = 0; 02343 } 02344 /* If we don't have any 3-way calls, check to see if we have 02345 precisely one slave */ 02346 if (useslavenative) { 02347 for (x = 0; x < MAX_SLAVES; x++) { 02348 if (p->slaves[x]) { 02349 if (slave) { 02350 /* Whoops already have a slave! No 02351 slave native and stop right away */ 02352 slave = NULL; 02353 useslavenative = 0; 02354 break; 02355 } else { 02356 /* We have one slave so far */ 02357 slave = p->slaves[x]; 02358 } 02359 } 02360 } 02361 } 02362 /* If no slave, slave native definitely out */ 02363 if (!slave) 02364 useslavenative = 0; 02365 else if (slave->law != p->law) { 02366 useslavenative = 0; 02367 slave = NULL; 02368 } 02369 if (out) 02370 *out = slave; 02371 return useslavenative; 02372 }
static int load_module | ( | void | ) | [static] |
Definition at line 15081 of file chan_dahdi.c.
References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_accept_r2_call_exec(), dahdi_chan_mode, dahdi_cli, dahdi_mfcr2_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, init_mfcr2_globals(), inuse, local_astman_register, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, setup_dahdi(), ss_thread_complete, ast_channel_tech::type, zap_accept_r2_call_exec(), zap_send_keypad_facility_exec(), and zap_tech.
15082 { 15083 int res; 15084 15085 #ifdef HAVE_PRI 15086 int y,i; 15087 memset(pris, 0, sizeof(pris)); 15088 for (y = 0; y < NUM_SPANS; y++) { 15089 ast_mutex_init(&pris[y].lock); 15090 pris[y].offset = -1; 15091 pris[y].master = AST_PTHREADT_NULL; 15092 for (i = 0; i < NUM_DCHANS; i++) 15093 pris[y].fds[i] = -1; 15094 } 15095 pri_set_error(dahdi_pri_error); 15096 pri_set_message(dahdi_pri_message); 15097 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 15098 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15099 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15100 } 15101 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 15102 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 15103 #endif 15104 15105 #ifdef HAVE_OPENR2 15106 init_mfcr2_globals(); 15107 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 15108 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec, 15109 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip); 15110 } 15111 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec, 15112 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip); 15113 #endif 15114 15115 if ((res = setup_dahdi(0))) { 15116 return AST_MODULE_LOAD_DECLINE; 15117 } 15118 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 15119 chan_tech = &dahdi_tech; 15120 } else { 15121 chan_tech = &zap_tech; 15122 } 15123 if (ast_channel_register(chan_tech)) { 15124 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 15125 __unload_module(); 15126 return -1; 15127 } 15128 #ifdef HAVE_PRI 15129 ast_string_field_init(&inuse, 16); 15130 ast_string_field_set(&inuse, name, "GR-303InUse"); 15131 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 15132 #endif 15133 15134 #ifdef HAVE_OPENR2 15135 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 15136 #endif 15137 15138 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 15139 15140 memset(round_robin, 0, sizeof(round_robin)); 15141 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 15142 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 15143 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 15144 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 15145 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 15146 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 15147 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 15148 15149 ast_cond_init(&ss_thread_complete, NULL); 15150 15151 return res; 15152 }
static struct dahdi_mfcr2* mfcr2_get_context | ( | int | id | ) | [static] |
Definition at line 8985 of file chan_dahdi.c.
References ast_log(), LOG_ERROR, and r2links.
Referenced by mkintf().
08986 { 08987 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) { 08988 ast_log(LOG_ERROR, "No more R2 links available!.\n"); 08989 return NULL; 08990 } 08991 return &r2links[id]; 08992 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 10287 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::r2chan, SUB_REAL, and dahdi_pvt::subs.
Referenced by setup_dahdi().
10288 { 10289 struct dahdi_pvt *p; 10290 struct dahdi_mfcr2 *mfcr2 = data; 10291 /* we should be using pthread_key_create 10292 and allocate pollers dynamically. 10293 I think do_monitor() could be leaking, since it 10294 could be cancelled at any time and is not 10295 using thread keys, why?, */ 10296 struct pollfd pollers[mfcr2->numchans]; 10297 int maxsleep = 20; 10298 int res = 0; 10299 int i = 0; 10300 int pollsize = 0; 10301 int oldstate = 0; 10302 int was_idle = 0; 10303 int quit_loop = 0; 10304 /* now that we're ready to get calls, unblock our side and 10305 get current line state */ 10306 for (i = 0; i < mfcr2->numchans; i++) { 10307 p = mfcr2->pvts[i]; 10308 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 10309 if (openr2_chan_set_idle(p->r2chan)) { 10310 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel); 10311 } else { 10312 ast_mutex_lock(&p->lock); 10313 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 10314 mfcr2->pvts[i]->mfcr2call = 0; 10315 ast_mutex_unlock(&p->lock); 10316 } 10317 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 10318 } 10319 while(1) { 10320 /* we trust here that the mfcr2 channel list will not ever change once 10321 the module is loaded */ 10322 pollsize = 0; 10323 for (i = 0; i < mfcr2->numchans; i++) { 10324 pollers[i].events = 0; 10325 pollers[i].revents = 0; 10326 if (mfcr2->pvts[i]->owner) { 10327 continue; 10328 } 10329 if (!mfcr2->pvts[i]->r2chan) { 10330 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 10331 quit_loop = 1; 10332 break; 10333 } 10334 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 10335 pollers[i].events = POLLIN | POLLPRI; 10336 pollsize++; 10337 } 10338 if (quit_loop) { 10339 break; 10340 } 10341 10342 if (pollsize == 0) { 10343 if (!was_idle) { 10344 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n"); 10345 was_idle = 1; 10346 } 10347 poll(NULL, 0, maxsleep); 10348 continue; 10349 } 10350 was_idle = 0; 10351 10352 /* probably poll() is a valid cancel point, lets just be on the safe side 10353 by calling pthread_testcancel */ 10354 pthread_testcancel(); 10355 res = poll(pollers, mfcr2->numchans, maxsleep); 10356 pthread_testcancel(); 10357 if ((res < 0) && (errno != EINTR)) { 10358 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 10359 break; 10360 } 10361 /* do we want to allow to cancel while processing events? */ 10362 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 10363 for (i = 0; i < mfcr2->numchans; i++) { 10364 if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) { 10365 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 10366 } 10367 } 10368 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 10369 } 10370 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 10371 return 0; 10372 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 9118 of file chan_dahdi.c.
References ast_calloc, ast_config_AST_LOG_DIR, ast_copy_string(), ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_pvt::call, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), DAHDI_R2_LOCAL_BLOCK, dahdi_r2_on_chan_log(), DAHDI_R2_REMOTE_BLOCK, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), errno, dahdi_pri::facilityenable, free, dahdi_pri::idledial, dahdi_pri::idleext, ifcount, ifend, iflist, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::logicalspan, MAX_CHANNELS, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_category, dahdi_pvt::mfcr2_charge_calls, mfcr2_cur_accept_on_offer, mfcr2_cur_allow_collect_calls, mfcr2_cur_call_files, mfcr2_cur_category, mfcr2_cur_charge_calls, mfcr2_cur_context_index, mfcr2_cur_double_answer, mfcr2_cur_forced_release, mfcr2_cur_get_ani_first, mfcr2_cur_immediate_accept, mfcr2_cur_logdir, mfcr2_cur_loglevel, mfcr2_cur_max_ani, mfcr2_cur_max_dnis, mfcr2_cur_metering_pulse_timeout, mfcr2_cur_mfback_timeout, mfcr2_cur_r2proto_file, mfcr2_cur_skip_category, mfcr2_cur_variant, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_forced_release, mfcr2_get_context(), dahdi_pvt::mfcr2block, dahdi_pvt::mfcr2call, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pri::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_mfcr2::numchans, dahdi_pri::numchans, offset, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_resolve_span(), dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_mfcr2::protocol_context, dahdi_mfcr2::pvts, dahdi_pri::pvts, dahdi_pvt::r2chan, dahdi_pri::resetinterval, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.
Referenced by build_channels().
09119 { 09120 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 09121 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 09122 char fn[80]; 09123 #if 1 09124 struct dahdi_bufferinfo bi; 09125 #endif 09126 int res; 09127 int span=0; 09128 int here = 0; 09129 int x; 09130 struct dahdi_pvt **wlist; 09131 struct dahdi_pvt **wend; 09132 struct dahdi_params p; 09133 09134 wlist = &iflist; 09135 wend = &ifend; 09136 09137 #ifdef HAVE_PRI 09138 if (pri) { 09139 wlist = &pri->crvs; 09140 wend = &pri->crvend; 09141 } 09142 #endif 09143 09144 tmp2 = *wlist; 09145 prev = NULL; 09146 09147 while (tmp2) { 09148 if (!tmp2->destroy) { 09149 if (tmp2->channel == channel) { 09150 tmp = tmp2; 09151 here = 1; 09152 break; 09153 } 09154 if (tmp2->channel > channel) { 09155 break; 09156 } 09157 } 09158 prev = tmp2; 09159 tmp2 = tmp2->next; 09160 } 09161 09162 if (!here && reloading != 1) { 09163 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 09164 if (tmp) 09165 free(tmp); 09166 return NULL; 09167 } 09168 ast_mutex_init(&tmp->lock); 09169 ifcount++; 09170 for (x = 0; x < 3; x++) 09171 tmp->subs[x].dfd = -1; 09172 tmp->channel = channel; 09173 tmp->priindication_oob = conf->chan.priindication_oob; 09174 } 09175 09176 if (tmp) { 09177 int chan_sig = conf->chan.sig; 09178 if (!here) { 09179 if ((channel != CHAN_PSEUDO) && !pri) { 09180 int count = 0; 09181 snprintf(fn, sizeof(fn), "%d", channel); 09182 /* Open non-blocking */ 09183 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 09184 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 */ 09185 usleep(1); 09186 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 09187 count++; 09188 } 09189 /* Allocate a DAHDI structure */ 09190 if (tmp->subs[SUB_REAL].dfd < 0) { 09191 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); 09192 destroy_dahdi_pvt(&tmp); 09193 return NULL; 09194 } 09195 memset(&p, 0, sizeof(p)); 09196 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 09197 if (res < 0) { 09198 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 09199 destroy_dahdi_pvt(&tmp); 09200 return NULL; 09201 } 09202 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 09203 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype)); 09204 destroy_dahdi_pvt(&tmp); 09205 return NULL; 09206 } 09207 tmp->law = p.curlaw; 09208 tmp->span = p.spanno; 09209 span = p.spanno - 1; 09210 } else { 09211 if (channel == CHAN_PSEUDO) 09212 chan_sig = 0; 09213 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 09214 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 09215 return NULL; 09216 } 09217 } 09218 tmp->outsigmod = conf->chan.outsigmod; 09219 09220 #ifdef HAVE_PRI 09221 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 09222 int offset; 09223 int myswitchtype; 09224 int matchesdchan; 09225 int x,y; 09226 offset = 0; 09227 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 09228 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 09229 destroy_dahdi_pvt(&tmp); 09230 return NULL; 09231 } 09232 if (span >= NUM_SPANS) { 09233 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 09234 destroy_dahdi_pvt(&tmp); 09235 return NULL; 09236 } else { 09237 struct dahdi_spaninfo si; 09238 si.spanno = 0; 09239 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 09240 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 09241 destroy_dahdi_pvt(&tmp); 09242 return NULL; 09243 } 09244 /* Store the logical span first based upon the real span */ 09245 tmp->logicalspan = pris[span].prilogicalspan; 09246 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 09247 if (span < 0) { 09248 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 09249 destroy_dahdi_pvt(&tmp); 09250 return NULL; 09251 } 09252 if (chan_sig == SIG_PRI) 09253 myswitchtype = conf->pri.switchtype; 09254 else 09255 myswitchtype = PRI_SWITCH_GR303_TMC; 09256 /* Make sure this isn't a d-channel */ 09257 matchesdchan=0; 09258 for (x = 0; x < NUM_SPANS; x++) { 09259 for (y = 0; y < NUM_DCHANS; y++) { 09260 if (pris[x].dchannels[y] == tmp->channel) { 09261 matchesdchan = 1; 09262 break; 09263 } 09264 } 09265 } 09266 offset = p.chanpos; 09267 if (!matchesdchan) { 09268 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 09269 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 09270 destroy_dahdi_pvt(&tmp); 09271 return NULL; 09272 } 09273 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 09274 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 09275 destroy_dahdi_pvt(&tmp); 09276 return NULL; 09277 } 09278 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 09279 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 09280 destroy_dahdi_pvt(&tmp); 09281 return NULL; 09282 } 09283 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 09284 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 09285 destroy_dahdi_pvt(&tmp); 09286 return NULL; 09287 } 09288 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 09289 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 09290 destroy_dahdi_pvt(&tmp); 09291 return NULL; 09292 } 09293 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 09294 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 09295 destroy_dahdi_pvt(&tmp); 09296 return NULL; 09297 } 09298 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 09299 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 09300 destroy_dahdi_pvt(&tmp); 09301 return NULL; 09302 } 09303 if (pris[span].numchans >= MAX_CHANNELS) { 09304 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 09305 pris[span].trunkgroup); 09306 destroy_dahdi_pvt(&tmp); 09307 return NULL; 09308 } 09309 pris[span].nodetype = conf->pri.nodetype; 09310 pris[span].switchtype = myswitchtype; 09311 pris[span].nsf = conf->pri.nsf; 09312 pris[span].dialplan = conf->pri.dialplan; 09313 pris[span].localdialplan = conf->pri.localdialplan; 09314 pris[span].pvts[pris[span].numchans++] = tmp; 09315 pris[span].minunused = conf->pri.minunused; 09316 pris[span].minidle = conf->pri.minidle; 09317 pris[span].overlapdial = conf->pri.overlapdial; 09318 #ifdef HAVE_PRI_INBANDDISCONNECT 09319 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 09320 #endif 09321 pris[span].facilityenable = conf->pri.facilityenable; 09322 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 09323 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 09324 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 09325 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 09326 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 09327 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 09328 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 09329 pris[span].resetinterval = conf->pri.resetinterval; 09330 09331 tmp->pri = &pris[span]; 09332 tmp->prioffset = offset; 09333 tmp->call = NULL; 09334 09335 tmp->priexclusive = conf->chan.priexclusive; 09336 } else { 09337 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 09338 destroy_dahdi_pvt(&tmp); 09339 return NULL; 09340 } 09341 } 09342 } else { 09343 tmp->prioffset = 0; 09344 } 09345 #endif 09346 09347 #ifdef HAVE_OPENR2 09348 if (chan_sig == SIG_MFCR2 && reloading != 1) { 09349 char logdir[OR2_MAX_PATH]; 09350 struct dahdi_mfcr2 *dahdi_r2; 09351 int threshold = 0; 09352 int snres = 0; 09353 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index); 09354 if (!dahdi_r2) { 09355 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 09356 } else if (!dahdi_r2->protocol_context){ 09357 char tmplogdir[] = "/tmp"; 09358 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 09359 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis); 09360 if (!dahdi_r2->protocol_context) { 09361 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 09362 destroy_dahdi_pvt(&tmp); 09363 return NULL; 09364 } 09365 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel); 09366 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first); 09367 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category); 09368 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold); 09369 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout); 09370 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout); 09371 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer); 09372 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept); 09373 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 09374 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off); 09375 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection); 09376 #endif 09377 if (ast_strlen_zero(mfcr2_cur_logdir)) { 09378 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) { 09379 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 09380 } 09381 } else { 09382 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir); 09383 if (snres >= sizeof(logdir)) { 09384 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 09385 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 09386 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 09387 } 09388 } else { 09389 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 09390 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 09391 } 09392 } 09393 } 09394 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) { 09395 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) { 09396 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file); 09397 } 09398 } 09399 } 09400 if (dahdi_r2) { 09401 /* TODO: should we check numchans overflow, or is it already done by DAHDI? */ 09402 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp; 09403 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context, 09404 tmp->subs[SUB_REAL].dfd, NULL, NULL); 09405 if (!tmp->r2chan) { 09406 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context); 09407 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 09408 destroy_dahdi_pvt(&tmp); 09409 return NULL; 09410 } 09411 openr2_chan_set_client_data(tmp->r2chan, tmp); 09412 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 09413 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 09414 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel); 09415 if (mfcr2_cur_call_files) { 09416 openr2_chan_enable_call_files(tmp->r2chan); 09417 } 09418 tmp->mfcr2_category = mfcr2_cur_category; 09419 tmp->mfcr2 = dahdi_r2; 09420 tmp->mfcr2call = 0; 09421 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK; 09422 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer; 09423 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls; 09424 tmp->mfcr2_ani_index = 0; 09425 tmp->mfcr2_dnis_index = 0; 09426 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls; 09427 tmp->mfcr2_forced_release = mfcr2_cur_forced_release; 09428 } 09429 } 09430 #endif 09431 09432 } else { 09433 chan_sig = tmp->sig; 09434 if (tmp->subs[SUB_REAL].dfd > -1) { 09435 memset(&p, 0, sizeof(p)); 09436 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 09437 } 09438 } 09439 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 09440 switch (chan_sig) { 09441 case SIG_FXSKS: 09442 case SIG_FXSLS: 09443 case SIG_EM: 09444 case SIG_EM_E1: 09445 case SIG_EMWINK: 09446 case SIG_FEATD: 09447 case SIG_FEATDMF: 09448 case SIG_FEATDMF_TA: 09449 case SIG_FEATB: 09450 case SIG_E911: 09451 case SIG_SF: 09452 case SIG_SFWINK: 09453 case SIG_FGC_CAMA: 09454 case SIG_FGC_CAMAMF: 09455 case SIG_SF_FEATD: 09456 case SIG_SF_FEATDMF: 09457 case SIG_SF_FEATB: 09458 p.starttime = 250; 09459 break; 09460 } 09461 09462 if (tmp->radio) { 09463 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 09464 p.channo = channel; 09465 p.rxwinktime = 1; 09466 p.rxflashtime = 1; 09467 p.starttime = 1; 09468 p.debouncetime = 5; 09469 } 09470 if (!tmp->radio) { 09471 p.channo = channel; 09472 /* Override timing settings based on config file */ 09473 if (conf->timing.prewinktime >= 0) 09474 p.prewinktime = conf->timing.prewinktime; 09475 if (conf->timing.preflashtime >= 0) 09476 p.preflashtime = conf->timing.preflashtime; 09477 if (conf->timing.winktime >= 0) 09478 p.winktime = conf->timing.winktime; 09479 if (conf->timing.flashtime >= 0) 09480 p.flashtime = conf->timing.flashtime; 09481 if (conf->timing.starttime >= 0) 09482 p.starttime = conf->timing.starttime; 09483 if (conf->timing.rxwinktime >= 0) 09484 p.rxwinktime = conf->timing.rxwinktime; 09485 if (conf->timing.rxflashtime >= 0) 09486 p.rxflashtime = conf->timing.rxflashtime; 09487 if (conf->timing.debouncetime >= 0) 09488 p.debouncetime = conf->timing.debouncetime; 09489 } 09490 09491 /* dont set parms on a pseudo-channel (or CRV) */ 09492 if (tmp->subs[SUB_REAL].dfd >= 0) 09493 { 09494 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09495 if (res < 0) { 09496 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09497 destroy_dahdi_pvt(&tmp); 09498 return NULL; 09499 } 09500 } 09501 #if 1 09502 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09503 memset(&bi, 0, sizeof(bi)); 09504 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09505 if (!res) { 09506 bi.txbufpolicy = conf->chan.buf_policy; 09507 bi.rxbufpolicy = conf->chan.buf_policy; 09508 bi.numbufs = conf->chan.buf_no; 09509 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09510 if (res < 0) { 09511 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09512 } 09513 } else { 09514 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09515 } 09516 tmp->buf_policy = conf->chan.buf_policy; 09517 tmp->buf_no = conf->chan.buf_no; 09518 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 09519 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 09520 * The reason the ioctl call above failed should to be determined before worrying about the 09521 * faxbuffer-related ioctl calls */ 09522 tmp->bufsize = bi.bufsize; 09523 } 09524 #endif 09525 tmp->immediate = conf->chan.immediate; 09526 tmp->transfertobusy = conf->chan.transfertobusy; 09527 tmp->sig = chan_sig; 09528 tmp->ringt_base = ringt_base; 09529 tmp->firstradio = 0; 09530 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09531 tmp->permcallwaiting = conf->chan.callwaiting; 09532 else 09533 tmp->permcallwaiting = 0; 09534 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09535 tmp->destroy = 0; 09536 tmp->drings = drings; 09537 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 09538 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09539 tmp->threewaycalling = conf->chan.threewaycalling; 09540 tmp->adsi = conf->chan.adsi; 09541 tmp->use_smdi = conf->chan.use_smdi; 09542 tmp->permhidecallerid = conf->chan.hidecallerid; 09543 tmp->hidecalleridname = conf->chan.hidecalleridname; 09544 tmp->callreturn = conf->chan.callreturn; 09545 tmp->echocancel = conf->chan.echocancel; 09546 tmp->echotraining = conf->chan.echotraining; 09547 tmp->pulse = conf->chan.pulse; 09548 if (tmp->echocancel) 09549 tmp->echocanbridged = conf->chan.echocanbridged; 09550 else { 09551 if (conf->chan.echocanbridged) 09552 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09553 tmp->echocanbridged = 0; 09554 } 09555 tmp->busydetect = conf->chan.busydetect; 09556 tmp->busycount = conf->chan.busycount; 09557 tmp->busycompare = conf->chan.busycompare; 09558 tmp->busytonelength = conf->chan.busytonelength; 09559 tmp->busyquietlength = conf->chan.busyquietlength; 09560 tmp->busyfuzziness = conf->chan.busyfuzziness; 09561 tmp->silencethreshold = conf->chan.silencethreshold; 09562 tmp->callprogress = conf->chan.callprogress; 09563 tmp->cancallforward = conf->chan.cancallforward; 09564 tmp->dtmfrelax = conf->chan.dtmfrelax; 09565 tmp->callwaiting = tmp->permcallwaiting; 09566 tmp->hidecallerid = tmp->permhidecallerid; 09567 tmp->channel = channel; 09568 tmp->stripmsd = conf->chan.stripmsd; 09569 tmp->use_callerid = conf->chan.use_callerid; 09570 tmp->cid_signalling = conf->chan.cid_signalling; 09571 tmp->cid_start = conf->chan.cid_start; 09572 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09573 tmp->restrictcid = conf->chan.restrictcid; 09574 tmp->use_callingpres = conf->chan.use_callingpres; 09575 if (tmp->usedistinctiveringdetection) { 09576 if (!tmp->use_callerid) { 09577 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09578 tmp->use_callerid = 1; 09579 } 09580 } 09581 09582 if (tmp->cid_signalling == CID_SIG_SMDI) { 09583 if (!tmp->use_smdi) { 09584 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09585 tmp->use_smdi = 1; 09586 } 09587 } 09588 if (tmp->use_smdi) { 09589 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09590 if (!(tmp->smdi_iface)) { 09591 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09592 tmp->use_smdi = 0; 09593 } 09594 } 09595 09596 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09597 tmp->amaflags = conf->chan.amaflags; 09598 if (!here) { 09599 tmp->confno = -1; 09600 tmp->propconfno = -1; 09601 } 09602 tmp->canpark = conf->chan.canpark; 09603 tmp->transfer = conf->chan.transfer; 09604 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09605 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09606 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09607 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09608 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09609 tmp->cid_ton = 0; 09610 if (chan_sig != SIG_PRI) { 09611 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09612 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09613 } else { 09614 tmp->cid_num[0] = '\0'; 09615 tmp->cid_name[0] = '\0'; 09616 } 09617 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09618 tmp->msgstate = -1; 09619 tmp->group = conf->chan.group; 09620 tmp->callgroup = conf->chan.callgroup; 09621 tmp->pickupgroup= conf->chan.pickupgroup; 09622 tmp->rxgain = conf->chan.rxgain; 09623 tmp->txgain = conf->chan.txgain; 09624 tmp->tonezone = conf->chan.tonezone; 09625 tmp->onhooktime = time(NULL); 09626 if (tmp->subs[SUB_REAL].dfd > -1) { 09627 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09628 if (tmp->dsp) 09629 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09630 update_conf(tmp); 09631 if (!here) { 09632 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2)) 09633 /* Hang it up to be sure it's good */ 09634 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09635 } 09636 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09637 #ifdef HAVE_PRI 09638 /* the dchannel is down so put the channel in alarm */ 09639 if (tmp->pri && !pri_is_up(tmp->pri)) { 09640 tmp->inalarm = 1; 09641 tmp->resetting = 0; 09642 } 09643 #endif 09644 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09645 tmp->inalarm = 1; 09646 #if defined(HAVE_PRI) 09647 tmp->resetting = 0; 09648 #endif /* defined(HAVE_PRI) */ 09649 handle_alarms(tmp, res); 09650 } else { 09651 /* yes, this looks strange... the unknown_alarm flag is only used to 09652 control whether an 'alarm cleared' message gets generated when we 09653 get an indication that the channel is no longer in alarm status. 09654 however, the channel *could* be in an alarm status that we aren't 09655 aware of (since get_alarms() only reports span alarms, not channel 09656 alarms). setting this flag will cause any potential 'alarm cleared' 09657 message to be suppressed, but if a real alarm occurs before that 09658 happens, this flag will get cleared by it and the situation will 09659 be normal. 09660 */ 09661 tmp->unknown_alarm = 1; 09662 } 09663 } 09664 09665 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09666 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09667 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09668 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09669 09670 } 09671 if (tmp && !here) { 09672 /* nothing on the iflist */ 09673 if (!*wlist) { 09674 *wlist = tmp; 09675 tmp->prev = NULL; 09676 tmp->next = NULL; 09677 *wend = tmp; 09678 } else { 09679 /* at least one member on the iflist */ 09680 struct dahdi_pvt *working = *wlist; 09681 09682 /* check if we maybe have to put it on the begining */ 09683 if (working->channel > tmp->channel) { 09684 tmp->next = *wlist; 09685 tmp->prev = NULL; 09686 (*wlist)->prev = tmp; 09687 *wlist = tmp; 09688 } else { 09689 /* go through all the members and put the member in the right place */ 09690 while (working) { 09691 /* in the middle */ 09692 if (working->next) { 09693 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09694 tmp->next = working->next; 09695 tmp->prev = working; 09696 working->next->prev = tmp; 09697 working->next = tmp; 09698 break; 09699 } 09700 } else { 09701 /* the last */ 09702 if (working->channel < tmp->channel) { 09703 working->next = tmp; 09704 tmp->next = NULL; 09705 tmp->prev = working; 09706 *wend = tmp; 09707 break; 09708 } 09709 } 09710 working = working->next; 09711 } 09712 } 09713 } 09714 } 09715 return tmp; 09716 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 6669 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, and dahdi_pvt::subs.
Referenced by dahdi_write().
06670 { 06671 int sent=0; 06672 int size; 06673 int res; 06674 int fd; 06675 fd = p->subs[index].dfd; 06676 while (len) { 06677 size = len; 06678 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06679 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06680 res = write(fd, buf, size); 06681 if (res != size) { 06682 if (option_debug) 06683 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06684 return sent; 06685 } 06686 len -= size; 06687 buf += size; 06688 } 06689 return sent; 06690 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 7196 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
07197 { 07198 char c; 07199 07200 *str = 0; /* start with empty output buffer */ 07201 for (;;) 07202 { 07203 /* Wait for the first digit (up to specified ms). */ 07204 c = ast_waitfordigit(chan, ms); 07205 /* if timeout, hangup or error, return as such */ 07206 if (c < 1) 07207 return c; 07208 *str++ = c; 07209 *str = 0; 07210 if (strchr(term, c)) 07211 return 1; 07212 } 07213 }
static int parse_buffers_policy | ( | const char * | parse, | |
int * | num_buffers, | |||
int * | policy | |||
) | [static] |
Definition at line 4417 of file chan_dahdi.c.
References ast_log(), and LOG_WARNING.
Referenced by dahdi_func_write(), and process_dahdi().
04418 { 04419 int res; 04420 char policy_str[21] = ""; 04421 04422 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) && 04423 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) { 04424 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse); 04425 return 1; 04426 } 04427 if (*num_buffers < 0) { 04428 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers); 04429 return -1; 04430 } 04431 if (!strcasecmp(policy_str, "full")) { 04432 *policy = DAHDI_POLICY_WHEN_FULL; 04433 } else if (!strcasecmp(policy_str, "immediate")) { 04434 *policy = DAHDI_POLICY_IMMEDIATE; 04435 #ifdef DAHDI_POLICY_HALF_FULL 04436 } else if (!strcasecmp(policy_str, "half")) { 04437 *policy = DAHDI_POLICY_HALF_FULL; 04438 #endif 04439 } else { 04440 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str); 04441 return -1; 04442 } 04443 04444 return 0; 04445 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3496 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, dahdi_pri::pri, and dahdi_pvt::pri.
Referenced by pri_find_principle().
03497 { 03498 int x = -1; 03499 03500 for (x = 0; x < NUM_DCHANS; x++) { 03501 if ((pri->dchans[x] == pri->pri)) 03502 break; 03503 } 03504 03505 return pri->fds[x]; 03506 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3466 of file chan_dahdi.c.
References dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, ast_channel::fds, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_request().
03467 { 03468 bearer->owner = &inuse; 03469 bearer->realcall = crv; 03470 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03471 if (crv->subs[SUB_REAL].owner) 03472 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 03473 crv->bearer = bearer; 03474 crv->call = bearer->call; 03475 crv->pri = pri; 03476 return 0; 03477 }
static void pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10916 of file chan_dahdi.c.
References dahdi_pri::lastreset, dahdi_pri::numchans, dahdi_pri::pri, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pri::resetpos, dahdi_pri::resetting, dahdi_pvt::resetting, and sig_pri_is_chan_in_use().
Referenced by pri_dchannel().
10917 { 10918 for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) { 10919 if (!pri->pvts[pri->resetpos] 10920 || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) { 10921 continue; 10922 } 10923 break; 10924 } 10925 if (pri->resetpos < pri->numchans) { 10926 /* Mark the channel as resetting and restart it */ 10927 pri->pvts[pri->resetpos]->resetting = 1; 10928 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10929 } else { 10930 pri->resetting = 0; 10931 time(&pri->lastreset); 10932 } 10933 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 9105 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
09106 { 09107 if (pris[span].mastertrunkgroup) { 09108 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); 09109 return -1; 09110 } 09111 pris[span].mastertrunkgroup = trunkgroup; 09112 pris[span].prilogicalspan = logicalspan; 09113 return 0; 09114 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 9042 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, dahdi_pri::span, and dahdi_pri::trunkgroup.
Referenced by setup_dahdi().
09043 { 09044 struct dahdi_spaninfo si; 09045 struct dahdi_params p; 09046 int fd; 09047 int span; 09048 int ospan=0; 09049 int x,y; 09050 for (x = 0; x < NUM_SPANS; x++) { 09051 if (pris[x].trunkgroup == trunkgroup) { 09052 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 09053 return -1; 09054 } 09055 } 09056 for (y = 0; y < NUM_DCHANS; y++) { 09057 if (!channels[y]) 09058 break; 09059 memset(&si, 0, sizeof(si)); 09060 memset(&p, 0, sizeof(p)); 09061 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 09062 if (fd < 0) { 09063 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 09064 return -1; 09065 } 09066 x = channels[y]; 09067 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 09068 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 09069 close(fd); 09070 return -1; 09071 } 09072 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 09073 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 09074 return -1; 09075 } 09076 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 09077 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 09078 close(fd); 09079 return -1; 09080 } 09081 span = p.spanno - 1; 09082 if (pris[span].trunkgroup) { 09083 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 09084 close(fd); 09085 return -1; 09086 } 09087 if (pris[span].pvts[0]) { 09088 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 09089 close(fd); 09090 return -1; 09091 } 09092 if (!y) { 09093 pris[span].trunkgroup = trunkgroup; 09094 pris[span].offset = channels[y] - p.chanpos; 09095 ospan = span; 09096 } 09097 pris[ospan].dchannels[y] = channels[y]; 09098 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 09099 pris[span].span = span + 1; 09100 close(fd); 09101 } 09102 return 0; 09103 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 11015 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::channel, dahdi_chan_name, dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, len(), dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pri::resetting, sig_pri_is_chan_available(), dahdi_pri::switchtype, and t.
11016 { 11017 struct dahdi_pri *pri = vpri; 11018 pri_event *e; 11019 struct pollfd fds[NUM_DCHANS]; 11020 int res; 11021 int chanpos = 0; 11022 int x; 11023 int haveidles; 11024 int activeidles; 11025 int nextidle = -1; 11026 struct ast_channel *c; 11027 struct timeval tv, lowest, *next; 11028 struct timeval lastidle = { 0, 0 }; 11029 int doidling=0; 11030 char *cc; 11031 char idlen[80]; 11032 struct ast_channel *idle; 11033 pthread_t p; 11034 time_t t; 11035 int i, which=-1; 11036 int numdchans; 11037 int cause=0; 11038 struct dahdi_pvt *crv; 11039 pthread_t threadid; 11040 pthread_attr_t attr; 11041 char ani2str[6]; 11042 char plancallingnum[256]; 11043 char plancallingani[256]; 11044 char calledtonstr[10]; 11045 unsigned int len; 11046 11047 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11048 11049 gettimeofday(&lastidle, NULL); 11050 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 11051 /* Need to do idle dialing, check to be sure though */ 11052 cc = strchr(pri->idleext, '@'); 11053 if (cc) { 11054 *cc = '\0'; 11055 cc++; 11056 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 11057 #if 0 11058 /* Extensions may not be loaded yet */ 11059 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 11060 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 11061 else 11062 #endif 11063 doidling = 1; 11064 } else 11065 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 11066 } 11067 for (;;) { 11068 for (i = 0; i < NUM_DCHANS; i++) { 11069 if (!pri->dchannels[i]) 11070 break; 11071 fds[i].fd = pri->fds[i]; 11072 fds[i].events = POLLIN | POLLPRI; 11073 fds[i].revents = 0; 11074 } 11075 numdchans = i; 11076 time(&t); 11077 ast_mutex_lock(&pri->lock); 11078 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 11079 if (pri->resetting && pri_is_up(pri)) { 11080 if (pri->resetpos < 0) { 11081 pri_check_restart(pri); 11082 } 11083 } else { 11084 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 11085 pri->resetting = 1; 11086 pri->resetpos = -1; 11087 } 11088 } 11089 } 11090 /* Look for any idle channels if appropriate */ 11091 if (doidling && pri_is_up(pri)) { 11092 nextidle = -1; 11093 haveidles = 0; 11094 activeidles = 0; 11095 for (x = pri->numchans; x >= 0; x--) { 11096 if (pri->pvts[x]) { 11097 if (sig_pri_is_chan_available(pri->pvts[x])) { 11098 if (haveidles < pri->minunused) { 11099 haveidles++; 11100 } else { 11101 nextidle = x; 11102 break; 11103 } 11104 } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 11105 activeidles++; 11106 } 11107 } 11108 } 11109 if (nextidle > -1) { 11110 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 11111 /* Don't create a new idle call more than once per second */ 11112 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 11113 /* 11114 * Release the PRI lock while we create the channel so other 11115 * threads can send D channel messages. 11116 */ 11117 ast_mutex_unlock(&pri->lock); 11118 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 11119 ast_mutex_lock(&pri->lock); 11120 if (idle) { 11121 pri->pvts[nextidle]->isidlecall = 1; 11122 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 11123 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 11124 ast_mutex_unlock(&pri->lock); 11125 ast_hangup(idle); 11126 ast_mutex_lock(&pri->lock); 11127 } 11128 } else { 11129 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 11130 } 11131 gettimeofday(&lastidle, NULL); 11132 } 11133 } else if ((haveidles < pri->minunused) && 11134 (activeidles > pri->minidle)) { 11135 /* Mark something for hangup if there is something 11136 that can be hungup */ 11137 for (x = pri->numchans; x >= 0; x--) { 11138 /* find a candidate channel */ 11139 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 11140 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11141 haveidles++; 11142 /* Stop if we have enough idle channels or 11143 can't spare any more active idle ones */ 11144 if ((haveidles >= pri->minunused) || 11145 (activeidles <= pri->minidle)) 11146 break; 11147 } 11148 } 11149 } 11150 } 11151 /* Start with reasonable max */ 11152 lowest = ast_tv(60, 0); 11153 for (i = 0; i < NUM_DCHANS; i++) { 11154 /* Find lowest available d-channel */ 11155 if (!pri->dchannels[i]) 11156 break; 11157 if ((next = pri_schedule_next(pri->dchans[i]))) { 11158 /* We need relative time here */ 11159 tv = ast_tvsub(*next, ast_tvnow()); 11160 if (tv.tv_sec < 0) { 11161 tv = ast_tv(0,0); 11162 } 11163 if (doidling || pri->resetting) { 11164 if (tv.tv_sec > 1) { 11165 tv = ast_tv(1, 0); 11166 } 11167 } else { 11168 if (tv.tv_sec > 60) { 11169 tv = ast_tv(60, 0); 11170 } 11171 } 11172 } else if (doidling || pri->resetting) { 11173 /* Make sure we stop at least once per second if we're 11174 monitoring idle channels */ 11175 tv = ast_tv(1,0); 11176 } else { 11177 /* Don't poll for more than 60 seconds */ 11178 tv = ast_tv(60, 0); 11179 } 11180 if (!i || ast_tvcmp(tv, lowest) < 0) { 11181 lowest = tv; 11182 } 11183 } 11184 ast_mutex_unlock(&pri->lock); 11185 11186 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11187 pthread_testcancel(); 11188 e = NULL; 11189 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11190 pthread_testcancel(); 11191 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11192 11193 ast_mutex_lock(&pri->lock); 11194 if (!res) { 11195 for (which = 0; which < NUM_DCHANS; which++) { 11196 if (!pri->dchans[which]) 11197 break; 11198 /* Just a timeout, run the scheduler */ 11199 e = pri_schedule_run(pri->dchans[which]); 11200 if (e) 11201 break; 11202 } 11203 } else if (res > -1) { 11204 for (which = 0; which < NUM_DCHANS; which++) { 11205 if (!pri->dchans[which]) 11206 break; 11207 if (fds[which].revents & POLLPRI) { 11208 /* Check for an event */ 11209 x = 0; 11210 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11211 if (x) 11212 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span); 11213 /* Keep track of alarm state */ 11214 if (x == DAHDI_EVENT_ALARM) { 11215 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11216 pri_find_dchan(pri); 11217 } else if (x == DAHDI_EVENT_NOALARM) { 11218 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11219 pri_restart(pri->dchans[which]); 11220 } 11221 11222 if (option_debug) 11223 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11224 } else if (fds[which].revents & POLLIN) { 11225 e = pri_check_event(pri->dchans[which]); 11226 } 11227 if (e) 11228 break; 11229 } 11230 } else if (errno != EINTR) 11231 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11232 11233 if (e) { 11234 if (pri->debug) 11235 pri_dump_event(pri->dchans[which], e); 11236 11237 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11238 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11239 if (option_verbose > 1) 11240 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11241 } 11242 pri->dchanavail[which] |= DCHAN_UP; 11243 } else { 11244 if (pri->dchanavail[which] & DCHAN_UP) { 11245 if (option_verbose > 1) 11246 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11247 } 11248 pri->dchanavail[which] &= ~DCHAN_UP; 11249 } 11250 11251 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11252 /* Must be an NFAS group that has the secondary dchan active */ 11253 pri->pri = pri->dchans[which]; 11254 11255 switch (e->e) { 11256 case PRI_EVENT_DCHAN_UP: 11257 pri->no_d_channels = 0; 11258 if (!pri->pri) pri_find_dchan(pri); 11259 11260 /* Note presense of D-channel */ 11261 time(&pri->lastreset); 11262 11263 /* Restart in 5 seconds */ 11264 if (pri->resetinterval > -1) { 11265 pri->lastreset -= pri->resetinterval; 11266 pri->lastreset += 5; 11267 } 11268 /* Take the channels from inalarm condition */ 11269 pri->resetting = 0; 11270 for (i = 0; i < pri->numchans; i++) { 11271 if (pri->pvts[i]) { 11272 pri->pvts[i]->inalarm = 0; 11273 pri->pvts[i]->resetting = 0; 11274 } 11275 } 11276 break; 11277 case PRI_EVENT_DCHAN_DOWN: 11278 pri_find_dchan(pri); 11279 if (!pri_is_up(pri)) { 11280 /* Hangup active channels and put them in alarm mode */ 11281 pri->resetting = 0; 11282 for (i = 0; i < pri->numchans; i++) { 11283 struct dahdi_pvt *p = pri->pvts[i]; 11284 if (p) { 11285 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11286 /* T309 is not enabled : destroy calls when alarm occurs */ 11287 if (p->call) { 11288 if (p->pri && p->pri->pri) { 11289 pri_destroycall(p->pri->pri, p->call); 11290 p->call = NULL; 11291 } else 11292 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 11293 } 11294 if (p->realcall) { 11295 pri_hangup_all(p->realcall, pri); 11296 } else if (p->owner) 11297 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11298 } 11299 p->inalarm = 1; 11300 p->resetting = 0; 11301 } 11302 } 11303 } 11304 break; 11305 case PRI_EVENT_RESTART: 11306 if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) { 11307 chanpos = pri_find_principle(pri, e->restart.channel); 11308 if (chanpos < 0) 11309 ast_log(LOG_WARNING, 11310 "Span %d: Restart requested on odd/unavailable channel number %d/%d\n", 11311 pri->span, PRI_SPAN(e->restart.channel), 11312 PRI_CHANNEL(e->restart.channel)); 11313 else { 11314 if (option_verbose > 2) 11315 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d restarted\n", 11316 pri->span, PRI_SPAN(e->restart.channel), 11317 PRI_CHANNEL(e->restart.channel)); 11318 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11319 if (pri->pvts[chanpos]->call) { 11320 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11321 pri->pvts[chanpos]->call = NULL; 11322 } 11323 /* Force soft hangup if appropriate */ 11324 if (pri->pvts[chanpos]->realcall) 11325 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11326 else if (pri->pvts[chanpos]->owner) 11327 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11328 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11329 } 11330 } else { 11331 if (option_verbose > 2) 11332 ast_verbose(VERBOSE_PREFIX_2 "Restart requested on entire span %d\n", 11333 pri->span); 11334 for (x = 0; x < pri->numchans; x++) 11335 if (pri->pvts[x]) { 11336 ast_mutex_lock(&pri->pvts[x]->lock); 11337 if (pri->pvts[x]->call) { 11338 pri_destroycall(pri->pri, pri->pvts[x]->call); 11339 pri->pvts[x]->call = NULL; 11340 } 11341 if (pri->pvts[x]->realcall) 11342 pri_hangup_all(pri->pvts[x]->realcall, pri); 11343 else if (pri->pvts[x]->owner) 11344 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11345 ast_mutex_unlock(&pri->pvts[x]->lock); 11346 } 11347 } 11348 break; 11349 case PRI_EVENT_KEYPAD_DIGIT: 11350 chanpos = pri_find_principle_by_call(pri, e->digit.call); 11351 if (chanpos < 0) { 11352 ast_log(LOG_WARNING, 11353 "Span %d: Received keypad digits for unknown call.\n", pri->span); 11354 break; 11355 } 11356 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11357 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11358 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11359 && pri->pvts[chanpos]->owner) { 11360 /* how to do that */ 11361 int digitlen = strlen(e->digit.digits); 11362 char digit; 11363 int i; 11364 for (i = 0; i < digitlen; i++) { 11365 digit = e->digit.digits[i]; 11366 { 11367 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11368 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11369 } 11370 } 11371 } 11372 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11373 break; 11374 11375 case PRI_EVENT_INFO_RECEIVED: 11376 chanpos = pri_find_principle_by_call(pri, e->ring.call); 11377 if (chanpos < 0) { 11378 ast_log(LOG_WARNING, 11379 "Span %d: Received INFORMATION for unknown call.\n", pri->span); 11380 break; 11381 } 11382 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11383 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11384 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11385 && pri->pvts[chanpos]->owner) { 11386 /* how to do that */ 11387 int digitlen = strlen(e->ring.callednum); 11388 char digit; 11389 int i; 11390 for (i = 0; i < digitlen; i++) { 11391 digit = e->ring.callednum[i]; 11392 { 11393 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11394 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11395 } 11396 } 11397 } 11398 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11399 break; 11400 case PRI_EVENT_RING: 11401 crv = NULL; 11402 chanpos = pri_find_principle_by_call(pri, e->ring.call); 11403 if (-1 < chanpos) { 11404 /* Libpri has already filtered out duplicate SETUPs. */ 11405 ast_log(LOG_WARNING, 11406 "Span %d: Got SETUP with duplicate call ptr. Dropping call.\n", 11407 pri->span); 11408 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE); 11409 break; 11410 } 11411 if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) { 11412 /* Any channel requested. */ 11413 chanpos = pri_find_empty_chan(pri, 1); 11414 } else if (PRI_CHANNEL(e->ring.channel) == 0x00) { 11415 /* No channel specified. */ 11416 { 11417 /* We will not accept incoming call waiting calls. */ 11418 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION); 11419 break; 11420 } 11421 } else { 11422 /* A channel is specified. */ 11423 chanpos = pri_find_principle(pri, e->ring.channel); 11424 if (chanpos < 0) { 11425 ast_log(LOG_WARNING, 11426 "Span %d: SETUP on unconfigured channel %d/%d\n", 11427 pri->span, PRI_SPAN(e->ring.channel), 11428 PRI_CHANNEL(e->ring.channel)); 11429 } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) { 11430 /* This is where we handle initial glare */ 11431 ast_log(LOG_DEBUG, 11432 "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n", 11433 pri->span, PRI_SPAN(e->ring.channel), 11434 PRI_CHANNEL(e->ring.channel)); 11435 chanpos = -1; 11436 } 11437 #if defined(ALWAYS_PICK_CHANNEL) 11438 if (e->ring.flexible) { 11439 chanpos = -1; 11440 } 11441 #endif /* defined(ALWAYS_PICK_CHANNEL) */ 11442 if (chanpos < 0 && e->ring.flexible) { 11443 /* We can try to pick another channel. */ 11444 chanpos = pri_find_empty_chan(pri, 1); 11445 } 11446 } 11447 if (chanpos < 0) { 11448 if (e->ring.flexible) { 11449 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11450 } else { 11451 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11452 } 11453 break; 11454 } 11455 11456 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11457 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11458 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11459 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11460 if (crv) 11461 ast_mutex_lock(&crv->lock); 11462 if (!crv || crv->owner) { 11463 pri->pvts[chanpos]->call = NULL; 11464 if (crv) { 11465 if (crv->owner) 11466 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11467 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span); 11468 } else 11469 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span); 11470 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11471 if (crv) 11472 ast_mutex_unlock(&crv->lock); 11473 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11474 break; 11475 } 11476 } 11477 11478 /* Mark channel as in use so noone else will steal it. */ 11479 pri->pvts[chanpos]->call = e->ring.call; 11480 11481 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11482 if (pri->pvts[chanpos]->use_callerid) { 11483 ast_shrink_phone_number(plancallingnum); 11484 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11485 #ifdef PRI_ANI 11486 if (!ast_strlen_zero(e->ring.callingani)) { 11487 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11488 ast_shrink_phone_number(plancallingani); 11489 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11490 } else { 11491 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11492 } 11493 #endif 11494 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11495 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11496 } else { 11497 pri->pvts[chanpos]->cid_num[0] = '\0'; 11498 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11499 pri->pvts[chanpos]->cid_name[0] = '\0'; 11500 pri->pvts[chanpos]->cid_ton = 0; 11501 } 11502 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11503 e->ring.redirectingnum, e->ring.callingplanrdnis); 11504 11505 /* Set DNID on all incoming calls -- even immediate */ 11506 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11507 11508 /* If immediate=yes go to s|1 */ 11509 if (pri->pvts[chanpos]->immediate) { 11510 if (option_verbose > 2) 11511 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 11512 pri->pvts[chanpos]->exten[0] = 's'; 11513 pri->pvts[chanpos]->exten[1] = '\0'; 11514 } 11515 /* Get called number */ 11516 else if (!ast_strlen_zero(e->ring.callednum)) { 11517 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11518 } else if (pri->overlapdial) 11519 pri->pvts[chanpos]->exten[0] = '\0'; 11520 else { 11521 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11522 pri->pvts[chanpos]->exten[0] = 's'; 11523 pri->pvts[chanpos]->exten[1] = '\0'; 11524 } 11525 /* No number yet, but received "sending complete"? */ 11526 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11527 if (option_verbose > 2) 11528 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 11529 pri->pvts[chanpos]->exten[0] = 's'; 11530 pri->pvts[chanpos]->exten[1] = '\0'; 11531 } 11532 11533 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11534 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11535 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11536 /* Setup law */ 11537 int law; 11538 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11539 /* Set to audio mode at this point */ 11540 law = 1; 11541 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11542 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11543 } 11544 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11545 law = DAHDI_LAW_ALAW; 11546 else 11547 law = DAHDI_LAW_MULAW; 11548 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11549 if (res < 0) 11550 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11551 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11552 if (res < 0) 11553 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11554 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11555 /* Just announce proceeding */ 11556 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING; 11557 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11558 } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11559 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT; 11560 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11561 } else { 11562 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP; 11563 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11564 } 11565 /* Get the use_callingpres state */ 11566 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11567 11568 /* Start PBX */ 11569 if (!e->ring.complete 11570 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11571 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11572 /* 11573 * Release the PRI lock while we create the channel so other 11574 * threads can send D channel messages. We must also release 11575 * the private lock to prevent deadlock while creating the 11576 * channel. 11577 */ 11578 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11579 ast_mutex_unlock(&pri->lock); 11580 if (crv) { 11581 /* Set bearer and such */ 11582 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11583 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11584 pri->pvts[chanpos]->owner = &inuse; 11585 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11586 } else { 11587 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11588 } 11589 ast_mutex_lock(&pri->lock); 11590 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11591 if (c) { 11592 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11593 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11594 } 11595 if (e->ring.ani2 >= 0) { 11596 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11597 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11598 } 11599 11600 #ifdef SUPPORT_USERUSER 11601 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11602 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11603 } 11604 #endif 11605 11606 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11607 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11608 if (e->ring.redirectingreason >= 0) 11609 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11610 11611 if (!pri->pvts[chanpos]->digital) { 11612 /* 11613 * Call has a channel. 11614 * Indicate that we are providing dialtone. 11615 */ 11616 pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */ 11617 pri_progress(pri->pri, e->ring.call, 11618 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11619 } 11620 } 11621 11622 pthread_attr_init(&attr); 11623 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11624 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 11625 if (option_verbose > 2) 11626 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11627 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11628 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11629 } else { 11630 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11631 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11632 if (c) { 11633 /* Avoid deadlock while destroying channel */ 11634 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11635 ast_mutex_unlock(&pri->lock); 11636 ast_hangup(c); 11637 ast_mutex_lock(&pri->lock); 11638 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11639 } else { 11640 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11641 pri->pvts[chanpos]->call = NULL; 11642 } 11643 } 11644 pthread_attr_destroy(&attr); 11645 } else { 11646 /* 11647 * Release the PRI lock while we create the channel so other 11648 * threads can send D channel messages. We must also release 11649 * the private lock to prevent deadlock while creating the 11650 * channel. 11651 */ 11652 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11653 ast_mutex_unlock(&pri->lock); 11654 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 11655 ast_mutex_lock(&pri->lock); 11656 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11657 if (c) { 11658 /* 11659 * It is reasonably safe to set the following 11660 * channel variables while the PRI and DAHDI private 11661 * structures are locked. The PBX has not been 11662 * started yet and it is unlikely that any other task 11663 * will do anything with the channel we have just 11664 * created. 11665 */ 11666 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11667 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11668 } 11669 if (e->ring.ani2 >= 0) { 11670 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11671 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11672 } 11673 11674 #ifdef SUPPORT_USERUSER 11675 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11676 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11677 } 11678 #endif 11679 11680 if (e->ring.redirectingreason >= 0) 11681 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11682 11683 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11684 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11685 } 11686 if (c && !ast_pbx_start(c)) { 11687 if (option_verbose > 2) 11688 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11689 plancallingnum, pri->pvts[chanpos]->exten, 11690 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11691 11692 dahdi_enable_ec(pri->pvts[chanpos]); 11693 } else { 11694 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11695 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11696 if (c) { 11697 /* Avoid deadlock while destroying channel */ 11698 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11699 ast_mutex_unlock(&pri->lock); 11700 ast_hangup(c); 11701 ast_mutex_lock(&pri->lock); 11702 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11703 } else { 11704 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11705 pri->pvts[chanpos]->call = NULL; 11706 } 11707 } 11708 } 11709 } else { 11710 if (option_verbose > 2) 11711 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n", 11712 pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, 11713 pri->pvts[chanpos]->cid_num); 11714 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11715 pri->pvts[chanpos]->call = NULL; 11716 pri->pvts[chanpos]->exten[0] = '\0'; 11717 } 11718 if (crv) 11719 ast_mutex_unlock(&crv->lock); 11720 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11721 break; 11722 case PRI_EVENT_RINGING: 11723 chanpos = pri_find_fixup_principle(pri, e->ringing.channel, 11724 e->ringing.call); 11725 if (chanpos < 0) { 11726 break; 11727 } 11728 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11729 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11730 dahdi_enable_ec(pri->pvts[chanpos]); 11731 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11732 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) { 11733 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING; 11734 } 11735 } else 11736 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 11737 if ( 11738 #ifdef PRI_PROGRESS_MASK 11739 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE 11740 #else 11741 e->ringing.progress == 8 11742 #endif 11743 ) { 11744 /* Now we can do call progress detection */ 11745 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11746 /* RINGING detection isn't required because we got ALERTING signal */ 11747 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11748 pri->pvts[chanpos]->dsp_features = 0; 11749 } 11750 } 11751 11752 #ifdef SUPPORT_USERUSER 11753 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11754 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11755 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11756 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11757 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11758 } 11759 #endif 11760 11761 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11762 break; 11763 case PRI_EVENT_PROGRESS: 11764 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel, 11765 e->proceeding.call); 11766 if (chanpos < 0) { 11767 break; 11768 } 11769 if ((!pri->pvts[chanpos]->progress) 11770 #ifdef PRI_PROGRESS_MASK 11771 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) 11772 #else 11773 || (e->proceeding.progress == 8) 11774 #endif 11775 ) { 11776 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11777 11778 if (e->proceeding.cause > -1) { 11779 if (option_verbose > 2) 11780 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 11781 11782 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11783 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11784 if (pri->pvts[chanpos]->owner) { 11785 if (option_verbose > 2) 11786 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11787 11788 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11789 f.subclass = AST_CONTROL_BUSY; 11790 } 11791 } 11792 } 11793 11794 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11795 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11796 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11797 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11798 if ( 11799 #ifdef PRI_PROGRESS_MASK 11800 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE 11801 #else 11802 e->proceeding.progress == 8 11803 #endif 11804 ) { 11805 /* Now we can do call progress detection */ 11806 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11807 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11808 pri->pvts[chanpos]->dsp_features = 0; 11809 } 11810 /* Bring voice path up */ 11811 f.subclass = AST_CONTROL_PROGRESS; 11812 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11813 } 11814 pri->pvts[chanpos]->progress = 1; 11815 pri->pvts[chanpos]->dialing = 0; 11816 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11817 } 11818 break; 11819 case PRI_EVENT_PROCEEDING: 11820 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel, 11821 e->proceeding.call); 11822 if (chanpos < 0) { 11823 break; 11824 } 11825 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11826 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) { 11827 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11828 11829 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING; 11830 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11831 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11832 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11833 if ( 11834 #ifdef PRI_PROGRESS_MASK 11835 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE 11836 #else 11837 e->proceeding.progress == 8 11838 #endif 11839 ) { 11840 /* Now we can do call progress detection */ 11841 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11842 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11843 pri->pvts[chanpos]->dsp_features = 0; 11844 } 11845 /* Bring voice path up */ 11846 f.subclass = AST_CONTROL_PROGRESS; 11847 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11848 } 11849 pri->pvts[chanpos]->dialing = 0; 11850 } 11851 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11852 break; 11853 case PRI_EVENT_FACNAME: 11854 chanpos = pri_find_principle_by_call(pri, e->facname.call); 11855 if (chanpos < 0) { 11856 ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n", 11857 pri->span); 11858 break; 11859 } 11860 if (pri->pvts[chanpos]->use_callerid) { 11861 /* Re-use *69 field for PRI */ 11862 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11863 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11864 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11865 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1; 11866 dahdi_enable_ec(pri->pvts[chanpos]); 11867 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11868 } 11869 break; 11870 case PRI_EVENT_ANSWER: 11871 chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call); 11872 if (chanpos < 0) { 11873 break; 11874 } 11875 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11876 /* Now we can do call progress detection */ 11877 11878 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11879 * By this time, we need DTMF detection and other features that were previously disabled 11880 * -- Matt F */ 11881 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11882 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11883 pri->pvts[chanpos]->dsp_features = 0; 11884 } 11885 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11886 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11887 x = DAHDI_START; 11888 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11889 if (res < 0) { 11890 if (errno != EINPROGRESS) { 11891 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11892 } 11893 } 11894 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11895 pri->pvts[chanpos]->dialing = 1; 11896 /* Send any "w" waited stuff */ 11897 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11898 if (res < 0) { 11899 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11900 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11901 } else 11902 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11903 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11904 } else if (pri->pvts[chanpos]->confirmanswer) { 11905 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11906 } else { 11907 pri->pvts[chanpos]->dialing = 0; 11908 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) { 11909 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT; 11910 } 11911 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11912 /* Enable echo cancellation if it's not on already */ 11913 dahdi_enable_ec(pri->pvts[chanpos]); 11914 } 11915 11916 #ifdef SUPPORT_USERUSER 11917 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11918 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11919 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11920 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11921 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11922 } 11923 #endif 11924 11925 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11926 break; 11927 case PRI_EVENT_HANGUP: 11928 chanpos = pri_find_principle_by_call(pri, e->hangup.call); 11929 if (chanpos < 0) { 11930 /* 11931 * Continue hanging up the call even though 11932 * we do not remember it (if we ever did). 11933 */ 11934 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); 11935 break; 11936 } 11937 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11938 switch (e->hangup.cause) { 11939 case PRI_CAUSE_INVALID_CALL_REFERENCE: 11940 /* 11941 * The peer denies the existence of this call so we must 11942 * continue hanging it up and forget about it. 11943 */ 11944 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); 11945 pri->pvts[chanpos]->call = NULL; 11946 break; 11947 default: 11948 break; 11949 } 11950 if (!pri->pvts[chanpos]->alreadyhungup) { 11951 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11952 pri->pvts[chanpos]->alreadyhungup = 1; 11953 if (pri->pvts[chanpos]->realcall) 11954 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11955 else if (pri->pvts[chanpos]->owner) { 11956 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11957 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11958 switch (pri->pvts[chanpos]->owner->_state) { 11959 case AST_STATE_BUSY: 11960 case AST_STATE_UP: 11961 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11962 break; 11963 default: 11964 if (!pri->pvts[chanpos]->outgoing) { 11965 /* 11966 * The incoming call leg hung up before getting 11967 * connected so just hangup the call. 11968 */ 11969 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11970 break; 11971 } 11972 switch (e->hangup.cause) { 11973 case PRI_CAUSE_USER_BUSY: 11974 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11975 break; 11976 case PRI_CAUSE_CALL_REJECTED: 11977 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11978 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11979 case PRI_CAUSE_SWITCH_CONGESTION: 11980 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11981 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11982 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11983 break; 11984 default: 11985 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11986 break; 11987 } 11988 break; 11989 } 11990 } else { 11991 /* 11992 * Continue hanging up the call even though 11993 * we do not have an owner. 11994 */ 11995 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11996 pri->pvts[chanpos]->call = NULL; 11997 } 11998 if (option_verbose > 2) 11999 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup, cause %d\n", 12000 pri->span, pri->pvts[chanpos]->logicalspan, 12001 pri->pvts[chanpos]->prioffset, e->hangup.cause); 12002 } else { 12003 /* Continue hanging up the call. */ 12004 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 12005 pri->pvts[chanpos]->call = NULL; 12006 } 12007 #if defined(FORCE_RESTART_UNAVAIL_CHANS) 12008 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 12009 && !pri->resetting && !pri->pvts[chanpos]->resetting) { 12010 if (option_verbose > 2) 12011 ast_verbose(VERBOSE_PREFIX_3 12012 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n", 12013 pri->span, pri->pvts[chanpos]->logicalspan, 12014 pri->pvts[chanpos]->prioffset); 12015 pri->pvts[chanpos]->resetting = 1; 12016 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 12017 } 12018 #endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */ 12019 if (e->hangup.aoc_units > -1) 12020 if (option_verbose > 2) 12021 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 12022 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 12023 12024 #ifdef SUPPORT_USERUSER 12025 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 12026 struct ast_channel *owner = pri->pvts[chanpos]->owner; 12027 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12028 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 12029 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12030 } 12031 #endif 12032 12033 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12034 break; 12035 #ifndef PRI_EVENT_HANGUP_REQ 12036 #error please update libpri 12037 #endif 12038 case PRI_EVENT_HANGUP_REQ: 12039 chanpos = pri_find_principle_by_call(pri, e->hangup.call); 12040 if (chanpos < 0) { 12041 /* 12042 * Continue hanging up the call even though 12043 * we do not remember it (if we ever did). 12044 */ 12045 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); 12046 break; 12047 } 12048 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12049 switch (e->hangup.cause) { 12050 case PRI_CAUSE_INVALID_CALL_REFERENCE: 12051 /* 12052 * The peer denies the existence of this call so we must 12053 * continue hanging it up and forget about it. We should not 12054 * get this cause here, but for completeness we will handle it 12055 * anyway. 12056 */ 12057 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); 12058 pri->pvts[chanpos]->call = NULL; 12059 break; 12060 default: 12061 break; 12062 } 12063 if (pri->pvts[chanpos]->realcall) 12064 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12065 else if (pri->pvts[chanpos]->owner) { 12066 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 12067 switch (pri->pvts[chanpos]->owner->_state) { 12068 case AST_STATE_BUSY: 12069 case AST_STATE_UP: 12070 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12071 break; 12072 default: 12073 if (!pri->pvts[chanpos]->outgoing) { 12074 /* 12075 * The incoming call leg hung up before getting 12076 * connected so just hangup the call. 12077 */ 12078 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12079 break; 12080 } 12081 switch (e->hangup.cause) { 12082 case PRI_CAUSE_USER_BUSY: 12083 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 12084 break; 12085 case PRI_CAUSE_CALL_REJECTED: 12086 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 12087 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 12088 case PRI_CAUSE_SWITCH_CONGESTION: 12089 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 12090 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 12091 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 12092 break; 12093 default: 12094 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12095 break; 12096 } 12097 break; 12098 } 12099 if (option_verbose > 2) 12100 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup request, cause %d\n", 12101 pri->span, pri->pvts[chanpos]->logicalspan, 12102 pri->pvts[chanpos]->prioffset, e->hangup.cause); 12103 if (e->hangup.aoc_units > -1) 12104 if (option_verbose > 2) 12105 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 12106 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 12107 } else { 12108 /* 12109 * Continue hanging up the call even though 12110 * we do not have an owner. 12111 */ 12112 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 12113 pri->pvts[chanpos]->call = NULL; 12114 } 12115 #if defined(FORCE_RESTART_UNAVAIL_CHANS) 12116 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 12117 && !pri->resetting && !pri->pvts[chanpos]->resetting) { 12118 if (option_verbose > 2) 12119 ast_verbose(VERBOSE_PREFIX_3 12120 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n", 12121 pri->span, pri->pvts[chanpos]->logicalspan, 12122 pri->pvts[chanpos]->prioffset); 12123 pri->pvts[chanpos]->resetting = 1; 12124 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 12125 } 12126 #endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */ 12127 12128 #ifdef SUPPORT_USERUSER 12129 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 12130 struct ast_channel *owner = pri->pvts[chanpos]->owner; 12131 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12132 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 12133 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12134 } 12135 #endif 12136 12137 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12138 break; 12139 case PRI_EVENT_HANGUP_ACK: 12140 chanpos = pri_find_principle_by_call(pri, e->hangup.call); 12141 if (chanpos < 0) { 12142 break; 12143 } 12144 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12145 pri->pvts[chanpos]->call = NULL; 12146 if (pri->pvts[chanpos]->owner) { 12147 if (option_verbose > 2) 12148 ast_verbose(VERBOSE_PREFIX_3 "Span %d: Channel %d/%d got hangup ACK\n", 12149 pri->span, pri->pvts[chanpos]->logicalspan, 12150 pri->pvts[chanpos]->prioffset); 12151 } 12152 #ifdef SUPPORT_USERUSER 12153 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 12154 struct ast_channel *owner = pri->pvts[chanpos]->owner; 12155 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12156 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 12157 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12158 } 12159 #endif 12160 12161 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12162 break; 12163 case PRI_EVENT_CONFIG_ERR: 12164 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err); 12165 break; 12166 case PRI_EVENT_RESTART_ACK: 12167 chanpos = pri_find_principle(pri, e->restartack.channel); 12168 if (chanpos < 0) { 12169 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 12170 channel number, so we have to figure it out... This must be why 12171 everybody resets exactly a channel at a time. */ 12172 for (x = 0; x < pri->numchans; x++) { 12173 if (pri->pvts[x] && pri->pvts[x]->resetting) { 12174 chanpos = x; 12175 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12176 ast_log(LOG_DEBUG, 12177 "Span %d: Assuming restart ack is for channel %d/%d\n", 12178 pri->span, pri->pvts[chanpos]->logicalspan, 12179 pri->pvts[chanpos]->prioffset); 12180 if (pri->pvts[chanpos]->realcall) 12181 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12182 else if (pri->pvts[chanpos]->owner) { 12183 ast_log(LOG_WARNING, 12184 "Span %d: Got restart ack on channel %d/%d with owner\n", 12185 pri->span, pri->pvts[chanpos]->logicalspan, 12186 pri->pvts[chanpos]->prioffset); 12187 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12188 } 12189 pri->pvts[chanpos]->resetting = 0; 12190 if (option_verbose > 2) 12191 ast_verbose(VERBOSE_PREFIX_3 12192 "Span %d: Channel %d/%d successfully restarted\n", 12193 pri->span, pri->pvts[chanpos]->logicalspan, 12194 pri->pvts[chanpos]->prioffset); 12195 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12196 if (pri->resetting) 12197 pri_check_restart(pri); 12198 break; 12199 } 12200 } 12201 if (chanpos < 0) { 12202 ast_log(LOG_WARNING, 12203 "Span %d: Restart ACK on strange channel %d/%d\n", 12204 pri->span, PRI_SPAN(e->restartack.channel), 12205 PRI_CHANNEL(e->restartack.channel)); 12206 } 12207 } else { 12208 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12209 if (pri->pvts[chanpos]->realcall) 12210 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12211 else if (pri->pvts[chanpos]->owner) { 12212 ast_log(LOG_WARNING, 12213 "Span %d: Got restart ack on channel %d/%d with owner\n", 12214 pri->span, pri->pvts[chanpos]->logicalspan, 12215 pri->pvts[chanpos]->prioffset); 12216 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12217 } 12218 pri->pvts[chanpos]->resetting = 0; 12219 if (option_verbose > 2) 12220 ast_verbose(VERBOSE_PREFIX_3 12221 "Span %d: Channel %d/%d successfully restarted\n", 12222 pri->span, pri->pvts[chanpos]->logicalspan, 12223 pri->pvts[chanpos]->prioffset); 12224 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12225 if (pri->resetting) 12226 pri_check_restart(pri); 12227 } 12228 break; 12229 case PRI_EVENT_SETUP_ACK: 12230 chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel, 12231 e->setup_ack.call); 12232 if (chanpos < 0) { 12233 break; 12234 } 12235 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12236 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) { 12237 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP; 12238 } 12239 12240 /* Send any queued digits */ 12241 len = strlen(pri->pvts[chanpos]->dialdest); 12242 for (x = 0; x < len; ++x) { 12243 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 12244 pri_information(pri->pri, pri->pvts[chanpos]->call, 12245 pri->pvts[chanpos]->dialdest[x]); 12246 } 12247 12248 if (!pri->pvts[chanpos]->progress 12249 && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) 12250 && !pri->pvts[chanpos]->digital) { 12251 /* 12252 * Call has a channel. 12253 * Indicate for overlap dialing that dialtone may be present. 12254 */ 12255 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 12256 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12257 pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */ 12258 pri->pvts[chanpos]->dialing = 0; 12259 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 12260 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 12261 pri->pvts[chanpos]->dsp_features = 0; 12262 } 12263 } 12264 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12265 break; 12266 case PRI_EVENT_NOTIFY: 12267 #if defined(HAVE_PRI_CALL_HOLD) 12268 chanpos = pri_find_principle_by_call(pri, e->notify.call); 12269 if (chanpos < 0) { 12270 ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n", 12271 pri->span); 12272 break; 12273 } 12274 #else 12275 /* 12276 * This version of libpri does not supply a call pointer for 12277 * this message. We are just going to have to trust that the 12278 * correct principle is found. 12279 */ 12280 chanpos = pri_find_principle(pri, e->notify.channel); 12281 if (chanpos < 0) { 12282 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 12283 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 12284 break; 12285 } 12286 #endif /* !defined(HAVE_PRI_CALL_HOLD) */ 12287 { 12288 struct ast_frame f = { AST_FRAME_CONTROL, }; 12289 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12290 switch (e->notify.info) { 12291 case PRI_NOTIFY_REMOTE_HOLD: 12292 f.subclass = AST_CONTROL_HOLD; 12293 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12294 break; 12295 case PRI_NOTIFY_REMOTE_RETRIEVAL: 12296 f.subclass = AST_CONTROL_UNHOLD; 12297 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12298 break; 12299 } 12300 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12301 } 12302 break; 12303 default: 12304 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 12305 } 12306 } 12307 ast_mutex_unlock(&pri->lock); 12308 } 12309 /* Never reached */ 12310 return NULL; 12311 }
Definition at line 10376 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
10377 { 10378 struct dahdi_pvt *p; 10379 p = pri->crvs; 10380 while (p) { 10381 if (p->channel == crv) 10382 return p; 10383 p = p->next; 10384 } 10385 return NULL; 10386 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3508 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03509 { 03510 int oldslot = -1; 03511 struct pri *old; 03512 int newslot = -1; 03513 int x; 03514 old = pri->pri; 03515 for (x = 0; x < NUM_DCHANS; x++) { 03516 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03517 newslot = x; 03518 if (pri->dchans[x] == old) { 03519 oldslot = x; 03520 } 03521 } 03522 if (newslot < 0) { 03523 newslot = 0; 03524 if (!pri->no_d_channels) { 03525 pri->no_d_channels = 1; 03526 ast_log(LOG_WARNING, 03527 "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03528 pri->dchannels[newslot]); 03529 } 03530 } else { 03531 pri->no_d_channels = 0; 03532 } 03533 if (old && (oldslot != newslot)) 03534 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03535 pri->dchannels[oldslot], pri->dchannels[newslot]); 03536 pri->pri = pri->dchans[newslot]; 03537 return 0; 03538 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9973 of file chan_dahdi.c.
References ast_log(), LOG_DEBUG, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::prioffset, dahdi_pri::pvts, and sig_pri_is_chan_available().
Referenced by dahdi_request().
09974 { 09975 int x; 09976 if (backwards) 09977 x = pri->numchans; 09978 else 09979 x = 0; 09980 for (;;) { 09981 if (backwards && (x < 0)) 09982 break; 09983 if (!backwards && (x >= pri->numchans)) 09984 break; 09985 if (pri->pvts[x] 09986 && sig_pri_is_chan_available(pri->pvts[x])) { 09987 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 09988 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09989 return x; 09990 } 09991 if (backwards) 09992 x--; 09993 else 09994 x++; 09995 } 09996 return -1; 09997 }
static int pri_find_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | channel, | |||
q931_call * | call | |||
) | [static] |
Definition at line 10737 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::pri, PRI_CHANNEL, pri_find_principle(), pri_fixup_principle(), PRI_SPAN, sig_pri_kill_call(), and dahdi_pri::span.
10738 { 10739 int chanpos; 10740 10741 chanpos = pri_find_principle(pri, channel); 10742 if (chanpos < 0) { 10743 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n", 10744 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel)); 10745 sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST); 10746 return -1; 10747 } 10748 chanpos = pri_fixup_principle(pri, chanpos, call); 10749 if (chanpos < 0) { 10750 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n", 10751 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel)); 10752 /* 10753 * Using Q.931 section 5.2.3.1 b) as the reason for picking 10754 * PRI_CAUSE_CHANNEL_UNACCEPTABLE. Receiving a 10755 * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart 10756 * that channel (which is not specified by Q.931) and kill some 10757 * other call which would be bad. 10758 */ 10759 sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE); 10760 return -1; 10761 } 10762 return chanpos; 10763 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 10552 of file chan_dahdi.c.
References dahdi_pvt::logicalspan, dahdi_pri::numchans, pri_active_dchan_fd(), PRI_CHANNEL, PRI_EXPLICIT, PRI_SPAN, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, and dahdi_pri::pvts.
Referenced by pri_find_fixup_principle().
10553 { 10554 int x; 10555 int span = PRI_SPAN(channel); 10556 int spanfd; 10557 struct dahdi_params param; 10558 int principle = -1; 10559 int explicit = PRI_EXPLICIT(channel); 10560 channel = PRI_CHANNEL(channel); 10561 10562 if (!explicit) { 10563 spanfd = pri_active_dchan_fd(pri); 10564 memset(¶m, 0, sizeof(param)); 10565 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10566 return -1; 10567 span = pris[param.spanno - 1].prilogicalspan; 10568 } 10569 10570 for (x = 0; x < pri->numchans; x++) { 10571 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10572 principle = x; 10573 break; 10574 } 10575 } 10576 10577 return principle; 10578 }
static int pri_find_principle_by_call | ( | struct dahdi_pri * | pri, | |
q931_call * | call | |||
) | [static] |
Definition at line 10485 of file chan_dahdi.c.
References dahdi_pvt::call, dahdi_pri::numchans, and dahdi_pri::pvts.
Referenced by sig_pri_kill_call().
10486 { 10487 int idx; 10488 10489 if (!call) { 10490 /* Cannot find a call without a call. */ 10491 return -1; 10492 } 10493 for (idx = 0; idx < pri->numchans; ++idx) { 10494 if (pri->pvts[idx] && pri->pvts[idx]->call == call) { 10495 /* Found the principle */ 10496 return idx; 10497 } 10498 } 10499 return -1; 10500 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 10595 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_build, ast_verbose(), dahdi_pvt::call, DAHDI_CALL_LEVEL_IDLE, dahdi_chan_name, name, dahdi_pri::numchans, option_verbose, dahdi_pvt::pri, dahdi_pri::pvts, sig_pri_is_chan_available(), sig_pri_lock_owner(), SUB_REAL, and VERBOSE_PREFIX_3.
Referenced by pri_find_fixup_principle().
10596 { 10597 int x; 10598 struct dahdi_pvt *crv; 10599 if (!c) { 10600 if (principle < 0) 10601 return -1; 10602 return principle; 10603 } 10604 if ((principle > -1) && 10605 (principle < pri->numchans) && 10606 (pri->pvts[principle]) && 10607 (pri->pvts[principle]->call == c)) 10608 return principle; 10609 /* First, check for other bearers */ 10610 for (x = 0; x < pri->numchans; x++) { 10611 if (!pri->pvts[x]) 10612 continue; 10613 if (pri->pvts[x]->call == c) { 10614 /* Found our call */ 10615 if (principle != x) { 10616 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10617 10618 /* Get locks to safely move to the new private structure. */ 10619 ast_mutex_lock(&old->lock); 10620 sig_pri_lock_owner(pri, x); 10621 ast_mutex_lock(&new->lock); 10622 10623 if (option_verbose > 2) { 10624 ast_verbose(VERBOSE_PREFIX_3 10625 "Moving call (%s) from channel %d to %d.\n", 10626 old->owner ? old->owner->name : "", 10627 old->channel, new->channel); 10628 } 10629 if (!sig_pri_is_chan_available(new)) { 10630 ast_log(LOG_WARNING, 10631 "Can't move call (%s) from channel %d to %d. It is already in use.\n", 10632 old->owner ? old->owner->name : "", 10633 old->channel, new->channel); 10634 ast_mutex_unlock(&new->lock); 10635 if (old->owner) { 10636 ast_mutex_unlock(&old->owner->lock); 10637 } 10638 ast_mutex_unlock(&old->lock); 10639 return -1; 10640 } 10641 10642 /* Fix it all up now */ 10643 new->owner = old->owner; 10644 old->owner = NULL; 10645 if (new->owner) { 10646 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 10647 new->owner->tech_pvt = new; 10648 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 10649 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10650 old->subs[SUB_REAL].owner = NULL; 10651 } else 10652 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel); 10653 new->call = old->call; 10654 old->call = NULL; 10655 10656 /* Copy any DSP that may be present */ 10657 new->dsp = old->dsp; 10658 new->dsp_features = old->dsp_features; 10659 old->dsp = NULL; 10660 old->dsp_features = 0; 10661 10662 /* Transfer flags from the old channel. */ 10663 new->alreadyhungup = old->alreadyhungup; 10664 new->isidlecall = old->isidlecall; 10665 new->progress = old->progress; 10666 new->allocated = old->allocated; 10667 new->outgoing = old->outgoing; 10668 new->digital = old->digital; 10669 old->alreadyhungup = 0; 10670 old->isidlecall = 0; 10671 old->progress = 0; 10672 old->allocated = 0; 10673 old->outgoing = 0; 10674 old->digital = 0; 10675 10676 /* More stuff to transfer to the new channel. */ 10677 new->call_level = old->call_level; 10678 old->call_level = DAHDI_CALL_LEVEL_IDLE; 10679 10680 ast_mutex_unlock(&old->lock); 10681 if (new->owner) { 10682 ast_mutex_unlock(&new->owner->lock); 10683 } 10684 ast_mutex_unlock(&new->lock); 10685 } 10686 return principle; 10687 } 10688 } 10689 /* Now check for a CRV with no bearer */ 10690 crv = pri->crvs; 10691 while (crv) { 10692 if (crv->call == c) { 10693 /* This is our match... Perform some basic checks */ 10694 if (crv->bearer) 10695 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10696 else if (pri->pvts[principle]->owner) 10697 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10698 else { 10699 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10700 wakeup the potential sleeper */ 10701 dahdi_close_sub(crv, SUB_REAL); 10702 pri->pvts[principle]->call = crv->call; 10703 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10704 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 10705 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10706 pri->trunkgroup, crv->channel); 10707 wakeup_sub(crv, SUB_REAL, pri); 10708 } 10709 return principle; 10710 } 10711 crv = crv->next; 10712 } 10713 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10714 return -1; 10715 }
Definition at line 1199 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pri::master, and dahdi_pvt::pri.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), send_keypad_facility_exec(), and ss_thread().
01200 { 01201 int res; 01202 /* Grab the lock first */ 01203 do { 01204 res = ast_mutex_trylock(&pri->lock); 01205 if (res) { 01206 DEADLOCK_AVOIDANCE(&pvt->lock); 01207 } 01208 } while (res); 01209 /* Then break the poll */ 01210 if (pri->master != AST_PTHREADT_NULL) 01211 pthread_kill(pri->master, SIGURG); 01212 return 0; 01213 }
Definition at line 10935 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, ast_channel::lock, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
10936 { 10937 int x; 10938 int redo; 10939 ast_mutex_unlock(&pri->lock); 10940 ast_mutex_lock(&p->lock); 10941 do { 10942 redo = 0; 10943 for (x = 0; x < 3; x++) { 10944 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 10945 redo++; 10946 DEADLOCK_AVOIDANCE(&p->lock); 10947 } 10948 if (p->subs[x].owner) { 10949 ast_queue_hangup(p->subs[x].owner); 10950 ast_mutex_unlock(&p->subs[x].owner->lock); 10951 } 10952 } 10953 } while (redo); 10954 ast_mutex_unlock(&p->lock); 10955 ast_mutex_lock(&pri->lock); 10956 return 0; 10957 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3456 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03457 { 03458 int x; 03459 for (x = 0; x < NUM_DCHANS; x++) { 03460 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03461 return 1; 03462 } 03463 return 0; 03464 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3479 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03480 { 03481 switch (level) { 03482 case 0: 03483 return "Primary"; 03484 case 1: 03485 return "Secondary"; 03486 case 2: 03487 return "Tertiary"; 03488 case 3: 03489 return "Quaternary"; 03490 default: 03491 return "<Unknown>"; 03492 } 03493 }
static void pri_queue_control | ( | struct dahdi_pri * | pri, | |
int | chanpos, | |||
int | subclass | |||
) | [static] |
Definition at line 10462 of file chan_dahdi.c.
References AST_FRAME_CONTROL, f, and pri_queue_frame().
Referenced by sig_pri_kill_call().
10463 { 10464 struct ast_frame f = {AST_FRAME_CONTROL, }; 10465 10466 f.subclass = subclass; 10467 pri_queue_frame(pri, chanpos, &f); 10468 }
static void pri_queue_frame | ( | struct dahdi_pri * | pri, | |
int | chanpos, | |||
struct ast_frame * | frame | |||
) | [static] |
Definition at line 10437 of file chan_dahdi.c.
References ast_channel_unlock, ast_queue_frame(), dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pvts, and sig_pri_lock_owner().
Referenced by pri_queue_control().
10438 { 10439 sig_pri_lock_owner(pri, chanpos); 10440 if (pri->pvts[chanpos]->owner) { 10441 ast_queue_frame(pri->pvts[chanpos]->owner, frame); 10442 ast_channel_unlock(pri->pvts[chanpos]->owner); 10443 } 10444 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 452 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::pri.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), send_keypad_facility_exec(), and ss_thread().
00453 { 00454 ast_mutex_unlock(&pri->lock); 00455 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8996 of file chan_dahdi.c.
References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pri::offset, pris, and dahdi_pri::span.
Referenced by mkintf().
08997 { 08998 int x; 08999 int trunkgroup; 09000 /* Get appropriate trunk group if there is one */ 09001 trunkgroup = pris[*span].mastertrunkgroup; 09002 if (trunkgroup) { 09003 /* Select a specific trunk group */ 09004 for (x = 0; x < NUM_SPANS; x++) { 09005 if (pris[x].trunkgroup == trunkgroup) { 09006 *span = x; 09007 return 0; 09008 } 09009 } 09010 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 09011 *span = -1; 09012 } else { 09013 if (pris[*span].trunkgroup) { 09014 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 09015 *span = -1; 09016 } else if (pris[*span].mastertrunkgroup) { 09017 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 09018 *span = -1; 09019 } else { 09020 if (si->totalchans == 31) { 09021 /* E1 */ 09022 pris[*span].dchannels[0] = 16 + offset; 09023 } else if (si->totalchans == 24) { 09024 /* T1 or J1 */ 09025 pris[*span].dchannels[0] = 24 + offset; 09026 } else if (si->totalchans == 3) { 09027 /* BRI */ 09028 pris[*span].dchannels[0] = 3 + offset; 09029 } else { 09030 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); 09031 *span = -1; 09032 return 0; 09033 } 09034 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 09035 pris[*span].offset = offset; 09036 pris[*span].span = *span + 1; 09037 } 09038 } 09039 return 0; 09040 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 14098 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, cadences, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_RING, cidrings, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, distinctiveringaftercid, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, mfcr2_cur_accept_on_offer, mfcr2_cur_allow_collect_calls, mfcr2_cur_call_files, mfcr2_cur_category, mfcr2_cur_charge_calls, mfcr2_cur_double_answer, mfcr2_cur_forced_release, mfcr2_cur_get_ani_first, mfcr2_cur_immediate_accept, mfcr2_cur_logdir, mfcr2_cur_loglevel, mfcr2_cur_max_ani, mfcr2_cur_max_dnis, mfcr2_cur_metering_pulse_timeout, mfcr2_cur_mfback_timeout, mfcr2_cur_r2proto_file, mfcr2_cur_skip_category, mfcr2_cur_variant, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, num_cadence, NUM_CADENCE_MAX, numbufs, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, parse_buffers_policy(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, progzone, dahdi_pvt::pulse, dahdi_pvt::radio, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ringt_base, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, 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_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, user_has_defined_cadences, ast_variable::value, and VERBOSE_PREFIX_3.
Referenced by setup_dahdi().
14099 { 14100 struct dahdi_pvt *tmp; 14101 int y; 14102 int found_pseudo = 0; 14103 char dahdichan[MAX_CHANLIST_LEN] = {}; 14104 14105 for (; v; v = v->next) { 14106 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14107 continue; 14108 14109 /* Create the interface list */ 14110 if (!strcasecmp(v->name, "channel") 14111 #ifdef HAVE_PRI 14112 || !strcasecmp(v->name, "crv") 14113 #endif 14114 ) { 14115 int iscrv; 14116 if (skipchannels) 14117 continue; 14118 iscrv = !strcasecmp(v->name, "crv"); 14119 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14120 return -1; 14121 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 14122 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14123 if (v->name[0] == 'z' || v->name[0] == 'Z') { 14124 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 14125 } 14126 } else if (!strcasecmp(v->name, "buffers")) { 14127 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) { 14128 ast_log(LOG_WARNING, "Using default buffer policy.\n"); 14129 confp->chan.buf_no = numbufs; 14130 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14131 } 14132 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14133 if (ast_true(v->value)) 14134 confp->chan.usedistinctiveringdetection = 1; 14135 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14136 if (ast_true(v->value)) 14137 distinctiveringaftercid = 1; 14138 } else if (!strcasecmp(v->name, "dring1context")) { 14139 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 14140 } else if (!strcasecmp(v->name, "dring2context")) { 14141 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 14142 } else if (!strcasecmp(v->name, "dring3context")) { 14143 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 14144 } else if (!strcasecmp(v->name, "dring1")) { 14145 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 14146 } else if (!strcasecmp(v->name, "dring2")) { 14147 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 14148 } else if (!strcasecmp(v->name, "dring3")) { 14149 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 14150 } else if (!strcasecmp(v->name, "usecallerid")) { 14151 confp->chan.use_callerid = ast_true(v->value); 14152 } else if (!strcasecmp(v->name, "cidsignalling")) { 14153 if (!strcasecmp(v->value, "bell")) 14154 confp->chan.cid_signalling = CID_SIG_BELL; 14155 else if (!strcasecmp(v->value, "v23")) 14156 confp->chan.cid_signalling = CID_SIG_V23; 14157 else if (!strcasecmp(v->value, "dtmf")) 14158 confp->chan.cid_signalling = CID_SIG_DTMF; 14159 else if (!strcasecmp(v->value, "smdi")) 14160 confp->chan.cid_signalling = CID_SIG_SMDI; 14161 else if (!strcasecmp(v->value, "v23_jp")) 14162 confp->chan.cid_signalling = CID_SIG_V23_JP; 14163 else if (ast_true(v->value)) 14164 confp->chan.cid_signalling = CID_SIG_BELL; 14165 } else if (!strcasecmp(v->name, "cidstart")) { 14166 if (!strcasecmp(v->value, "ring")) 14167 confp->chan.cid_start = CID_START_RING; 14168 else if (!strcasecmp(v->value, "polarity")) 14169 confp->chan.cid_start = CID_START_POLARITY; 14170 else if (!strcasecmp(v->value, "dtmf")) 14171 confp->chan.cid_start = CID_START_DTMF_NOALERT; 14172 else if (ast_true(v->value)) 14173 confp->chan.cid_start = CID_START_RING; 14174 } else if (!strcasecmp(v->name, "threewaycalling")) { 14175 confp->chan.threewaycalling = ast_true(v->value); 14176 } else if (!strcasecmp(v->name, "cancallforward")) { 14177 confp->chan.cancallforward = ast_true(v->value); 14178 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14179 if (ast_true(v->value)) 14180 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14181 else 14182 confp->chan.dtmfrelax = 0; 14183 } else if (!strcasecmp(v->name, "mailbox")) { 14184 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14185 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14186 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14187 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14188 } 14189 } else if (!strcasecmp(v->name, "adsi")) { 14190 confp->chan.adsi = ast_true(v->value); 14191 } else if (!strcasecmp(v->name, "usesmdi")) { 14192 confp->chan.use_smdi = ast_true(v->value); 14193 } else if (!strcasecmp(v->name, "smdiport")) { 14194 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14195 } else if (!strcasecmp(v->name, "transfer")) { 14196 confp->chan.transfer = ast_true(v->value); 14197 } else if (!strcasecmp(v->name, "canpark")) { 14198 confp->chan.canpark = ast_true(v->value); 14199 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14200 confp->chan.echocanbridged = ast_true(v->value); 14201 } else if (!strcasecmp(v->name, "busydetect")) { 14202 confp->chan.busydetect = ast_true(v->value); 14203 } else if (!strcasecmp(v->name, "busycount")) { 14204 confp->chan.busycount = atoi(v->value); 14205 } else if (!strcasecmp(v->name, "silencethreshold")) { 14206 confp->chan.silencethreshold = atoi(v->value); 14207 } else if (!strcasecmp(v->name, "busycompare")) { 14208 confp->chan.busycompare = ast_true(v->value); 14209 } else if (!strcasecmp(v->name, "busypattern")) { 14210 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 14211 if (count == 1) 14212 confp->chan.busyquietlength = 0; 14213 else if (count < 1) 14214 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 14215 } else if (!strcasecmp(v->name, "busyfuzziness")) { 14216 confp->chan.busyfuzziness = atoi(v->value); 14217 } else if (!strcasecmp(v->name, "callprogress")) { 14218 if (ast_true(v->value)) 14219 confp->chan.callprogress |= 1; 14220 else 14221 confp->chan.callprogress &= ~1; 14222 } else if (!strcasecmp(v->name, "faxdetect")) { 14223 if (!strcasecmp(v->value, "incoming")) { 14224 confp->chan.callprogress |= 4; 14225 confp->chan.callprogress &= ~2; 14226 } else if (!strcasecmp(v->value, "outgoing")) { 14227 confp->chan.callprogress &= ~4; 14228 confp->chan.callprogress |= 2; 14229 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14230 confp->chan.callprogress |= 6; 14231 else 14232 confp->chan.callprogress &= ~6; 14233 } else if (!strcasecmp(v->name, "echocancel")) { 14234 if (!ast_strlen_zero(v->value)) { 14235 y = atoi(v->value); 14236 } else 14237 y = 0; 14238 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 14239 confp->chan.echocancel = y; 14240 else { 14241 confp->chan.echocancel = ast_true(v->value); 14242 if (confp->chan.echocancel) 14243 confp->chan.echocancel=128; 14244 } 14245 } else if (!strcasecmp(v->name, "echotraining")) { 14246 if (sscanf(v->value, "%30d", &y) == 1) { 14247 if ((y < 10) || (y > 4000)) { 14248 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 14249 } else { 14250 confp->chan.echotraining = y; 14251 } 14252 } else if (ast_true(v->value)) { 14253 confp->chan.echotraining = 400; 14254 } else 14255 confp->chan.echotraining = 0; 14256 } else if (!strcasecmp(v->name, "hidecallerid")) { 14257 confp->chan.hidecallerid = ast_true(v->value); 14258 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14259 confp->chan.hidecalleridname = ast_true(v->value); 14260 } else if (!strcasecmp(v->name, "pulsedial")) { 14261 confp->chan.pulse = ast_true(v->value); 14262 } else if (!strcasecmp(v->name, "callreturn")) { 14263 confp->chan.callreturn = ast_true(v->value); 14264 } else if (!strcasecmp(v->name, "callwaiting")) { 14265 confp->chan.callwaiting = ast_true(v->value); 14266 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14267 confp->chan.callwaitingcallerid = ast_true(v->value); 14268 } else if (!strcasecmp(v->name, "context")) { 14269 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14270 } else if (!strcasecmp(v->name, "language")) { 14271 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14272 } else if (!strcasecmp(v->name, "progzone")) { 14273 ast_copy_string(progzone, v->value, sizeof(progzone)); 14274 } else if (!strcasecmp(v->name, "mohinterpret") 14275 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14276 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14277 } else if (!strcasecmp(v->name, "mohsuggest")) { 14278 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14279 } else if (!strcasecmp(v->name, "stripmsd")) { 14280 confp->chan.stripmsd = atoi(v->value); 14281 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14282 numbufs = atoi(v->value); 14283 } else if (!strcasecmp(v->name, "group")) { 14284 confp->chan.group = ast_get_group(v->value); 14285 } else if (!strcasecmp(v->name, "callgroup")) { 14286 confp->chan.callgroup = ast_get_group(v->value); 14287 } else if (!strcasecmp(v->name, "pickupgroup")) { 14288 confp->chan.pickupgroup = ast_get_group(v->value); 14289 } else if (!strcasecmp(v->name, "immediate")) { 14290 confp->chan.immediate = ast_true(v->value); 14291 } else if (!strcasecmp(v->name, "transfertobusy")) { 14292 confp->chan.transfertobusy = ast_true(v->value); 14293 } else if (!strcasecmp(v->name, "rxgain")) { 14294 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 14295 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 14296 } 14297 } else if (!strcasecmp(v->name, "txgain")) { 14298 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 14299 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 14300 } 14301 } else if (!strcasecmp(v->name, "tonezone")) { 14302 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 14303 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 14304 } 14305 } else if (!strcasecmp(v->name, "callerid")) { 14306 if (!strcasecmp(v->value, "asreceived")) { 14307 confp->chan.cid_num[0] = '\0'; 14308 confp->chan.cid_name[0] = '\0'; 14309 } else { 14310 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14311 } 14312 } else if (!strcasecmp(v->name, "fullname")) { 14313 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14314 } else if (!strcasecmp(v->name, "cid_number")) { 14315 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14316 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 14317 confp->chan.dahditrcallerid = ast_true(v->value); 14318 if (strstr(v->name, "zap")) { 14319 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 14320 } 14321 } else if (!strcasecmp(v->name, "restrictcid")) { 14322 confp->chan.restrictcid = ast_true(v->value); 14323 } else if (!strcasecmp(v->name, "usecallingpres")) { 14324 confp->chan.use_callingpres = ast_true(v->value); 14325 } else if (!strcasecmp(v->name, "accountcode")) { 14326 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14327 } else if (!strcasecmp(v->name, "amaflags")) { 14328 y = ast_cdr_amaflags2int(v->value); 14329 if (y < 0) 14330 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 14331 else 14332 confp->chan.amaflags = y; 14333 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14334 confp->chan.polarityonanswerdelay = atoi(v->value); 14335 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14336 confp->chan.answeronpolarityswitch = ast_true(v->value); 14337 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14338 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14339 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14340 confp->chan.sendcalleridafter = atoi(v->value); 14341 } else if (reload != 1) { 14342 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14343 confp->chan.outsigmod = -1; 14344 if (!strcasecmp(v->value, "em")) { 14345 confp->chan.sig = SIG_EM; 14346 } else if (!strcasecmp(v->value, "em_e1")) { 14347 confp->chan.sig = SIG_EM_E1; 14348 } else if (!strcasecmp(v->value, "em_w")) { 14349 confp->chan.sig = SIG_EMWINK; 14350 confp->chan.radio = 0; 14351 } else if (!strcasecmp(v->value, "fxs_ls")) { 14352 confp->chan.sig = SIG_FXSLS; 14353 confp->chan.radio = 0; 14354 } else if (!strcasecmp(v->value, "fxs_gs")) { 14355 confp->chan.sig = SIG_FXSGS; 14356 confp->chan.radio = 0; 14357 } else if (!strcasecmp(v->value, "fxs_ks")) { 14358 confp->chan.sig = SIG_FXSKS; 14359 confp->chan.radio = 0; 14360 } else if (!strcasecmp(v->value, "fxo_ls")) { 14361 confp->chan.sig = SIG_FXOLS; 14362 confp->chan.radio = 0; 14363 } else if (!strcasecmp(v->value, "fxo_gs")) { 14364 confp->chan.sig = SIG_FXOGS; 14365 confp->chan.radio = 0; 14366 } else if (!strcasecmp(v->value, "fxo_ks")) { 14367 confp->chan.sig = SIG_FXOKS; 14368 confp->chan.radio = 0; 14369 } else if (!strcasecmp(v->value, "fxs_rx")) { 14370 confp->chan.sig = SIG_FXSKS; 14371 confp->chan.radio = 1; 14372 } else if (!strcasecmp(v->value, "fxo_rx")) { 14373 confp->chan.sig = SIG_FXOLS; 14374 confp->chan.radio = 1; 14375 } else if (!strcasecmp(v->value, "fxs_tx")) { 14376 confp->chan.sig = SIG_FXSLS; 14377 confp->chan.radio = 1; 14378 } else if (!strcasecmp(v->value, "fxo_tx")) { 14379 confp->chan.sig = SIG_FXOGS; 14380 confp->chan.radio = 1; 14381 } else if (!strcasecmp(v->value, "em_rx")) { 14382 confp->chan.sig = SIG_EM; 14383 confp->chan.radio = 1; 14384 } else if (!strcasecmp(v->value, "em_tx")) { 14385 confp->chan.sig = SIG_EM; 14386 confp->chan.radio = 1; 14387 } else if (!strcasecmp(v->value, "em_rxtx")) { 14388 confp->chan.sig = SIG_EM; 14389 confp->chan.radio = 2; 14390 } else if (!strcasecmp(v->value, "em_txrx")) { 14391 confp->chan.sig = SIG_EM; 14392 confp->chan.radio = 2; 14393 } else if (!strcasecmp(v->value, "sf")) { 14394 confp->chan.sig = SIG_SF; 14395 confp->chan.radio = 0; 14396 } else if (!strcasecmp(v->value, "sf_w")) { 14397 confp->chan.sig = SIG_SFWINK; 14398 confp->chan.radio = 0; 14399 } else if (!strcasecmp(v->value, "sf_featd")) { 14400 confp->chan.sig = SIG_FEATD; 14401 confp->chan.radio = 0; 14402 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14403 confp->chan.sig = SIG_FEATDMF; 14404 confp->chan.radio = 0; 14405 } else if (!strcasecmp(v->value, "sf_featb")) { 14406 confp->chan.sig = SIG_SF_FEATB; 14407 confp->chan.radio = 0; 14408 } else if (!strcasecmp(v->value, "sf")) { 14409 confp->chan.sig = SIG_SF; 14410 confp->chan.radio = 0; 14411 } else if (!strcasecmp(v->value, "sf_rx")) { 14412 confp->chan.sig = SIG_SF; 14413 confp->chan.radio = 1; 14414 } else if (!strcasecmp(v->value, "sf_tx")) { 14415 confp->chan.sig = SIG_SF; 14416 confp->chan.radio = 1; 14417 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14418 confp->chan.sig = SIG_SF; 14419 confp->chan.radio = 2; 14420 } else if (!strcasecmp(v->value, "sf_txrx")) { 14421 confp->chan.sig = SIG_SF; 14422 confp->chan.radio = 2; 14423 } else if (!strcasecmp(v->value, "featd")) { 14424 confp->chan.sig = SIG_FEATD; 14425 confp->chan.radio = 0; 14426 } else if (!strcasecmp(v->value, "featdmf")) { 14427 confp->chan.sig = SIG_FEATDMF; 14428 confp->chan.radio = 0; 14429 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14430 confp->chan.sig = SIG_FEATDMF_TA; 14431 confp->chan.radio = 0; 14432 } else if (!strcasecmp(v->value, "e911")) { 14433 confp->chan.sig = SIG_E911; 14434 confp->chan.radio = 0; 14435 } else if (!strcasecmp(v->value, "fgccama")) { 14436 confp->chan.sig = SIG_FGC_CAMA; 14437 confp->chan.radio = 0; 14438 } else if (!strcasecmp(v->value, "fgccamamf")) { 14439 confp->chan.sig = SIG_FGC_CAMAMF; 14440 confp->chan.radio = 0; 14441 } else if (!strcasecmp(v->value, "featb")) { 14442 confp->chan.sig = SIG_FEATB; 14443 confp->chan.radio = 0; 14444 #ifdef HAVE_OPENR2 14445 } else if (!strcasecmp(v->value, "mfcr2")) { 14446 confp->chan.sig = SIG_MFCR2; 14447 #endif 14448 14449 #ifdef HAVE_PRI 14450 } else if (!strcasecmp(v->value, "pri_net")) { 14451 confp->chan.radio = 0; 14452 confp->chan.sig = SIG_PRI; 14453 confp->pri.nodetype = PRI_NETWORK; 14454 } else if (!strcasecmp(v->value, "pri_cpe")) { 14455 confp->chan.sig = SIG_PRI; 14456 confp->chan.radio = 0; 14457 confp->pri.nodetype = PRI_CPE; 14458 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14459 confp->chan.sig = SIG_GR303FXOKS; 14460 confp->chan.radio = 0; 14461 confp->pri.nodetype = PRI_NETWORK; 14462 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14463 confp->chan.sig = SIG_GR303FXSKS; 14464 confp->chan.radio = 0; 14465 confp->pri.nodetype = PRI_CPE; 14466 #endif 14467 } else { 14468 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 14469 } 14470 } else if (!strcasecmp(v->name, "outsignalling")) { 14471 if (!strcasecmp(v->value, "em")) { 14472 confp->chan.outsigmod = SIG_EM; 14473 } else if (!strcasecmp(v->value, "em_e1")) { 14474 confp->chan.outsigmod = SIG_EM_E1; 14475 } else if (!strcasecmp(v->value, "em_w")) { 14476 confp->chan.outsigmod = SIG_EMWINK; 14477 } else if (!strcasecmp(v->value, "sf")) { 14478 confp->chan.outsigmod = SIG_SF; 14479 } else if (!strcasecmp(v->value, "sf_w")) { 14480 confp->chan.outsigmod = SIG_SFWINK; 14481 } else if (!strcasecmp(v->value, "sf_featd")) { 14482 confp->chan.outsigmod = SIG_FEATD; 14483 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14484 confp->chan.outsigmod = SIG_FEATDMF; 14485 } else if (!strcasecmp(v->value, "sf_featb")) { 14486 confp->chan.outsigmod = SIG_SF_FEATB; 14487 } else if (!strcasecmp(v->value, "sf")) { 14488 confp->chan.outsigmod = SIG_SF; 14489 } else if (!strcasecmp(v->value, "featd")) { 14490 confp->chan.outsigmod = SIG_FEATD; 14491 } else if (!strcasecmp(v->value, "featdmf")) { 14492 confp->chan.outsigmod = SIG_FEATDMF; 14493 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14494 confp->chan.outsigmod = SIG_FEATDMF_TA; 14495 } else if (!strcasecmp(v->value, "e911")) { 14496 confp->chan.outsigmod = SIG_E911; 14497 } else if (!strcasecmp(v->value, "fgccama")) { 14498 confp->chan.outsigmod = SIG_FGC_CAMA; 14499 } else if (!strcasecmp(v->value, "fgccamamf")) { 14500 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14501 } else if (!strcasecmp(v->value, "featb")) { 14502 confp->chan.outsigmod = SIG_FEATB; 14503 } else { 14504 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 14505 } 14506 #ifdef HAVE_PRI 14507 } else if (!strcasecmp(v->name, "pridialplan")) { 14508 if (!strcasecmp(v->value, "national")) { 14509 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14510 } else if (!strcasecmp(v->value, "unknown")) { 14511 confp->pri.dialplan = PRI_UNKNOWN + 1; 14512 } else if (!strcasecmp(v->value, "private")) { 14513 confp->pri.dialplan = PRI_PRIVATE + 1; 14514 } else if (!strcasecmp(v->value, "international")) { 14515 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14516 } else if (!strcasecmp(v->value, "local")) { 14517 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14518 } else if (!strcasecmp(v->value, "dynamic")) { 14519 confp->pri.dialplan = -1; 14520 } else { 14521 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14522 } 14523 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14524 if (!strcasecmp(v->value, "national")) { 14525 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14526 } else if (!strcasecmp(v->value, "unknown")) { 14527 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14528 } else if (!strcasecmp(v->value, "private")) { 14529 confp->pri.localdialplan = PRI_PRIVATE + 1; 14530 } else if (!strcasecmp(v->value, "international")) { 14531 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14532 } else if (!strcasecmp(v->value, "local")) { 14533 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14534 } else if (!strcasecmp(v->value, "dynamic")) { 14535 confp->pri.localdialplan = -1; 14536 } else { 14537 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14538 } 14539 } else if (!strcasecmp(v->name, "switchtype")) { 14540 if (!strcasecmp(v->value, "national")) 14541 confp->pri.switchtype = PRI_SWITCH_NI2; 14542 else if (!strcasecmp(v->value, "ni1")) 14543 confp->pri.switchtype = PRI_SWITCH_NI1; 14544 else if (!strcasecmp(v->value, "dms100")) 14545 confp->pri.switchtype = PRI_SWITCH_DMS100; 14546 else if (!strcasecmp(v->value, "4ess")) 14547 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14548 else if (!strcasecmp(v->value, "5ess")) 14549 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14550 else if (!strcasecmp(v->value, "euroisdn")) 14551 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14552 else if (!strcasecmp(v->value, "qsig")) 14553 confp->pri.switchtype = PRI_SWITCH_QSIG; 14554 else { 14555 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 14556 return -1; 14557 } 14558 } else if (!strcasecmp(v->name, "nsf")) { 14559 if (!strcasecmp(v->value, "sdn")) 14560 confp->pri.nsf = PRI_NSF_SDN; 14561 else if (!strcasecmp(v->value, "megacom")) 14562 confp->pri.nsf = PRI_NSF_MEGACOM; 14563 else if (!strcasecmp(v->value, "tollfreemegacom")) 14564 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14565 else if (!strcasecmp(v->value, "accunet")) 14566 confp->pri.nsf = PRI_NSF_ACCUNET; 14567 else if (!strcasecmp(v->value, "none")) 14568 confp->pri.nsf = PRI_NSF_NONE; 14569 else { 14570 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 14571 confp->pri.nsf = PRI_NSF_NONE; 14572 } 14573 } else if (!strcasecmp(v->name, "priindication")) { 14574 if (!strcasecmp(v->value, "outofband")) 14575 confp->chan.priindication_oob = 1; 14576 else if (!strcasecmp(v->value, "inband")) 14577 confp->chan.priindication_oob = 0; 14578 else 14579 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 14580 v->value, v->lineno); 14581 } else if (!strcasecmp(v->name, "priexclusive")) { 14582 confp->chan.priexclusive = ast_true(v->value); 14583 } else if (!strcasecmp(v->name, "internationalprefix")) { 14584 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14585 } else if (!strcasecmp(v->name, "nationalprefix")) { 14586 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14587 } else if (!strcasecmp(v->name, "localprefix")) { 14588 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14589 } else if (!strcasecmp(v->name, "privateprefix")) { 14590 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14591 } else if (!strcasecmp(v->name, "unknownprefix")) { 14592 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14593 } else if (!strcasecmp(v->name, "resetinterval")) { 14594 if (!strcasecmp(v->value, "never")) 14595 confp->pri.resetinterval = -1; 14596 else if (atoi(v->value) >= 60) 14597 confp->pri.resetinterval = atoi(v->value); 14598 else 14599 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 14600 v->value, v->lineno); 14601 } else if (!strcasecmp(v->name, "minunused")) { 14602 confp->pri.minunused = atoi(v->value); 14603 } else if (!strcasecmp(v->name, "minidle")) { 14604 confp->pri.minidle = atoi(v->value); 14605 } else if (!strcasecmp(v->name, "idleext")) { 14606 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14607 } else if (!strcasecmp(v->name, "idledial")) { 14608 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14609 } else if (!strcasecmp(v->name, "overlapdial")) { 14610 if (ast_true(v->value)) { 14611 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14612 } else if (!strcasecmp(v->value, "incoming")) { 14613 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14614 } else if (!strcasecmp(v->value, "outgoing")) { 14615 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14616 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14617 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14618 } else { 14619 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14620 } 14621 #ifdef HAVE_PRI_INBANDDISCONNECT 14622 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14623 confp->pri.inbanddisconnect = ast_true(v->value); 14624 #endif 14625 } else if (!strcasecmp(v->name, "pritimer")) { 14626 #ifdef PRI_GETSET_TIMERS 14627 char tmp[20]; 14628 char *timerc; 14629 char *c; 14630 int timer; 14631 int timeridx; 14632 14633 ast_copy_string(tmp, v->value, sizeof(tmp)); 14634 c = tmp; 14635 timerc = strsep(&c, ","); 14636 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 14637 timeridx = pri_timer2idx(timerc); 14638 timer = atoi(c); 14639 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 14640 ast_log(LOG_WARNING, 14641 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 14642 v->lineno); 14643 } else if (!timer) { 14644 ast_log(LOG_WARNING, 14645 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 14646 c, timerc, v->lineno); 14647 } else { 14648 pritimers[timeridx] = timer; 14649 } 14650 } else { 14651 ast_log(LOG_WARNING, 14652 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 14653 v->value, v->lineno); 14654 } 14655 #endif /* PRI_GETSET_TIMERS */ 14656 } else if (!strcasecmp(v->name, "facilityenable")) { 14657 confp->pri.facilityenable = ast_true(v->value); 14658 #endif /* HAVE_PRI */ 14659 14660 #ifdef HAVE_OPENR2 14661 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 14662 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file)); 14663 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", mfcr2_cur_r2proto_file); 14664 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 14665 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir)); 14666 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 14667 mfcr2_cur_variant = openr2_proto_get_variant(v->value); 14668 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) { 14669 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno); 14670 } 14671 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 14672 mfcr2_cur_mfback_timeout = atoi(v->value); 14673 if (!mfcr2_cur_mfback_timeout) { 14674 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 14675 mfcr2_cur_mfback_timeout = -1; 14676 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) { 14677 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 14678 } 14679 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 14680 mfcr2_cur_metering_pulse_timeout = atoi(v->value); 14681 if (mfcr2_cur_metering_pulse_timeout > 500) { 14682 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n"); 14683 } 14684 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 14685 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) { 14686 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0; 14687 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) { 14688 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0; 14689 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) { 14690 mfcr2_cur_dtmf_time_on = atoi(v->value); 14691 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) { 14692 mfcr2_cur_dtmf_time_off = atoi(v->value); 14693 #endif 14694 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 14695 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0; 14696 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 14697 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0; 14698 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 14699 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0; 14700 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 14701 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0; 14702 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 14703 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0; 14704 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 14705 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0; 14706 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 14707 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0; 14708 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 14709 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0; 14710 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 14711 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0; 14712 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 14713 mfcr2_cur_max_ani = atoi(v->value); 14714 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) { 14715 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1; 14716 } 14717 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 14718 mfcr2_cur_max_dnis = atoi(v->value); 14719 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) { 14720 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1; 14721 } 14722 } else if (!strcasecmp(v->name, "mfcr2_category")) { 14723 mfcr2_cur_category = openr2_proto_get_category(v->value); 14724 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) { 14725 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 14726 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 14727 v->value, v->lineno); 14728 } 14729 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 14730 openr2_log_level_t tmplevel; 14731 char *toklevel = NULL; 14732 char *saveptr = NULL; 14733 char *logval = ast_strdupa(v->value); 14734 toklevel = strtok_r(logval, ",", &saveptr); 14735 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14736 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno); 14737 } else if (OR2_LOG_NOTHING == tmplevel) { 14738 mfcr2_cur_loglevel = tmplevel; 14739 } else { 14740 mfcr2_cur_loglevel |= tmplevel; 14741 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 14742 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 14743 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno); 14744 continue; 14745 } 14746 mfcr2_cur_loglevel |= tmplevel; 14747 } 14748 } 14749 #endif /* HAVE_OPENR2 */ 14750 14751 } else if (!strcasecmp(v->name, "cadence")) { 14752 /* setup to scan our argument */ 14753 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14754 int i; 14755 struct dahdi_ring_cadence new_cadence; 14756 int cid_location = -1; 14757 int firstcadencepos = 0; 14758 char original_args[80]; 14759 int cadence_is_ok = 1; 14760 14761 ast_copy_string(original_args, v->value, sizeof(original_args)); 14762 /* 16 cadences allowed (8 pairs) */ 14763 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]); 14764 14765 /* Cadence must be even (on/off) */ 14766 if (element_count % 2 == 1) { 14767 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 14768 cadence_is_ok = 0; 14769 } 14770 14771 /* Ring cadences cannot be negative */ 14772 for (i = 0; i < element_count; i++) { 14773 if (c[i] == 0) { 14774 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 14775 cadence_is_ok = 0; 14776 break; 14777 } else if (c[i] < 0) { 14778 if (i % 2 == 1) { 14779 /* Silence duration, negative possibly okay */ 14780 if (cid_location == -1) { 14781 cid_location = i; 14782 c[i] *= -1; 14783 } else { 14784 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 14785 cadence_is_ok = 0; 14786 break; 14787 } 14788 } else { 14789 if (firstcadencepos == 0) { 14790 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 14791 /* duration will be passed negative to the DAHDI driver */ 14792 } else { 14793 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 14794 cadence_is_ok = 0; 14795 break; 14796 } 14797 } 14798 } 14799 } 14800 14801 /* Substitute our scanned cadence */ 14802 for (i = 0; i < 16; i++) { 14803 new_cadence.ringcadence[i] = c[i]; 14804 } 14805 14806 if (cadence_is_ok) { 14807 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 14808 if (element_count < 2) { 14809 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 14810 } else { 14811 if (cid_location == -1) { 14812 /* user didn't say; default to first pause */ 14813 cid_location = 1; 14814 } else { 14815 /* convert element_index to cidrings value */ 14816 cid_location = (cid_location + 1) / 2; 14817 } 14818 /* ---we like their cadence; try to install it--- */ 14819 if (!user_has_defined_cadences++) 14820 /* this is the first user-defined cadence; clear the default user cadences */ 14821 num_cadence = 0; 14822 if ((num_cadence+1) >= NUM_CADENCE_MAX) 14823 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 14824 else { 14825 cadences[num_cadence] = new_cadence; 14826 cidrings[num_cadence++] = cid_location; 14827 if (option_verbose > 2) 14828 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 14829 } 14830 } 14831 } 14832 } else if (!strcasecmp(v->name, "ringtimeout")) { 14833 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 14834 } else if (!strcasecmp(v->name, "prewink")) { 14835 confp->timing.prewinktime = atoi(v->value); 14836 } else if (!strcasecmp(v->name, "preflash")) { 14837 confp->timing.preflashtime = atoi(v->value); 14838 } else if (!strcasecmp(v->name, "wink")) { 14839 confp->timing.winktime = atoi(v->value); 14840 } else if (!strcasecmp(v->name, "flash")) { 14841 confp->timing.flashtime = atoi(v->value); 14842 } else if (!strcasecmp(v->name, "start")) { 14843 confp->timing.starttime = atoi(v->value); 14844 } else if (!strcasecmp(v->name, "rxwink")) { 14845 confp->timing.rxwinktime = atoi(v->value); 14846 } else if (!strcasecmp(v->name, "rxflash")) { 14847 confp->timing.rxflashtime = atoi(v->value); 14848 } else if (!strcasecmp(v->name, "debounce")) { 14849 confp->timing.debouncetime = atoi(v->value); 14850 } else if (!strcasecmp(v->name, "toneduration")) { 14851 int toneduration; 14852 int ctlfd; 14853 int res; 14854 struct dahdi_dialparams dps; 14855 14856 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 14857 14858 if (ctlfd == -1) { 14859 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 14860 return -1; 14861 } 14862 14863 toneduration = atoi(v->value); 14864 if (toneduration > -1) { 14865 memset(&dps, 0, sizeof(dps)); 14866 14867 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 14868 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 14869 if (res < 0) { 14870 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 14871 close(ctlfd); 14872 return -1; 14873 } 14874 } 14875 close(ctlfd); 14876 } else if (!strcasecmp(v->name, "defaultcic")) { 14877 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 14878 } else if (!strcasecmp(v->name, "defaultozz")) { 14879 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 14880 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 14881 dtmfcid_level = atoi(v->value); 14882 } 14883 } else if (!skipchannels) 14884 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 14885 } 14886 if (dahdichan[0]) { 14887 /* The user has set 'dahdichan' */ 14888 /*< \todo pass proper line number instead of 0 */ 14889 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 14890 return -1; 14891 } 14892 } 14893 /*< \todo why check for the pseudo in the per-channel section. 14894 * Any actual use for manual setup of the pseudo channel? */ 14895 if (!found_pseudo && reload != 1) { 14896 /* use the default configuration for a channel, so 14897 that any settings from real configured channels 14898 don't "leak" into the pseudo channel config 14899 */ 14900 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 14901 14902 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 14903 14904 if (tmp) { 14905 if (option_verbose > 2) 14906 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 14907 } else { 14908 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 14909 } 14910 } 14911 return 0; 14912 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10959 of file chan_dahdi.c.
Referenced by __oh323_new().
10960 { 10961 switch (redirectingreason) { 10962 case 0: 10963 return "UNKNOWN"; 10964 case 1: 10965 return "BUSY"; 10966 case 2: 10967 return "NO_REPLY"; 10968 case 0xF: 10969 return "UNCONDITIONAL"; 10970 default: 10971 return "NOREDIRECT"; 10972 } 10973 }
static int reload | ( | void | ) | [static] |
Definition at line 15255 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
15256 { 15257 int res = 0; 15258 15259 res = setup_dahdi(1); 15260 if (res) { 15261 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15262 return -1; 15263 } 15264 return 0; 15265 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2374 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().
02375 { 02376 p->confno = -1; 02377 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 02378 if (p->subs[SUB_REAL].dfd > -1) { 02379 struct dahdi_confinfo zi; 02380 02381 memset(&zi, 0, sizeof(zi)); 02382 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 02383 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 02384 } 02385 return 0; 02386 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8953 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(), oh323_request(), phone_hangup(), phone_request(), setup_dahdi(), sip_reload(), sip_request_call(), and skinny_request().
08954 { 08955 pthread_attr_t attr; 08956 pthread_attr_init(&attr); 08957 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08958 /* If we're supposed to be stopped -- stay stopped */ 08959 if (monitor_thread == AST_PTHREADT_STOP) 08960 return 0; 08961 ast_mutex_lock(&monlock); 08962 if (monitor_thread == pthread_self()) { 08963 ast_mutex_unlock(&monlock); 08964 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08965 return -1; 08966 } 08967 if (monitor_thread != AST_PTHREADT_NULL) { 08968 /* Wake up the thread */ 08969 pthread_kill(monitor_thread, SIGURG); 08970 } else { 08971 /* Start a new monitor */ 08972 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 08973 ast_mutex_unlock(&monlock); 08974 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08975 pthread_attr_destroy(&attr); 08976 return -1; 08977 } 08978 } 08979 ast_mutex_unlock(&monlock); 08980 pthread_attr_destroy(&attr); 08981 return 0; 08982 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2707 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), handle_init_event(), and send_callerid().
02708 { 02709 int res; 02710 if (p->saveconf.confmode) { 02711 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02712 p->saveconf.confmode = 0; 02713 if (res) { 02714 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02715 return -1; 02716 } 02717 if (option_debug) 02718 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02719 } 02720 return 0; 02721 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2634 of file chan_dahdi.c.
References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by dahdi_hangup(), and ss_thread().
02635 { 02636 int res; 02637 02638 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02639 if (res) { 02640 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02641 return -1; 02642 } 02643 02644 return 0; 02645 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2680 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
02681 { 02682 struct dahdi_confinfo c; 02683 int res; 02684 if (p->saveconf.confmode) { 02685 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02686 return -1; 02687 } 02688 p->saveconf.chan = 0; 02689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02690 if (res) { 02691 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02692 p->saveconf.confmode = 0; 02693 return -1; 02694 } 02695 memset(&c, 0, sizeof(c)); 02696 c.confmode = DAHDI_CONF_NORMAL; 02697 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02698 if (res) { 02699 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02700 return -1; 02701 } 02702 if (option_debug) 02703 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02704 return 0; 02705 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2748 of file chan_dahdi.c.
References 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, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_call(), dahdi_callwait(), and send_cwcidspill().
02749 { 02750 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02751 int res; 02752 /* Take out of linear mode if necessary */ 02753 if (p->subs[SUB_REAL].linear) { 02754 p->subs[SUB_REAL].linear = 0; 02755 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02756 } 02757 while (p->cidpos < p->cidlen) { 02758 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02759 if (res < 0) { 02760 if (errno == EAGAIN) 02761 return 0; 02762 else { 02763 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02764 return -1; 02765 } 02766 } 02767 if (!res) 02768 return 0; 02769 p->cidpos += res; 02770 } 02771 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES; 02772 free(p->cidspill); 02773 p->cidspill = NULL; 02774 if (p->callwaitcas) { 02775 /* Wait for CID/CW to expire */ 02776 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02777 p->cid_suppress_expire = p->cidcwexpire; 02778 } else 02779 restore_conference(p); 02780 return 0; 02781 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2725 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), 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, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_dtmf().
02726 { 02727 p->callwaitcas = 0; 02728 p->cidcwexpire = 0; 02729 p->cid_suppress_expire = 0; 02730 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02731 return -1; 02732 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02733 /* Make sure we account for the end */ 02734 p->cidlen += READ_SIZE * 4; 02735 p->cidpos = 0; 02736 send_callerid(p); 02737 if (option_verbose > 2) 02738 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02739 return 0; 02740 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3405 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, LOG_DEBUG, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.
Referenced by dahdi_send_keypad_facility_exec(), and zap_send_keypad_facility_exec().
03406 { 03407 /* Data will be our digit string */ 03408 struct dahdi_pvt *p; 03409 char *digits = (char *) data; 03410 03411 if (ast_strlen_zero(digits)) { 03412 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 03413 return -1; 03414 } 03415 03416 p = (struct dahdi_pvt *)chan->tech_pvt; 03417 03418 if (!p) { 03419 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 03420 return -1; 03421 } 03422 03423 ast_mutex_lock(&p->lock); 03424 03425 if (!p->pri || !p->call) { 03426 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 03427 ast_mutex_unlock(&p->lock); 03428 return -1; 03429 } 03430 03431 if (!pri_grab(p, p->pri)) { 03432 pri_keypad_facility(p->pri->pri, p->call, digits); 03433 pri_rel(p->pri); 03434 } else { 03435 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 03436 ast_mutex_unlock(&p->lock); 03437 return -1; 03438 } 03439 03440 ast_mutex_unlock(&p->lock); 03441 03442 return 0; 03443 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2615 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02616 { 02617 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02618 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2597 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
02598 { 02599 struct dahdi_gains g; 02600 int res; 02601 02602 memset(&g, 0, sizeof(g)); 02603 g.chan = chan; 02604 res = ioctl(fd, DAHDI_GETGAINS, &g); 02605 if (res) { 02606 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02607 return res; 02608 } 02609 02610 fill_rxgain(&g, gain, law); 02611 02612 return ioctl(fd, DAHDI_SETGAINS, &g); 02613 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2578 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
02579 { 02580 struct dahdi_gains g; 02581 int res; 02582 02583 memset(&g, 0, sizeof(g)); 02584 g.chan = chan; 02585 res = ioctl(fd, DAHDI_GETGAINS, &g); 02586 if (res) { 02587 if (option_debug) 02588 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02589 return res; 02590 } 02591 02592 fill_txgain(&g, gain, law); 02593 02594 return ioctl(fd, DAHDI_SETGAINS, &g); 02595 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 14914 of file chan_dahdi.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, master, mfcr2_monitor(), ast_variable::name, ast_variable::next, NUM_SPANS, option_verbose, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), r2links, restart_monitor(), start_pri(), ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by dahdi_restart(), load_module(), and reload().
14915 { 14916 struct ast_config *cfg; 14917 struct ast_variable *v; 14918 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 14919 int res; 14920 14921 #ifdef HAVE_PRI 14922 char *c; 14923 int spanno; 14924 int i, x; 14925 int logicalspan; 14926 int trunkgroup; 14927 int dchannels[NUM_DCHANS]; 14928 #endif 14929 14930 #ifdef HAVE_ZAPTEL 14931 int load_from_zapata_conf = 1; 14932 #else 14933 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 14934 #endif 14935 14936 if (load_from_zapata_conf) { 14937 if (!(cfg = ast_config_load("zapata.conf"))) { 14938 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 14939 return 0; 14940 } 14941 } else { 14942 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 14943 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 14944 return 0; 14945 } 14946 } 14947 14948 /* It's a little silly to lock it, but we mind as well just to be sure */ 14949 ast_mutex_lock(&iflock); 14950 #ifdef HAVE_PRI 14951 if (reload != 1) { 14952 /* Process trunkgroups first */ 14953 v = ast_variable_browse(cfg, "trunkgroups"); 14954 while (v) { 14955 if (!strcasecmp(v->name, "trunkgroup")) { 14956 trunkgroup = atoi(v->value); 14957 if (trunkgroup > 0) { 14958 if ((c = strchr(v->value, ','))) { 14959 i = 0; 14960 memset(dchannels, 0, sizeof(dchannels)); 14961 while (c && (i < NUM_DCHANS)) { 14962 dchannels[i] = atoi(c + 1); 14963 if (dchannels[i] < 0) { 14964 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); 14965 } else 14966 i++; 14967 c = strchr(c + 1, ','); 14968 } 14969 if (i) { 14970 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 14971 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); 14972 } else if (option_verbose > 1) 14973 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); 14974 } else 14975 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 14976 } else 14977 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 14978 } else 14979 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 14980 } else if (!strcasecmp(v->name, "spanmap")) { 14981 spanno = atoi(v->value); 14982 if (spanno > 0) { 14983 if ((c = strchr(v->value, ','))) { 14984 trunkgroup = atoi(c + 1); 14985 if (trunkgroup > 0) { 14986 if ((c = strchr(c + 1, ','))) 14987 logicalspan = atoi(c + 1); 14988 else 14989 logicalspan = 0; 14990 if (logicalspan >= 0) { 14991 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 14992 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 14993 } else if (option_verbose > 1) 14994 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 14995 } else 14996 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); 14997 } else 14998 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 14999 } else 15000 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15001 } else 15002 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15003 } else { 15004 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15005 } 15006 v = v->next; 15007 } 15008 } 15009 #endif 15010 15011 /* Copy the default jb config over global_jbconf */ 15012 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 15013 15014 v = ast_variable_browse(cfg, "channels"); 15015 res = process_dahdi(&conf, "", v, reload, 0); 15016 ast_mutex_unlock(&iflock); 15017 ast_config_destroy(cfg); 15018 if (res) 15019 return res; 15020 cfg = ast_config_load("users.conf"); 15021 if (cfg) { 15022 char *cat; 15023 15024 /* Reset conf back to defaults, so values from chan_dahdi.conf don't leak in. */ 15025 conf = dahdi_chan_conf_default(); 15026 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 15027 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15028 if (!strcasecmp(cat, "general")) 15029 continue; 15030 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 15031 struct dahdi_chan_conf sect_conf; 15032 memcpy(§_conf, &conf, sizeof(sect_conf)); 15033 15034 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 15035 } 15036 } 15037 ast_config_destroy(cfg); 15038 } 15039 #ifdef HAVE_PRI 15040 if (reload != 1) { 15041 for (x = 0; x < NUM_SPANS; x++) { 15042 if (pris[x].pvts[0]) { 15043 if (start_pri(pris + x)) { 15044 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15045 return -1; 15046 } else if (option_verbose > 1) 15047 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 15048 } 15049 } 15050 } 15051 #endif 15052 15053 #ifdef HAVE_OPENR2 15054 if (reload != 1) { 15055 int x; 15056 for (x = 0; x < NUM_SPANS; x++) { 15057 if (r2links[x].protocol_context) { 15058 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) { 15059 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1); 15060 return -1; 15061 } else { 15062 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1); 15063 } 15064 } 15065 } 15066 } 15067 #endif 15068 15069 /* And start the monitor for the first time */ 15070 restart_monitor(); 15071 return 0; 15072 }
static int sig_pri_available | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9775 of file chan_dahdi.c.
References dahdi_pvt::allocated, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::pri, dahdi_pri::pri, and sig_pri_available_check().
Referenced by available().
09776 { 09777 struct dahdi_pvt *p = pvt; 09778 struct dahdi_pri *pri; 09779 09780 if (!p->pri) { 09781 /* Something is wrong here. A PRI channel without the pri pointer? */ 09782 return 0; 09783 } 09784 pri = p->pri; 09785 09786 ast_mutex_lock(&pri->lock); 09787 if (sig_pri_available_check(p)) { 09788 p->allocated = 1; 09789 ast_mutex_unlock(&pri->lock); 09790 return 1; 09791 } 09792 09793 ast_mutex_unlock(&pri->lock); 09794 return 0; 09795 }
static int sig_pri_available_check | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9761 of file chan_dahdi.c.
References sig_pri_is_chan_available().
Referenced by sig_pri_available().
09762 { 09763 /* 09764 * If interface is available for use 09765 * then the channel is available. 09766 */ 09767 if (sig_pri_is_chan_available(pvt)) { 09768 return 1; 09769 } 09770 return 0; 09771 }
static int sig_pri_is_chan_available | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9744 of file chan_dahdi.c.
References sig_pri_is_chan_in_use().
Referenced by pri_dchannel(), pri_find_empty_chan(), pri_fixup_principle(), and sig_pri_available_check().
09745 { 09746 return !sig_pri_is_chan_in_use(pvt); 09747 }
static int sig_pri_is_chan_in_use | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9728 of file chan_dahdi.c.
References dahdi_pvt::allocated, dahdi_pvt::call, dahdi_pvt::inalarm, dahdi_pvt::owner, and dahdi_pvt::resetting.
Referenced by pri_check_restart(), and sig_pri_is_chan_available().
09729 { 09730 return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm; 09731 }
static void sig_pri_kill_call | ( | struct dahdi_pri * | pri, | |
q931_call * | call, | |||
int | cause | |||
) | [static] |
Definition at line 10517 of file chan_dahdi.c.
References AST_CONTROL_HANGUP, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::call, ast_channel::hangupcause, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pri::pri, pri_find_principle_by_call(), pri_queue_control(), and dahdi_pri::pvts.
Referenced by pri_find_fixup_principle().
10518 { 10519 int chanpos; 10520 10521 chanpos = pri_find_principle_by_call(pri, call); 10522 if (chanpos < 0) { 10523 pri_hangup(pri->pri, call, cause); 10524 return; 10525 } 10526 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10527 if (!pri->pvts[chanpos]->owner) { 10528 pri_hangup(pri->pri, call, cause); 10529 pri->pvts[chanpos]->call = NULL; 10530 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10531 return; 10532 } 10533 pri->pvts[chanpos]->owner->hangupcause = cause; 10534 pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP); 10535 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10536 }
static void sig_pri_lock_owner | ( | struct dahdi_pri * | pri, | |
int | chanpos | |||
) | [static] |
Definition at line 10403 of file chan_dahdi.c.
References ast_channel_trylock, dahdi_pvt::owner, dahdi_pvt::pri, and dahdi_pri::pvts.
Referenced by pri_fixup_principle(), and pri_queue_frame().
10404 { 10405 for (;;) { 10406 if (!pri->pvts[chanpos]->owner) { 10407 /* There is no owner lock to get. */ 10408 break; 10409 } 10410 if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) { 10411 /* We got the lock */ 10412 break; 10413 } 10414 /* We must unlock the PRI to avoid the possibility of a deadlock */ 10415 ast_mutex_unlock(&pri->lock); 10416 DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock); 10417 ast_mutex_lock(&pri->lock); 10418 } 10419 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 7233 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_clear_flag, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FRAME_CONTROL, 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(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), 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_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call, dahdi_pvt::call_forward, dahdi_pvt::call_level, 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, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, 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, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, DAHDI_CALL_LEVEL_PROCEEDING, dahdi_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index, DAHDI_OVERLAPDIAL_INCOMING, dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, f, firstdigittimeout, free, ast_smdi_md_message::fwd_st, gendigittimeout, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, manager_event(), matchdigittimeout, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PVT_TO_CHANNEL, quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, 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_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, dahdi_pvt::span, ss_thread_count, ss_thread_lock, 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, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event(), and handle_init_event().
07234 { 07235 struct ast_channel *chan = data; 07236 struct dahdi_pvt *p = chan->tech_pvt; 07237 char exten[AST_MAX_EXTENSION] = ""; 07238 char exten2[AST_MAX_EXTENSION] = ""; 07239 unsigned char buf[256]; 07240 char dtmfcid[300]; 07241 char dtmfbuf[300]; 07242 struct callerid_state *cs = NULL; 07243 char *name = NULL, *number = NULL; 07244 int distMatches; 07245 int curRingData[3]; 07246 int receivedRingT; 07247 int counter1; 07248 int counter; 07249 int samples = 0; 07250 struct ast_smdi_md_message *smdi_msg = NULL; 07251 int flags = 0; 07252 int i; 07253 int timeout; 07254 int getforward = 0; 07255 char *s1, *s2; 07256 int len = 0; 07257 int res; 07258 int index; 07259 07260 ast_mutex_lock(&ss_thread_lock); 07261 ss_thread_count++; 07262 ast_mutex_unlock(&ss_thread_lock); 07263 /* in the bizarre case where the channel has become a zombie before we 07264 even get started here, abort safely 07265 */ 07266 if (!p) { 07267 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 07268 ast_hangup(chan); 07269 goto quit; 07270 } 07271 if (option_verbose > 2) 07272 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 07273 index = dahdi_get_index(chan, p, 0); 07274 if (index < 0) { 07275 ast_hangup(chan); 07276 goto quit; 07277 } 07278 if (p->dsp) 07279 ast_dsp_digitreset(p->dsp); 07280 switch (p->sig) { 07281 #ifdef HAVE_PRI 07282 case SIG_PRI: 07283 /* Now loop looking for an extension */ 07284 ast_copy_string(exten, p->exten, sizeof(exten)); 07285 len = strlen(exten); 07286 res = 0; 07287 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07288 if (len && !ast_ignore_pattern(chan->context, exten)) 07289 tone_zone_play_tone(p->subs[index].dfd, -1); 07290 else 07291 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07292 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 07293 timeout = matchdigittimeout; 07294 else 07295 timeout = gendigittimeout; 07296 res = ast_waitfordigit(chan, timeout); 07297 if (res < 0) { 07298 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07299 ast_hangup(chan); 07300 goto quit; 07301 } else if (res) { 07302 exten[len++] = res; 07303 exten[len] = '\0'; 07304 } else 07305 break; 07306 } 07307 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 07308 if (ast_strlen_zero(exten)) { 07309 if (option_verbose > 2) 07310 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 07311 exten[0] = 's'; 07312 exten[1] = '\0'; 07313 } 07314 tone_zone_play_tone(p->subs[index].dfd, -1); 07315 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 07316 /* Start the real PBX */ 07317 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07318 if (p->dsp) { 07319 ast_dsp_digitreset(p->dsp); 07320 } 07321 #if defined(ISSUE_16789) 07322 /* 07323 * Conditionaled out this code to effectively revert the Mantis 07324 * issue 16789 change. It breaks overlap dialing through 07325 * Asterisk. There is not enough information available at this 07326 * point to know if dialing is complete. The 07327 * ast_exists_extension(), ast_matchmore_extension(), and 07328 * ast_canmatch_extension() calls are not adequate to detect a 07329 * dial through extension pattern of "_9!". 07330 * 07331 * Workaround is to use the dialplan Proceeding() application 07332 * early on non-dial through extensions. 07333 */ 07334 if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 07335 && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07336 ast_mutex_lock(&p->lock); 07337 if (p->pri->pri) { 07338 if (!pri_grab(p, p->pri)) { 07339 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) { 07340 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING; 07341 } 07342 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0); 07343 pri_rel(p->pri); 07344 } else { 07345 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07346 } 07347 } 07348 ast_mutex_unlock(&p->lock); 07349 } 07350 #endif /* defined(ISSUE_16789) */ 07351 07352 dahdi_enable_ec(p); 07353 ast_setstate(chan, AST_STATE_RING); 07354 res = ast_pbx_run(chan); 07355 if (res) { 07356 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 07357 } 07358 } else { 07359 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 07360 chan->hangupcause = AST_CAUSE_UNALLOCATED; 07361 ast_hangup(chan); 07362 p->exten[0] = '\0'; 07363 /* Since we send release complete here, we won't get one */ 07364 p->call = NULL; 07365 } 07366 goto quit; 07367 break; 07368 #endif 07369 case SIG_FEATD: 07370 case SIG_FEATDMF: 07371 case SIG_FEATDMF_TA: 07372 case SIG_E911: 07373 case SIG_FGC_CAMAMF: 07374 case SIG_FEATB: 07375 case SIG_EMWINK: 07376 case SIG_SF_FEATD: 07377 case SIG_SF_FEATDMF: 07378 case SIG_SF_FEATB: 07379 case SIG_SFWINK: 07380 if (dahdi_wink(p, index)) 07381 goto quit; 07382 /* Fall through */ 07383 case SIG_EM: 07384 case SIG_EM_E1: 07385 case SIG_SF: 07386 case SIG_FGC_CAMA: 07387 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07388 if (p->dsp) 07389 ast_dsp_digitreset(p->dsp); 07390 /* set digit mode appropriately */ 07391 if (p->dsp) { 07392 if (NEED_MFDETECT(p)) 07393 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 07394 else 07395 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07396 } 07397 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 07398 /* Wait for the first digit only if immediate=no */ 07399 if (!p->immediate) 07400 /* Wait for the first digit (up to 5 seconds). */ 07401 res = ast_waitfordigit(chan, 5000); 07402 else 07403 res = 0; 07404 if (res > 0) { 07405 /* save first char */ 07406 dtmfbuf[0] = res; 07407 switch (p->sig) { 07408 case SIG_FEATD: 07409 case SIG_SF_FEATD: 07410 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 07411 if (res > 0) 07412 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 07413 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07414 break; 07415 case SIG_FEATDMF_TA: 07416 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07417 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07418 if (dahdi_wink(p, index)) goto quit; 07419 dtmfbuf[0] = 0; 07420 /* Wait for the first digit (up to 5 seconds). */ 07421 res = ast_waitfordigit(chan, 5000); 07422 if (res <= 0) break; 07423 dtmfbuf[0] = res; 07424 /* fall through intentionally */ 07425 case SIG_FEATDMF: 07426 case SIG_E911: 07427 case SIG_FGC_CAMAMF: 07428 case SIG_SF_FEATDMF: 07429 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07430 /* if international caca, do it again to get real ANO */ 07431 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 07432 { 07433 if (dahdi_wink(p, index)) goto quit; 07434 dtmfbuf[0] = 0; 07435 /* Wait for the first digit (up to 5 seconds). */ 07436 res = ast_waitfordigit(chan, 5000); 07437 if (res <= 0) break; 07438 dtmfbuf[0] = res; 07439 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07440 } 07441 if (res > 0) { 07442 /* if E911, take off hook */ 07443 if (p->sig == SIG_E911) 07444 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07445 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 07446 } 07447 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07448 break; 07449 case SIG_FEATB: 07450 case SIG_SF_FEATB: 07451 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07452 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07453 break; 07454 case SIG_EMWINK: 07455 /* if we received a '*', we are actually receiving Feature Group D 07456 dial syntax, so use that mode; otherwise, fall through to normal 07457 mode 07458 */ 07459 if (res == '*') { 07460 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 07461 if (res > 0) 07462 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 07463 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07464 break; 07465 } 07466 default: 07467 /* If we got the first digit, get the rest */ 07468 len = 1; 07469 dtmfbuf[len] = '\0'; 07470 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 07471 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 07472 timeout = matchdigittimeout; 07473 } else { 07474 timeout = gendigittimeout; 07475 } 07476 res = ast_waitfordigit(chan, timeout); 07477 if (res < 0) { 07478 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07479 ast_hangup(chan); 07480 goto quit; 07481 } else if (res) { 07482 dtmfbuf[len++] = res; 07483 dtmfbuf[len] = '\0'; 07484 } else { 07485 break; 07486 } 07487 } 07488 break; 07489 } 07490 } 07491 if (res == -1) { 07492 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 07493 ast_hangup(chan); 07494 goto quit; 07495 } else if (res < 0) { 07496 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 07497 ast_hangup(chan); 07498 goto quit; 07499 } 07500 07501 if (p->sig == SIG_FGC_CAMA) { 07502 char anibuf[100]; 07503 07504 if (ast_safe_sleep(chan,1000) == -1) { 07505 ast_hangup(chan); 07506 goto quit; 07507 } 07508 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07509 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 07510 res = my_getsigstr(chan, anibuf, "#", 10000); 07511 if ((res > 0) && (strlen(anibuf) > 2)) { 07512 if (anibuf[strlen(anibuf) - 1] == '#') 07513 anibuf[strlen(anibuf) - 1] = 0; 07514 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07515 } 07516 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07517 } 07518 07519 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07520 if (ast_strlen_zero(exten)) 07521 ast_copy_string(exten, "s", sizeof(exten)); 07522 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07523 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07524 if (exten[0] == '*') { 07525 char *stringp=NULL; 07526 ast_copy_string(exten2, exten, sizeof(exten2)); 07527 /* Parse out extension and callerid */ 07528 stringp=exten2 +1; 07529 s1 = strsep(&stringp, "*"); 07530 s2 = strsep(&stringp, "*"); 07531 if (s2) { 07532 if (!ast_strlen_zero(p->cid_num)) 07533 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07534 else 07535 ast_set_callerid(chan, s1, NULL, s1); 07536 ast_copy_string(exten, s2, sizeof(exten)); 07537 } else 07538 ast_copy_string(exten, s1, sizeof(exten)); 07539 } else if (p->sig == SIG_FEATD) 07540 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07541 } 07542 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07543 if (exten[0] == '*') { 07544 char *stringp=NULL; 07545 ast_copy_string(exten2, exten, sizeof(exten2)); 07546 /* Parse out extension and callerid */ 07547 stringp=exten2 +1; 07548 s1 = strsep(&stringp, "#"); 07549 s2 = strsep(&stringp, "#"); 07550 if (s2) { 07551 if (!ast_strlen_zero(p->cid_num)) 07552 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07553 else 07554 if (*(s1 + 2)) 07555 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07556 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07557 } else 07558 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07559 } else 07560 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07561 } 07562 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07563 if (exten[0] == '*') { 07564 char *stringp=NULL; 07565 ast_copy_string(exten2, exten, sizeof(exten2)); 07566 /* Parse out extension and callerid */ 07567 stringp=exten2 +1; 07568 s1 = strsep(&stringp, "#"); 07569 s2 = strsep(&stringp, "#"); 07570 if (s2 && (*(s2 + 1) == '0')) { 07571 if (*(s2 + 2)) 07572 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07573 } 07574 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07575 else ast_copy_string(exten, "911", sizeof(exten)); 07576 } else 07577 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 07578 } 07579 if (p->sig == SIG_FEATB) { 07580 if (exten[0] == '*') { 07581 char *stringp=NULL; 07582 ast_copy_string(exten2, exten, sizeof(exten2)); 07583 /* Parse out extension and callerid */ 07584 stringp=exten2 +1; 07585 s1 = strsep(&stringp, "#"); 07586 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 07587 } else 07588 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 07589 } 07590 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07591 dahdi_wink(p, index); 07592 /* some switches require a minimum guard time between 07593 the last FGD wink and something that answers 07594 immediately. This ensures it */ 07595 if (ast_safe_sleep(chan, 100)) { 07596 ast_hangup(chan); 07597 goto quit; 07598 } 07599 } 07600 dahdi_enable_ec(p); 07601 if (NEED_MFDETECT(p)) { 07602 if (p->dsp) { 07603 if (!p->hardwaredtmf) 07604 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07605 else { 07606 ast_dsp_free(p->dsp); 07607 p->dsp = NULL; 07608 } 07609 } 07610 } 07611 07612 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 07613 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07614 if (p->dsp) ast_dsp_digitreset(p->dsp); 07615 res = ast_pbx_run(chan); 07616 if (res) { 07617 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07618 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07619 } 07620 goto quit; 07621 } else { 07622 if (option_verbose > 2) 07623 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 07624 sleep(2); 07625 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 07626 if (res < 0) 07627 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 07628 else 07629 sleep(1); 07630 res = ast_streamfile(chan, "ss-noservice", chan->language); 07631 if (res >= 0) 07632 ast_waitstream(chan, ""); 07633 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07634 ast_hangup(chan); 07635 goto quit; 07636 } 07637 break; 07638 case SIG_FXOLS: 07639 case SIG_FXOGS: 07640 case SIG_FXOKS: 07641 /* Read the first digit */ 07642 timeout = firstdigittimeout; 07643 /* If starting a threeway call, never timeout on the first digit so someone 07644 can use flash-hook as a "hold" feature */ 07645 if (p->subs[SUB_THREEWAY].owner) 07646 timeout = 999999; 07647 while (len < AST_MAX_EXTENSION-1) { 07648 /* Read digit unless it's supposed to be immediate, in which case the 07649 only answer is 's' */ 07650 if (p->immediate) 07651 res = 's'; 07652 else 07653 res = ast_waitfordigit(chan, timeout); 07654 timeout = 0; 07655 if (res < 0) { 07656 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07657 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07658 ast_hangup(chan); 07659 goto quit; 07660 } else if (res) { 07661 exten[len++]=res; 07662 exten[len] = '\0'; 07663 } 07664 if (!ast_ignore_pattern(chan->context, exten)) 07665 tone_zone_play_tone(p->subs[index].dfd, -1); 07666 else 07667 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07668 if (!strcmp(exten,ast_pickup_ext())) { 07669 /* Scan all channels and see if there are any 07670 * ringing channels that have call groups 07671 * that equal this channels pickup group 07672 */ 07673 if (index == SUB_REAL) { 07674 /* Switch us from Third call to Call Wait */ 07675 if (p->subs[SUB_THREEWAY].owner) { 07676 /* If you make a threeway call and the *8# a call, it should actually 07677 look like a callwait */ 07678 alloc_sub(p, SUB_CALLWAIT); 07679 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07680 unalloc_sub(p, SUB_THREEWAY); 07681 } 07682 dahdi_enable_ec(p); 07683 if (ast_pickup_call(chan)) { 07684 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 07685 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07686 dahdi_wait_event(p->subs[index].dfd); 07687 } 07688 ast_hangup(chan); 07689 goto quit; 07690 } else { 07691 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07692 ast_hangup(chan); 07693 goto quit; 07694 } 07695 07696 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 07697 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07698 if (getforward) { 07699 /* Record this as the forwarding extension */ 07700 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 07701 if (option_verbose > 2) 07702 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 07703 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07704 if (res) 07705 break; 07706 usleep(500000); 07707 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07708 sleep(1); 07709 memset(exten, 0, sizeof(exten)); 07710 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07711 len = 0; 07712 getforward = 0; 07713 } else { 07714 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07715 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07716 if (!ast_strlen_zero(p->cid_num)) { 07717 if (!p->hidecallerid) 07718 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07719 else 07720 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07721 } 07722 if (!ast_strlen_zero(p->cid_name)) { 07723 if (!p->hidecallerid) 07724 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07725 } 07726 ast_setstate(chan, AST_STATE_RING); 07727 dahdi_enable_ec(p); 07728 res = ast_pbx_run(chan); 07729 if (res) { 07730 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07731 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07732 } 07733 goto quit; 07734 } 07735 } else { 07736 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07737 so just set the timeout to matchdigittimeout and wait some more */ 07738 timeout = matchdigittimeout; 07739 } 07740 } else if (res == 0) { 07741 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 07742 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07743 dahdi_wait_event(p->subs[index].dfd); 07744 ast_hangup(chan); 07745 goto quit; 07746 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07747 if (option_verbose > 2) 07748 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 07749 /* Disable call waiting if enabled */ 07750 p->callwaiting = 0; 07751 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07752 if (res) { 07753 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07754 chan->name, strerror(errno)); 07755 } 07756 len = 0; 07757 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 07758 memset(exten, 0, sizeof(exten)); 07759 timeout = firstdigittimeout; 07760 07761 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07762 if (option_verbose > 2) 07763 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 07764 /* Disable Caller*ID if enabled */ 07765 p->hidecallerid = 1; 07766 if (chan->cid.cid_num) 07767 free(chan->cid.cid_num); 07768 chan->cid.cid_num = NULL; 07769 if (chan->cid.cid_name) 07770 free(chan->cid.cid_name); 07771 chan->cid.cid_name = NULL; 07772 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07773 if (res) { 07774 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07775 chan->name, strerror(errno)); 07776 } 07777 len = 0; 07778 memset(exten, 0, sizeof(exten)); 07779 timeout = firstdigittimeout; 07780 } else if (p->callreturn && !strcmp(exten, "*69")) { 07781 res = 0; 07782 if (!ast_strlen_zero(p->lastcid_num)) { 07783 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07784 } 07785 if (!res) 07786 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07787 break; 07788 } else if (!strcmp(exten, "*78")) { 07789 /* Do not disturb */ 07790 if (option_verbose > 2) 07791 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 07792 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07793 "Channel: %s/%d\r\n" 07794 "Status: enabled\r\n", dahdi_chan_name, p->channel); 07795 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07796 p->dnd = 1; 07797 getforward = 0; 07798 memset(exten, 0, sizeof(exten)); 07799 len = 0; 07800 } else if (!strcmp(exten, "*79")) { 07801 /* Do not disturb */ 07802 if (option_verbose > 2) 07803 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 07804 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07805 "Channel: %s/%d\r\n" 07806 "Status: disabled\r\n", dahdi_chan_name, p->channel); 07807 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07808 p->dnd = 0; 07809 getforward = 0; 07810 memset(exten, 0, sizeof(exten)); 07811 len = 0; 07812 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07813 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07814 getforward = 1; 07815 memset(exten, 0, sizeof(exten)); 07816 len = 0; 07817 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07818 if (option_verbose > 2) 07819 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 07820 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07821 memset(p->call_forward, 0, sizeof(p->call_forward)); 07822 getforward = 0; 07823 memset(exten, 0, sizeof(exten)); 07824 len = 0; 07825 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07826 p->subs[SUB_THREEWAY].owner && 07827 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07828 /* This is a three way call, the main call being a real channel, 07829 and we're parking the first call. */ 07830 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07831 if (option_verbose > 2) 07832 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 07833 break; 07834 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07835 if (option_verbose > 2) 07836 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 07837 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07838 if (!res) { 07839 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07840 memset(exten, 0, sizeof(exten)); 07841 len = 0; 07842 } 07843 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07844 if (option_verbose > 2) 07845 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 07846 /* Enable Caller*ID if enabled */ 07847 p->hidecallerid = 0; 07848 if (chan->cid.cid_num) 07849 free(chan->cid.cid_num); 07850 chan->cid.cid_num = NULL; 07851 if (chan->cid.cid_name) 07852 free(chan->cid.cid_name); 07853 chan->cid.cid_name = NULL; 07854 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07855 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07856 if (res) { 07857 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07858 chan->name, strerror(errno)); 07859 } 07860 len = 0; 07861 memset(exten, 0, sizeof(exten)); 07862 timeout = firstdigittimeout; 07863 } else if (!strcmp(exten, "*0")) { 07864 struct ast_channel *nbridge = 07865 p->subs[SUB_THREEWAY].owner; 07866 struct dahdi_pvt *pbridge = NULL; 07867 /* set up the private struct of the bridged one, if any */ 07868 if (nbridge && ast_bridged_channel(nbridge)) 07869 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07870 if (nbridge && pbridge && 07871 (nbridge->tech == chan_tech) && 07872 (ast_bridged_channel(nbridge)->tech == chan_tech) && 07873 ISTRUNK(pbridge)) { 07874 int func = DAHDI_FLASH; 07875 /* Clear out the dial buffer */ 07876 p->dop.dialstr[0] = '\0'; 07877 /* flash hookswitch */ 07878 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07879 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07880 nbridge->name, strerror(errno)); 07881 } 07882 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07883 unalloc_sub(p, SUB_THREEWAY); 07884 p->owner = p->subs[SUB_REAL].owner; 07885 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07886 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07887 ast_hangup(chan); 07888 goto quit; 07889 } else { 07890 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07891 dahdi_wait_event(p->subs[index].dfd); 07892 tone_zone_play_tone(p->subs[index].dfd, -1); 07893 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07894 unalloc_sub(p, SUB_THREEWAY); 07895 p->owner = p->subs[SUB_REAL].owner; 07896 ast_hangup(chan); 07897 goto quit; 07898 } 07899 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07900 ((exten[0] != '*') || (strlen(exten) > 2))) { 07901 if (option_debug) 07902 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context); 07903 break; 07904 } 07905 if (!timeout) 07906 timeout = gendigittimeout; 07907 if (len && !ast_ignore_pattern(chan->context, exten)) 07908 tone_zone_play_tone(p->subs[index].dfd, -1); 07909 } 07910 break; 07911 case SIG_FXSLS: 07912 case SIG_FXSGS: 07913 case SIG_FXSKS: 07914 #ifdef HAVE_PRI 07915 if (p->pri) { 07916 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07917 struct ast_frame *f; 07918 int res; 07919 time_t start; 07920 07921 time(&start); 07922 ast_setstate(chan, AST_STATE_RING); 07923 while (time(NULL) < start + 3) { 07924 res = ast_waitfor(chan, 1000); 07925 if (res) { 07926 f = ast_read(chan); 07927 if (!f) { 07928 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07929 ast_hangup(chan); 07930 goto quit; 07931 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07932 res = 1; 07933 } else 07934 res = 0; 07935 ast_frfree(f); 07936 if (res) { 07937 ast_log(LOG_DEBUG, "Got ring!\n"); 07938 res = 0; 07939 break; 07940 } 07941 } 07942 } 07943 } 07944 #endif 07945 /* check for SMDI messages */ 07946 if (p->use_smdi && p->smdi_iface) { 07947 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07948 07949 if (smdi_msg != NULL) { 07950 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07951 07952 if (smdi_msg->type == 'B') 07953 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07954 else if (smdi_msg->type == 'N') 07955 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07956 07957 ast_log(LOG_DEBUG, "Received SMDI message on %s\n", chan->name); 07958 } else { 07959 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07960 } 07961 } 07962 07963 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07964 number = smdi_msg->calling_st; 07965 07966 /* If we want caller id, we're in a prering state due to a polarity reversal 07967 * and we're set to use a polarity reversal to trigger the start of caller id, 07968 * grab the caller id and wait for ringing to start... */ 07969 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 07970 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) { 07971 /* If set to use DTMF CID signalling, listen for DTMF */ 07972 if (p->cid_signalling == CID_SIG_DTMF) { 07973 int i = 0; 07974 cs = NULL; 07975 ast_log(LOG_DEBUG, "Receiving DTMF cid on channel %s\n", chan->name); 07976 dahdi_setlinear(p->subs[index].dfd, 0); 07977 /* 07978 * We are the only party interested in the Rx stream since 07979 * we have not answered yet. We don't need or even want DTMF 07980 * emulation. The DTMF digits can come so fast that emulation 07981 * can drop some of them. 07982 */ 07983 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY); 07984 res = 4000;/* This is a typical OFF time between rings. */ 07985 for (;;) { 07986 struct ast_frame *f; 07987 res = ast_waitfor(chan, res); 07988 if (res <= 0) { 07989 /* 07990 * We do not need to restore the dahdi_setlinear() 07991 * or AST_FLAG_END_DTMF_ONLY flag settings since we 07992 * are hanging up the channel. 07993 */ 07994 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07995 "Exiting simple switch\n"); 07996 ast_hangup(chan); 07997 goto quit; 07998 } 07999 f = ast_read(chan); 08000 if (!f) 08001 break; 08002 if (f->frametype == AST_FRAME_DTMF) { 08003 if (i < ARRAY_LEN(dtmfbuf) - 1) { 08004 dtmfbuf[i++] = f->subclass; 08005 } 08006 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 08007 res = 4000;/* This is a typical OFF time between rings. */ 08008 } 08009 ast_frfree(f); 08010 if (chan->_state == AST_STATE_RING || 08011 chan->_state == AST_STATE_RINGING) 08012 break; /* Got ring */ 08013 } 08014 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY); 08015 dtmfbuf[i] = '\0'; 08016 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 08017 /* Got cid and ring. */ 08018 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 08019 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 08020 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", dtmfcid, flags); 08021 /* If first byte is NULL, we have no cid */ 08022 if (!ast_strlen_zero(dtmfcid)) 08023 number = dtmfcid; 08024 else 08025 number = NULL; 08026 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 08027 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 08028 cs = callerid_new(p->cid_signalling); 08029 if (cs) { 08030 samples = 0; 08031 #if 1 08032 bump_gains(p); 08033 #endif 08034 /* Take out of linear mode for Caller*ID processing */ 08035 dahdi_setlinear(p->subs[index].dfd, 0); 08036 08037 /* First we wait and listen for the Caller*ID */ 08038 for (;;) { 08039 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08040 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 08041 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08042 callerid_free(cs); 08043 ast_hangup(chan); 08044 goto quit; 08045 } 08046 if (i & DAHDI_IOMUX_SIGEVENT) { 08047 res = dahdi_get_event(p->subs[index].dfd); 08048 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08049 if (res == DAHDI_EVENT_NOALARM) { 08050 p->inalarm = 0; 08051 } 08052 08053 if (p->cid_signalling == CID_SIG_V23_JP) { 08054 #ifdef DAHDI_EVENT_RINGBEGIN 08055 if (res == DAHDI_EVENT_RINGBEGIN) { 08056 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08057 usleep(1); 08058 } 08059 #endif 08060 } else { 08061 res = 0; 08062 break; 08063 } 08064 } else if (i & DAHDI_IOMUX_READ) { 08065 res = read(p->subs[index].dfd, buf, sizeof(buf)); 08066 if (res < 0) { 08067 if (errno != ELAST) { 08068 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08069 callerid_free(cs); 08070 ast_hangup(chan); 08071 goto quit; 08072 } 08073 break; 08074 } 08075 samples += res; 08076 08077 if (p->cid_signalling == CID_SIG_V23_JP) { 08078 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 08079 } else { 08080 res = callerid_feed(cs, buf, res, AST_LAW(p)); 08081 } 08082 if (res < 0) { 08083 /* 08084 * The previous diagnostic message output likely 08085 * explains why it failed. 08086 */ 08087 ast_log(LOG_WARNING, 08088 "Failed to decode CallerID on channel '%s'\n", 08089 chan->name); 08090 break; 08091 } else if (res) 08092 break; 08093 else if (samples > (8000 * 10)) 08094 break; 08095 } 08096 } 08097 if (res == 1) { 08098 callerid_get(cs, &name, &number, &flags); 08099 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 08100 } 08101 08102 if (p->cid_signalling == CID_SIG_V23_JP) { 08103 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08104 usleep(1); 08105 } 08106 08107 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 08108 res = 4000;/* This is a typical OFF time between rings. */ 08109 for (;;) { 08110 struct ast_frame *f; 08111 res = ast_waitfor(chan, res); 08112 if (res <= 0) { 08113 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 08114 "Exiting simple switch\n"); 08115 ast_hangup(chan); 08116 goto quit; 08117 } 08118 if (!(f = ast_read(chan))) { 08119 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 08120 ast_hangup(chan); 08121 goto quit; 08122 } 08123 ast_frfree(f); 08124 if (chan->_state == AST_STATE_RING || 08125 chan->_state == AST_STATE_RINGING) 08126 break; /* Got ring */ 08127 } 08128 08129 /* We must have a ring by now, so, if configured, lets try to listen for 08130 * distinctive ringing */ 08131 if (p->usedistinctiveringdetection) { 08132 len = 0; 08133 distMatches = 0; 08134 /* Clear the current ring data array so we dont have old data in it. */ 08135 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 08136 curRingData[receivedRingT] = 0; 08137 receivedRingT = 0; 08138 counter = 0; 08139 counter1 = 0; 08140 /* Check to see if context is what it should be, if not set to be. */ 08141 if (strcmp(p->context,p->defcontext) != 0) { 08142 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 08143 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 08144 } 08145 08146 for (;;) { 08147 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08148 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 08149 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08150 callerid_free(cs); 08151 ast_hangup(chan); 08152 goto quit; 08153 } 08154 if (i & DAHDI_IOMUX_SIGEVENT) { 08155 res = dahdi_get_event(p->subs[index].dfd); 08156 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08157 if (res == DAHDI_EVENT_NOALARM) { 08158 p->inalarm = 0; 08159 } 08160 res = 0; 08161 /* Let us detect distinctive ring */ 08162 08163 curRingData[receivedRingT] = p->ringt; 08164 08165 if (p->ringt < p->ringt_base/2) 08166 break; 08167 /* Increment the ringT counter so we can match it against 08168 values in chan_dahdi.conf for distinctive ring */ 08169 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 08170 break; 08171 } else if (i & DAHDI_IOMUX_READ) { 08172 res = read(p->subs[index].dfd, buf, sizeof(buf)); 08173 if (res < 0) { 08174 if (errno != ELAST) { 08175 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08176 callerid_free(cs); 08177 ast_hangup(chan); 08178 goto quit; 08179 } 08180 break; 08181 } 08182 if (p->ringt) 08183 p->ringt--; 08184 if (p->ringt == 1) { 08185 res = -1; 08186 break; 08187 } 08188 } 08189 } 08190 if (option_verbose > 2) 08191 /* this only shows up if you have n of the dring patterns filled in */ 08192 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 08193 08194 for (counter = 0; counter < 3; counter++) { 08195 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 08196 channel */ 08197 distMatches = 0; 08198 for (counter1 = 0; counter1 < 3; counter1++) { 08199 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 08200 (p->drings.ringnum[counter].ring[counter1]-10)) { 08201 distMatches++; 08202 } 08203 } 08204 if (distMatches == 3) { 08205 /* The ring matches, set the context to whatever is for distinctive ring.. */ 08206 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 08207 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 08208 if (option_verbose > 2) 08209 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 08210 break; 08211 } 08212 } 08213 } 08214 /* Restore linear mode (if appropriate) for Caller*ID processing */ 08215 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 08216 #if 1 08217 restore_gains(p); 08218 #endif 08219 } else 08220 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 08221 } else { 08222 ast_log(LOG_WARNING, "Channel %s in prering " 08223 "state, but I have nothing to do. " 08224 "Terminating simple switch, should be " 08225 "restarted by the actual ring.\n", 08226 chan->name); 08227 ast_hangup(chan); 08228 goto quit; 08229 } 08230 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 08231 /* FSK Bell202 callerID */ 08232 cs = callerid_new(p->cid_signalling); 08233 if (cs) { 08234 #if 1 08235 bump_gains(p); 08236 #endif 08237 samples = 0; 08238 len = 0; 08239 distMatches = 0; 08240 /* Clear the current ring data array so we dont have old data in it. */ 08241 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 08242 curRingData[receivedRingT] = 0; 08243 receivedRingT = 0; 08244 counter = 0; 08245 counter1 = 0; 08246 /* Check to see if context is what it should be, if not set to be. */ 08247 if (strcmp(p->context,p->defcontext) != 0) { 08248 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 08249 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 08250 } 08251 08252 /* Take out of linear mode for Caller*ID processing */ 08253 dahdi_setlinear(p->subs[index].dfd, 0); 08254 for (;;) { 08255 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08256 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 08257 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08258 callerid_free(cs); 08259 ast_hangup(chan); 08260 goto quit; 08261 } 08262 if (i & DAHDI_IOMUX_SIGEVENT) { 08263 res = dahdi_get_event(p->subs[index].dfd); 08264 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08265 if (res == DAHDI_EVENT_NOALARM) { 08266 p->inalarm = 0; 08267 } 08268 /* If we get a PR event, they hung up while processing calerid */ 08269 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 08270 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 08271 p->polarity = POLARITY_IDLE; 08272 callerid_free(cs); 08273 ast_hangup(chan); 08274 goto quit; 08275 } 08276 res = 0; 08277 /* Let us detect callerid when the telco uses distinctive ring */ 08278 08279 curRingData[receivedRingT] = p->ringt; 08280 08281 if (p->ringt < p->ringt_base/2) 08282 break; 08283 /* Increment the ringT counter so we can match it against 08284 values in chan_dahdi.conf for distinctive ring */ 08285 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 08286 break; 08287 } else if (i & DAHDI_IOMUX_READ) { 08288 res = read(p->subs[index].dfd, buf, sizeof(buf)); 08289 if (res < 0) { 08290 if (errno != ELAST) { 08291 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08292 callerid_free(cs); 08293 ast_hangup(chan); 08294 goto quit; 08295 } 08296 break; 08297 } 08298 if (p->ringt) 08299 p->ringt--; 08300 if (p->ringt == 1) { 08301 res = -1; 08302 break; 08303 } 08304 samples += res; 08305 res = callerid_feed(cs, buf, res, AST_LAW(p)); 08306 if (res < 0) { 08307 /* 08308 * The previous diagnostic message output likely 08309 * explains why it failed. 08310 */ 08311 ast_log(LOG_WARNING, 08312 "Failed to decode CallerID on channel '%s'\n", 08313 chan->name); 08314 break; 08315 } else if (res) 08316 break; 08317 else if (samples > (8000 * 10)) 08318 break; 08319 } 08320 } 08321 if (res == 1) { 08322 callerid_get(cs, &name, &number, &flags); 08323 if (option_debug) 08324 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 08325 } 08326 if (distinctiveringaftercid == 1) { 08327 /* Clear the current ring data array so we dont have old data in it. */ 08328 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 08329 curRingData[receivedRingT] = 0; 08330 } 08331 receivedRingT = 0; 08332 if (option_verbose > 2) 08333 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 08334 for (;;) { 08335 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08336 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 08337 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08338 callerid_free(cs); 08339 ast_hangup(chan); 08340 goto quit; 08341 } 08342 if (i & DAHDI_IOMUX_SIGEVENT) { 08343 res = dahdi_get_event(p->subs[index].dfd); 08344 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08345 if (res == DAHDI_EVENT_NOALARM) { 08346 p->inalarm = 0; 08347 } 08348 res = 0; 08349 /* Let us detect callerid when the telco uses distinctive ring */ 08350 08351 curRingData[receivedRingT] = p->ringt; 08352 08353 if (p->ringt < p->ringt_base/2) 08354 break; 08355 /* Increment the ringT counter so we can match it against 08356 values in chan_dahdi.conf for distinctive ring */ 08357 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 08358 break; 08359 } else if (i & DAHDI_IOMUX_READ) { 08360 res = read(p->subs[index].dfd, buf, sizeof(buf)); 08361 if (res < 0) { 08362 if (errno != ELAST) { 08363 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08364 callerid_free(cs); 08365 ast_hangup(chan); 08366 goto quit; 08367 } 08368 break; 08369 } 08370 if (p->ringt) 08371 p->ringt--; 08372 if (p->ringt == 1) { 08373 res = -1; 08374 break; 08375 } 08376 } 08377 } 08378 } 08379 if (p->usedistinctiveringdetection) { 08380 if (option_verbose > 2) 08381 /* this only shows up if you have n of the dring patterns filled in */ 08382 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 08383 08384 for (counter = 0; counter < 3; counter++) { 08385 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 08386 channel */ 08387 if (option_verbose > 2) 08388 /* this only shows up if you have n of the dring patterns filled in */ 08389 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 08390 p->drings.ringnum[counter].ring[0], 08391 p->drings.ringnum[counter].ring[1], 08392 p->drings.ringnum[counter].ring[2]); 08393 distMatches = 0; 08394 for (counter1 = 0; counter1 < 3; counter1++) { 08395 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 08396 (p->drings.ringnum[counter].ring[counter1]-10)) { 08397 distMatches++; 08398 } 08399 } 08400 if (distMatches == 3) { 08401 /* The ring matches, set the context to whatever is for distinctive ring.. */ 08402 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 08403 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 08404 if (option_verbose > 2) 08405 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 08406 break; 08407 } 08408 } 08409 } 08410 /* Restore linear mode (if appropriate) for Caller*ID processing */ 08411 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 08412 #if 1 08413 restore_gains(p); 08414 #endif 08415 if (res < 0) { 08416 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 08417 } 08418 } else 08419 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 08420 } 08421 else 08422 cs = NULL; 08423 08424 if (number) 08425 ast_shrink_phone_number(number); 08426 ast_set_callerid(chan, number, name, number); 08427 08428 if (smdi_msg) 08429 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 08430 08431 if (cs) 08432 callerid_free(cs); 08433 08434 ast_setstate(chan, AST_STATE_RING); 08435 chan->rings = 1; 08436 p->ringt = p->ringt_base; 08437 res = ast_pbx_run(chan); 08438 if (res) { 08439 ast_hangup(chan); 08440 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 08441 } 08442 goto quit; 08443 default: 08444 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 08445 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 08446 if (res < 0) 08447 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 08448 } 08449 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 08450 if (res < 0) 08451 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 08452 ast_hangup(chan); 08453 quit: 08454 ast_mutex_lock(&ss_thread_lock); 08455 ss_thread_count--; 08456 ast_cond_signal(&ss_thread_complete); 08457 ast_mutex_unlock(&ss_thread_lock); 08458 return NULL; 08459 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12313 of file chan_dahdi.c.
References ast_log(), dahdi_close_pri_fd(), DAHDI_FILE_CHANNEL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, and dahdi_pri::switchtype.
Referenced by setup_dahdi().
12314 { 12315 int res, x; 12316 struct dahdi_params p; 12317 struct dahdi_bufferinfo bi; 12318 struct dahdi_spaninfo si; 12319 int i; 12320 12321 for (i = 0; i < NUM_DCHANS; i++) { 12322 if (!pri->dchannels[i]) 12323 break; 12324 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 12325 x = pri->dchannels[i]; 12326 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 12327 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 12328 return -1; 12329 } 12330 memset(&p, 0, sizeof(p)); 12331 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 12332 if (res) { 12333 dahdi_close_pri_fd(pri, i); 12334 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 12335 return -1; 12336 } 12337 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 12338 dahdi_close_pri_fd(pri, i); 12339 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 12340 return -1; 12341 } 12342 memset(&si, 0, sizeof(si)); 12343 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 12344 if (res) { 12345 dahdi_close_pri_fd(pri, i); 12346 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 12347 } 12348 if (!si.alarms) 12349 pri->dchanavail[i] |= DCHAN_NOTINALARM; 12350 else 12351 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 12352 memset(&bi, 0, sizeof(bi)); 12353 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12354 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12355 bi.numbufs = 32; 12356 bi.bufsize = 1024; 12357 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12358 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12359 dahdi_close_pri_fd(pri, i); 12360 return -1; 12361 } 12362 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12363 /* Force overlap dial if we're doing GR-303! */ 12364 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12365 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12366 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12367 #ifdef HAVE_PRI_INBANDDISCONNECT 12368 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12369 #endif 12370 /* Enslave to master if appropriate */ 12371 if (i) 12372 pri_enslave(pri->dchans[0], pri->dchans[i]); 12373 if (!pri->dchans[i]) { 12374 dahdi_close_pri_fd(pri, i); 12375 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12376 return -1; 12377 } 12378 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12379 pri_set_nsf(pri->dchans[i], pri->nsf); 12380 #ifdef PRI_GETSET_TIMERS 12381 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12382 if (pritimers[x] != 0) 12383 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12384 } 12385 #endif 12386 } 12387 /* Assume primary is the one we use */ 12388 pri->pri = pri->dchans[0]; 12389 pri->resetpos = -1; 12390 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12391 for (i = 0; i < NUM_DCHANS; i++) { 12392 if (!pri->dchannels[i]) 12393 break; 12394 dahdi_close_pri_fd(pri, i); 12395 } 12396 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12397 return -1; 12398 } 12399 return 0; 12400 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1849 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01850 { 01851 int tchan; 01852 int tinthreeway; 01853 struct ast_channel *towner; 01854 01855 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 01856 01857 tchan = p->subs[a].chan; 01858 towner = p->subs[a].owner; 01859 tinthreeway = p->subs[a].inthreeway; 01860 01861 p->subs[a].chan = p->subs[b].chan; 01862 p->subs[a].owner = p->subs[b].owner; 01863 p->subs[a].inthreeway = p->subs[b].inthreeway; 01864 01865 p->subs[b].chan = tchan; 01866 p->subs[b].owner = towner; 01867 p->subs[b].inthreeway = tinthreeway; 01868 01869 if (p->subs[a].owner) 01870 p->subs[a].owner->fds[0] = p->subs[a].dfd; 01871 if (p->subs[b].owner) 01872 p->subs[b].owner->fds[0] = p->subs[b].dfd; 01873 wakeup_sub(p, a, NULL); 01874 wakeup_sub(p, b, NULL); 01875 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1988 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01989 { 01990 if (!x) { 01991 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01992 return -1; 01993 } 01994 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01995 dahdi_close_sub(p, x); 01996 p->subs[x].linear = 0; 01997 p->subs[x].chan = 0; 01998 p->subs[x].owner = NULL; 01999 p->subs[x].inthreeway = 0; 02000 p->polarity = POLARITY_IDLE; 02001 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 02002 return 0; 02003 }
static int unload_module | ( | void | ) | [static] |
Definition at line 13988 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
13989 { 13990 #ifdef HAVE_PRI 13991 int y; 13992 for (y = 0; y < NUM_SPANS; y++) 13993 ast_mutex_destroy(&pris[y].lock); 13994 #endif 13995 return __unload_module(); 13996 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2388 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().
02389 { 02390 int needconf = 0; 02391 int x; 02392 int useslavenative; 02393 struct dahdi_pvt *slave = NULL; 02394 02395 useslavenative = isslavenative(p, &slave); 02396 /* Start with the obvious, general stuff */ 02397 for (x = 0; x < 3; x++) { 02398 /* Look for three way calls */ 02399 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 02400 conf_add(p, &p->subs[x], x, 0); 02401 needconf++; 02402 } else { 02403 conf_del(p, &p->subs[x], x); 02404 } 02405 } 02406 /* If we have a slave, add him to our conference now. or DAX 02407 if this is slave native */ 02408 for (x = 0; x < MAX_SLAVES; x++) { 02409 if (p->slaves[x]) { 02410 if (useslavenative) 02411 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02412 else { 02413 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02414 needconf++; 02415 } 02416 } 02417 } 02418 /* If we're supposed to be in there, do so now */ 02419 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02420 if (useslavenative) 02421 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02422 else { 02423 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02424 needconf++; 02425 } 02426 } 02427 /* If we have a master, add ourselves to his conference */ 02428 if (p->master) { 02429 if (isslavenative(p->master, NULL)) { 02430 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02431 } else { 02432 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02433 } 02434 } 02435 if (!needconf) { 02436 /* Nobody is left (or should be left) in our conference. 02437 Kill it. */ 02438 p->confno = -1; 02439 } 02440 if (option_debug) 02441 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02442 return 0; 02443 }
Definition at line 1295 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), dahdi_lock_sub_owner(), ast_channel::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by swap_subs().
01296 { 01297 #ifdef HAVE_PRI 01298 if (pri) 01299 ast_mutex_unlock(&pri->lock); 01300 #endif 01301 dahdi_lock_sub_owner(p, a); 01302 if (p->subs[a].owner) { 01303 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01304 ast_mutex_unlock(&p->subs[a].owner->lock); 01305 } 01306 #ifdef HAVE_PRI 01307 if (pri) 01308 ast_mutex_lock(&pri->lock); 01309 #endif 01310 }
static int zap_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3657 of file chan_dahdi.c.
References dahdi_accept_r2_call_exec().
Referenced by load_module().
03658 { 03659 return dahdi_accept_r2_call_exec(chan, data); 03660 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13806 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
13807 { 13808 return __action_dialoffhook(s, m, 1); 13809 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13706 of file chan_dahdi.c.
References __action_dnd(), and s.
13707 { 13708 return __action_dnd(s, m, 1, 0); 13709 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13696 of file chan_dahdi.c.
References __action_dnd(), and s.
13697 { 13698 return __action_dnd(s, m, 1, 1); 13699 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13885 of file chan_dahdi.c.
References __action_restart(), and s.
13886 { 13887 return __action_restart(s, m, 1); 13888 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13861 of file chan_dahdi.c.
References __action_showchannels(), and s.
13862 { 13863 return __action_showchannels(s, m, 1); 13864 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13735 of file chan_dahdi.c.
References __action_transfer(), and s.
13736 { 13737 return __action_transfer(s, m, 1); 13738 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 13763 of file chan_dahdi.c.
References __action_transferhangup(), and s.
13764 { 13765 return __action_transferhangup(s, m, 1); 13766 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3450 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
03451 { 03452 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app); 03453 return send_keypad_facility_exec(chan, data); 03454 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 15281 of file chan_dahdi.c.
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str(), and dahdi_show_status().
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15281 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1220 of file chan_dahdi.c.
Referenced by dahdi_call(), handle_dahdi_show_cadences(), and process_dahdi().
struct ast_channel_tech* chan_tech [static] |
Definition at line 1188 of file chan_dahdi.c.
Referenced by __unload_module(), ast_device_state(), dahdi_new(), load_module(), and ss_thread().
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 1231 of file chan_dahdi.c.
Referenced by dahdi_call(), handle_dahdi_show_cadences(), and process_dahdi().
struct ast_cli_entry cli_zap_destroy_channel_deprecated [static] |
Initial value:
{ { "zap", "destroy", "channel", NULL }, dahdi_destroy_channel, NULL, NULL }
Definition at line 13602 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_restart_deprecated [static] |
Initial value:
{ { "zap", "restart", NULL }, dahdi_restart_cmd, NULL, NULL }
Definition at line 13607 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_cadences_deprecated [static] |
Initial value:
{ { "zap", "show", "cadences", NULL }, handle_dahdi_show_cadences, NULL, NULL }
Definition at line 13587 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_channel_deprecated [static] |
Initial value:
{ { "zap", "show", "channel", NULL }, dahdi_show_channel, NULL, NULL }
Definition at line 13597 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_channels_deprecated [static] |
Initial value:
{ { "zap", "show", "channels", NULL }, dahdi_show_channels, NULL, NULL }
Definition at line 13592 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_status_deprecated [static] |
Initial value:
{ { "zap", "show", "status", NULL }, dahdi_show_status, NULL, NULL }
Definition at line 13612 of file chan_dahdi.c.
char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 3542 of file chan_dahdi.c.
char* dahdi_accept_r2_call_descrip [static] |
Initial value:
" DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n" " You can specify yes or no as argument to accept with or without charge.\n"
Definition at line 3548 of file chan_dahdi.c.
char* dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static] |
Definition at line 3545 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
struct ast_cli_entry dahdi_mfcr2_cli[] [static] |
struct ast_cli_entry dahdi_pri_cli[] [static] |
const char dahdi_r2_callfiles_help[] [static] |
Initial value:
"Usage: mfcr2 call files [on|off] <channel>\n" " Enable call files creation on the specified channel.\n" " If no channel is specified call files creation policy will be applied to all channels.\n"
Definition at line 13012 of file chan_dahdi.c.
openr2_event_interface_t dahdi_r2_event_iface [static] |
Definition at line 1809 of file chan_dahdi.c.
const char dahdi_r2_setblocked_help[] [static] |
Initial value:
"Usage: mfcr2 set blocked <channel>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" " Force the given channel into BLOCKED state.\n" " If no channel is specified, all channels will be set to BLOCKED.\n"
Definition at line 13021 of file chan_dahdi.c.
const char dahdi_r2_setdebug_help[] [static] |
Initial value:
"Usage: mfcr2 set debug <loglevel> <channel>\n" " Set a new logging level for the specified channel.\n" " If no channel is specified the logging level will be applied to all channels.\n"
Definition at line 13008 of file chan_dahdi.c.
const char dahdi_r2_setidle_help[] [static] |
Initial value:
"Usage: mfcr2 set idle <channel>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" " Force the given channel into IDLE state.\n" " If no channel is specified, all channels will be set to IDLE.\n"
Definition at line 13016 of file chan_dahdi.c.
const char dahdi_r2_showchannels_help[] [static] |
Initial value:
"Usage: mfcr2 show channels [group <group> | context <context>]\n" " Shows the zap channels configured with MFC/R2 signaling.\n"
Definition at line 13005 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 1840 of file chan_dahdi.c.
const char dahdi_r2_variants_help[] [static] |
Initial value:
"Usage: mfcr2 show variants\n" " Show supported MFC/R2 variants.\n"
Definition at line 13002 of file chan_dahdi.c.
const char dahdi_r2_version_help[] [static] |
Initial value:
"Usage: mfcr2 show version\n" " Shows the version of the OpenR2 library being used.\n"
Definition at line 12999 of file chan_dahdi.c.
char dahdi_restart_usage[] [static] |
Definition at line 13580 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3392 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_descrip [static] |
Initial value:
" DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n" " IE over the current channel.\n"
Definition at line 3398 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3395 of file chan_dahdi.c.
char dahdi_show_cadences_usage[] [static] |
Initial value:
"Usage: dahdi show cadences\n" " Shows all cadences currently defined\n"
Definition at line 13473 of file chan_dahdi.c.
char dahdi_show_status_usage[] [static] |
Initial value:
"Usage: dahdi show status\n" " Shows a list of DAHDI cards with status\n"
Definition at line 13572 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1144 of file chan_dahdi.c.
Referenced by dahdi_accept_r2_call_exec(), and load_module().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 115 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
char defaultozz[64] = "" [static] |
char destroy_channel_usage[] [static] |
Initial value:
"Usage: dahdi destroy channel <chan num>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"
Definition at line 13576 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
struct dahdi_distRings drings [static] |
int dtmfcid_level = 256 [static] |
Definition at line 236 of file chan_dahdi.c.
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 248 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), skinny_ss(), and ss_thread().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 251 of file chan_dahdi.c.
Referenced by mgcp_ss(), skinny_ss(), and ss_thread().
struct ast_jb_conf global_jbconf [static] |
Definition at line 122 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 260 of file chan_dahdi.c.
Referenced by destroy_all_channels(), do_monitor(), and mkintf().
Referenced by dahdi_request(), destroy_channel(), and mkintf().
Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), 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(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 257 of file chan_dahdi.c.
Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call(), find_call_locked(), get_sip_pvt_byid_locked(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), sip_alloc(), sip_destroy(), sip_show_channel(), sip_show_history(), and unload_module().
struct ast_channel inuse [static] |
Definition at line 239 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), and update_call_counter().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 254 of file chan_dahdi.c.
Referenced by mgcp_ss(), skinny_ss(), and ss_thread().
int mfcr2_cur_accept_on_offer = 1 [static] |
int mfcr2_cur_allow_collect_calls = 0 [static] |
Definition at line 349 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_call_files = 0 [static] |
Definition at line 348 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static] |
Definition at line 365 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_charge_calls = 1 [static] |
int mfcr2_cur_context_index = 0 [static] |
Definition at line 347 of file chan_dahdi.c.
Referenced by build_channels(), init_mfcr2_globals(), and mkintf().
int mfcr2_cur_double_answer = 0 [static] |
Definition at line 353 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_forced_release = 0 [static] |
Definition at line 352 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_get_ani_first = -1 [static] |
Definition at line 345 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_immediate_accept = -1 [static] |
Definition at line 354 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
char mfcr2_cur_logdir[OR2_MAX_PATH] [static] |
Definition at line 362 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static] |
Definition at line 364 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_max_ani = 10 [static] |
Definition at line 343 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_max_dnis = 4 [static] |
Definition at line 344 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_metering_pulse_timeout = -1 [static] |
Definition at line 342 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_mfback_timeout = -1 [static] |
Definition at line 341 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static] |
Definition at line 363 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
int mfcr2_cur_skip_category = -1 [static] |
Definition at line 346 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static] |
Definition at line 340 of file chan_dahdi.c.
Referenced by init_mfcr2_globals(), mkintf(), and process_dahdi().
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 272 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), reload_config(), restart_monitor(), and unload_module().
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [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 268 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 2158 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1217 of file chan_dahdi.c.
Referenced by dahdi_call(), handle_dahdi_show_cadences(), and process_dahdi().
int num_restart_pending = 0 [static] |
Definition at line 277 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_softhangup_all(), and destroy_all_channels().
int numbufs = 4 [static] |
const char pri_debug_help[] [static] |
Initial value:
"Usage: pri debug span <span>\n" " Enables debugging on a given PRI span\n"
Definition at line 12667 of file chan_dahdi.c.
const char pri_no_debug_help[] [static] |
Initial value:
"Usage: pri no debug span <span>\n" " Disables debugging on a given PRI span\n"
Definition at line 12671 of file chan_dahdi.c.
const char pri_really_debug_help[] [static] |
Initial value:
"Usage: pri intensive debug span <span>\n" " Enables debugging down to the Q.921 level\n"
Definition at line 12675 of file chan_dahdi.c.
const char pri_show_span_help[] [static] |
Initial value:
"Usage: pri show span <span>\n" " Displays PRI Information on a given PRI span\n"
Definition at line 12679 of file chan_dahdi.c.
const char pri_show_spans_help[] [static] |
Initial value:
"Usage: pri show spans\n" " Displays PRI Information\n"
Definition at line 12683 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 243 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), and handle_pri_show_debug().
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 263 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), and handle_pri_show_debug().
char pridebugfilename[1024] = "" [static] |
Definition at line 244 of file chan_dahdi.c.
Referenced by handle_pri_set_debug_file(), and handle_pri_show_debug().
Definition at line 444 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 231 of file chan_dahdi.c.
Referenced by dahdi_new(), dahdi_show_channel(), and process_dahdi().
struct dahdi_mfcr2 r2links[NUM_SPANS] [static] |
Definition at line 339 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), dahdi_restart(), init_mfcr2_globals(), mfcr2_get_context(), and setup_dahdi().
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 328 of file chan_dahdi.c.
Referenced by process_dahdi().
struct dahdi_pvt* round_robin[32] |
char show_channel_usage[] [static] |
Initial value:
"Usage: dahdi show channel <chan num>\n" " Detailed information about a given channel\n"
Definition at line 13568 of file chan_dahdi.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: dahdi show channels\n" " Shows a list of available channels\n"
Definition at line 13564 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 273 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and load_module().
int ss_thread_count = 0 [static] |
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
char* subnames[] [static] |
Initial value:
{ "Real", "Callwait", "Threeway" }
Definition at line 484 of file chan_dahdi.c.
Referenced by alloc_sub(), dahdi_bridge(), and dahdi_new().
const char tdesc[] [static] |
Definition at line 174 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static] |
Definition at line 3543 of file chan_dahdi.c.
char* zap_accept_r2_call_descrip [static] |
Initial value:
" ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n" " You can specify yes or no as argument to accept with or without charge.\n"
Definition at line 3552 of file chan_dahdi.c.
char* zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static] |
Definition at line 3546 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 3393 of file chan_dahdi.c.
char* zap_send_keypad_facility_descrip [static] |
Initial value:
" ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n" " IE over the current channel.\n"
Definition at line 3401 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3396 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |