#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 | 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 | CHANNEL_PSEUDO -12 |
#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_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 | 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_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 |
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 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_get_event (int fd) |
Avoid the silly dahdi_getevent which ignores a bunch of events. | |
static int | dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok) |
static void | dahdi_handle_dtmfup (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 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 | 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 int | 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_principle (struct dahdi_pri *pri, int channel) |
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_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 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 156 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 298 of file chan_dahdi.c.
#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 200 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().
#define CHANNEL_PSEUDO -12 |
Definition at line 154 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 473 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 474 of file chan_dahdi.c.
#define DAHDI_EVENT_DTMFDOWN 0 |
#define DAHDI_EVENT_DTMFUP 0 |
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 211 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), and process_dahdi().
#define DAHDI_OVERLAPDIAL_NONE 0 |
#define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 210 of file chan_dahdi.c.
Referenced by dahdi_read(), process_dahdi(), and start_pri().
#define DAHDI_R2_LOCAL_BLOCK (1 << 1) |
Definition at line 1646 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 1645 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 202 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 204 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 152 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 302 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#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 1137 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 12499 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 1184 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 12529 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 12530 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 295 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 296 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 12944 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 198 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 159 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 1162 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 197 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 196 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 431 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 432 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and handle_init_event().
#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)) |
Definition at line 353 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), and pri_check_restart().
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 293 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
#define sig2str dahdi_sig2str |
Definition at line 2166 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 175 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 170 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 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_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 171 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 174 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 172 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 173 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 176 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 177 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 178 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 183 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 184 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 182 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 180 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 181 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 179 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 193 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 186 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 185 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_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_SF DAHDI_SIG_SF |
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_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
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_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 189 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 190 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 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 SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 427 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define SUB_REAL 0 |
Active call
Definition at line 426 of file chan_dahdi.c.
Referenced by __dahdi_exception(), 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_get_index(), 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(), 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 428 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define tdesc "DAHDI Telephony w/PRI" |
Definition at line 14120 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 12498 of file chan_dahdi.c.
Referenced by __action_transfer(), and dahdi_fake_event().
static int __action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12628 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().
12629 { 12630 struct dahdi_pvt *p = NULL; 12631 const char *channel = local_astman_header(m, "Channel", zap_mode); 12632 const char *number = astman_get_header(m, "Number"); 12633 int i; 12634 12635 if (ast_strlen_zero(channel)) { 12636 astman_send_error(s, m, "No channel specified"); 12637 return 0; 12638 } 12639 if (ast_strlen_zero(number)) { 12640 astman_send_error(s, m, "No number specified"); 12641 return 0; 12642 } 12643 if (!(p = find_channel(atoi(channel)))) { 12644 astman_send_error(s, m, "No such channel"); 12645 return 0; 12646 } 12647 if (!p->owner) { 12648 astman_send_error(s, m, "Channel does not have an owner"); 12649 return 0; 12650 } 12651 for (i = 0; i < strlen(number); i++) { 12652 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 12653 12654 dahdi_queue_frame(p, &f, NULL); 12655 } 12656 local_astman_ack(s, m, "DialOffHook", zap_mode); 12657 12658 return 0; 12659 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 12532 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().
12533 { 12534 struct dahdi_pvt *p = NULL; 12535 const char *channel = local_astman_header(m, "Channel", zap_mode); 12536 12537 if (ast_strlen_zero(channel)) { 12538 astman_send_error(s, m, "No channel specified"); 12539 return 0; 12540 } 12541 if (!(p = find_channel(atoi(channel)))) { 12542 astman_send_error(s, m, "No such channel"); 12543 return 0; 12544 } 12545 p->dnd = dnd; 12546 local_astman_ack(s, m, "DND", zap_mode); 12547 12548 return 0; 12549 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12726 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().
12727 { 12728 if (dahdi_restart() != 0) { 12729 if (zap_mode) { 12730 astman_send_error(s, m, "Failed to restart Zap"); 12731 } else { 12732 astman_send_error(s, m, "Failed to restart DAHDI"); 12733 } 12734 return 1; 12735 } 12736 local_astman_ack(s, m, "Restart: Success", zap_mode); 12737 return 0; 12738 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12671 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().
12672 { 12673 struct dahdi_pvt *tmp = NULL; 12674 const char *id = astman_get_header(m, "ActionID"); 12675 char idText[256] = ""; 12676 12677 local_astman_ack(s, m, " channel status will follow", zap_mode); 12678 if (!ast_strlen_zero(id)) 12679 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 12680 12681 ast_mutex_lock(&iflock); 12682 12683 tmp = iflist; 12684 while (tmp) { 12685 if (tmp->channel > 0) { 12686 int alarm = get_alarms(tmp); 12687 astman_append(s, 12688 "Event: %sShowChannels\r\n" 12689 "Channel: %d\r\n" 12690 "Signalling: %s\r\n" 12691 "Context: %s\r\n" 12692 "DND: %s\r\n" 12693 "Alarm: %s\r\n" 12694 "%s" 12695 "\r\n", 12696 dahdi_chan_name, 12697 tmp->channel, sig2str(tmp->sig), tmp->context, 12698 tmp->dnd ? "Enabled" : "Disabled", 12699 alarm2str(alarm), idText); 12700 } 12701 12702 tmp = tmp->next; 12703 } 12704 12705 ast_mutex_unlock(&iflock); 12706 12707 astman_append(s, 12708 "Event: %sShowChannelsComplete\r\n" 12709 "%s" 12710 "\r\n", 12711 dahdi_chan_name, 12712 idText); 12713 return 0; 12714 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12571 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().
12572 { 12573 struct dahdi_pvt *p = NULL; 12574 const char *channel = local_astman_header(m, "Channel", zap_mode); 12575 12576 if (ast_strlen_zero(channel)) { 12577 astman_send_error(s, m, "No channel specified"); 12578 return 0; 12579 } 12580 if (!(p = find_channel(atoi(channel)))) { 12581 astman_send_error(s, m, "No such channel"); 12582 return 0; 12583 } 12584 dahdi_fake_event(p,TRANSFER); 12585 local_astman_ack(s, m, "Transfer", zap_mode); 12586 12587 return 0; 12588 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12600 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().
12601 { 12602 struct dahdi_pvt *p = NULL; 12603 const char *channel = local_astman_header(m, "Channel", zap_mode); 12604 12605 if (ast_strlen_zero(channel)) { 12606 astman_send_error(s, m, "No channel specified"); 12607 return 0; 12608 } 12609 if (!(p = find_channel(atoi(channel)))) { 12610 astman_send_error(s, m, "No such channel"); 12611 return 0; 12612 } 12613 dahdi_fake_event(p, HANGUP); 12614 local_astman_ack(s, m, "Hangup", zap_mode); 12615 return 0; 12616 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5791 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(), and dahdi_read().
05792 { 05793 struct dahdi_pvt *p = ast->tech_pvt; 05794 int res; 05795 int usedindex=-1; 05796 int index; 05797 struct ast_frame *f; 05798 05799 05800 index = dahdi_get_index(ast, p, 1); 05801 05802 p->subs[index].f.frametype = AST_FRAME_NULL; 05803 p->subs[index].f.datalen = 0; 05804 p->subs[index].f.samples = 0; 05805 p->subs[index].f.mallocd = 0; 05806 p->subs[index].f.offset = 0; 05807 p->subs[index].f.subclass = 0; 05808 p->subs[index].f.delivery = ast_tv(0,0); 05809 p->subs[index].f.src = "dahdi_exception"; 05810 p->subs[index].f.data = NULL; 05811 05812 05813 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05814 /* If nobody owns us, absorb the event appropriately, otherwise 05815 we loop indefinitely. This occurs when, during call waiting, the 05816 other end hangs up our channel so that it no longer exists, but we 05817 have neither FLASH'd nor ONHOOK'd to signify our desire to 05818 change to the other channel. */ 05819 if (p->fake_event) { 05820 res = p->fake_event; 05821 p->fake_event = 0; 05822 } else 05823 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05824 /* Switch to real if there is one and this isn't something really silly... */ 05825 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05826 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05827 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 05828 p->owner = p->subs[SUB_REAL].owner; 05829 if (p->owner && ast_bridged_channel(p->owner)) 05830 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05831 p->subs[SUB_REAL].needunhold = 1; 05832 } 05833 switch (res) { 05834 case DAHDI_EVENT_ONHOOK: 05835 dahdi_disable_ec(p); 05836 if (p->owner) { 05837 if (option_verbose > 2) 05838 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 05839 dahdi_ring_phone(p); 05840 p->callwaitingrepeat = 0; 05841 p->cidcwexpire = 0; 05842 } else 05843 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05844 update_conf(p); 05845 break; 05846 case DAHDI_EVENT_RINGOFFHOOK: 05847 dahdi_enable_ec(p); 05848 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05849 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05850 p->subs[SUB_REAL].needanswer = 1; 05851 p->dialing = 0; 05852 } 05853 break; 05854 case DAHDI_EVENT_HOOKCOMPLETE: 05855 case DAHDI_EVENT_RINGERON: 05856 case DAHDI_EVENT_RINGEROFF: 05857 /* Do nothing */ 05858 break; 05859 case DAHDI_EVENT_WINKFLASH: 05860 gettimeofday(&p->flashtime, NULL); 05861 if (p->owner) { 05862 if (option_verbose > 2) 05863 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05864 if (p->owner->_state != AST_STATE_UP) { 05865 /* Answer if necessary */ 05866 usedindex = dahdi_get_index(p->owner, p, 0); 05867 if (usedindex > -1) { 05868 p->subs[usedindex].needanswer = 1; 05869 } 05870 ast_setstate(p->owner, AST_STATE_UP); 05871 } 05872 p->callwaitingrepeat = 0; 05873 p->cidcwexpire = 0; 05874 if (ast_bridged_channel(p->owner)) 05875 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05876 p->subs[SUB_REAL].needunhold = 1; 05877 } else 05878 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05879 update_conf(p); 05880 break; 05881 default: 05882 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05883 } 05884 f = &p->subs[index].f; 05885 return f; 05886 } 05887 if (!(p->radio || (p->oprmode < 0)) && option_debug) 05888 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05889 /* If it's not us, return NULL immediately */ 05890 if (ast != p->owner) { 05891 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05892 f = &p->subs[index].f; 05893 return f; 05894 } 05895 f = dahdi_handle_event(ast); 05896 return f; 05897 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 14129 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 12757 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, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, pris, and r2links.
Referenced by load_module(), and unload_module().
12758 { 12759 struct dahdi_pvt *p; 12760 #ifdef HAVE_OPENR2 12761 int r; 12762 #endif 12763 #ifdef HAVE_PRI 12764 int i, j; 12765 for (i = 0; i < NUM_SPANS; i++) { 12766 if (pris[i].master != AST_PTHREADT_NULL) 12767 pthread_cancel(pris[i].master); 12768 } 12769 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12770 12771 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12772 ast_unregister_application(dahdi_send_keypad_facility_app); 12773 } 12774 ast_unregister_application(zap_send_keypad_facility_app); 12775 #endif 12776 #ifdef HAVE_OPENR2 12777 for (r = 0; r < NUM_SPANS; r++) { 12778 if (r2links[r].master != AST_PTHREADT_NULL) { 12779 pthread_cancel(r2links[r].master); 12780 pthread_join(r2links[r].master, NULL); 12781 } 12782 } 12783 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0])); 12784 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12785 ast_unregister_application(dahdi_accept_r2_call_app); 12786 } 12787 ast_unregister_application(zap_accept_r2_call_app); 12788 #endif 12789 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12790 local_astman_unregister("DialOffHook"); 12791 local_astman_unregister("Hangup"); 12792 local_astman_unregister("Transfer"); 12793 local_astman_unregister("DNDoff"); 12794 local_astman_unregister("DNDon"); 12795 local_astman_unregister("ShowChannels"); 12796 local_astman_unregister("Restart"); 12797 ast_channel_unregister(chan_tech); 12798 ast_mutex_lock(&iflock); 12799 /* Hangup all interfaces if they have an owner */ 12800 p = iflist; 12801 while (p) { 12802 if (p->owner) 12803 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 12804 p = p->next; 12805 } 12806 ast_mutex_unlock(&iflock); 12807 ast_mutex_lock(&monlock); 12808 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12809 pthread_cancel(monitor_thread); 12810 pthread_kill(monitor_thread, SIGURG); 12811 pthread_join(monitor_thread, NULL); 12812 } 12813 monitor_thread = AST_PTHREADT_STOP; 12814 ast_mutex_unlock(&monlock); 12815 12816 destroy_all_channels(); 12817 #ifdef HAVE_PRI 12818 for (i = 0; i < NUM_SPANS; i++) { 12819 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 12820 pthread_join(pris[i].master, NULL); 12821 for (j = 0; j < NUM_DCHANS; j++) { 12822 dahdi_close_pri_fd(&(pris[i]), j); 12823 } 12824 } 12825 #endif 12826 #ifdef HAVE_OPENR2 12827 for (r = 0; r < NUM_SPANS; r++) { 12828 if (r2links[r].protocol_context) { 12829 openr2_context_delete(r2links[r].protocol_context); 12830 } 12831 } 12832 #endif 12833 ast_cond_destroy(&ss_thread_complete); 12834 return 0; 12835 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 14129 of file chan_dahdi.c.
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 2075 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
02076 { 02077 int x; 02078 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 02079 if (alarms[x].alarm & alarm) 02080 return alarms[x].name; 02081 } 02082 return alarm ? "Unknown Alarm" : "No Alarm"; 02083 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1877 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, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
01878 { 01879 struct dahdi_bufferinfo bi; 01880 int res; 01881 if (p->subs[x].dfd < 0) { 01882 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 01883 if (p->subs[x].dfd > -1) { 01884 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01885 if (!res) { 01886 bi.txbufpolicy = p->buf_policy; 01887 bi.rxbufpolicy = p->buf_policy; 01888 bi.numbufs = p->buf_no; 01889 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01890 if (res < 0) { 01891 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01892 } 01893 } else 01894 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01895 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01896 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01897 dahdi_close_sub(p, x); 01898 return -1; 01899 } 01900 if (option_debug) 01901 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01902 return 0; 01903 } else 01904 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01905 return -1; 01906 } 01907 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01908 return -1; 01909 }
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 10002 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.
10003 { 10004 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10005 if (size) { 10006 *buf = '\0'; 10007 } 10008 return; 10009 } 10010 10011 switch (plan) { 10012 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10013 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10014 break; 10015 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10016 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10017 break; 10018 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10019 snprintf(buf, size, "%s%s", pri->localprefix, number); 10020 break; 10021 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10022 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10023 break; 10024 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10025 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10026 break; 10027 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10028 snprintf(buf, size, "%s", number); 10029 break; 10030 } 10031 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4718 of file chan_dahdi.c.
References ast_channel::_softhangup, 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_SOFTHANGUP_DEV, 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().
04719 { 04720 /* In order to transfer, we need at least one of the channels to 04721 actually be in a call bridge. We can't conference two applications 04722 together (but then, why would we want to?) */ 04723 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04724 /* The three-way person we're about to transfer to could still be in MOH, so 04725 stop if now if appropriate */ 04726 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04727 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04728 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04729 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04730 } 04731 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04732 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04733 } 04734 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04735 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04736 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04737 return -1; 04738 } 04739 /* Orphan the channel after releasing the lock */ 04740 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04741 unalloc_sub(p, SUB_THREEWAY); 04742 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04743 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04744 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04745 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04746 } 04747 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04748 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04749 } 04750 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04751 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04752 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04753 return -1; 04754 } 04755 /* Three-way is now the REAL */ 04756 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04757 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 04758 unalloc_sub(p, SUB_THREEWAY); 04759 /* Tell the caller not to hangup */ 04760 return 1; 04761 } else { 04762 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04763 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04764 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04765 return -1; 04766 } 04767 return 0; 04768 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9151 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, 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::resetting, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __ast_string_field_index_build_va(), and dahdi_request().
09152 { 09153 int res; 09154 struct dahdi_params par; 09155 09156 /* First, check group matching */ 09157 if (groupmatch) { 09158 if ((p->group & groupmatch) != groupmatch) 09159 return 0; 09160 *groupmatched = 1; 09161 } 09162 /* Check to see if we have a channel match */ 09163 if (channelmatch != -1) { 09164 if (p->channel != channelmatch) 09165 return 0; 09166 *channelmatched = 1; 09167 } 09168 /* We're at least busy at this point */ 09169 if (busy) { 09170 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09171 *busy = 1; 09172 } 09173 /* If do not disturb, definitely not */ 09174 if (p->dnd) 09175 return 0; 09176 /* If guard time, definitely not */ 09177 if (p->guardtime && (time(NULL) < p->guardtime)) 09178 return 0; 09179 09180 /* If no owner definitely available */ 09181 if (!p->owner) { 09182 #ifdef HAVE_PRI 09183 /* Trust PRI */ 09184 if (p->pri) { 09185 if (p->resetting || p->call) 09186 return 0; 09187 else 09188 return 1; 09189 } 09190 #endif 09191 #ifdef HAVE_OPENR2 09192 /* Trust MFC/R2 */ 09193 if (p->mfcr2) { 09194 if (p->mfcr2call || p->mfcr2block) 09195 return 0; 09196 else 09197 return 1; 09198 } 09199 #endif 09200 if (!(p->radio || (p->oprmode < 0))) 09201 { 09202 if (!p->sig || (p->sig == SIG_FXSLS)) 09203 return 1; 09204 /* Check hook state */ 09205 if (p->subs[SUB_REAL].dfd > -1) { 09206 memset(&par, 0, sizeof(par)); 09207 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09208 } else { 09209 /* Assume not off hook on CVRS */ 09210 res = 0; 09211 par.rxisoffhook = 0; 09212 } 09213 if (res) { 09214 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09215 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09216 /* When "onhook" that means no battery on the line, and thus 09217 it is out of service..., if it's on a TDM card... If it's a channel 09218 bank, there is no telling... */ 09219 if (par.rxbits > -1) 09220 return 1; 09221 if (par.rxisoffhook) 09222 return 1; 09223 else 09224 #ifdef DAHDI_CHECK_HOOKSTATE 09225 return 0; 09226 #else 09227 return 1; 09228 #endif 09229 } else if (par.rxisoffhook) { 09230 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 09231 /* Not available when the other end is off hook */ 09232 return 0; 09233 } 09234 } 09235 return 1; 09236 } 09237 09238 /* If it's not an FXO, forget about call wait */ 09239 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09240 return 0; 09241 09242 if (!p->callwaiting) { 09243 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09244 return 0; 09245 } 09246 09247 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09248 /* If there is already a call waiting call, then we can't take a second one */ 09249 return 0; 09250 } 09251 09252 if ((p->owner->_state != AST_STATE_UP) && 09253 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09254 /* If the current call is not up, then don't allow the call */ 09255 return 0; 09256 } 09257 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09258 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09259 return 0; 09260 } 09261 /* We're cool */ 09262 return 1; 09263 }
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 12847 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, 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().
12848 { 12849 char *c, *chan; 12850 int x, start, finish; 12851 struct dahdi_pvt *tmp; 12852 #ifdef HAVE_PRI 12853 struct dahdi_pri *pri; 12854 int trunkgroup, y; 12855 #endif 12856 12857 if ((reload == 0) && (conf->chan.sig < 0)) { 12858 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 12859 return -1; 12860 } 12861 12862 c = ast_strdupa(value); 12863 12864 #ifdef HAVE_PRI 12865 pri = NULL; 12866 if (iscrv) { 12867 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 12868 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 12869 return -1; 12870 } 12871 if (trunkgroup < 1) { 12872 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 12873 return -1; 12874 } 12875 c += y; 12876 for (y = 0; y < NUM_SPANS; y++) { 12877 if (pris[y].trunkgroup == trunkgroup) { 12878 pri = pris + y; 12879 break; 12880 } 12881 } 12882 if (!pri) { 12883 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 12884 return -1; 12885 } 12886 } 12887 #endif 12888 12889 while ((chan = strsep(&c, ","))) { 12890 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 12891 /* Range */ 12892 } else if (sscanf(chan, "%30d", &start)) { 12893 /* Just one */ 12894 finish = start; 12895 } else if (!strcasecmp(chan, "pseudo")) { 12896 finish = start = CHAN_PSEUDO; 12897 if (found_pseudo) 12898 *found_pseudo = 1; 12899 } else { 12900 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 12901 return -1; 12902 } 12903 if (finish < start) { 12904 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 12905 x = finish; 12906 finish = start; 12907 start = x; 12908 } 12909 12910 for (x = start; x <= finish; x++) { 12911 #ifdef HAVE_PRI 12912 tmp = mkintf(x, conf, pri, reload); 12913 #else 12914 tmp = mkintf(x, conf, NULL, reload); 12915 #endif 12916 12917 if (tmp) { 12918 if (option_verbose > 2) { 12919 #ifdef HAVE_PRI 12920 if (pri) 12921 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 12922 else 12923 #endif 12924 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 12925 } 12926 } else { 12927 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 12928 (reload == 1) ? "reconfigure" : "register", value); 12929 return -1; 12930 } 12931 } 12932 #ifdef HAVE_OPENR2 12933 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) { 12934 mfcr2_cur_context_index++; 12935 } 12936 #endif 12937 } 12938 12939 return 0; 12940 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 11417 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
11418 { 11419 if (!s || len < 1) { 11420 return; 11421 } 11422 s[0] = '\0'; 11423 if (status & DCHAN_PROVISIONED) 11424 strncat(s, "Provisioned, ", len - strlen(s) - 1); 11425 if (!(status & DCHAN_NOTINALARM)) 11426 strncat(s, "In Alarm, ", len - strlen(s) - 1); 11427 if (status & DCHAN_UP) 11428 strncat(s, "Up", len - strlen(s) - 1); 11429 else 11430 strncat(s, "Down", len - strlen(s) - 1); 11431 if (active) 11432 strncat(s, ", Active", len - strlen(s) - 1); 11433 else 11434 strncat(s, ", Standby", len - strlen(s) - 1); 11435 s[len - 1] = '\0'; 11436 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2526 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().
02527 { 02528 int res; 02529 02530 /* Bump receive gain by 5.0db */ 02531 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 02532 if (res) { 02533 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02534 return -1; 02535 } 02536 02537 return 0; 02538 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 7917 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
07918 { 07919 int x; 07920 int sum = 0; 07921 07922 if (!len) 07923 return 0; 07924 07925 for (x = 0; x < len; x++) 07926 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 07927 07928 return sum / len; 07929 }
Definition at line 9265 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().
09266 { 09267 struct dahdi_pvt *p; 09268 struct dahdi_bufferinfo bi; 09269 int res; 09270 09271 if ((p = ast_malloc(sizeof(*p)))) { 09272 memcpy(p, src, sizeof(struct dahdi_pvt)); 09273 ast_mutex_init(&p->lock); 09274 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 09275 /* Allocate a DAHDI structure */ 09276 if (p->subs[SUB_REAL].dfd < 0) { 09277 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09278 destroy_dahdi_pvt(&p); 09279 return NULL; 09280 } 09281 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09282 if (!res) { 09283 bi.txbufpolicy = p->buf_policy; 09284 bi.rxbufpolicy = p->buf_policy; 09285 bi.numbufs = p->buf_no; 09286 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09287 if (res < 0) { 09288 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09289 } 09290 } else 09291 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09292 } 09293 p->destroy = 1; 09294 p->next = iflist; 09295 p->prev = NULL; 09296 iflist = p; 09297 if (iflist->next) 09298 iflist->next->prev = p; 09299 return p; 09300 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4770 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().
04771 { 04772 struct dahdi_confinfo ci; 04773 /* Fine if we already have a master, etc */ 04774 if (p->master || (p->confno > -1)) 04775 return 0; 04776 memset(&ci, 0, sizeof(ci)); 04777 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04778 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04779 return 0; 04780 } 04781 /* If we have no master and don't have a confno, then 04782 if we're in a conference, it's probably a MeetMe room or 04783 some such, so don't let us 3-way out! */ 04784 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04785 if (option_verbose > 2) 04786 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 04787 return 1; 04788 } 04789 return 0; 04790 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11284 of file chan_dahdi.c.
References complete_span_helper().
11285 { 11286 return complete_span_helper(line,word,pos,state,3); 11287 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11289 of file chan_dahdi.c.
References complete_span_helper().
11290 { 11291 return complete_span_helper(line,word,pos,state,4); 11292 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 11265 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
11266 { 11267 int which, span; 11268 char *ret = NULL; 11269 11270 if (pos != rpos) 11271 return ret; 11272 11273 for (which = span = 0; span < NUM_SPANS; span++) { 11274 if (pris[span].pri && ++which > state) { 11275 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 11276 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 11277 } 11278 break; 11279 } 11280 } 11281 return ret; 11282 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 2168 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().
02169 { 02170 /* If the conference already exists, and we're already in it 02171 don't bother doing anything */ 02172 struct dahdi_confinfo zi; 02173 02174 memset(&zi, 0, sizeof(zi)); 02175 zi.chan = 0; 02176 02177 if (slavechannel > 0) { 02178 /* If we have only one slave, do a digital mon */ 02179 zi.confmode = DAHDI_CONF_DIGITALMON; 02180 zi.confno = slavechannel; 02181 } else { 02182 if (!index) { 02183 /* Real-side and pseudo-side both participate in conference */ 02184 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 02185 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02186 } else 02187 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02188 zi.confno = p->confno; 02189 } 02190 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 02191 return 0; 02192 if (c->dfd < 0) 02193 return 0; 02194 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02195 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 02196 return -1; 02197 } 02198 if (slavechannel < 1) { 02199 p->confno = zi.confno; 02200 } 02201 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02202 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02203 return 0; 02204 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 2217 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().
02218 { 02219 struct dahdi_confinfo zi; 02220 if (/* Can't delete if there's no dfd */ 02221 (c->dfd < 0) || 02222 /* Don't delete from the conference if it's not our conference */ 02223 !isourconf(p, c) 02224 /* Don't delete if we don't think it's conferenced at all (implied) */ 02225 ) return 0; 02226 memset(&zi, 0, sizeof(zi)); 02227 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02228 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 02229 return -1; 02230 } 02231 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02232 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02233 return 0; 02234 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3445 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().
03446 { 03447 /* data is whether to accept with charge or no charge */ 03448 openr2_call_mode_t accept_mode; 03449 int res, timeout, maxloops; 03450 struct ast_frame *f; 03451 struct dahdi_pvt *p; 03452 char *parse; 03453 AST_DECLARE_APP_ARGS(args, 03454 AST_APP_ARG(charge); 03455 ); 03456 03457 if (ast_strlen_zero(data)) { 03458 ast_log(LOG_DEBUG, "No data sent to application!\n"); 03459 return -1; 03460 } 03461 03462 if (chan->tech != &dahdi_tech) { 03463 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 03464 return -1; 03465 } 03466 03467 p = (struct dahdi_pvt *)chan->tech_pvt; 03468 if (!p) { 03469 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 03470 return -1; 03471 } 03472 03473 parse = ast_strdupa(data); 03474 AST_STANDARD_APP_ARGS(args, parse); 03475 03476 if (ast_strlen_zero(args.charge)) { 03477 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 03478 return -1; 03479 } 03480 03481 ast_mutex_lock(&p->lock); 03482 if (!p->mfcr2 || !p->mfcr2call) { 03483 ast_mutex_unlock(&p->lock); 03484 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 03485 return -1; 03486 } 03487 03488 if (p->mfcr2_call_accepted) { 03489 ast_mutex_unlock(&p->lock); 03490 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 03491 return 0; 03492 } 03493 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 03494 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 03495 ast_mutex_unlock(&p->lock); 03496 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03497 return -1; 03498 } 03499 ast_mutex_unlock(&p->lock); 03500 03501 res = 0; 03502 timeout = 100; 03503 maxloops = 50; /* wait up to 5 seconds */ 03504 /* we need to read() until the call is accepted */ 03505 while (maxloops > 0) { 03506 maxloops--; 03507 if (ast_check_hangup(chan)) { 03508 break; 03509 } 03510 res = ast_waitfor(chan, timeout); 03511 if (res < 0) { 03512 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 03513 res = -1; 03514 break; 03515 } 03516 if (res == 0) { 03517 continue; 03518 } 03519 f = ast_read(chan); 03520 if (!f) { 03521 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 03522 res = -1; 03523 break; 03524 } 03525 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 03526 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 03527 ast_frfree(f); 03528 res = -1; 03529 break; 03530 } 03531 ast_frfree(f); 03532 ast_mutex_lock(&p->lock); 03533 if (p->mfcr2_call_accepted) { 03534 ast_mutex_unlock(&p->lock); 03535 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 03536 break; 03537 } 03538 ast_mutex_unlock(&p->lock); 03539 } 03540 if (res == -1) { 03541 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03542 } 03543 return res; 03544 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12666 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12667 { 12668 return __action_dialoffhook(s, m, 0); 12669 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12566 of file chan_dahdi.c.
References __action_dnd(), and s.
12567 { 12568 return __action_dnd(s, m, 0, 0); 12569 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12556 of file chan_dahdi.c.
References __action_dnd(), and s.
12557 { 12558 return __action_dnd(s, m, 0, 1); 12559 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12745 of file chan_dahdi.c.
References __action_restart(), and s.
12746 { 12747 return __action_restart(s, m, 0); 12748 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12721 of file chan_dahdi.c.
References __action_showchannels(), and s.
12722 { 12723 return __action_showchannels(s, m, 0); 12724 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12595 of file chan_dahdi.c.
References __action_transfer(), and s.
12596 { 12597 return __action_transfer(s, m, 0); 12598 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12623 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12624 { 12625 return __action_transferhangup(s, m, 0); 12626 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3946 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::channel, 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::proceeding, 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.
03947 { 03948 struct dahdi_pvt *p = ast->tech_pvt; 03949 int res = 0; 03950 int index; 03951 int oldstate = ast->_state; 03952 ast_setstate(ast, AST_STATE_UP); 03953 ast_mutex_lock(&p->lock); 03954 index = dahdi_get_index(ast, p, 0); 03955 if (index < 0) 03956 index = SUB_REAL; 03957 /* nothing to do if a radio channel */ 03958 if ((p->radio || (p->oprmode < 0))) { 03959 ast_mutex_unlock(&p->lock); 03960 return 0; 03961 } 03962 switch (p->sig) { 03963 case SIG_FXSLS: 03964 case SIG_FXSGS: 03965 case SIG_FXSKS: 03966 p->ringt = 0; 03967 /* Fall through */ 03968 case SIG_EM: 03969 case SIG_EM_E1: 03970 case SIG_EMWINK: 03971 case SIG_FEATD: 03972 case SIG_FEATDMF: 03973 case SIG_FEATDMF_TA: 03974 case SIG_E911: 03975 case SIG_FGC_CAMA: 03976 case SIG_FGC_CAMAMF: 03977 case SIG_FEATB: 03978 case SIG_SF: 03979 case SIG_SFWINK: 03980 case SIG_SF_FEATD: 03981 case SIG_SF_FEATDMF: 03982 case SIG_SF_FEATB: 03983 case SIG_FXOLS: 03984 case SIG_FXOGS: 03985 case SIG_FXOKS: 03986 /* Pick up the line */ 03987 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03988 if (p->hanguponpolarityswitch) { 03989 gettimeofday(&p->polaritydelaytv, NULL); 03990 } 03991 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03992 tone_zone_play_tone(p->subs[index].dfd, -1); 03993 p->dialing = 0; 03994 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03995 if (oldstate == AST_STATE_RINGING) { 03996 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03997 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03998 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03999 p->owner = p->subs[SUB_REAL].owner; 04000 } 04001 } 04002 if (p->sig & __DAHDI_SIG_FXS) { 04003 dahdi_enable_ec(p); 04004 dahdi_train_ec(p); 04005 } 04006 break; 04007 #ifdef HAVE_PRI 04008 case SIG_PRI: 04009 /* Send a pri acknowledge */ 04010 if (!pri_grab(p, p->pri)) { 04011 p->proceeding = 1; 04012 p->dialing = 0; 04013 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04014 pri_rel(p->pri); 04015 } else { 04016 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04017 res = -1; 04018 } 04019 break; 04020 #endif 04021 #ifdef HAVE_OPENR2 04022 case SIG_MFCR2: 04023 if (!p->mfcr2_accept_on_offer) { 04024 /* the call was not accepted on offer, so it must be accepted now before answering, 04025 the answer will be executed when the callback on_call_accepted is executed */ 04026 if (p->mfcr2_charge_calls) { 04027 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel); 04028 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04029 } else { 04030 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel); 04031 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04032 } 04033 } else { 04034 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04035 res = dahdi_r2_answer(p); 04036 } 04037 break; 04038 #endif 04039 case 0: 04040 ast_mutex_unlock(&p->lock); 04041 return 0; 04042 default: 04043 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04044 res = -1; 04045 } 04046 ast_mutex_unlock(&p->lock); 04047 return res; 04048 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 3551 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().
03552 { 03553 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 03554 switch (cause) { 03555 case AST_CAUSE_USER_BUSY: 03556 case AST_CAUSE_CALL_REJECTED: 03557 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 03558 r2cause = OR2_CAUSE_BUSY_NUMBER; 03559 break; 03560 03561 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 03562 case AST_CAUSE_SWITCH_CONGESTION: 03563 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 03564 break; 03565 03566 case AST_CAUSE_UNALLOCATED: 03567 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 03568 break; 03569 03570 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 03571 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 03572 r2cause = OR2_CAUSE_OUT_OF_ORDER; 03573 break; 03574 03575 case AST_CAUSE_NO_ANSWER: 03576 case AST_CAUSE_NO_USER_RESPONSE: 03577 r2cause = OR2_CAUSE_NO_ANSWER; 03578 break; 03579 03580 default: 03581 r2cause = OR2_CAUSE_NORMAL_CLEARING; 03582 break; 03583 } 03584 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 03585 r2cause, openr2_proto_get_disconnect_string(r2cause), cause); 03586 return r2cause; 03587 }
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 4373 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::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_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, ast_channel::name, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.
04374 { 04375 struct ast_channel *who; 04376 struct dahdi_pvt *p0, *p1, *op0, *op1; 04377 struct dahdi_pvt *master = NULL, *slave = NULL; 04378 struct ast_frame *f; 04379 int inconf = 0; 04380 int nothingok = 1; 04381 int ofd0, ofd1; 04382 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04383 int os0 = -1, os1 = -1; 04384 int priority = 0; 04385 struct ast_channel *oc0, *oc1; 04386 enum ast_bridge_result res; 04387 04388 #ifdef PRI_2BCT 04389 int triedtopribridge = 0; 04390 q931_call *q931c0 = NULL, *q931c1 = NULL; 04391 #endif 04392 04393 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04394 There is code below to handle it properly until DTMF is actually seen, 04395 but due to currently unresolved issues it's ignored... 04396 */ 04397 04398 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04399 return AST_BRIDGE_FAILED_NOWARN; 04400 04401 ast_mutex_lock(&c0->lock); 04402 while (ast_mutex_trylock(&c1->lock)) { 04403 DEADLOCK_AVOIDANCE(&c0->lock); 04404 } 04405 04406 p0 = c0->tech_pvt; 04407 p1 = c1->tech_pvt; 04408 /* cant do pseudo-channels here */ 04409 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04410 ast_mutex_unlock(&c0->lock); 04411 ast_mutex_unlock(&c1->lock); 04412 return AST_BRIDGE_FAILED_NOWARN; 04413 } 04414 04415 oi0 = dahdi_get_index(c0, p0, 0); 04416 oi1 = dahdi_get_index(c1, p1, 0); 04417 if ((oi0 < 0) || (oi1 < 0)) { 04418 ast_mutex_unlock(&c0->lock); 04419 ast_mutex_unlock(&c1->lock); 04420 return AST_BRIDGE_FAILED; 04421 } 04422 04423 op0 = p0 = c0->tech_pvt; 04424 op1 = p1 = c1->tech_pvt; 04425 ofd0 = c0->fds[0]; 04426 ofd1 = c1->fds[0]; 04427 oc0 = p0->owner; 04428 oc1 = p1->owner; 04429 04430 if (ast_mutex_trylock(&p0->lock)) { 04431 /* Don't block, due to potential for deadlock */ 04432 ast_mutex_unlock(&c0->lock); 04433 ast_mutex_unlock(&c1->lock); 04434 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04435 return AST_BRIDGE_RETRY; 04436 } 04437 if (ast_mutex_trylock(&p1->lock)) { 04438 /* Don't block, due to potential for deadlock */ 04439 ast_mutex_unlock(&p0->lock); 04440 ast_mutex_unlock(&c0->lock); 04441 ast_mutex_unlock(&c1->lock); 04442 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04443 return AST_BRIDGE_RETRY; 04444 } 04445 04446 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04447 if (p0->owner && p1->owner) { 04448 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04449 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04450 master = p0; 04451 slave = p1; 04452 inconf = 1; 04453 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04454 master = p1; 04455 slave = p0; 04456 inconf = 1; 04457 } else { 04458 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04459 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04460 p0->channel, 04461 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04462 p0->subs[SUB_REAL].inthreeway, p0->channel, 04463 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04464 p1->subs[SUB_REAL].inthreeway); 04465 } 04466 nothingok = 0; 04467 } 04468 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04469 if (p1->subs[SUB_THREEWAY].inthreeway) { 04470 master = p1; 04471 slave = p0; 04472 nothingok = 0; 04473 } 04474 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04475 if (p0->subs[SUB_THREEWAY].inthreeway) { 04476 master = p0; 04477 slave = p1; 04478 nothingok = 0; 04479 } 04480 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04481 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04482 don't put us in anything */ 04483 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04484 master = p1; 04485 slave = p0; 04486 nothingok = 0; 04487 } 04488 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04489 /* Same as previous */ 04490 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04491 master = p0; 04492 slave = p1; 04493 nothingok = 0; 04494 } 04495 } 04496 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 04497 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04498 if (master && slave) { 04499 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04500 in an active threeway call with a channel that is ringing, we should 04501 indicate ringing. */ 04502 if ((oi1 == SUB_THREEWAY) && 04503 p1->subs[SUB_THREEWAY].inthreeway && 04504 p1->subs[SUB_REAL].owner && 04505 p1->subs[SUB_REAL].inthreeway && 04506 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04507 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04508 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04509 os1 = p1->subs[SUB_REAL].owner->_state; 04510 } else { 04511 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04512 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04513 } 04514 if ((oi0 == SUB_THREEWAY) && 04515 p0->subs[SUB_THREEWAY].inthreeway && 04516 p0->subs[SUB_REAL].owner && 04517 p0->subs[SUB_REAL].inthreeway && 04518 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04519 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04520 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04521 os0 = p0->subs[SUB_REAL].owner->_state; 04522 } else { 04523 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04524 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04525 } 04526 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04527 if (!p0->echocanbridged || !p1->echocanbridged) { 04528 /* Disable echo cancellation if appropriate */ 04529 dahdi_disable_ec(p0); 04530 dahdi_disable_ec(p1); 04531 } 04532 } 04533 dahdi_link(slave, master); 04534 master->inconference = inconf; 04535 } else if (!nothingok) 04536 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04537 04538 update_conf(p0); 04539 update_conf(p1); 04540 t0 = p0->subs[SUB_REAL].inthreeway; 04541 t1 = p1->subs[SUB_REAL].inthreeway; 04542 04543 ast_mutex_unlock(&p0->lock); 04544 ast_mutex_unlock(&p1->lock); 04545 04546 ast_mutex_unlock(&c0->lock); 04547 ast_mutex_unlock(&c1->lock); 04548 04549 /* Native bridge failed */ 04550 if ((!master || !slave) && !nothingok) { 04551 dahdi_enable_ec(p0); 04552 dahdi_enable_ec(p1); 04553 return AST_BRIDGE_FAILED; 04554 } 04555 04556 if (option_verbose > 2) 04557 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 04558 04559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04560 disable_dtmf_detect(op0); 04561 04562 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04563 disable_dtmf_detect(op1); 04564 04565 for (;;) { 04566 struct ast_channel *c0_priority[2] = {c0, c1}; 04567 struct ast_channel *c1_priority[2] = {c1, c0}; 04568 04569 /* Here's our main loop... Start by locking things, looking for private parts, 04570 and then balking if anything is wrong */ 04571 ast_mutex_lock(&c0->lock); 04572 while (ast_mutex_trylock(&c1->lock)) { 04573 DEADLOCK_AVOIDANCE(&c0->lock); 04574 } 04575 04576 p0 = c0->tech_pvt; 04577 p1 = c1->tech_pvt; 04578 04579 if (op0 == p0) 04580 i0 = dahdi_get_index(c0, p0, 1); 04581 if (op1 == p1) 04582 i1 = dahdi_get_index(c1, p1, 1); 04583 ast_mutex_unlock(&c0->lock); 04584 ast_mutex_unlock(&c1->lock); 04585 04586 if (!timeoutms || 04587 (op0 != p0) || 04588 (op1 != p1) || 04589 (ofd0 != c0->fds[0]) || 04590 (ofd1 != c1->fds[0]) || 04591 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04592 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04593 (oc0 != p0->owner) || 04594 (oc1 != p1->owner) || 04595 (t0 != p0->subs[SUB_REAL].inthreeway) || 04596 (t1 != p1->subs[SUB_REAL].inthreeway) || 04597 (oi0 != i0) || 04598 (oi1 != i1)) { 04599 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04600 op0->channel, oi0, op1->channel, oi1); 04601 res = AST_BRIDGE_RETRY; 04602 goto return_from_bridge; 04603 } 04604 04605 #ifdef PRI_2BCT 04606 q931c0 = p0->call; 04607 q931c1 = p1->call; 04608 if (p0->transfer && p1->transfer 04609 && q931c0 && q931c1 04610 && !triedtopribridge) { 04611 pri_channel_bridge(q931c0, q931c1); 04612 triedtopribridge = 1; 04613 } 04614 #endif 04615 04616 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04617 if (!who) { 04618 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 04619 continue; 04620 } 04621 f = ast_read(who); 04622 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04623 *fo = f; 04624 *rc = who; 04625 res = AST_BRIDGE_COMPLETE; 04626 goto return_from_bridge; 04627 } 04628 if (f->frametype == AST_FRAME_DTMF) { 04629 if ((who == c0) && p0->pulsedial) { 04630 ast_write(c1, f); 04631 } else if ((who == c1) && p1->pulsedial) { 04632 ast_write(c0, f); 04633 } else { 04634 *fo = f; 04635 *rc = who; 04636 res = AST_BRIDGE_COMPLETE; 04637 goto return_from_bridge; 04638 } 04639 } 04640 ast_frfree(f); 04641 04642 /* Swap who gets priority */ 04643 priority = !priority; 04644 } 04645 04646 return_from_bridge: 04647 if (op0 == p0) 04648 dahdi_enable_ec(p0); 04649 04650 if (op1 == p1) 04651 dahdi_enable_ec(p1); 04652 04653 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04654 enable_dtmf_detect(op0); 04655 04656 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04657 enable_dtmf_detect(op1); 04658 04659 dahdi_unlink(slave, master, 1); 04660 04661 return res; 04662 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2714 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, dahdi_pvt::call, 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, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_r2_get_channel_category(), 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, 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.
02715 { 02716 struct dahdi_pvt *p = ast->tech_pvt; 02717 int x, res, index,mysig; 02718 char *c, *n, *l; 02719 #ifdef HAVE_PRI 02720 char *s = NULL; 02721 #endif 02722 char dest[256]; /* must be same length as p->dialdest */ 02723 ast_mutex_lock(&p->lock); 02724 ast_copy_string(dest, rdest, sizeof(dest)); 02725 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02726 if ((ast->_state == AST_STATE_BUSY)) { 02727 p->subs[SUB_REAL].needbusy = 1; 02728 ast_mutex_unlock(&p->lock); 02729 return 0; 02730 } 02731 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02732 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02733 ast_mutex_unlock(&p->lock); 02734 return -1; 02735 } 02736 p->dialednone = 0; 02737 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02738 { 02739 /* Special pseudo -- automatically up */ 02740 ast_setstate(ast, AST_STATE_UP); 02741 ast_mutex_unlock(&p->lock); 02742 return 0; 02743 } 02744 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02745 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02746 if (res) 02747 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02748 p->outgoing = 1; 02749 02750 if (IS_DIGITAL(ast->transfercapability)) { 02751 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02752 } else { 02753 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02754 } 02755 02756 mysig = p->sig; 02757 if (p->outsigmod > -1) 02758 mysig = p->outsigmod; 02759 02760 switch (mysig) { 02761 case SIG_FXOLS: 02762 case SIG_FXOGS: 02763 case SIG_FXOKS: 02764 if (p->owner == ast) { 02765 /* Normal ring, on hook */ 02766 02767 /* Don't send audio while on hook, until the call is answered */ 02768 p->dialing = 1; 02769 if (p->use_callerid) { 02770 /* Generate the Caller-ID spill if desired */ 02771 if (p->cidspill) { 02772 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02773 free(p->cidspill); 02774 } 02775 p->callwaitcas = 0; 02776 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02777 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02778 p->cidpos = 0; 02779 send_callerid(p); 02780 } 02781 } 02782 /* Choose proper cadence */ 02783 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02784 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02785 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02786 p->cidrings = cidrings[p->distinctivering - 1]; 02787 } else { 02788 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02789 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02790 p->cidrings = p->sendcalleridafter; 02791 } 02792 02793 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02794 c = strchr(dest, '/'); 02795 if (c) 02796 c++; 02797 if (c && (strlen(c) < p->stripmsd)) { 02798 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02799 c = NULL; 02800 } 02801 if (c) { 02802 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02803 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02804 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02805 } else { 02806 p->dop.dialstr[0] = '\0'; 02807 } 02808 x = DAHDI_RING; 02809 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02810 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02811 ast_mutex_unlock(&p->lock); 02812 return -1; 02813 } 02814 p->dialing = 1; 02815 } else { 02816 /* Call waiting call */ 02817 p->callwaitrings = 0; 02818 if (ast->cid.cid_num) 02819 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02820 else 02821 p->callwait_num[0] = '\0'; 02822 if (ast->cid.cid_name) 02823 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02824 else 02825 p->callwait_name[0] = '\0'; 02826 /* Call waiting tone instead */ 02827 if (dahdi_callwait(ast)) { 02828 ast_mutex_unlock(&p->lock); 02829 return -1; 02830 } 02831 /* Make ring-back */ 02832 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02833 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02834 02835 } 02836 n = ast->cid.cid_name; 02837 l = ast->cid.cid_num; 02838 if (l) 02839 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02840 else 02841 p->lastcid_num[0] = '\0'; 02842 if (n) 02843 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02844 else 02845 p->lastcid_name[0] = '\0'; 02846 ast_setstate(ast, AST_STATE_RINGING); 02847 index = dahdi_get_index(ast, p, 0); 02848 if (index > -1) { 02849 p->subs[index].needringing = 1; 02850 } 02851 break; 02852 case SIG_FXSLS: 02853 case SIG_FXSGS: 02854 case SIG_FXSKS: 02855 case SIG_EMWINK: 02856 case SIG_EM: 02857 case SIG_EM_E1: 02858 case SIG_FEATD: 02859 case SIG_FEATDMF: 02860 case SIG_E911: 02861 case SIG_FGC_CAMA: 02862 case SIG_FGC_CAMAMF: 02863 case SIG_FEATB: 02864 case SIG_SFWINK: 02865 case SIG_SF: 02866 case SIG_SF_FEATD: 02867 case SIG_SF_FEATDMF: 02868 case SIG_FEATDMF_TA: 02869 case SIG_SF_FEATB: 02870 c = strchr(dest, '/'); 02871 if (c) 02872 c++; 02873 else 02874 c = ""; 02875 if (strlen(c) < p->stripmsd) { 02876 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02877 ast_mutex_unlock(&p->lock); 02878 return -1; 02879 } 02880 #ifdef HAVE_PRI 02881 /* Start the trunk, if not GR-303 */ 02882 if (!p->pri) { 02883 #endif 02884 x = DAHDI_START; 02885 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02886 if (res < 0) { 02887 if (errno != EINPROGRESS) { 02888 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02889 ast_mutex_unlock(&p->lock); 02890 return -1; 02891 } 02892 } 02893 #ifdef HAVE_PRI 02894 } 02895 #endif 02896 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02897 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02898 02899 c += p->stripmsd; 02900 02901 switch (mysig) { 02902 case SIG_FEATD: 02903 l = ast->cid.cid_num; 02904 if (l) 02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02906 else 02907 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02908 break; 02909 case SIG_FEATDMF: 02910 l = ast->cid.cid_num; 02911 if (l) 02912 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02913 else 02914 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02915 break; 02916 case SIG_FEATDMF_TA: 02917 { 02918 const char *cic, *ozz; 02919 02920 /* If you have to go through a Tandem Access point you need to use this */ 02921 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02922 if (!ozz) 02923 ozz = defaultozz; 02924 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02925 if (!cic) 02926 cic = defaultcic; 02927 if (!ozz || !cic) { 02928 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02929 ast_mutex_unlock(&p->lock); 02930 return -1; 02931 } 02932 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02933 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02934 p->whichwink = 0; 02935 } 02936 break; 02937 case SIG_E911: 02938 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02939 break; 02940 case SIG_FGC_CAMA: 02941 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02942 break; 02943 case SIG_FGC_CAMAMF: 02944 case SIG_FEATB: 02945 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02946 break; 02947 default: 02948 if (p->pulse) 02949 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02950 else 02951 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02952 break; 02953 } 02954 02955 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02956 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02957 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02958 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02959 p->echobreak = 1; 02960 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02961 } else 02962 p->echobreak = 0; 02963 if (!res) { 02964 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02965 int saveerr = errno; 02966 02967 x = DAHDI_ONHOOK; 02968 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02969 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02970 ast_mutex_unlock(&p->lock); 02971 return -1; 02972 } 02973 } else 02974 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res); 02975 p->dialing = 1; 02976 if (ast_strlen_zero(c)) 02977 p->dialednone = 1; 02978 ast_setstate(ast, AST_STATE_DIALING); 02979 break; 02980 case 0: 02981 /* Special pseudo -- automatically up*/ 02982 ast_setstate(ast, AST_STATE_UP); 02983 break; 02984 case SIG_PRI: 02985 case SIG_MFCR2: 02986 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02987 p->dialdest[0] = '\0'; 02988 p->dialing = 1; 02989 break; 02990 default: 02991 ast_log(LOG_DEBUG, "not yet implemented\n"); 02992 ast_mutex_unlock(&p->lock); 02993 return -1; 02994 } 02995 #ifdef HAVE_OPENR2 02996 if (p->mfcr2) { 02997 int strip = p->stripmsd; 02998 int callres = 0; 02999 c = strchr(dest, '/'); 03000 if (c) { 03001 c++; 03002 } else { 03003 c = dest; 03004 } 03005 if (!p->hidecallerid) { 03006 l = ast->cid.cid_num; 03007 } else { 03008 l = NULL; 03009 } 03010 if (strlen(c) < strip) { 03011 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip); 03012 strip = 0; 03013 } 03014 p->dialing = 1; 03015 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast)); 03016 if (-1 == callres) { 03017 ast_mutex_unlock(&p->lock); 03018 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03019 return -1; 03020 } 03021 ast_setstate(ast, AST_STATE_DIALING); 03022 } 03023 #endif /* HAVE_OPENR2 */ 03024 #ifdef HAVE_PRI 03025 if (p->pri) { 03026 struct pri_sr *sr; 03027 #ifdef SUPPORT_USERUSER 03028 const char *useruser; 03029 #endif 03030 int pridialplan; 03031 int dp_strip; 03032 int prilocaldialplan; 03033 int ldp_strip; 03034 int exclusive; 03035 const char *rr_str; 03036 int redirect_reason; 03037 03038 c = strchr(dest, '/'); 03039 if (c) { 03040 c++; 03041 } else { 03042 c = ""; 03043 } 03044 03045 l = NULL; 03046 n = NULL; 03047 if (!p->hidecallerid) { 03048 l = ast->cid.cid_num; 03049 if (!p->hidecalleridname) { 03050 n = ast->cid.cid_name; 03051 } 03052 } 03053 03054 03055 if (strlen(c) < p->stripmsd) { 03056 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03057 ast_mutex_unlock(&p->lock); 03058 return -1; 03059 } 03060 if (mysig != SIG_FXSKS) { 03061 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03062 s = strchr(c + p->stripmsd, 'w'); 03063 if (s) { 03064 if (strlen(s) > 1) 03065 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03066 else 03067 p->dop.dialstr[0] = '\0'; 03068 *s = '\0'; 03069 } else { 03070 p->dop.dialstr[0] = '\0'; 03071 } 03072 } 03073 if (pri_grab(p, p->pri)) { 03074 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03075 ast_mutex_unlock(&p->lock); 03076 return -1; 03077 } 03078 if (!(p->call = pri_new_call(p->pri->pri))) { 03079 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03080 pri_rel(p->pri); 03081 ast_mutex_unlock(&p->lock); 03082 return -1; 03083 } 03084 if (!(sr = pri_sr_new())) { 03085 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03086 pri_destroycall(p->pri->pri, p->call); 03087 p->call = NULL; 03088 pri_rel(p->pri); 03089 ast_mutex_unlock(&p->lock); 03090 return -1; 03091 } 03092 if (p->bearer || (mysig == SIG_FXSKS)) { 03093 if (p->bearer) { 03094 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); 03095 p->bearer->call = p->call; 03096 } else 03097 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 03098 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03099 } 03100 p->digital = IS_DIGITAL(ast->transfercapability); 03101 03102 /* Should the picked channel be used exclusively? */ 03103 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03104 exclusive = 1; 03105 } else { 03106 exclusive = 0; 03107 } 03108 03109 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03110 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03111 (p->digital ? -1 : 03112 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03113 if (p->pri->facilityenable) 03114 pri_facility_enable(p->pri->pri); 03115 03116 if (option_verbose > 2) 03117 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03118 dp_strip = 0; 03119 pridialplan = p->pri->dialplan - 1; 03120 if (pridialplan == -2) { /* compute dynamically */ 03121 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03122 dp_strip = strlen(p->pri->internationalprefix); 03123 pridialplan = PRI_INTERNATIONAL_ISDN; 03124 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03125 dp_strip = strlen(p->pri->nationalprefix); 03126 pridialplan = PRI_NATIONAL_ISDN; 03127 } else { 03128 pridialplan = PRI_LOCAL_ISDN; 03129 } 03130 } 03131 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03132 03133 ldp_strip = 0; 03134 prilocaldialplan = p->pri->localdialplan - 1; 03135 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 03136 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03137 ldp_strip = strlen(p->pri->internationalprefix); 03138 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03139 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03140 ldp_strip = strlen(p->pri->nationalprefix); 03141 prilocaldialplan = PRI_NATIONAL_ISDN; 03142 } else { 03143 prilocaldialplan = PRI_LOCAL_ISDN; 03144 } 03145 } 03146 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03147 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03148 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03149 if (!strcasecmp(rr_str, "UNKNOWN")) 03150 redirect_reason = 0; 03151 else if (!strcasecmp(rr_str, "BUSY")) 03152 redirect_reason = 1; 03153 else if (!strcasecmp(rr_str, "NO_REPLY")) 03154 redirect_reason = 2; 03155 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03156 redirect_reason = 15; 03157 else 03158 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03159 } else 03160 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03161 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03162 03163 #ifdef SUPPORT_USERUSER 03164 /* User-user info */ 03165 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03166 03167 if (useruser) 03168 pri_sr_set_useruser(sr, useruser); 03169 #endif 03170 03171 if (pri_setup(p->pri->pri, p->call, sr)) { 03172 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03173 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03174 pri_rel(p->pri); 03175 ast_mutex_unlock(&p->lock); 03176 pri_sr_free(sr); 03177 return -1; 03178 } 03179 pri_sr_free(sr); 03180 ast_setstate(ast, AST_STATE_DIALING); 03181 pri_rel(p->pri); 03182 } 03183 #endif 03184 ast_mutex_unlock(&p->lock); 03185 return 0; 03186 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2686 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(), and dahdi_read().
02687 { 02688 struct dahdi_pvt *p = ast->tech_pvt; 02689 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02690 if (p->cidspill) { 02691 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02692 free(p->cidspill); 02693 } 02694 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02695 return -1; 02696 save_conference(p); 02697 /* Silence */ 02698 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02699 if (!p->callwaitrings && p->callwaitingcallerid) { 02700 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02701 p->callwaitcas = 1; 02702 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02703 } else { 02704 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02705 p->callwaitcas = 0; 02706 p->cidlen = 2400 + READ_SIZE * 4; 02707 } 02708 p->cidpos = 0; 02709 send_callerid(p); 02710 02711 return 0; 02712 }
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 997 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().
00997 { 00998 /* recall that if a field is not included here it is initialized 00999 * to 0 or equivalent 01000 */ 01001 struct dahdi_chan_conf conf = { 01002 #ifdef HAVE_PRI 01003 .pri = { 01004 .nsf = PRI_NSF_NONE, 01005 .switchtype = PRI_SWITCH_NI2, 01006 .dialplan = PRI_NATIONAL_ISDN + 1, 01007 .localdialplan = PRI_NATIONAL_ISDN + 1, 01008 .nodetype = PRI_CPE, 01009 01010 .minunused = 2, 01011 .idleext = "", 01012 .idledial = "", 01013 .internationalprefix = "", 01014 .nationalprefix = "", 01015 .localprefix = "", 01016 .privateprefix = "", 01017 .unknownprefix = "", 01018 01019 .resetinterval = 3600 01020 }, 01021 #endif 01022 .chan = { 01023 .context = "default", 01024 .cid_num = "", 01025 .cid_name = "", 01026 .mohinterpret = "default", 01027 .mohsuggest = "", 01028 .transfertobusy = 1, 01029 01030 .cid_signalling = CID_SIG_BELL, 01031 .cid_start = CID_START_RING, 01032 .dahditrcallerid = 0, 01033 .use_callerid = 1, 01034 .sig = -1, 01035 .outsigmod = -1, 01036 01037 .tonezone = -1, 01038 01039 .echocancel = 1, 01040 01041 .busycount = 3, 01042 .busycompare = 0, 01043 .busytonelength = 0, 01044 .busyquietlength = 0, 01045 .busyfuzziness = 0, 01046 .silencethreshold = 0, 01047 01048 .accountcode = "", 01049 01050 .mailbox = "", 01051 01052 01053 .polarityonanswerdelay = 600, 01054 01055 .sendcalleridafter = DEFAULT_CIDRINGS, 01056 01057 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01058 .buf_no = numbufs 01059 }, 01060 .timing = { 01061 .prewinktime = -1, 01062 .preflashtime = -1, 01063 .winktime = -1, 01064 .flashtime = -1, 01065 .starttime = -1, 01066 .rxwinktime = -1, 01067 .rxflashtime = -1, 01068 .debouncetime = -1 01069 }, 01070 .smdi_port = "/dev/ttyS0", 01071 }; 01072 01073 return conf; 01074 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1847 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 1860 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01861 { 01862 dahdi_close(pri->fds[fd_num]); 01863 pri->fds[fd_num] = -1; 01864 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1853 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().
01854 { 01855 dahdi_close(chan_pvt->subs[sub_num].dfd); 01856 chan_pvt->subs[sub_num].dfd = -1; 01857 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2570 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_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().
02571 { 02572 int x, y, res; 02573 x = muted; 02574 if (p->sig == SIG_PRI) { 02575 y = 1; 02576 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02577 if (res) 02578 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02579 } 02580 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02581 if (res < 0) 02582 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02583 return res; 02584 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11921 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
11922 { 11923 int channel; 11924 11925 if (argc != 4) 11926 return RESULT_SHOWUSAGE; 11927 11928 channel = atoi(argv[3]); 11929 11930 return dahdi_destroy_channel_bynum(channel); 11931 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7932 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().
07933 { 07934 struct dahdi_pvt *tmp = NULL; 07935 struct dahdi_pvt *prev = NULL; 07936 07937 ast_mutex_lock(&iflock); 07938 tmp = iflist; 07939 while (tmp) { 07940 if (tmp->channel == channel) { 07941 int x = DAHDI_FLASH; 07942 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 */ 07943 destroy_channel(prev, tmp, 1); 07944 ast_mutex_unlock(&iflock); 07945 ast_module_unref(ast_module_info->self); 07946 return RESULT_SUCCESS; 07947 } 07948 prev = tmp; 07949 tmp = tmp->next; 07950 } 07951 ast_mutex_unlock(&iflock); 07952 return RESULT_FAILURE; 07953 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1944 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_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulse, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01945 { 01946 struct dahdi_pvt *pvt; 01947 int index; 01948 int dtmf = -1; 01949 01950 pvt = chan->tech_pvt; 01951 01952 ast_mutex_lock(&pvt->lock); 01953 01954 index = dahdi_get_index(chan, pvt, 0); 01955 01956 if ((index != SUB_REAL) || !pvt->owner) 01957 goto out; 01958 01959 #ifdef HAVE_PRI 01960 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01961 if (pvt->setup_ack) { 01962 if (!pri_grab(pvt, pvt->pri)) { 01963 pri_information(pvt->pri->pri, pvt->call, digit); 01964 pri_rel(pvt->pri); 01965 } else 01966 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01967 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01968 int res; 01969 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01970 res = strlen(pvt->dialdest); 01971 pvt->dialdest[res++] = digit; 01972 pvt->dialdest[res] = '\0'; 01973 } 01974 goto out; 01975 } 01976 #endif 01977 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01978 goto out; 01979 01980 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01981 int res; 01982 struct dahdi_dialoperation zo = { 01983 .op = DAHDI_DIAL_OP_APPEND, 01984 .dialstr[0] = 'T', 01985 .dialstr[1] = digit, 01986 .dialstr[2] = 0, 01987 }; 01988 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01989 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01990 else 01991 pvt->dialing = 1; 01992 } else { 01993 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01994 pvt->dialing = 1; 01995 pvt->begindigit = digit; 01996 } 01997 01998 out: 01999 ast_mutex_unlock(&pvt->lock); 02000 02001 return 0; 02002 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2004 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.
02005 { 02006 struct dahdi_pvt *pvt; 02007 int res = 0; 02008 int index; 02009 int x; 02010 02011 pvt = chan->tech_pvt; 02012 02013 ast_mutex_lock(&pvt->lock); 02014 02015 index = dahdi_get_index(chan, pvt, 0); 02016 02017 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 02018 goto out; 02019 02020 #ifdef HAVE_PRI 02021 /* This means that the digit was already sent via PRI signalling */ 02022 if (pvt->sig == SIG_PRI && !pvt->begindigit) 02023 goto out; 02024 #endif 02025 02026 if (pvt->begindigit) { 02027 x = -1; 02028 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 02029 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 02030 pvt->dialing = 0; 02031 pvt->begindigit = 0; 02032 } 02033 02034 out: 02035 ast_mutex_unlock(&pvt->lock); 02036 02037 return res; 02038 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2401 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().
02402 { 02403 int x; 02404 int res; 02405 if (p->echocancel) { 02406 x = 0; 02407 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02408 if (res) 02409 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02410 else if (option_debug) 02411 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 02412 } 02413 p->echocanon = 0; 02414 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2351 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().
02352 { 02353 int x; 02354 int res; 02355 if (!p) 02356 return; 02357 if (p->echocanon) { 02358 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 02359 return; 02360 } 02361 if (p->digital) { 02362 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 02363 return; 02364 } 02365 if (p->echocancel) { 02366 if (p->sig == SIG_PRI) { 02367 x = 1; 02368 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02369 if (res) 02370 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02371 } 02372 x = p->echocancel; 02373 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02374 if (res) 02375 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02376 else { 02377 p->echocanon = 1; 02378 if (option_debug) 02379 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 02380 } 02381 } else if (option_debug) 02382 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 02383 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5899 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05900 { 05901 struct dahdi_pvt *p = ast->tech_pvt; 05902 struct ast_frame *f; 05903 ast_mutex_lock(&p->lock); 05904 f = __dahdi_exception(ast); 05905 ast_mutex_unlock(&p->lock); 05906 return f; 05907 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 12501 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().
12502 { 12503 if (p) { 12504 switch (mode) { 12505 case TRANSFER: 12506 p->fake_event = DAHDI_EVENT_WINKFLASH; 12507 break; 12508 case HANGUP: 12509 p->fake_event = DAHDI_EVENT_ONHOOK; 12510 break; 12511 default: 12512 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 12513 } 12514 } 12515 return 0; 12516 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4664 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.
04665 { 04666 struct dahdi_pvt *p = newchan->tech_pvt; 04667 int x; 04668 ast_mutex_lock(&p->lock); 04669 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 04670 if (p->owner == oldchan) { 04671 p->owner = newchan; 04672 } 04673 for (x = 0; x < 3; x++) 04674 if (p->subs[x].owner == oldchan) { 04675 if (!x) 04676 dahdi_unlink(NULL, p, 0); 04677 p->subs[x].owner = newchan; 04678 } 04679 if (newchan->_state == AST_STATE_RINGING) 04680 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04681 update_conf(p); 04682 ast_mutex_unlock(&p->lock); 04683 return 0; 04684 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4236 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.
04237 { 04238 struct dahdi_pvt *p = chan->tech_pvt; 04239 04240 if (!strcasecmp(data, "rxgain")) { 04241 ast_mutex_lock(&p->lock); 04242 snprintf(buf, len, "%f", p->rxgain); 04243 ast_mutex_unlock(&p->lock); 04244 } else if (!strcasecmp(data, "txgain")) { 04245 ast_mutex_lock(&p->lock); 04246 snprintf(buf, len, "%f", p->txgain); 04247 ast_mutex_unlock(&p->lock); 04248 } else { 04249 ast_copy_string(buf, "", len); 04250 } 04251 return 0; 04252 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 272 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00273 { 00274 int j; 00275 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00276 return -1; 00277 return j; 00278 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1190 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
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().
01191 { 01192 int res; 01193 if (p->subs[SUB_REAL].owner == ast) 01194 res = 0; 01195 else if (p->subs[SUB_CALLWAIT].owner == ast) 01196 res = 1; 01197 else if (p->subs[SUB_THREEWAY].owner == ast) 01198 res = 2; 01199 else { 01200 res = -1; 01201 if (!nullok) 01202 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01203 } 01204 return res; 01205 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4826 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_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(), and dahdi_read().
04827 { 04828 struct dahdi_pvt *p = ast->tech_pvt; 04829 struct ast_frame *f = *dest; 04830 04831 if (option_debug) 04832 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04833 04834 if (p->confirmanswer) { 04835 if (option_debug) 04836 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04837 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04838 of a DTMF digit */ 04839 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04840 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04841 *dest = &p->subs[index].f; 04842 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04843 p->confirmanswer = 0; 04844 } else if (p->callwaitcas) { 04845 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04846 if (option_debug) 04847 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04848 if (p->cidspill) 04849 free(p->cidspill); 04850 send_cwcidspill(p); 04851 } 04852 if ((f->subclass != 'm') && (f->subclass != 'u')) 04853 p->callwaitcas = 0; 04854 p->subs[index].f.frametype = AST_FRAME_NULL; 04855 p->subs[index].f.subclass = 0; 04856 *dest = &p->subs[index].f; 04857 } else if (f->subclass == 'f') { 04858 /* Fax tone -- Handle and return NULL */ 04859 if ((p->callprogress & 0x6) && !p->faxhandled) { 04860 p->faxhandled = 1; 04861 if (strcmp(ast->exten, "fax")) { 04862 const char *target_context = S_OR(ast->macrocontext, ast->context); 04863 04864 /* We need to unlock 'ast' here because ast_exists_extension has the 04865 * potential to start autoservice on the channel. Such action is prone 04866 * to deadlock. 04867 */ 04868 ast_mutex_unlock(&p->lock); 04869 ast_channel_unlock(ast); 04870 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04871 ast_channel_lock(ast); 04872 ast_mutex_lock(&p->lock); 04873 if (option_verbose > 2) 04874 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04875 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04876 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04877 if (ast_async_goto(ast, target_context, "fax", 1)) 04878 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04879 } else { 04880 ast_channel_lock(ast); 04881 ast_mutex_lock(&p->lock); 04882 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04883 } 04884 } else if (option_debug) 04885 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04886 } else if (option_debug) 04887 ast_log(LOG_DEBUG, "Fax already handled\n"); 04888 dahdi_confmute(p, 0); 04889 p->subs[index].f.frametype = AST_FRAME_NULL; 04890 p->subs[index].f.subclass = 0; 04891 *dest = &p->subs[index].f; 04892 } else if (f->subclass == 'm') { 04893 /* Confmute request */ 04894 dahdi_confmute(p, 1); 04895 p->subs[index].f.frametype = AST_FRAME_NULL; 04896 p->subs[index].f.subclass = 0; 04897 *dest = &p->subs[index].f; 04898 } else if (f->subclass == 'u') { 04899 /* Unmute */ 04900 dahdi_confmute(p, 0); 04901 p->subs[index].f.frametype = AST_FRAME_NULL; 04902 p->subs[index].f.subclass = 0; 04903 *dest = &p->subs[index].f; 04904 } else 04905 dahdi_confmute(p, 0); 04906 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4928 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_lock(), ast_mutex_trylock(), ast_mutex_unlock(), 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::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_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, 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, dahdi_pvt::lock, LOG_DEBUG, 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::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::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, 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().
04929 { 04930 int res, x; 04931 int index, mysig; 04932 char *c; 04933 struct dahdi_pvt *p = ast->tech_pvt; 04934 pthread_t threadid; 04935 pthread_attr_t attr; 04936 struct ast_channel *chan; 04937 struct ast_frame *f; 04938 04939 index = dahdi_get_index(ast, p, 0); 04940 mysig = p->sig; 04941 if (p->outsigmod > -1) 04942 mysig = p->outsigmod; 04943 p->subs[index].f.frametype = AST_FRAME_NULL; 04944 p->subs[index].f.subclass = 0; 04945 p->subs[index].f.datalen = 0; 04946 p->subs[index].f.samples = 0; 04947 p->subs[index].f.mallocd = 0; 04948 p->subs[index].f.offset = 0; 04949 p->subs[index].f.src = "dahdi_handle_event"; 04950 p->subs[index].f.data = NULL; 04951 f = &p->subs[index].f; 04952 04953 if (index < 0) 04954 return &p->subs[index].f; 04955 if (p->fake_event) { 04956 res = p->fake_event; 04957 p->fake_event = 0; 04958 } else 04959 res = dahdi_get_event(p->subs[index].dfd); 04960 04961 if (option_debug) 04962 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04963 04964 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04965 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04966 04967 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04968 #ifdef HAVE_PRI 04969 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04970 /* absorb event */ 04971 } else { 04972 #endif 04973 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04974 p->subs[index].f.subclass = res & 0xff; 04975 #ifdef HAVE_PRI 04976 } 04977 #endif 04978 dahdi_handle_dtmfup(ast, index, &f); 04979 return f; 04980 } 04981 04982 if (res & DAHDI_EVENT_DTMFDOWN) { 04983 if (option_debug) 04984 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04985 /* Mute conference */ 04986 dahdi_confmute(p, 1); 04987 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04988 p->subs[index].f.subclass = res & 0xff; 04989 return &p->subs[index].f; 04990 } 04991 04992 switch (res) { 04993 #ifdef DAHDI_EVENT_EC_DISABLED 04994 case DAHDI_EVENT_EC_DISABLED: 04995 if (option_verbose > 2) 04996 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04997 p->echocanon = 0; 04998 break; 04999 #endif 05000 case DAHDI_EVENT_BITSCHANGED: 05001 #ifdef HAVE_OPENR2 05002 if (p->sig != SIG_MFCR2) { 05003 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05004 } else { 05005 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 05006 openr2_chan_handle_cas(p->r2chan); 05007 } 05008 #else 05009 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05010 #endif 05011 case DAHDI_EVENT_PULSE_START: 05012 /* Stop tone if there's a pulse start and the PBX isn't started */ 05013 if (!ast->pbx) 05014 tone_zone_play_tone(p->subs[index].dfd, -1); 05015 break; 05016 case DAHDI_EVENT_DIALCOMPLETE: 05017 #ifdef HAVE_OPENR2 05018 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05019 /* we don't need to do anything for this event for R2 signaling 05020 if the call is being setup */ 05021 break; 05022 } 05023 #endif 05024 if (p->inalarm) break; 05025 if ((p->radio || (p->oprmode < 0))) break; 05026 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 05027 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05028 return NULL; 05029 } 05030 if (!x) { /* if not still dialing in driver */ 05031 dahdi_enable_ec(p); 05032 if (p->echobreak) { 05033 dahdi_train_ec(p); 05034 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05035 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05037 p->echobreak = 0; 05038 } else { 05039 p->dialing = 0; 05040 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05041 /* if thru with dialing after offhook */ 05042 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05043 ast_setstate(ast, AST_STATE_UP); 05044 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05045 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05046 break; 05047 } else { /* if to state wait for offhook to dial rest */ 05048 /* we now wait for off hook */ 05049 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05050 } 05051 } 05052 if (ast->_state == AST_STATE_DIALING) { 05053 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05054 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 05055 } 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)))) { 05056 ast_setstate(ast, AST_STATE_RINGING); 05057 } else if (!p->answeronpolarityswitch) { 05058 ast_setstate(ast, AST_STATE_UP); 05059 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05060 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05061 /* If aops=0 and hops=1, this is necessary */ 05062 p->polarity = POLARITY_REV; 05063 } else { 05064 /* Start clean, so we can catch the change to REV polarity when party answers */ 05065 p->polarity = POLARITY_IDLE; 05066 } 05067 } 05068 } 05069 } 05070 break; 05071 case DAHDI_EVENT_ALARM: 05072 #ifdef HAVE_PRI 05073 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05074 /* T309 is not enabled : hangup calls when alarm occurs */ 05075 if (p->call) { 05076 if (p->pri && p->pri->pri) { 05077 if (!pri_grab(p, p->pri)) { 05078 pri_hangup(p->pri->pri, p->call, -1); 05079 pri_destroycall(p->pri->pri, p->call); 05080 p->call = NULL; 05081 pri_rel(p->pri); 05082 } else 05083 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 05084 } else 05085 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05086 } 05087 if (p->owner) 05088 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05089 } 05090 if (p->bearer) 05091 p->bearer->inalarm = 1; 05092 else 05093 #endif 05094 p->inalarm = 1; 05095 res = get_alarms(p); 05096 handle_alarms(p, res); 05097 #ifdef HAVE_PRI 05098 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05099 /* fall through intentionally */ 05100 } else { 05101 break; 05102 } 05103 #endif 05104 #ifdef HAVE_OPENR2 05105 if (p->sig == SIG_MFCR2) 05106 break; 05107 #endif 05108 case DAHDI_EVENT_ONHOOK: 05109 if (p->radio) { 05110 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05111 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05112 break; 05113 } 05114 if (p->oprmode < 0) 05115 { 05116 if (p->oprmode != -1) break; 05117 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05118 { 05119 /* Make sure it starts ringing */ 05120 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05121 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05122 save_conference(p->oprpeer); 05123 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05124 } 05125 break; 05126 } 05127 switch (p->sig) { 05128 case SIG_FXOLS: 05129 case SIG_FXOGS: 05130 case SIG_FXOKS: 05131 p->onhooktime = time(NULL); 05132 p->msgstate = -1; 05133 /* Check for some special conditions regarding call waiting */ 05134 if (index == SUB_REAL) { 05135 /* The normal line was hung up */ 05136 if (p->subs[SUB_CALLWAIT].owner) { 05137 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05138 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05139 if (option_verbose > 2) 05140 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05141 unalloc_sub(p, SUB_CALLWAIT); 05142 #if 0 05143 p->subs[index].needanswer = 0; 05144 p->subs[index].needringing = 0; 05145 #endif 05146 p->callwaitingrepeat = 0; 05147 p->cidcwexpire = 0; 05148 p->owner = NULL; 05149 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05150 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05151 p->dialing = 1; 05152 dahdi_ring_phone(p); 05153 } else if (p->subs[SUB_THREEWAY].owner) { 05154 unsigned int mssinceflash; 05155 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 05156 the private structure -- not especially easy or clean */ 05157 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 05158 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 05159 ast_mutex_unlock(&p->lock); 05160 DEADLOCK_AVOIDANCE(&ast->lock); 05161 /* We can grab ast and p in that order, without worry. We should make sure 05162 nothing seriously bad has happened though like some sort of bizarre double 05163 masquerade! */ 05164 ast_mutex_lock(&p->lock); 05165 if (p->owner != ast) { 05166 ast_log(LOG_WARNING, "This isn't good...\n"); 05167 return NULL; 05168 } 05169 } 05170 if (!p->subs[SUB_THREEWAY].owner) { 05171 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05172 return NULL; 05173 } 05174 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05175 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 05176 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05177 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05178 hanging up. Hangup both channels now */ 05179 if (p->subs[SUB_THREEWAY].owner) 05180 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 05181 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05182 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05183 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05184 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05185 if (p->transfer) { 05186 /* In any case this isn't a threeway call anymore */ 05187 p->subs[SUB_REAL].inthreeway = 0; 05188 p->subs[SUB_THREEWAY].inthreeway = 0; 05189 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05190 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05191 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05192 /* Swap subs and dis-own channel */ 05193 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05194 p->owner = NULL; 05195 /* Ring the phone */ 05196 dahdi_ring_phone(p); 05197 } else { 05198 if ((res = attempt_transfer(p)) < 0) { 05199 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05200 if (p->subs[SUB_THREEWAY].owner) 05201 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05202 } else if (res) { 05203 /* Don't actually hang up at this point */ 05204 if (p->subs[SUB_THREEWAY].owner) 05205 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05206 break; 05207 } 05208 } 05209 } else { 05210 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05211 if (p->subs[SUB_THREEWAY].owner) 05212 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05213 } 05214 } else { 05215 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05216 /* Swap subs and dis-own channel */ 05217 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05218 p->owner = NULL; 05219 /* Ring the phone */ 05220 dahdi_ring_phone(p); 05221 } 05222 } 05223 } else { 05224 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 05225 } 05226 /* Fall through */ 05227 default: 05228 dahdi_disable_ec(p); 05229 return NULL; 05230 } 05231 break; 05232 case DAHDI_EVENT_RINGOFFHOOK: 05233 if (p->inalarm) break; 05234 if (p->oprmode < 0) 05235 { 05236 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05237 { 05238 /* Make sure it stops ringing */ 05239 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05240 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 05241 restore_conference(p->oprpeer); 05242 } 05243 break; 05244 } 05245 if (p->radio) 05246 { 05247 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05248 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05249 break; 05250 } 05251 /* for E911, its supposed to wait for offhook then dial 05252 the second half of the dial string */ 05253 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05254 c = strchr(p->dialdest, '/'); 05255 if (c) 05256 c++; 05257 else 05258 c = p->dialdest; 05259 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05260 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05261 if (strlen(p->dop.dialstr) > 4) { 05262 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05263 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05264 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05265 p->echobreak = 1; 05266 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05267 } else 05268 p->echobreak = 0; 05269 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05270 int saveerr = errno; 05271 05272 x = DAHDI_ONHOOK; 05273 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05274 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05275 return NULL; 05276 } 05277 p->dialing = 1; 05278 return &p->subs[index].f; 05279 } 05280 switch (p->sig) { 05281 case SIG_FXOLS: 05282 case SIG_FXOGS: 05283 case SIG_FXOKS: 05284 switch (ast->_state) { 05285 case AST_STATE_RINGING: 05286 dahdi_enable_ec(p); 05287 dahdi_train_ec(p); 05288 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05289 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05290 /* Make sure it stops ringing */ 05291 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05292 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 05293 if (p->cidspill) { 05294 /* Cancel any running CallerID spill */ 05295 free(p->cidspill); 05296 p->cidspill = NULL; 05297 } 05298 p->dialing = 0; 05299 p->callwaitcas = 0; 05300 if (p->confirmanswer) { 05301 /* Ignore answer if "confirm answer" is enabled */ 05302 p->subs[index].f.frametype = AST_FRAME_NULL; 05303 p->subs[index].f.subclass = 0; 05304 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05305 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05306 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05307 if (res < 0) { 05308 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05309 p->dop.dialstr[0] = '\0'; 05310 return NULL; 05311 } else { 05312 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05313 p->subs[index].f.frametype = AST_FRAME_NULL; 05314 p->subs[index].f.subclass = 0; 05315 p->dialing = 1; 05316 } 05317 p->dop.dialstr[0] = '\0'; 05318 ast_setstate(ast, AST_STATE_DIALING); 05319 } else 05320 ast_setstate(ast, AST_STATE_UP); 05321 return &p->subs[index].f; 05322 case AST_STATE_DOWN: 05323 ast_setstate(ast, AST_STATE_RING); 05324 ast->rings = 1; 05325 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05326 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05327 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 05328 return &p->subs[index].f; 05329 case AST_STATE_UP: 05330 /* Make sure it stops ringing */ 05331 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05332 /* Okay -- probably call waiting*/ 05333 if (ast_bridged_channel(p->owner)) 05334 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05335 p->subs[index].needunhold = 1; 05336 break; 05337 case AST_STATE_RESERVED: 05338 /* Start up dialtone */ 05339 if (has_voicemail(p)) 05340 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05341 else 05342 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05343 break; 05344 default: 05345 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05346 } 05347 break; 05348 case SIG_FXSLS: 05349 case SIG_FXSGS: 05350 case SIG_FXSKS: 05351 if (ast->_state == AST_STATE_RING) { 05352 p->ringt = p->ringt_base; 05353 } 05354 05355 /* Fall through */ 05356 case SIG_EM: 05357 case SIG_EM_E1: 05358 case SIG_EMWINK: 05359 case SIG_FEATD: 05360 case SIG_FEATDMF: 05361 case SIG_FEATDMF_TA: 05362 case SIG_E911: 05363 case SIG_FGC_CAMA: 05364 case SIG_FGC_CAMAMF: 05365 case SIG_FEATB: 05366 case SIG_SF: 05367 case SIG_SFWINK: 05368 case SIG_SF_FEATD: 05369 case SIG_SF_FEATDMF: 05370 case SIG_SF_FEATB: 05371 if (ast->_state == AST_STATE_PRERING) 05372 ast_setstate(ast, AST_STATE_RING); 05373 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05374 if (option_debug) 05375 ast_log(LOG_DEBUG, "Ring detected\n"); 05376 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05377 p->subs[index].f.subclass = AST_CONTROL_RING; 05378 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05379 if (option_debug) 05380 ast_log(LOG_DEBUG, "Line answered\n"); 05381 if (p->confirmanswer) { 05382 p->subs[index].f.frametype = AST_FRAME_NULL; 05383 p->subs[index].f.subclass = 0; 05384 } else { 05385 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05386 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05387 ast_setstate(ast, AST_STATE_UP); 05388 } 05389 } else if (ast->_state != AST_STATE_RING) 05390 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05391 break; 05392 default: 05393 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05394 } 05395 break; 05396 #ifdef DAHDI_EVENT_RINGBEGIN 05397 case DAHDI_EVENT_RINGBEGIN: 05398 switch (p->sig) { 05399 case SIG_FXSLS: 05400 case SIG_FXSGS: 05401 case SIG_FXSKS: 05402 if (ast->_state == AST_STATE_RING) { 05403 p->ringt = p->ringt_base; 05404 } 05405 break; 05406 } 05407 break; 05408 #endif 05409 case DAHDI_EVENT_RINGEROFF: 05410 if (p->inalarm) break; 05411 if ((p->radio || (p->oprmode < 0))) break; 05412 ast->rings++; 05413 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05414 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05415 free(p->cidspill); 05416 p->cidspill = NULL; 05417 p->callwaitcas = 0; 05418 } 05419 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05420 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05421 break; 05422 case DAHDI_EVENT_RINGERON: 05423 break; 05424 case DAHDI_EVENT_NOALARM: 05425 p->inalarm = 0; 05426 #ifdef HAVE_PRI 05427 /* Extremely unlikely but just in case */ 05428 if (p->bearer) 05429 p->bearer->inalarm = 0; 05430 #endif 05431 if (!p->unknown_alarm) { 05432 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05433 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05434 "Channel: %d\r\n", p->channel); 05435 } else { 05436 p->unknown_alarm = 0; 05437 } 05438 break; 05439 case DAHDI_EVENT_WINKFLASH: 05440 if (p->inalarm) break; 05441 if (p->radio) break; 05442 if (p->oprmode < 0) break; 05443 if (p->oprmode > 1) 05444 { 05445 struct dahdi_params par; 05446 05447 memset(&par, 0, sizeof(par)); 05448 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05449 { 05450 if (!par.rxisoffhook) 05451 { 05452 /* Make sure it stops ringing */ 05453 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05454 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05455 save_conference(p); 05456 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05457 } 05458 } 05459 break; 05460 } 05461 /* Remember last time we got a flash-hook */ 05462 gettimeofday(&p->flashtime, NULL); 05463 switch (mysig) { 05464 case SIG_FXOLS: 05465 case SIG_FXOGS: 05466 case SIG_FXOKS: 05467 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05468 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05469 p->callwaitcas = 0; 05470 05471 if (index != SUB_REAL) { 05472 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05473 goto winkflashdone; 05474 } 05475 05476 if (p->subs[SUB_CALLWAIT].owner) { 05477 /* Swap to call-wait */ 05478 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05479 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05480 p->owner = p->subs[SUB_REAL].owner; 05481 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 05482 if (p->owner->_state == AST_STATE_RINGING) { 05483 ast_setstate(p->owner, AST_STATE_UP); 05484 p->subs[SUB_REAL].needanswer = 1; 05485 } 05486 p->callwaitingrepeat = 0; 05487 p->cidcwexpire = 0; 05488 /* Start music on hold if appropriate */ 05489 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05490 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05491 S_OR(p->mohsuggest, NULL), 05492 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05493 } 05494 p->subs[SUB_CALLWAIT].needhold = 1; 05495 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05496 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05497 S_OR(p->mohsuggest, NULL), 05498 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05499 } 05500 p->subs[SUB_REAL].needunhold = 1; 05501 } else if (!p->subs[SUB_THREEWAY].owner) { 05502 if (!p->threewaycalling) { 05503 /* Just send a flash if no 3-way calling */ 05504 p->subs[SUB_REAL].needflash = 1; 05505 goto winkflashdone; 05506 } else if (!check_for_conference(p)) { 05507 char cid_num[256]; 05508 char cid_name[256]; 05509 05510 cid_num[0] = 0; 05511 cid_name[0] = 0; 05512 if (p->dahditrcallerid && p->owner) { 05513 if (p->owner->cid.cid_num) 05514 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05515 if (p->owner->cid.cid_name) 05516 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05517 } 05518 /* XXX This section needs much more error checking!!! XXX */ 05519 /* Start a 3-way call if feasible */ 05520 if (!((ast->pbx) || 05521 (ast->_state == AST_STATE_UP) || 05522 (ast->_state == AST_STATE_RING))) { 05523 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 05524 goto winkflashdone; 05525 } 05526 if (alloc_sub(p, SUB_THREEWAY)) { 05527 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05528 goto winkflashdone; 05529 } 05530 /* Make new channel */ 05531 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05532 if (p->dahditrcallerid) { 05533 if (!p->origcid_num) 05534 p->origcid_num = ast_strdup(p->cid_num); 05535 if (!p->origcid_name) 05536 p->origcid_name = ast_strdup(p->cid_name); 05537 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05538 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05539 } 05540 /* Swap things around between the three-way and real call */ 05541 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05542 /* Disable echo canceller for better dialing */ 05543 dahdi_disable_ec(p); 05544 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05545 if (res) 05546 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05547 p->owner = chan; 05548 pthread_attr_init(&attr); 05549 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05550 if (!chan) { 05551 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05552 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 05553 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05554 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05555 dahdi_enable_ec(p); 05556 ast_hangup(chan); 05557 } else { 05558 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05559 int way3bridge = 0, cdr3way = 0; 05560 05561 if (!other) { 05562 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05563 } else 05564 way3bridge = 1; 05565 05566 if (p->subs[SUB_THREEWAY].owner->cdr) 05567 cdr3way = 1; 05568 05569 if (option_verbose > 2) 05570 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 05571 /* Start music on hold if appropriate */ 05572 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05573 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05574 S_OR(p->mohsuggest, NULL), 05575 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05576 } 05577 p->subs[SUB_THREEWAY].needhold = 1; 05578 } 05579 pthread_attr_destroy(&attr); 05580 } 05581 } else { 05582 /* Already have a 3 way call */ 05583 if (p->subs[SUB_THREEWAY].inthreeway) { 05584 /* Call is already up, drop the last person */ 05585 if (option_debug) 05586 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05587 /* If the primary call isn't answered yet, use it */ 05588 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05589 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05590 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05591 p->owner = p->subs[SUB_REAL].owner; 05592 } 05593 /* Drop the last call and stop the conference */ 05594 if (option_verbose > 2) 05595 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05596 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05597 p->subs[SUB_REAL].inthreeway = 0; 05598 p->subs[SUB_THREEWAY].inthreeway = 0; 05599 } else { 05600 /* Lets see what we're up to */ 05601 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05602 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05603 int otherindex = SUB_THREEWAY; 05604 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05605 int way3bridge = 0, cdr3way = 0; 05606 05607 if (!other) { 05608 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05609 } else 05610 way3bridge = 1; 05611 05612 if (p->subs[SUB_THREEWAY].owner->cdr) 05613 cdr3way = 1; 05614 05615 if (option_verbose > 2) 05616 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05617 /* Put them in the threeway, and flip */ 05618 p->subs[SUB_THREEWAY].inthreeway = 1; 05619 p->subs[SUB_REAL].inthreeway = 1; 05620 if (ast->_state == AST_STATE_UP) { 05621 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05622 otherindex = SUB_REAL; 05623 } 05624 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05625 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05626 p->subs[otherindex].needunhold = 1; 05627 p->owner = p->subs[SUB_REAL].owner; 05628 if (ast->_state == AST_STATE_RINGING) { 05629 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 05630 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05631 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05632 } 05633 } else { 05634 if (option_verbose > 2) 05635 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05636 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05637 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05638 p->owner = p->subs[SUB_REAL].owner; 05639 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05640 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05641 p->subs[SUB_REAL].needunhold = 1; 05642 dahdi_enable_ec(p); 05643 } 05644 05645 } 05646 } 05647 winkflashdone: 05648 update_conf(p); 05649 break; 05650 case SIG_EM: 05651 case SIG_EM_E1: 05652 case SIG_FEATD: 05653 case SIG_SF: 05654 case SIG_SFWINK: 05655 case SIG_SF_FEATD: 05656 case SIG_FXSLS: 05657 case SIG_FXSGS: 05658 if (p->dialing) 05659 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 05660 else 05661 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05662 break; 05663 case SIG_FEATDMF_TA: 05664 switch (p->whichwink) { 05665 case 0: 05666 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05667 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05668 break; 05669 case 1: 05670 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05671 break; 05672 case 2: 05673 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05674 return NULL; 05675 } 05676 p->whichwink++; 05677 /* Fall through */ 05678 case SIG_FEATDMF: 05679 case SIG_E911: 05680 case SIG_FGC_CAMAMF: 05681 case SIG_FGC_CAMA: 05682 case SIG_FEATB: 05683 case SIG_SF_FEATDMF: 05684 case SIG_SF_FEATB: 05685 case SIG_EMWINK: 05686 /* FGD MF and EMWINK *Must* wait for wink */ 05687 if (!ast_strlen_zero(p->dop.dialstr)) { 05688 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05689 if (res < 0) { 05690 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05691 p->dop.dialstr[0] = '\0'; 05692 return NULL; 05693 } else 05694 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05695 } 05696 p->dop.dialstr[0] = '\0'; 05697 break; 05698 default: 05699 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05700 } 05701 break; 05702 case DAHDI_EVENT_HOOKCOMPLETE: 05703 if (p->inalarm) break; 05704 if ((p->radio || (p->oprmode < 0))) break; 05705 switch (mysig) { 05706 case SIG_FXSLS: /* only interesting for FXS */ 05707 case SIG_FXSGS: 05708 case SIG_FXSKS: 05709 case SIG_EM: 05710 case SIG_EM_E1: 05711 case SIG_EMWINK: 05712 case SIG_FEATD: 05713 case SIG_SF: 05714 case SIG_SFWINK: 05715 case SIG_SF_FEATD: 05716 if (!ast_strlen_zero(p->dop.dialstr)) { 05717 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05718 if (res < 0) { 05719 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05720 p->dop.dialstr[0] = '\0'; 05721 return NULL; 05722 } else 05723 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05724 } 05725 p->dop.dialstr[0] = '\0'; 05726 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05727 break; 05728 case SIG_FEATDMF: 05729 case SIG_FEATDMF_TA: 05730 case SIG_E911: 05731 case SIG_FGC_CAMA: 05732 case SIG_FGC_CAMAMF: 05733 case SIG_FEATB: 05734 case SIG_SF_FEATDMF: 05735 case SIG_SF_FEATB: 05736 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05737 break; 05738 default: 05739 break; 05740 } 05741 break; 05742 case DAHDI_EVENT_POLARITY: 05743 /* 05744 * If we get a Polarity Switch event, check to see 05745 * if we should change the polarity state and 05746 * mark the channel as UP or if this is an indication 05747 * of remote end disconnect. 05748 */ 05749 if (p->polarity == POLARITY_IDLE) { 05750 p->polarity = POLARITY_REV; 05751 if (p->answeronpolarityswitch && 05752 ((ast->_state == AST_STATE_DIALING) || 05753 (ast->_state == AST_STATE_RINGING))) { 05754 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 05755 ast_setstate(p->owner, AST_STATE_UP); 05756 if (p->hanguponpolarityswitch) { 05757 gettimeofday(&p->polaritydelaytv, NULL); 05758 } 05759 } else 05760 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05761 } 05762 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05763 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05764 if (p->hanguponpolarityswitch && 05765 (p->polarityonanswerdelay > 0) && 05766 (p->polarity == POLARITY_REV) && 05767 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05768 /* Added log_debug information below to provide a better indication of what is going on */ 05769 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) ); 05770 05771 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05772 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05773 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05774 p->polarity = POLARITY_IDLE; 05775 } else { 05776 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); 05777 } 05778 } else { 05779 p->polarity = POLARITY_IDLE; 05780 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05781 } 05782 /* Added more log_debug information below to provide a better indication of what is going on */ 05783 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) ); 05784 break; 05785 default: 05786 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05787 } 05788 return &p->subs[index].f; 05789 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3590 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::alerting, 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::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), dahdi_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, dahdi_pvt::lock, LOG_DEBUG, 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, 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::proceeding, 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::setup_ack, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.
Referenced by pri_dchannel().
03591 { 03592 int res; 03593 int index,x, law; 03594 /*static int restore_gains(struct dahdi_pvt *p);*/ 03595 struct dahdi_pvt *p = ast->tech_pvt; 03596 struct dahdi_pvt *tmp = NULL; 03597 struct dahdi_pvt *prev = NULL; 03598 struct dahdi_params par; 03599 03600 if (option_debug) 03601 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 03602 if (!ast->tech_pvt) { 03603 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03604 return 0; 03605 } 03606 03607 ast_mutex_lock(&p->lock); 03608 03609 index = dahdi_get_index(ast, p, 1); 03610 03611 if (p->sig == SIG_PRI) { 03612 x = 1; 03613 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03614 p->cid_num[0] = '\0'; 03615 p->cid_name[0] = '\0'; 03616 } 03617 03618 x = 0; 03619 dahdi_confmute(p, 0); 03620 restore_gains(p); 03621 if (p->origcid_num) { 03622 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03623 free(p->origcid_num); 03624 p->origcid_num = NULL; 03625 } 03626 if (p->origcid_name) { 03627 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03628 free(p->origcid_name); 03629 p->origcid_name = NULL; 03630 } 03631 if (p->dsp) 03632 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 03633 p->exten[0] = '\0'; 03634 03635 if (option_debug) 03636 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03637 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03638 p->ignoredtmf = 0; 03639 03640 if (index > -1) { 03641 /* Real channel, do some fixup */ 03642 p->subs[index].owner = NULL; 03643 p->subs[index].needanswer = 0; 03644 p->subs[index].needflash = 0; 03645 p->subs[index].needringing = 0; 03646 p->subs[index].needbusy = 0; 03647 p->subs[index].needcongestion = 0; 03648 p->subs[index].linear = 0; 03649 p->subs[index].needcallerid = 0; 03650 p->polarity = POLARITY_IDLE; 03651 dahdi_setlinear(p->subs[index].dfd, 0); 03652 if (index == SUB_REAL) { 03653 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03654 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03655 if (p->subs[SUB_CALLWAIT].inthreeway) { 03656 /* We had flipped over to answer a callwait and now it's gone */ 03657 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 03658 /* Move to the call-wait, but un-own us until they flip back. */ 03659 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03660 unalloc_sub(p, SUB_CALLWAIT); 03661 p->owner = NULL; 03662 } else { 03663 /* The three way hung up, but we still have a call wait */ 03664 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03665 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03666 unalloc_sub(p, SUB_THREEWAY); 03667 if (p->subs[SUB_REAL].inthreeway) { 03668 /* This was part of a three way call. Immediately make way for 03669 another call */ 03670 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03671 p->owner = p->subs[SUB_REAL].owner; 03672 } else { 03673 /* This call hasn't been completed yet... Set owner to NULL */ 03674 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03675 p->owner = NULL; 03676 } 03677 p->subs[SUB_REAL].inthreeway = 0; 03678 } 03679 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03680 /* Move to the call-wait and switch back to them. */ 03681 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03682 unalloc_sub(p, SUB_CALLWAIT); 03683 p->owner = p->subs[SUB_REAL].owner; 03684 if (p->owner->_state != AST_STATE_UP) 03685 p->subs[SUB_REAL].needanswer = 1; 03686 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03687 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03688 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03689 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03690 unalloc_sub(p, SUB_THREEWAY); 03691 if (p->subs[SUB_REAL].inthreeway) { 03692 /* This was part of a three way call. Immediately make way for 03693 another call */ 03694 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03695 p->owner = p->subs[SUB_REAL].owner; 03696 } else { 03697 /* This call hasn't been completed yet... Set owner to NULL */ 03698 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03699 p->owner = NULL; 03700 } 03701 p->subs[SUB_REAL].inthreeway = 0; 03702 } 03703 } else if (index == SUB_CALLWAIT) { 03704 /* Ditch the holding callwait call, and immediately make it availabe */ 03705 if (p->subs[SUB_CALLWAIT].inthreeway) { 03706 /* This is actually part of a three way, placed on hold. Place the third part 03707 on music on hold now */ 03708 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03709 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03710 S_OR(p->mohsuggest, NULL), 03711 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03712 } 03713 p->subs[SUB_THREEWAY].inthreeway = 0; 03714 /* Make it the call wait now */ 03715 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03716 unalloc_sub(p, SUB_THREEWAY); 03717 } else 03718 unalloc_sub(p, SUB_CALLWAIT); 03719 } else if (index == SUB_THREEWAY) { 03720 if (p->subs[SUB_CALLWAIT].inthreeway) { 03721 /* The other party of the three way call is currently in a call-wait state. 03722 Start music on hold for them, and take the main guy out of the third call */ 03723 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03724 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03725 S_OR(p->mohsuggest, NULL), 03726 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03727 } 03728 p->subs[SUB_CALLWAIT].inthreeway = 0; 03729 } 03730 p->subs[SUB_REAL].inthreeway = 0; 03731 /* If this was part of a three way call index, let us make 03732 another three way call */ 03733 unalloc_sub(p, SUB_THREEWAY); 03734 } else { 03735 /* This wasn't any sort of call, but how are we an index? */ 03736 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03737 } 03738 } 03739 03740 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03741 p->owner = NULL; 03742 p->ringt = 0; 03743 p->distinctivering = 0; 03744 p->confirmanswer = 0; 03745 p->cidrings = 1; 03746 p->outgoing = 0; 03747 p->digital = 0; 03748 p->faxhandled = 0; 03749 p->pulsedial = 0; 03750 p->onhooktime = time(NULL); 03751 #ifdef HAVE_PRI 03752 p->proceeding = 0; 03753 p->dialing = 0; 03754 p->progress = 0; 03755 p->alerting = 0; 03756 p->setup_ack = 0; 03757 #endif 03758 if (p->dsp) { 03759 ast_dsp_free(p->dsp); 03760 p->dsp = NULL; 03761 } 03762 03763 law = DAHDI_LAW_DEFAULT; 03764 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03765 if (res < 0) 03766 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03767 /* Perform low level hangup if no owner left */ 03768 #ifdef HAVE_OPENR2 03769 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 03770 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 03771 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause); 03772 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 03773 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 03774 } else { 03775 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE"); 03776 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 03777 openr2_call_disconnect_cause_t r2cause = r2cause_user 03778 ? dahdi_ast_cause_to_r2_cause(r2cause_user) 03779 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 03780 dahdi_r2_disconnect_call(p, r2cause); 03781 } 03782 } else if (p->mfcr2call) { 03783 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 03784 p->mfcr2call = 0; 03785 } 03786 #endif 03787 #ifdef HAVE_PRI 03788 if (p->pri) { 03789 #ifdef SUPPORT_USERUSER 03790 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03791 #endif 03792 03793 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03794 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03795 if (!pri_grab(p, p->pri)) { 03796 if (p->alreadyhungup) { 03797 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03798 03799 #ifdef SUPPORT_USERUSER 03800 pri_call_set_useruser(p->call, useruser); 03801 #endif 03802 03803 pri_hangup(p->pri->pri, p->call, -1); 03804 p->call = NULL; 03805 if (p->bearer) 03806 p->bearer->call = NULL; 03807 } else { 03808 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03809 int icause = ast->hangupcause ? ast->hangupcause : -1; 03810 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03811 03812 #ifdef SUPPORT_USERUSER 03813 pri_call_set_useruser(p->call, useruser); 03814 #endif 03815 03816 p->alreadyhungup = 1; 03817 if (p->bearer) 03818 p->bearer->alreadyhungup = 1; 03819 if (cause) { 03820 if (atoi(cause)) 03821 icause = atoi(cause); 03822 } 03823 pri_hangup(p->pri->pri, p->call, icause); 03824 } 03825 if (res < 0) 03826 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03827 pri_rel(p->pri); 03828 } else { 03829 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03830 res = -1; 03831 } 03832 } else { 03833 if (p->bearer) 03834 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03835 p->call = NULL; 03836 res = 0; 03837 } 03838 } 03839 #endif 03840 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2)) 03841 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03842 if (res < 0) { 03843 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03844 } 03845 switch (p->sig) { 03846 case SIG_FXOGS: 03847 case SIG_FXOLS: 03848 case SIG_FXOKS: 03849 memset(&par, 0, sizeof(par)); 03850 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03851 if (!res) { 03852 #if 0 03853 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03854 #endif 03855 /* If they're off hook, try playing congestion */ 03856 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03857 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03858 else 03859 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03860 } 03861 break; 03862 case SIG_FXSGS: 03863 case SIG_FXSLS: 03864 case SIG_FXSKS: 03865 /* Make sure we're not made available for at least two seconds assuming 03866 we were actually used for an inbound or outbound call. */ 03867 if (ast->_state != AST_STATE_RESERVED) { 03868 time(&p->guardtime); 03869 p->guardtime += 2; 03870 } 03871 break; 03872 default: 03873 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03874 } 03875 if (p->cidspill) 03876 free(p->cidspill); 03877 if (p->sig) 03878 dahdi_disable_ec(p); 03879 x = 0; 03880 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03881 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03882 p->didtdd = 0; 03883 p->cidspill = NULL; 03884 p->callwaitcas = 0; 03885 p->callwaiting = p->permcallwaiting; 03886 p->hidecallerid = p->permhidecallerid; 03887 p->dialing = 0; 03888 p->rdnis[0] = '\0'; 03889 update_conf(p); 03890 reset_conf(p); 03891 /* Restore data mode */ 03892 if (p->sig == SIG_PRI) { 03893 x = 0; 03894 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03895 } 03896 #ifdef HAVE_PRI 03897 if (p->bearer) { 03898 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03899 /* Free up the bearer channel as well, and 03900 don't use its file descriptor anymore */ 03901 update_conf(p->bearer); 03902 reset_conf(p->bearer); 03903 p->bearer->owner = NULL; 03904 p->bearer->realcall = NULL; 03905 p->bearer = NULL; 03906 p->subs[SUB_REAL].dfd = -1; 03907 p->pri = NULL; 03908 } 03909 #endif 03910 if (num_restart_pending == 0) 03911 restart_monitor(); 03912 } 03913 03914 p->callwaitingrepeat = 0; 03915 p->cidcwexpire = 0; 03916 p->oprmode = 0; 03917 ast->tech_pvt = NULL; 03918 ast_mutex_unlock(&p->lock); 03919 ast_module_unref(ast_module_info->self); 03920 if (option_verbose > 2) 03921 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03922 03923 ast_mutex_lock(&iflock); 03924 03925 if (p->restartpending) { 03926 num_restart_pending--; 03927 } 03928 03929 tmp = iflist; 03930 prev = NULL; 03931 if (p->destroy) { 03932 while (tmp) { 03933 if (tmp == p) { 03934 destroy_channel(prev, tmp, 0); 03935 break; 03936 } else { 03937 prev = tmp; 03938 tmp = tmp->next; 03939 } 03940 } 03941 } 03942 ast_mutex_unlock(&iflock); 03943 return 0; 03944 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6335 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, AST_CAUSE_CONGESTION, 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_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::proceeding, 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.
06336 { 06337 struct dahdi_pvt *p = chan->tech_pvt; 06338 int res=-1; 06339 int index; 06340 int func = DAHDI_FLASH; 06341 ast_mutex_lock(&p->lock); 06342 index = dahdi_get_index(chan, p, 0); 06343 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 06344 #ifdef HAVE_OPENR2 06345 if (p->mfcr2 && !p->mfcr2_call_accepted) { 06346 ast_mutex_unlock(&p->lock); 06347 /* if this an R2 call and the call is not yet accepted we don't want the 06348 tone indications to mess up with the MF tones */ 06349 return 0; 06350 } 06351 #endif 06352 if (index == SUB_REAL) { 06353 switch (condition) { 06354 case AST_CONTROL_BUSY: 06355 #ifdef HAVE_PRI 06356 if (p->priindication_oob && p->sig == SIG_PRI) { 06357 chan->hangupcause = AST_CAUSE_USER_BUSY; 06358 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06359 res = 0; 06360 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06361 if (p->pri->pri) { 06362 if (!pri_grab(p, p->pri)) { 06363 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06364 pri_rel(p->pri); 06365 } 06366 else 06367 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06368 } 06369 p->progress = 1; 06370 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06371 } else 06372 #endif 06373 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06374 break; 06375 case AST_CONTROL_RINGING: 06376 #ifdef HAVE_PRI 06377 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06378 if (p->pri->pri) { 06379 if (!pri_grab(p, p->pri)) { 06380 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06381 pri_rel(p->pri); 06382 } 06383 else 06384 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06385 } 06386 p->alerting = 1; 06387 } 06388 #endif 06389 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06390 if (chan->_state != AST_STATE_UP) { 06391 if ((chan->_state != AST_STATE_RING) || 06392 ((p->sig != SIG_FXSKS) && 06393 (p->sig != SIG_FXSLS) && 06394 (p->sig != SIG_FXSGS))) 06395 ast_setstate(chan, AST_STATE_RINGING); 06396 } 06397 break; 06398 case AST_CONTROL_PROCEEDING: 06399 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06400 #ifdef HAVE_PRI 06401 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06402 if (p->pri->pri) { 06403 if (!pri_grab(p, p->pri)) { 06404 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06405 pri_rel(p->pri); 06406 } 06407 else 06408 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06409 } 06410 p->proceeding = 1; 06411 p->dialing = 0; 06412 } 06413 #endif 06414 /* don't continue in ast_indicate */ 06415 res = 0; 06416 break; 06417 case AST_CONTROL_PROGRESS: 06418 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06419 #ifdef HAVE_PRI 06420 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06421 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06422 if (p->pri->pri) { 06423 if (!pri_grab(p, p->pri)) { 06424 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06425 pri_rel(p->pri); 06426 } 06427 else 06428 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06429 } 06430 p->progress = 1; 06431 } 06432 #endif 06433 /* don't continue in ast_indicate */ 06434 res = 0; 06435 break; 06436 case AST_CONTROL_CONGESTION: 06437 chan->hangupcause = AST_CAUSE_CONGESTION; 06438 #ifdef HAVE_PRI 06439 if (p->priindication_oob && p->sig == SIG_PRI) { 06440 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06441 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06442 res = 0; 06443 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06444 if (p->pri) { 06445 if (!pri_grab(p, p->pri)) { 06446 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06447 pri_rel(p->pri); 06448 } else 06449 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06450 } 06451 p->progress = 1; 06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06453 } else 06454 #endif 06455 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06456 break; 06457 case AST_CONTROL_HOLD: 06458 #ifdef HAVE_PRI 06459 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06460 if (!pri_grab(p, p->pri)) { 06461 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06462 pri_rel(p->pri); 06463 } else 06464 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06465 } else 06466 #endif 06467 ast_moh_start(chan, data, p->mohinterpret); 06468 break; 06469 case AST_CONTROL_UNHOLD: 06470 #ifdef HAVE_PRI 06471 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06472 if (!pri_grab(p, p->pri)) { 06473 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06474 pri_rel(p->pri); 06475 } else 06476 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06477 } else 06478 #endif 06479 ast_moh_stop(chan); 06480 break; 06481 case AST_CONTROL_RADIO_KEY: 06482 if (p->radio) 06483 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06484 res = 0; 06485 break; 06486 case AST_CONTROL_RADIO_UNKEY: 06487 if (p->radio) 06488 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06489 res = 0; 06490 break; 06491 case AST_CONTROL_FLASH: 06492 /* flash hookswitch */ 06493 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06494 /* Clear out the dial buffer */ 06495 p->dop.dialstr[0] = '\0'; 06496 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06497 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06498 chan->name, strerror(errno)); 06499 } else 06500 res = 0; 06501 } else 06502 res = 0; 06503 break; 06504 case AST_CONTROL_SRCUPDATE: 06505 res = 0; 06506 break; 06507 case -1: 06508 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06509 break; 06510 } 06511 } else 06512 res = 0; 06513 ast_mutex_unlock(&p->lock); 06514 return res; 06515 }
Definition at line 4311 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04311 { 04312 int x; 04313 if (!slave || !master) { 04314 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04315 return; 04316 } 04317 for (x = 0; x < MAX_SLAVES; x++) { 04318 if (!master->slaves[x]) { 04319 master->slaves[x] = slave; 04320 break; 04321 } 04322 } 04323 if (x >= MAX_SLAVES) { 04324 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04325 master->slaves[MAX_SLAVES - 1] = slave; 04326 } 04327 if (slave->master) 04328 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04329 slave->master = master; 04330 04331 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04332 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | index, | |||
int | law, | |||
int | transfercapability | |||
) | [static] |
Definition at line 6517 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, 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, 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().
06518 { 06519 struct ast_channel *tmp; 06520 int deflaw; 06521 int res; 06522 int x,y; 06523 int features; 06524 char *b2 = NULL; 06525 struct dahdi_params ps; 06526 char chanprefix[*dahdi_chan_name_len + 4]; 06527 06528 if (i->subs[index].owner) { 06529 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 06530 return NULL; 06531 } 06532 y = 1; 06533 do { 06534 if (b2) 06535 free(b2); 06536 #ifdef HAVE_PRI 06537 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06538 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06539 else 06540 #endif 06541 if (i->channel == CHAN_PSEUDO) 06542 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 06543 else 06544 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 06545 for (x = 0; x < 3; x++) { 06546 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 06547 break; 06548 } 06549 y++; 06550 } while (x < 3); 06551 strcpy(chanprefix, dahdi_chan_name); 06552 strcat(chanprefix, "/%s"); 06553 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 06554 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 06555 free(b2); 06556 if (!tmp) 06557 return NULL; 06558 tmp->tech = chan_tech; 06559 memset(&ps, 0, sizeof(ps)); 06560 ps.channo = i->channel; 06561 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06562 if (res) { 06563 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06564 ps.curlaw = DAHDI_LAW_MULAW; 06565 } 06566 if (ps.curlaw == DAHDI_LAW_ALAW) 06567 deflaw = AST_FORMAT_ALAW; 06568 else 06569 deflaw = AST_FORMAT_ULAW; 06570 if (law) { 06571 if (law == DAHDI_LAW_ALAW) 06572 deflaw = AST_FORMAT_ALAW; 06573 else 06574 deflaw = AST_FORMAT_ULAW; 06575 } 06576 tmp->fds[0] = i->subs[index].dfd; 06577 tmp->nativeformats = deflaw; 06578 /* Start out assuming ulaw since it's smaller :) */ 06579 tmp->rawreadformat = deflaw; 06580 tmp->readformat = deflaw; 06581 tmp->rawwriteformat = deflaw; 06582 tmp->writeformat = deflaw; 06583 i->subs[index].linear = 0; 06584 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 06585 features = 0; 06586 if (index == SUB_REAL) { 06587 if (i->busydetect && CANBUSYDETECT(i)) 06588 features |= DSP_FEATURE_BUSY_DETECT; 06589 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 06590 features |= DSP_FEATURE_CALL_PROGRESS; 06591 if ((!i->outgoing && (i->callprogress & 4)) || 06592 (i->outgoing && (i->callprogress & 2))) { 06593 features |= DSP_FEATURE_FAX_DETECT; 06594 } 06595 #ifdef DAHDI_TONEDETECT 06596 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06597 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 06598 #endif 06599 i->hardwaredtmf = 0; 06600 features |= DSP_FEATURE_DTMF_DETECT; 06601 #ifdef DAHDI_TONEDETECT 06602 } else if (NEED_MFDETECT(i)) { 06603 i->hardwaredtmf = 1; 06604 features |= DSP_FEATURE_DTMF_DETECT; 06605 } 06606 #endif 06607 } 06608 if (features) { 06609 if (i->dsp) { 06610 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 06611 } else { 06612 if (i->channel != CHAN_PSEUDO) 06613 i->dsp = ast_dsp_new(); 06614 else 06615 i->dsp = NULL; 06616 if (i->dsp) { 06617 i->dsp_features = features; 06618 #ifdef HAVE_PRI 06619 /* We cannot do progress detection until receives PROGRESS message */ 06620 if (i->outgoing && (i->sig == SIG_PRI)) { 06621 /* Remember requested DSP features, don't treat 06622 talking as ANSWER */ 06623 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06624 features = 0; 06625 } 06626 #endif 06627 ast_dsp_set_features(i->dsp, features); 06628 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06629 if (!ast_strlen_zero(progzone)) 06630 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06631 if (i->busydetect && CANBUSYDETECT(i)) { 06632 if(i->silencethreshold > 0) 06633 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06634 ast_dsp_set_busy_count(i->dsp, i->busycount); 06635 if(i->busytonelength > 0) 06636 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06637 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06638 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06639 } 06640 } 06641 } 06642 } 06643 06644 if (state == AST_STATE_RING) 06645 tmp->rings = 1; 06646 tmp->tech_pvt = i; 06647 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06648 /* Only FXO signalled stuff can be picked up */ 06649 tmp->callgroup = i->callgroup; 06650 tmp->pickupgroup = i->pickupgroup; 06651 } 06652 if (!ast_strlen_zero(i->language)) 06653 ast_string_field_set(tmp, language, i->language); 06654 if (!i->owner) 06655 i->owner = tmp; 06656 if (!ast_strlen_zero(i->accountcode)) 06657 ast_string_field_set(tmp, accountcode, i->accountcode); 06658 if (i->amaflags) 06659 tmp->amaflags = i->amaflags; 06660 i->subs[index].owner = tmp; 06661 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06662 ast_string_field_set(tmp, call_forward, i->call_forward); 06663 /* If we've been told "no ADSI" then enforce it */ 06664 if (!i->adsi) 06665 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06666 if (!ast_strlen_zero(i->exten)) 06667 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06668 if (!ast_strlen_zero(i->rdnis)) 06669 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06670 if (!ast_strlen_zero(i->dnid)) 06671 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06672 06673 /* Don't use ast_set_callerid() here because it will 06674 * generate a needless NewCallerID event */ 06675 #ifdef PRI_ANI 06676 if (!ast_strlen_zero(i->cid_ani)) 06677 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06678 else 06679 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06680 #else 06681 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06682 #endif 06683 tmp->cid.cid_pres = i->callingpres; 06684 tmp->cid.cid_ton = i->cid_ton; 06685 #ifdef HAVE_PRI 06686 tmp->transfercapability = transfercapability; 06687 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06688 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 06689 i->digital = 1; 06690 /* Assume calls are not idle calls unless we're told differently */ 06691 i->isidlecall = 0; 06692 i->alreadyhungup = 0; 06693 #endif 06694 /* clear the fake event in case we posted one before we had ast_channel */ 06695 i->fake_event = 0; 06696 /* Assure there is no confmute on this channel */ 06697 dahdi_confmute(i, 0); 06698 /* Configure the new channel jb */ 06699 ast_jb_configure(tmp, &global_jbconf); 06700 if (startpbx) { 06701 #ifdef HAVE_OPENR2 06702 if (i->mfcr2call) { 06703 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 06704 } 06705 #endif 06706 if (ast_pbx_start(tmp)) { 06707 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06708 ast_hangup(tmp); 06709 i->owner = NULL; 06710 return NULL; 06711 } 06712 } 06713 06714 ast_module_ref(ast_module_info->self); 06715 06716 return tmp; 06717 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1800 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01801 { 01802 int fd; 01803 int isnum; 01804 int chan = 0; 01805 int bs; 01806 int x; 01807 isnum = 1; 01808 for (x = 0; x < strlen(fn); x++) { 01809 if (!isdigit(fn[x])) { 01810 isnum = 0; 01811 break; 01812 } 01813 } 01814 if (isnum) { 01815 chan = atoi(fn); 01816 if (chan < 1) { 01817 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01818 return -1; 01819 } 01820 fn = DAHDI_FILE_CHANNEL; 01821 } 01822 fd = open(fn, O_RDWR | O_NONBLOCK); 01823 if (fd < 0) { 01824 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01825 return -1; 01826 } 01827 if (chan) { 01828 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01829 x = errno; 01830 close(fd); 01831 errno = x; 01832 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01833 return -1; 01834 } 01835 } 01836 bs = READ_SIZE; 01837 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01838 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01839 x = errno; 01840 close(fd); 01841 errno = x; 01842 return -1; 01843 } 01844 return fd; 01845 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9901 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
09902 { 09903 int x, y; 09904 int dchan = -1, span = -1; 09905 int dchancount = 0; 09906 09907 if (pri) { 09908 for (x = 0; x < NUM_SPANS; x++) { 09909 for (y = 0; y < NUM_DCHANS; y++) { 09910 if (pris[x].dchans[y]) 09911 dchancount++; 09912 09913 if (pris[x].dchans[y] == pri) 09914 dchan = y; 09915 } 09916 if (dchan >= 0) { 09917 span = x; 09918 break; 09919 } 09920 dchancount = 0; 09921 } 09922 if ((dchan >= 0) && (span >= 0)) { 09923 if (dchancount > 1) 09924 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 09925 else 09926 ast_log(LOG_ERROR, "%s", s); 09927 } else 09928 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09929 } else 09930 ast_log(LOG_ERROR, "%s", s); 09931 09932 ast_mutex_lock(&pridebugfdlock); 09933 09934 if (pridebugfd >= 0) { 09935 if (write(pridebugfd, s, strlen(s)) < 0) { 09936 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09937 } 09938 } 09939 09940 ast_mutex_unlock(&pridebugfdlock); 09941 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9859 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.
Referenced by dahdi_restart(), and load_module().
09860 { 09861 int x, y; 09862 int dchan = -1, span = -1; 09863 int dchancount = 0; 09864 09865 if (pri) { 09866 for (x = 0; x < NUM_SPANS; x++) { 09867 for (y = 0; y < NUM_DCHANS; y++) { 09868 if (pris[x].dchans[y]) 09869 dchancount++; 09870 09871 if (pris[x].dchans[y] == pri) 09872 dchan = y; 09873 } 09874 if (dchan >= 0) { 09875 span = x; 09876 break; 09877 } 09878 dchancount = 0; 09879 } 09880 if ((dchan >= 0) && (span >= 0)) { 09881 if (dchancount > 1) 09882 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 09883 else 09884 ast_verbose("%s", s); 09885 } else 09886 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09887 } else 09888 ast_verbose("%s", s); 09889 09890 ast_mutex_lock(&pridebugfdlock); 09891 09892 if (pridebugfd >= 0) { 09893 if (write(pridebugfd, s, strlen(s)) < 0) { 09894 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09895 } 09896 } 09897 09898 ast_mutex_unlock(&pridebugfdlock); 09899 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 1236 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
01240 { 01241 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01242 #ifdef HAVE_PRI 01243 if (pri) 01244 ast_mutex_unlock(&pri->lock); 01245 #endif 01246 for (;;) { 01247 if (p->owner) { 01248 if (ast_mutex_trylock(&p->owner->lock)) { 01249 DEADLOCK_AVOIDANCE(&p->lock); 01250 } else { 01251 ast_queue_frame(p->owner, f); 01252 ast_mutex_unlock(&p->owner->lock); 01253 break; 01254 } 01255 } else 01256 break; 01257 } 01258 #ifdef HAVE_PRI 01259 if (pri) 01260 ast_mutex_lock(&pri->lock); 01261 #endif 01262 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 1753 of file chan_dahdi.c.
References AST_ALAW.
01754 { 01755 return AST_ALAW(sample); 01756 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1298 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().
01299 { 01300 int res = 0; 01301 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 01302 * and does not has support for openr2_chan_answer_call_with_mode 01303 * */ 01304 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01305 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 01306 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 01307 if (!double_answer) { 01308 /* this still can result in double answer if the channel context 01309 * was configured that way */ 01310 res = openr2_chan_answer_call(p->r2chan); 01311 } else if (wants_double_answer) { 01312 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 01313 } else { 01314 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 01315 } 01316 #else 01317 res = openr2_chan_answer_call(p->r2chan); 01318 #endif 01319 return res; 01320 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1411 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().
01412 { 01413 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 01414 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 01415 p->channel, openr2_proto_get_disconnect_string(cause)); 01416 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 01417 openr2_chan_set_idle(p->r2chan); 01418 ast_mutex_lock(&p->lock); 01419 p->mfcr2call = 0; 01420 ast_mutex_unlock(&p->lock); 01421 } 01422 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 1322 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().
01323 { 01324 openr2_calling_party_category_t cat; 01325 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 01326 struct dahdi_pvt *p = c->tech_pvt; 01327 if (ast_strlen_zero(catstr)) { 01328 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 01329 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01330 return p->mfcr2_category; 01331 } 01332 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 01333 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 01334 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01335 return p->mfcr2_category; 01336 } 01337 ast_log(LOG_DEBUG, "Using category %s\n", catstr); 01338 return cat; 01339 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 1758 of file chan_dahdi.c.
References AST_LIN2A.
01759 { 01760 return AST_LIN2A(sample); 01761 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1717 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
01718 { 01719 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01720 p->cid_num[p->mfcr2_ani_index] = digit; 01721 p->cid_name[p->mfcr2_ani_index] = digit; 01722 p->mfcr2_ani_index++; 01723 p->cid_num[p->mfcr2_ani_index] = 0; 01724 p->cid_name[p->mfcr2_ani_index] = 0; 01725 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1727 of file chan_dahdi.c.
References ast_log(), and LOG_NOTICE.
01728 { 01729 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 01730 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 1485 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.
01486 { 01487 struct dahdi_pvt *p = NULL; 01488 struct ast_channel *c = NULL; 01489 p = openr2_chan_get_client_data(r2chan); 01490 dahdi_enable_ec(p); 01491 p->mfcr2_call_accepted = 1; 01492 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 01493 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 01494 /* if accept on offer is not set, it means at this point the PBX thread is already 01495 launched and therefore this callback is being executed in the PBX thread rather than 01496 the monitor thread, don't launch any other thread, just disable the R2 reading and 01497 answer the call */ 01498 if (!p->mfcr2_accept_on_offer) { 01499 openr2_chan_disable_read(r2chan); 01500 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 01501 dahdi_r2_answer(p); 01502 return; 01503 } 01504 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01505 if (c) { 01506 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01507 openr2_chan_disable_read(r2chan); 01508 } else { 01509 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01511 return; 01512 } 01513 } else { 01514 ast_verbose("Call accepted on forward channel %d\n", p->channel); 01515 p->subs[SUB_REAL].needringing = 1; 01516 p->dialing = 0; 01517 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01518 openr2_chan_disable_read(r2chan); 01519 } 01520 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1522 of file chan_dahdi.c.
References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
01523 { 01524 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01525 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan)); 01526 p->subs[SUB_REAL].needanswer = 1; 01527 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1555 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.
01556 { 01557 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01558 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan)); 01559 ast_mutex_lock(&p->lock); 01560 if (p->owner) { 01561 /* when we have an owner we don't call openr2_chan_disconnect_call here, that will 01562 be done in zt_hangup */ 01563 if (p->owner->_state == AST_STATE_UP) { 01564 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01565 ast_mutex_unlock(&p->lock); 01566 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 01567 /* being the forward side we must report what happened to the call to whoever requested it */ 01568 switch (cause) { 01569 case OR2_CAUSE_BUSY_NUMBER: 01570 p->owner->hangupcause = AST_CAUSE_BUSY; 01571 p->subs[SUB_REAL].needbusy = 1; 01572 break; 01573 case OR2_CAUSE_NUMBER_CHANGED: 01574 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED; 01575 p->subs[SUB_REAL].needcongestion = 1; 01576 break; 01577 case OR2_CAUSE_NETWORK_CONGESTION: 01578 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER; 01579 p->subs[SUB_REAL].needcongestion = 1; 01580 break; 01581 case OR2_CAUSE_OUT_OF_ORDER: 01582 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01583 p->subs[SUB_REAL].needcongestion = 1; 01584 break; 01585 case OR2_CAUSE_UNALLOCATED_NUMBER: 01586 p->owner->hangupcause = AST_CAUSE_UNALLOCATED; 01587 p->subs[SUB_REAL].needcongestion = 1; 01588 break; 01589 case OR2_CAUSE_NO_ANSWER: 01590 p->owner->hangupcause = AST_CAUSE_NO_ANSWER; 01591 p->subs[SUB_REAL].needcongestion = 1; 01592 break; 01593 case OR2_CAUSE_UNSPECIFIED: 01594 p->owner->hangupcause = AST_CAUSE_NOTDEFINED; 01595 p->subs[SUB_REAL].needcongestion = 1; 01596 break; 01597 case OR2_CAUSE_NORMAL_CLEARING: 01598 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01599 p->subs[SUB_REAL].needcongestion = 1; 01600 break; 01601 default: 01602 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause); 01603 } 01604 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01605 ast_mutex_unlock(&p->lock); 01606 } else { 01607 ast_mutex_unlock(&p->lock); 01608 /* being the backward side and not UP yet, we only need to request hangup */ 01609 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 01610 ast_queue_hangup(p->owner); 01611 } 01612 } else { 01613 ast_mutex_unlock(&p->lock); 01614 /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */ 01615 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 01616 } 01617 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1475 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
01476 { 01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01478 ast_verbose("MFC/R2 call end on chan %d\n", p->channel); 01479 ast_mutex_lock(&p->lock); 01480 p->mfcr2call = 0; 01481 ast_mutex_unlock(&p->lock); 01482 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1341 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.
01342 { 01343 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01344 ast_mutex_lock(&p->lock); 01345 if (p->mfcr2call) { 01346 ast_mutex_unlock(&p->lock); 01347 /* TODO: This can happen when some other thread just finished zt_request requesting this very same 01348 interface but has not yet seized the line (zt_call), and the far end wins and seize the line, 01349 can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since 01350 the other end will see our seize as a forced release and drop the call, we will see an invalid 01351 pattern that will be seen and treated as protocol error. */ 01352 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 01353 return; 01354 } 01355 p->mfcr2call = 1; 01356 /* better safe than sorry ... */ 01357 p->cid_name[0] = 0; 01358 p->cid_num[0] = 0; 01359 p->rdnis[0] = 0; 01360 p->exten[0] = 0; 01361 p->mfcr2_ani_index = 0; 01362 p->mfcr2_dnis_index = 0; 01363 p->mfcr2_dnis_matched = 0; 01364 p->mfcr2_call_accepted = 0; 01365 ast_mutex_unlock(&p->lock); 01366 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 01367 }
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 1424 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.
01425 { 01426 struct dahdi_pvt *p; 01427 struct ast_channel *c; 01428 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 01429 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category)); 01430 p = openr2_chan_get_client_data(r2chan); 01431 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 01432 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel); 01433 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 01434 return; 01435 } 01436 ast_mutex_lock(&p->lock); 01437 p->mfcr2_recvd_category = category; 01438 /* if we're not supposed to use CID, clear whatever we have */ 01439 if (!p->use_callerid) { 01440 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 01441 p->cid_num[0] = 0; 01442 p->cid_name[0] = 0; 01443 } 01444 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 01445 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 01446 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 01447 p->exten[0] = 's'; 01448 p->exten[1] = 0; 01449 } 01450 ast_mutex_unlock(&p->lock); 01451 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01452 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 01453 p->channel, p->exten, p->context); 01454 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 01455 } else { 01456 /* if the user does not want to accept on offer, then we should launch the PBX thread now */ 01457 if (!p->mfcr2_accept_on_offer) { 01458 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01459 if (!c) { 01460 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01461 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01462 } 01463 /* Don't disable reading since we still need to generate MF tone to accept 01464 the call or reject it and detect the tone off condition of the other end */ 01465 } else if (p->mfcr2_charge_calls) { 01466 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel); 01467 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 01468 } else { 01469 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel); 01470 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 01471 } 01472 } 01473 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 1529 of file chan_dahdi.c.
01530 { 01531 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 01532 }
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 1678 of file chan_dahdi.c.
References dahdi_r2_write_log().
Referenced by mkintf().
01679 { 01680 char logmsg[256]; 01681 char completemsg[sizeof(logmsg)+50]; 01682 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01683 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg); 01684 dahdi_r2_write_log(level, completemsg); 01685 }
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 1667 of file chan_dahdi.c.
References dahdi_r2_write_log().
01668 { 01669 char logmsg[256]; 01670 char completemsg[sizeof(logmsg)+50]; 01671 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01672 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg); 01673 dahdi_r2_write_log(level, completemsg); 01674 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1687 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.
01688 { 01689 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01690 /* if 'immediate' is set, let's stop requesting DNIS */ 01691 if (p->immediate) { 01692 return 0; 01693 } 01694 p->exten[p->mfcr2_dnis_index] = digit; 01695 p->rdnis[p->mfcr2_dnis_index] = digit; 01696 p->mfcr2_dnis_index++; 01697 p->exten[p->mfcr2_dnis_index] = 0; 01698 p->rdnis[p->mfcr2_dnis_index] = 0; 01699 /* 01700 ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten); 01701 int ret; 01702 ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num); 01703 ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01704 ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num); 01705 ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01706 */ 01707 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 01708 if ((p->mfcr2_dnis_matched || 01709 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 01710 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01711 return 0; 01712 } 01713 /* otherwise keep going */ 01714 return 1; 01715 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 1371 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.
01372 { 01373 int res; 01374 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01375 ast_mutex_lock(&p->lock); 01376 p->inalarm = alarm ? 1 : 0; 01377 if (p->inalarm) { 01378 res = get_alarms(p); 01379 /* unknown_alarm may be set here */ 01380 handle_alarms(p, res); 01381 } else { 01382 if (!p->unknown_alarm) { 01383 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 01384 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 01385 } else { 01386 p->unknown_alarm = 0; 01387 } 01388 } 01389 ast_mutex_unlock(&p->lock); 01390 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan)); 01391 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1647 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.
01648 { 01649 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01650 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel); 01651 ast_mutex_lock(&p->lock); 01652 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK; 01653 ast_mutex_unlock(&p->lock); 01654 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1656 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.
01657 { 01658 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01659 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 01660 ast_mutex_lock(&p->lock); 01661 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK; 01662 ast_mutex_unlock(&p->lock); 01663 }
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 1398 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.
01399 { 01400 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01401 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 01402 if (p->owner) { 01403 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 01404 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01405 } 01406 ast_mutex_lock(&p->lock); 01407 p->mfcr2call = 0; 01408 ast_mutex_unlock(&p->lock); 01409 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 1619 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().
01620 { 01621 switch (level) { 01622 case OR2_LOG_NOTICE: 01623 ast_verbose("%s", logmessage); 01624 break; 01625 case OR2_LOG_WARNING: 01626 ast_log(LOG_WARNING, "%s", logmessage); 01627 break; 01628 case OR2_LOG_ERROR: 01629 ast_log(LOG_ERROR, "%s", logmessage); 01630 break; 01631 case OR2_LOG_STACK_TRACE: 01632 case OR2_LOG_MF_TRACE: 01633 case OR2_LOG_CAS_TRACE: 01634 case OR2_LOG_DEBUG: 01635 case OR2_LOG_EX_DEBUG: 01636 ast_log(LOG_DEBUG, "%s", logmessage); 01637 break; 01638 default: 01639 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 01640 ast_log(LOG_NOTICE, "%s", logmessage); 01641 break; 01642 } 01643 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5909 of file chan_dahdi.c.
References __dahdi_exception(), 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_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_handle_dtmfup(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, 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::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
05910 { 05911 struct dahdi_pvt *p = ast->tech_pvt; 05912 int res; 05913 int index; 05914 void *readbuf; 05915 struct ast_frame *f; 05916 05917 while (ast_mutex_trylock(&p->lock)) { 05918 DEADLOCK_AVOIDANCE(&ast->lock); 05919 } 05920 05921 index = dahdi_get_index(ast, p, 0); 05922 05923 /* Hang up if we don't really exist */ 05924 if (index < 0) { 05925 ast_log(LOG_WARNING, "We dont exist?\n"); 05926 ast_mutex_unlock(&p->lock); 05927 return NULL; 05928 } 05929 05930 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05931 ast_mutex_unlock(&p->lock); 05932 return NULL; 05933 } 05934 05935 p->subs[index].f.frametype = AST_FRAME_NULL; 05936 p->subs[index].f.datalen = 0; 05937 p->subs[index].f.samples = 0; 05938 p->subs[index].f.mallocd = 0; 05939 p->subs[index].f.offset = 0; 05940 p->subs[index].f.subclass = 0; 05941 p->subs[index].f.delivery = ast_tv(0,0); 05942 p->subs[index].f.src = "dahdi_read"; 05943 p->subs[index].f.data = NULL; 05944 05945 /* make sure it sends initial key state as first frame */ 05946 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05947 { 05948 struct dahdi_params ps; 05949 05950 memset(&ps, 0, sizeof(ps)); 05951 ps.channo = p->channel; 05952 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05953 ast_mutex_unlock(&p->lock); 05954 return NULL; 05955 } 05956 p->firstradio = 1; 05957 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05958 if (ps.rxisoffhook) 05959 { 05960 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05961 } 05962 else 05963 { 05964 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05965 } 05966 ast_mutex_unlock(&p->lock); 05967 return &p->subs[index].f; 05968 } 05969 if (p->ringt == 1) { 05970 ast_mutex_unlock(&p->lock); 05971 return NULL; 05972 } 05973 else if (p->ringt > 0) 05974 p->ringt--; 05975 05976 #ifdef HAVE_OPENR2 05977 if (p->mfcr2) { 05978 openr2_chan_process_event(p->r2chan); 05979 } 05980 #endif 05981 05982 if (p->subs[index].needringing) { 05983 /* Send ringing frame if requested */ 05984 p->subs[index].needringing = 0; 05985 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05986 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05987 ast_setstate(ast, AST_STATE_RINGING); 05988 ast_mutex_unlock(&p->lock); 05989 return &p->subs[index].f; 05990 } 05991 05992 if (p->subs[index].needbusy) { 05993 /* Send busy frame if requested */ 05994 p->subs[index].needbusy = 0; 05995 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05996 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05997 ast_mutex_unlock(&p->lock); 05998 return &p->subs[index].f; 05999 } 06000 06001 if (p->subs[index].needcongestion) { 06002 /* Send congestion frame if requested */ 06003 p->subs[index].needcongestion = 0; 06004 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06005 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 06006 ast_mutex_unlock(&p->lock); 06007 return &p->subs[index].f; 06008 } 06009 06010 if (p->subs[index].needcallerid) { 06011 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06012 S_OR(p->lastcid_name, NULL), 06013 S_OR(p->lastcid_num, NULL) 06014 ); 06015 p->subs[index].needcallerid = 0; 06016 } 06017 06018 if (p->subs[index].needanswer) { 06019 /* Send answer frame if requested */ 06020 p->subs[index].needanswer = 0; 06021 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06022 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 06023 ast_mutex_unlock(&p->lock); 06024 return &p->subs[index].f; 06025 } 06026 06027 #ifdef HAVE_OPENR2 06028 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06029 /* openr2 took care of reading and handling any event 06030 (needanswer, needbusy etc), if we continue we will read() 06031 twice, lets just return a null frame. This should only 06032 happen when openr2 is dialing out */ 06033 p->subs[index].f.frametype = AST_FRAME_NULL; 06034 p->subs[index].f.subclass = 0; 06035 p->subs[index].f.samples = 0; 06036 p->subs[index].f.mallocd = 0; 06037 p->subs[index].f.offset = 0; 06038 p->subs[index].f.data = NULL; 06039 p->subs[index].f.datalen= 0; 06040 ast_mutex_unlock(&p->lock); 06041 return &p->subs[index].f; 06042 } 06043 #endif 06044 06045 if (p->subs[index].needflash) { 06046 /* Send answer frame if requested */ 06047 p->subs[index].needflash = 0; 06048 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06049 p->subs[index].f.subclass = AST_CONTROL_FLASH; 06050 ast_mutex_unlock(&p->lock); 06051 return &p->subs[index].f; 06052 } 06053 06054 if (p->subs[index].needhold) { 06055 /* Send answer frame if requested */ 06056 p->subs[index].needhold = 0; 06057 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06058 p->subs[index].f.subclass = AST_CONTROL_HOLD; 06059 ast_mutex_unlock(&p->lock); 06060 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 06061 return &p->subs[index].f; 06062 } 06063 06064 if (p->subs[index].needunhold) { 06065 /* Send answer frame if requested */ 06066 p->subs[index].needunhold = 0; 06067 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06068 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 06069 ast_mutex_unlock(&p->lock); 06070 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 06071 return &p->subs[index].f; 06072 } 06073 06074 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06075 if (!p->subs[index].linear) { 06076 p->subs[index].linear = 1; 06077 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06078 if (res) 06079 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 06080 } 06081 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06082 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06083 if (p->subs[index].linear) { 06084 p->subs[index].linear = 0; 06085 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06086 if (res) 06087 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 06088 } 06089 } else { 06090 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06091 ast_mutex_unlock(&p->lock); 06092 return NULL; 06093 } 06094 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 06095 CHECK_BLOCKING(ast); 06096 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06097 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06098 /* Check for hangup */ 06099 if (res < 0) { 06100 f = NULL; 06101 if (res == -1) { 06102 if (errno == EAGAIN) { 06103 /* Return "NULL" frame if there is nobody there */ 06104 ast_mutex_unlock(&p->lock); 06105 return &p->subs[index].f; 06106 } else if (errno == ELAST) { 06107 f = __dahdi_exception(ast); 06108 } else 06109 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06110 } 06111 ast_mutex_unlock(&p->lock); 06112 return f; 06113 } 06114 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 06115 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06116 f = __dahdi_exception(ast); 06117 ast_mutex_unlock(&p->lock); 06118 return f; 06119 } 06120 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06121 int c; 06122 06123 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06124 if (c < 0) { 06125 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 06126 ast_mutex_unlock(&p->lock); 06127 return NULL; 06128 } 06129 if (c) { /* if a char to return */ 06130 p->subs[index].f.subclass = 0; 06131 p->subs[index].f.frametype = AST_FRAME_TEXT; 06132 p->subs[index].f.mallocd = 0; 06133 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06134 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 06135 p->subs[index].f.datalen = 1; 06136 *((char *) p->subs[index].f.data) = c; 06137 ast_mutex_unlock(&p->lock); 06138 return &p->subs[index].f; 06139 } 06140 } 06141 /* Ensure the CW timer decrements only on a single subchannel */ 06142 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 06143 p->callwaitingrepeat--; 06144 } 06145 if (p->cidcwexpire) 06146 p->cidcwexpire--; 06147 /* Repeat callwaiting */ 06148 if (p->callwaitingrepeat == 1) { 06149 p->callwaitrings++; 06150 dahdi_callwait(ast); 06151 } 06152 /* Expire CID/CW */ 06153 if (p->cidcwexpire == 1) { 06154 if (option_verbose > 2) 06155 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 06156 restore_conference(p); 06157 } 06158 if (p->subs[index].linear) { 06159 p->subs[index].f.datalen = READ_SIZE * 2; 06160 } else 06161 p->subs[index].f.datalen = READ_SIZE; 06162 06163 /* Handle CallerID Transmission */ 06164 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06165 send_callerid(p); 06166 } 06167 06168 p->subs[index].f.frametype = AST_FRAME_VOICE; 06169 p->subs[index].f.subclass = ast->rawreadformat; 06170 p->subs[index].f.samples = READ_SIZE; 06171 p->subs[index].f.mallocd = 0; 06172 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06173 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 06174 #if 0 06175 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 06176 #endif 06177 if (p->dialing || /* Transmitting something */ 06178 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06179 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06180 ) { 06181 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06182 don't send anything */ 06183 p->subs[index].f.frametype = AST_FRAME_NULL; 06184 p->subs[index].f.subclass = 0; 06185 p->subs[index].f.samples = 0; 06186 p->subs[index].f.mallocd = 0; 06187 p->subs[index].f.offset = 0; 06188 p->subs[index].f.data = NULL; 06189 p->subs[index].f.datalen= 0; 06190 } 06191 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 06192 /* Perform busy detection. etc on the dahdi line */ 06193 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 06194 if (f) { 06195 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 06196 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 06197 /* Treat this as a "hangup" instead of a "busy" on the assumption that 06198 a busy */ 06199 f = NULL; 06200 } 06201 } else if (f->frametype == AST_FRAME_DTMF) { 06202 #ifdef HAVE_PRI 06203 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial && 06204 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 06205 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 06206 /* Don't accept in-band DTMF when in overlap dial mode */ 06207 f->frametype = AST_FRAME_NULL; 06208 f->subclass = 0; 06209 } 06210 #endif 06211 /* DSP clears us of being pulse */ 06212 p->pulsedial = 0; 06213 } 06214 } 06215 } else 06216 f = &p->subs[index].f; 06217 06218 if (f && (f->frametype == AST_FRAME_DTMF)) 06219 dahdi_handle_dtmfup(ast, index, &f); 06220 06221 /* If we have a fake_event, trigger exception to handle it */ 06222 if (p->fake_event) 06223 ast_set_flag(ast, AST_FLAG_EXCEPTION); 06224 06225 ast_mutex_unlock(&p->lock); 06226 return f; 06227 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9330 of file chan_dahdi.c.
References alloc_sub(), 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, 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, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
09331 { 09332 ast_group_t groupmatch = 0; 09333 int channelmatch = -1; 09334 int roundrobin = 0; 09335 int callwait = 0; 09336 int busy = 0; 09337 struct dahdi_pvt *p; 09338 struct ast_channel *tmp = NULL; 09339 char *dest=NULL; 09340 int x; 09341 char *s; 09342 char opt=0; 09343 int res=0, y=0; 09344 int backwards = 0; 09345 #ifdef HAVE_PRI 09346 int crv; 09347 int bearer = -1; 09348 int trunkgroup; 09349 struct dahdi_pri *pri=NULL; 09350 #endif 09351 struct dahdi_pvt *exit, *start, *end; 09352 ast_mutex_t *lock; 09353 int channelmatched = 0; 09354 int groupmatched = 0; 09355 09356 /* 09357 * data is ---v 09358 * Dial(DAHDI/pseudo[/extension]) 09359 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09360 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09361 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09362 * 09363 * g - channel group allocation search forward 09364 * G - channel group allocation search backward 09365 * r - channel group allocation round robin search forward 09366 * R - channel group allocation round robin search backward 09367 * 09368 * c - Wait for DTMF digit to confirm answer 09369 * r<cadance#> - Set distintive ring cadance number 09370 * d - Force bearer capability for ISDN call to digital. 09371 */ 09372 09373 /* Assume we're locking the iflock */ 09374 lock = &iflock; 09375 start = iflist; 09376 end = ifend; 09377 if (data) { 09378 dest = ast_strdupa((char *)data); 09379 } else { 09380 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09381 return NULL; 09382 } 09383 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09384 /* Retrieve the group number */ 09385 char *stringp; 09386 09387 stringp = dest + 1; 09388 s = strsep(&stringp, "/"); 09389 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09390 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09391 return NULL; 09392 } 09393 groupmatch = ((ast_group_t) 1 << x); 09394 if (toupper(dest[0]) == 'G') { 09395 if (dest[0] == 'G') { 09396 backwards = 1; 09397 p = ifend; 09398 } else 09399 p = iflist; 09400 } else { 09401 if (dest[0] == 'R') { 09402 backwards = 1; 09403 p = round_robin[x]?round_robin[x]->prev:ifend; 09404 if (!p) 09405 p = ifend; 09406 } else { 09407 p = round_robin[x]?round_robin[x]->next:iflist; 09408 if (!p) 09409 p = iflist; 09410 } 09411 roundrobin = 1; 09412 } 09413 } else { 09414 char *stringp; 09415 09416 stringp = dest; 09417 s = strsep(&stringp, "/"); 09418 p = iflist; 09419 if (!strcasecmp(s, "pseudo")) { 09420 /* Special case for pseudo */ 09421 x = CHAN_PSEUDO; 09422 channelmatch = x; 09423 } 09424 #ifdef HAVE_PRI 09425 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09426 if ((trunkgroup < 1) || (crv < 1)) { 09427 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09428 return NULL; 09429 } 09430 res--; 09431 for (x = 0; x < NUM_SPANS; x++) { 09432 if (pris[x].trunkgroup == trunkgroup) { 09433 pri = pris + x; 09434 lock = &pri->lock; 09435 start = pri->crvs; 09436 end = pri->crvend; 09437 break; 09438 } 09439 } 09440 if (!pri) { 09441 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09442 return NULL; 09443 } 09444 channelmatch = crv; 09445 p = pris[x].crvs; 09446 } 09447 #endif 09448 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09449 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09450 return NULL; 09451 } else { 09452 channelmatch = x; 09453 } 09454 } 09455 /* Search for an unowned channel */ 09456 ast_mutex_lock(lock); 09457 exit = p; 09458 while (p && !tmp) { 09459 if (roundrobin) 09460 round_robin[x] = p; 09461 #if 0 09462 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09463 #endif 09464 09465 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09466 if (option_debug) 09467 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 09468 if (p->inalarm) 09469 goto next; 09470 09471 callwait = (p->owner != NULL); 09472 #ifdef HAVE_PRI 09473 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09474 if (p->sig != SIG_FXSKS) { 09475 /* Gotta find an actual channel to use for this 09476 CRV if this isn't a callwait */ 09477 bearer = pri_find_empty_chan(pri, 0); 09478 if (bearer < 0) { 09479 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09480 p = NULL; 09481 break; 09482 } 09483 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09484 } else { 09485 if (alloc_sub(p, 0)) { 09486 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09487 p = NULL; 09488 break; 09489 } else 09490 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 09491 p->pri = pri; 09492 } 09493 } 09494 #endif 09495 #ifdef HAVE_OPENR2 09496 if (p->mfcr2) { 09497 ast_mutex_lock(&p->lock); 09498 if (p->mfcr2call) { 09499 ast_mutex_unlock(&p->lock); 09500 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 09501 goto next; 09502 } 09503 if (p->mfcr2block) { 09504 ast_mutex_unlock(&p->lock); 09505 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block); 09506 goto next; 09507 } 09508 p->mfcr2call = 1; 09509 ast_mutex_unlock(&p->lock); 09510 } 09511 #endif 09512 if (p->channel == CHAN_PSEUDO) { 09513 p = chandup(p); 09514 if (!p) { 09515 break; 09516 } 09517 } 09518 if (p->owner) { 09519 if (alloc_sub(p, SUB_CALLWAIT)) { 09520 p = NULL; 09521 break; 09522 } 09523 } 09524 p->outgoing = 1; 09525 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09526 if (!tmp) { 09527 p->outgoing = 0; 09528 } 09529 #ifdef HAVE_PRI 09530 if (p->bearer) { 09531 /* Log owner to bearer channel, too */ 09532 p->bearer->owner = tmp; 09533 } 09534 #endif 09535 /* Make special notes */ 09536 if (res > 1) { 09537 if (opt == 'c') { 09538 /* Confirm answer */ 09539 p->confirmanswer = 1; 09540 } else if (opt == 'r') { 09541 /* Distinctive ring */ 09542 if (res < 3) 09543 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09544 else 09545 p->distinctivering = y; 09546 } else if (opt == 'd') { 09547 /* If this is an ISDN call, make it digital */ 09548 p->digital = 1; 09549 if (tmp) 09550 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09551 } else { 09552 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09553 } 09554 } 09555 /* Note if the call is a call waiting call */ 09556 if (tmp && callwait) 09557 tmp->cdrflags |= AST_CDR_CALLWAIT; 09558 break; 09559 } 09560 next: 09561 if (backwards) { 09562 p = p->prev; 09563 if (!p) 09564 p = end; 09565 } else { 09566 p = p->next; 09567 if (!p) 09568 p = start; 09569 } 09570 /* stop when you roll to the one that we started from */ 09571 if (p == exit) 09572 break; 09573 } 09574 ast_mutex_unlock(lock); 09575 restart_monitor(); 09576 if (callwait) 09577 *cause = AST_CAUSE_BUSY; 09578 else if (!tmp) { 09579 if (channelmatched) { 09580 if (busy) 09581 *cause = AST_CAUSE_BUSY; 09582 } else if (groupmatched) { 09583 *cause = AST_CAUSE_CONGESTION; 09584 } 09585 } 09586 09587 return tmp; 09588 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 11962 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, monlock, dahdi_pvt::next, NUM_SPANS, option_debug, option_verbose, dahdi_pvt::owner, pris, r2links, restart_lock, setup_dahdi(), ss_thread_lock, and dahdi_pvt::subs.
Referenced by __action_restart(), and dahdi_restart_cmd().
11963 { 11964 #ifdef HAVE_OPENR2 11965 int r; 11966 #endif 11967 #if defined(HAVE_PRI) 11968 int i, j; 11969 #endif 11970 int cancel_code; 11971 struct dahdi_pvt *p; 11972 11973 ast_mutex_lock(&restart_lock); 11974 11975 if (option_verbose) 11976 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 11977 dahdi_softhangup_all(); 11978 if (option_verbose > 3) 11979 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 11980 11981 #ifdef HAVE_OPENR2 11982 for (r = 0; r < NUM_SPANS; r++) { 11983 if (r2links[r].master != AST_PTHREADT_NULL) { 11984 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master); 11985 pthread_cancel(r2links[r].master); 11986 pthread_join(r2links[r].master, NULL); 11987 openr2_context_delete(r2links[r].protocol_context); 11988 } 11989 } 11990 init_mfcr2_globals(); 11991 #endif 11992 11993 #if defined(HAVE_PRI) 11994 for (i = 0; i < NUM_SPANS; i++) { 11995 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 11996 cancel_code = pthread_cancel(pris[i].master); 11997 pthread_kill(pris[i].master, SIGURG); 11998 if (option_debug > 3) 11999 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12000 pthread_join(pris[i].master, NULL); 12001 if (option_debug > 3) 12002 ast_verbose("Joined thread of span %d\n", i); 12003 } 12004 } 12005 #endif 12006 12007 ast_mutex_lock(&monlock); 12008 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12009 cancel_code = pthread_cancel(monitor_thread); 12010 pthread_kill(monitor_thread, SIGURG); 12011 if (option_debug > 3) 12012 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12013 pthread_join(monitor_thread, NULL); 12014 if (option_debug > 3) 12015 ast_verbose("Joined monitor thread\n"); 12016 } 12017 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12018 12019 ast_mutex_lock(&ss_thread_lock); 12020 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12021 int x = DAHDI_FLASH; 12022 if (option_debug > 2) 12023 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12024 12025 for (p = iflist; p; p = p->next) { 12026 if (p->owner) 12027 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 */ 12028 } 12029 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12030 } 12031 12032 /* ensure any created channels before monitor threads were stopped are hungup */ 12033 dahdi_softhangup_all(); 12034 if (option_verbose > 3) 12035 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 12036 destroy_all_channels(); 12037 if (option_debug) 12038 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12039 12040 ast_mutex_unlock(&monlock); 12041 12042 #ifdef HAVE_PRI 12043 for (i = 0; i < NUM_SPANS; i++) { 12044 for (j = 0; j < NUM_DCHANS; j++) 12045 dahdi_close_pri_fd(&(pris[i]), j); 12046 } 12047 12048 memset(pris, 0, sizeof(pris)); 12049 for (i = 0; i < NUM_SPANS; i++) { 12050 ast_mutex_init(&pris[i].lock); 12051 pris[i].offset = -1; 12052 pris[i].master = AST_PTHREADT_NULL; 12053 for (j = 0; j < NUM_DCHANS; j++) 12054 pris[i].fds[j] = -1; 12055 } 12056 pri_set_error(dahdi_pri_error); 12057 pri_set_message(dahdi_pri_message); 12058 #endif 12059 12060 if (setup_dahdi(2) != 0) { 12061 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12062 ast_mutex_unlock(&ss_thread_lock); 12063 return 1; 12064 } 12065 ast_mutex_unlock(&ss_thread_lock); 12066 ast_mutex_unlock(&restart_lock); 12067 return 0; 12068 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12070 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12071 { 12072 if (argc != 2) { 12073 return RESULT_SHOWUSAGE; 12074 } 12075 12076 if (dahdi_restart() != 0) 12077 return RESULT_FAILURE; 12078 return RESULT_SUCCESS; 12079 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4686 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04687 { 04688 int x; 04689 int res; 04690 /* Make sure our transmit state is on hook */ 04691 x = 0; 04692 x = DAHDI_ONHOOK; 04693 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04694 do { 04695 x = DAHDI_RING; 04696 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04697 if (res) { 04698 switch (errno) { 04699 case EBUSY: 04700 case EINTR: 04701 /* Wait just in case */ 04702 usleep(10000); 04703 continue; 04704 case EINPROGRESS: 04705 res = 0; 04706 break; 04707 default: 04708 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04709 res = 0; 04710 } 04711 } 04712 } while (res); 04713 return res; 04714 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3340 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
03341 { 03342 return send_keypad_facility_exec(chan, data); 03343 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 14002 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, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
14003 { 14004 #define END_SILENCE_LEN 400 14005 #define HEADER_MS 50 14006 #define TRAILER_MS 5 14007 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 14008 #define ASCII_BYTES_PER_CHAR 80 14009 14010 unsigned char *buf,*mybuf; 14011 struct dahdi_pvt *p = c->tech_pvt; 14012 struct pollfd fds[1]; 14013 int size,res,fd,len,x; 14014 int bytes=0; 14015 /* Initial carrier (imaginary) */ 14016 float cr = 1.0; 14017 float ci = 0.0; 14018 float scont = 0.0; 14019 int index; 14020 14021 index = dahdi_get_index(c, p, 0); 14022 if (index < 0) { 14023 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 14024 return -1; 14025 } 14026 if (!text[0]) return(0); /* if nothing to send, dont */ 14027 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 14028 if (p->mate) 14029 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 14030 else 14031 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 14032 if (!buf) 14033 return -1; 14034 mybuf = buf; 14035 if (p->mate) { 14036 int codec = AST_LAW(p); 14037 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 14038 PUT_CLID_MARKMS; 14039 } 14040 /* Put actual message */ 14041 for (x = 0; text[x]; x++) { 14042 PUT_CLID(text[x]); 14043 } 14044 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 14045 PUT_CLID_MARKMS; 14046 } 14047 len = bytes; 14048 buf = mybuf; 14049 } else { 14050 len = tdd_generate(p->tdd, buf, text); 14051 if (len < 1) { 14052 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 14053 free(mybuf); 14054 return -1; 14055 } 14056 } 14057 memset(buf + len, 0x7f, END_SILENCE_LEN); 14058 len += END_SILENCE_LEN; 14059 fd = p->subs[index].dfd; 14060 while (len) { 14061 if (ast_check_hangup(c)) { 14062 free(mybuf); 14063 return -1; 14064 } 14065 size = len; 14066 if (size > READ_SIZE) 14067 size = READ_SIZE; 14068 fds[0].fd = fd; 14069 fds[0].events = POLLOUT | POLLPRI; 14070 fds[0].revents = 0; 14071 res = poll(fds, 1, -1); 14072 if (!res) { 14073 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 14074 continue; 14075 } 14076 /* if got exception */ 14077 if (fds[0].revents & POLLPRI) { 14078 ast_free(mybuf); 14079 return -1; 14080 } 14081 if (!(fds[0].revents & POLLOUT)) { 14082 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 14083 continue; 14084 } 14085 res = write(fd, buf, size); 14086 if (res != size) { 14087 if (res == -1) { 14088 free(mybuf); 14089 return -1; 14090 } 14091 if (option_debug) 14092 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 14093 break; 14094 } 14095 len -= size; 14096 buf += size; 14097 } 14098 free(mybuf); 14099 return(0); 14100 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2553 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().
02554 { 02555 int x, res; 02556 02557 x = hs; 02558 res = ioctl(fd, DAHDI_HOOK, &x); 02559 02560 if (res < 0) { 02561 if (errno == EINPROGRESS) 02562 return 0; 02563 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02564 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02565 } 02566 02567 return res; 02568 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 10033 of file chan_dahdi.c.
10034 { 10035 int res; 10036 res = ioctl(dfd, DAHDI_SETLAW, &law); 10037 if (res) 10038 return res; 10039 return 0; 10040 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1867 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01868 { 01869 int res; 01870 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01871 if (res) 01872 return res; 01873 return 0; 01874 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 4050 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.
04051 { 04052 char *cp; 04053 signed char *scp; 04054 int x; 04055 int index; 04056 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04057 struct oprmode *oprmode; 04058 04059 04060 /* all supported options require data */ 04061 if (!data || (datalen < 1)) { 04062 errno = EINVAL; 04063 return -1; 04064 } 04065 04066 switch (option) { 04067 case AST_OPTION_TXGAIN: 04068 scp = (signed char *) data; 04069 index = dahdi_get_index(chan, p, 0); 04070 if (index < 0) { 04071 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04072 return -1; 04073 } 04074 if (option_debug) 04075 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04076 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 04077 case AST_OPTION_RXGAIN: 04078 scp = (signed char *) data; 04079 index = dahdi_get_index(chan, p, 0); 04080 if (index < 0) { 04081 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04082 return -1; 04083 } 04084 if (option_debug) 04085 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04086 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 04087 case AST_OPTION_TONE_VERIFY: 04088 if (!p->dsp) 04089 break; 04090 cp = (char *) data; 04091 switch (*cp) { 04092 case 1: 04093 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04094 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04095 break; 04096 case 2: 04097 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04098 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04099 break; 04100 default: 04101 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04102 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04103 break; 04104 } 04105 break; 04106 case AST_OPTION_TDD: 04107 /* turn on or off TDD */ 04108 cp = (char *) data; 04109 p->mate = 0; 04110 if (!*cp) { /* turn it off */ 04111 if (option_debug) 04112 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04113 if (p->tdd) 04114 tdd_free(p->tdd); 04115 p->tdd = 0; 04116 break; 04117 } 04118 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 04119 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04120 dahdi_disable_ec(p); 04121 /* otherwise, turn it on */ 04122 if (!p->didtdd) { /* if havent done it yet */ 04123 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04124 unsigned char *buf; 04125 int size, res, fd, len; 04126 struct pollfd fds[1]; 04127 04128 buf = mybuf; 04129 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04130 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04131 len = 40000; 04132 index = dahdi_get_index(chan, p, 0); 04133 if (index < 0) { 04134 ast_log(LOG_WARNING, "No index in TDD?\n"); 04135 return -1; 04136 } 04137 fd = p->subs[index].dfd; 04138 while (len) { 04139 if (ast_check_hangup(chan)) 04140 return -1; 04141 size = len; 04142 if (size > READ_SIZE) 04143 size = READ_SIZE; 04144 fds[0].fd = fd; 04145 fds[0].events = POLLPRI | POLLOUT; 04146 fds[0].revents = 0; 04147 res = poll(fds, 1, -1); 04148 if (!res) { 04149 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 04150 continue; 04151 } 04152 /* if got exception */ 04153 if (fds[0].revents & POLLPRI) 04154 return -1; 04155 if (!(fds[0].revents & POLLOUT)) { 04156 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 04157 continue; 04158 } 04159 res = write(fd, buf, size); 04160 if (res != size) { 04161 if (res == -1) return -1; 04162 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04163 break; 04164 } 04165 len -= size; 04166 buf += size; 04167 } 04168 p->didtdd = 1; /* set to have done it now */ 04169 } 04170 if (*cp == 2) { /* Mate mode */ 04171 if (p->tdd) 04172 tdd_free(p->tdd); 04173 p->tdd = 0; 04174 p->mate = 1; 04175 break; 04176 } 04177 if (!p->tdd) { /* if we dont have one yet */ 04178 p->tdd = tdd_new(); /* allocate one */ 04179 } 04180 break; 04181 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04182 if (!p->dsp) 04183 break; 04184 cp = (char *) data; 04185 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04186 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04187 p->dtmfrelax = 0; 04188 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 04189 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04190 break; 04191 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04192 cp = (char *) data; 04193 if (!*cp) { 04194 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04195 x = 0; 04196 dahdi_disable_ec(p); 04197 } else { 04198 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04199 x = 1; 04200 } 04201 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04202 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04203 break; 04204 case AST_OPTION_OPRMODE: /* Operator services mode */ 04205 oprmode = (struct oprmode *) data; 04206 pp = oprmode->peer->tech_pvt; 04207 p->oprmode = pp->oprmode = 0; 04208 /* setup peers */ 04209 p->oprpeer = pp; 04210 pp->oprpeer = p; 04211 /* setup modes, if any */ 04212 if (oprmode->mode) 04213 { 04214 pp->oprmode = oprmode->mode; 04215 p->oprmode = -oprmode->mode; 04216 } 04217 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 04218 oprmode->mode, chan->name,oprmode->peer->name);; 04219 break; 04220 case AST_OPTION_ECHOCAN: 04221 cp = (char *) data; 04222 if (*cp) { 04223 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 04224 dahdi_enable_ec(p); 04225 } else { 04226 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 04227 dahdi_disable_ec(p); 04228 } 04229 break; 04230 } 04231 errno = 0; 04232 04233 return 0; 04234 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12142 of file chan_dahdi.c.
References 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, 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.
12143 { 12144 int channel; 12145 struct dahdi_pvt *tmp = NULL; 12146 struct dahdi_confinfo ci; 12147 struct dahdi_params ps; 12148 int x; 12149 ast_mutex_t *lock; 12150 struct dahdi_pvt *start; 12151 #ifdef HAVE_PRI 12152 char *c; 12153 int trunkgroup; 12154 struct dahdi_pri *pri=NULL; 12155 #endif 12156 12157 lock = &iflock; 12158 start = iflist; 12159 12160 if (argc != 4) 12161 return RESULT_SHOWUSAGE; 12162 #ifdef HAVE_PRI 12163 if ((c = strchr(argv[3], ':'))) { 12164 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12165 return RESULT_SHOWUSAGE; 12166 if ((trunkgroup < 1) || (channel < 1)) 12167 return RESULT_SHOWUSAGE; 12168 for (x = 0; x < NUM_SPANS; x++) { 12169 if (pris[x].trunkgroup == trunkgroup) { 12170 pri = pris + x; 12171 break; 12172 } 12173 } 12174 if (pri) { 12175 start = pri->crvs; 12176 lock = &pri->lock; 12177 } else { 12178 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12179 return RESULT_FAILURE; 12180 } 12181 } else 12182 #endif 12183 channel = atoi(argv[3]); 12184 12185 ast_mutex_lock(lock); 12186 tmp = start; 12187 while (tmp) { 12188 if (tmp->channel == channel) { 12189 #ifdef HAVE_PRI 12190 if (pri) 12191 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12192 else 12193 #endif 12194 ast_cli(fd, "Channel: %d\n", tmp->channel); 12195 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12196 ast_cli(fd, "Span: %d\n", tmp->span); 12197 ast_cli(fd, "Extension: %s\n", tmp->exten); 12198 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12199 ast_cli(fd, "Context: %s\n", tmp->context); 12200 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 12201 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 12202 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 12203 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 12204 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 12205 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12206 ast_cli(fd, "Radio: %d\n", tmp->radio); 12207 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12208 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)" : ""); 12209 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)" : ""); 12210 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)" : ""); 12211 ast_cli(fd, "Confno: %d\n", tmp->confno); 12212 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 12213 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 12214 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12215 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12216 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12217 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12218 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12219 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12220 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 12221 if (tmp->master) 12222 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 12223 for (x = 0; x < MAX_SLAVES; x++) { 12224 if (tmp->slaves[x]) 12225 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12226 } 12227 #ifdef HAVE_OPENR2 12228 if (tmp->mfcr2) { 12229 char calldir[OR2_MAX_PATH]; 12230 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 12231 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 12232 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No"); 12233 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No"); 12234 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 12235 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 12236 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 12237 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 12238 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 12239 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 12240 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 12241 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 12243 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No"); 12244 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No"); 12245 #endif 12246 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 12247 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 12248 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 12249 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 12250 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 12251 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 12252 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 12253 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 12254 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 12255 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 12256 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 12257 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 12258 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 12259 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 12260 } 12261 #endif 12262 #ifdef HAVE_PRI 12263 if (tmp->pri) { 12264 ast_cli(fd, "PRI Flags: "); 12265 if (tmp->resetting) 12266 ast_cli(fd, "Resetting "); 12267 if (tmp->call) 12268 ast_cli(fd, "Call "); 12269 if (tmp->bearer) 12270 ast_cli(fd, "Bearer "); 12271 ast_cli(fd, "\n"); 12272 if (tmp->logicalspan) 12273 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12274 else 12275 ast_cli(fd, "PRI Logical Span: Implicit\n"); 12276 } 12277 12278 #endif 12279 memset(&ci, 0, sizeof(ci)); 12280 ps.channo = tmp->channel; 12281 if (tmp->subs[SUB_REAL].dfd > -1) { 12282 memset(&ci, 0, sizeof(ci)); 12283 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12284 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12285 } 12286 #ifdef DAHDI_GETCONFMUTE 12287 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12288 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12289 } 12290 #endif 12291 memset(&ps, 0, sizeof(ps)); 12292 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12293 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12294 } else { 12295 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12296 } 12297 } 12298 if (ISTRUNK(tmp)) { 12299 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12300 if (!ast_strlen_zero(progzone)) 12301 ast_cli(fd, "Progress Zone: %s\n", progzone); 12302 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12303 if(tmp->busydetect) { 12304 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 12305 if(tmp->busytonelength > 0) { 12306 ast_cli(fd, "Busy Pattern:\n"); 12307 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12308 if (tmp->busyquietlength > 0) 12309 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12310 else 12311 ast_cli(fd, " -- Detect Tone Only\n"); 12312 if(tmp->busyfuzziness > 0) 12313 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12314 } 12315 } 12316 } 12317 ast_mutex_unlock(lock); 12318 return RESULT_SUCCESS; 12319 } 12320 tmp = tmp->next; 12321 } 12322 12323 ast_cli(fd, "Unable to find given channel %d\n", channel); 12324 ast_mutex_unlock(lock); 12325 return RESULT_FAILURE; 12326 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12081 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.
12082 { 12083 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12084 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12085 struct dahdi_pvt *tmp = NULL; 12086 char tmps[20] = ""; 12087 ast_mutex_t *lock; 12088 struct dahdi_pvt *start; 12089 #ifdef HAVE_PRI 12090 int trunkgroup; 12091 struct dahdi_pri *pri = NULL; 12092 int x; 12093 #endif 12094 12095 lock = &iflock; 12096 start = iflist; 12097 12098 #ifdef HAVE_PRI 12099 if (argc == 4) { 12100 if ((trunkgroup = atoi(argv[3])) < 1) 12101 return RESULT_SHOWUSAGE; 12102 for (x = 0; x < NUM_SPANS; x++) { 12103 if (pris[x].trunkgroup == trunkgroup) { 12104 pri = pris + x; 12105 break; 12106 } 12107 } 12108 if (pri) { 12109 start = pri->crvs; 12110 lock = &pri->lock; 12111 } else { 12112 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12113 return RESULT_FAILURE; 12114 } 12115 } else 12116 #endif 12117 if (argc != 3) 12118 return RESULT_SHOWUSAGE; 12119 12120 ast_mutex_lock(lock); 12121 #ifdef HAVE_PRI 12122 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12123 #else 12124 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12125 #endif 12126 12127 tmp = start; 12128 while (tmp) { 12129 if (tmp->channel > 0) { 12130 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12131 } else 12132 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12133 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 12134 tmp = tmp->next; 12135 } 12136 ast_mutex_unlock(lock); 12137 return RESULT_SUCCESS; 12138 #undef FORMAT 12139 #undef FORMAT2 12140 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12359 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
12359 { 12360 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 12361 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 12362 12363 int span; 12364 int res; 12365 char alarms[50]; 12366 12367 int ctl; 12368 struct dahdi_spaninfo s; 12369 12370 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 12371 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 12372 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 12373 return RESULT_FAILURE; 12374 } 12375 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 12376 12377 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 12378 s.spanno = span; 12379 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 12380 if (res) { 12381 continue; 12382 } 12383 alarms[0] = '\0'; 12384 if (s.alarms > 0) { 12385 if (s.alarms & DAHDI_ALARM_BLUE) 12386 strcat(alarms, "BLU/"); 12387 if (s.alarms & DAHDI_ALARM_YELLOW) 12388 strcat(alarms, "YEL/"); 12389 if (s.alarms & DAHDI_ALARM_RED) 12390 strcat(alarms, "RED/"); 12391 if (s.alarms & DAHDI_ALARM_LOOPBACK) 12392 strcat(alarms, "LB/"); 12393 if (s.alarms & DAHDI_ALARM_RECOVER) 12394 strcat(alarms, "REC/"); 12395 if (s.alarms & DAHDI_ALARM_NOTOPEN) 12396 strcat(alarms, "NOP/"); 12397 if (!strlen(alarms)) 12398 strcat(alarms, "UUU/"); 12399 if (strlen(alarms)) { 12400 /* Strip trailing / */ 12401 alarms[strlen(alarms) - 1] = '\0'; 12402 } 12403 } else { 12404 if (s.numchans) 12405 strcpy(alarms, "OK"); 12406 else 12407 strcpy(alarms, "UNCONFIGURED"); 12408 } 12409 12410 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 12411 } 12412 close(ctl); 12413 12414 return RESULT_SUCCESS; 12415 #undef FORMAT 12416 #undef FORMAT2 12417 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2104 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.
02105 { 02106 static char buf[256]; 02107 switch (sig) { 02108 case SIG_EM: 02109 return "E & M Immediate"; 02110 case SIG_EMWINK: 02111 return "E & M Wink"; 02112 case SIG_EM_E1: 02113 return "E & M E1"; 02114 case SIG_FEATD: 02115 return "Feature Group D (DTMF)"; 02116 case SIG_FEATDMF: 02117 return "Feature Group D (MF)"; 02118 case SIG_FEATDMF_TA: 02119 return "Feature Groud D (MF) Tandem Access"; 02120 case SIG_FEATB: 02121 return "Feature Group B (MF)"; 02122 case SIG_E911: 02123 return "E911 (MF)"; 02124 case SIG_FGC_CAMA: 02125 return "FGC/CAMA (Dialpulse)"; 02126 case SIG_FGC_CAMAMF: 02127 return "FGC/CAMA (MF)"; 02128 case SIG_FXSLS: 02129 return "FXS Loopstart"; 02130 case SIG_FXSGS: 02131 return "FXS Groundstart"; 02132 case SIG_FXSKS: 02133 return "FXS Kewlstart"; 02134 case SIG_FXOLS: 02135 return "FXO Loopstart"; 02136 case SIG_FXOGS: 02137 return "FXO Groundstart"; 02138 case SIG_FXOKS: 02139 return "FXO Kewlstart"; 02140 case SIG_PRI: 02141 return "ISDN PRI"; 02142 case SIG_MFCR2: 02143 return "MFC/R2"; 02144 case SIG_SF: 02145 return "SF (Tone) Immediate"; 02146 case SIG_SFWINK: 02147 return "SF (Tone) Wink"; 02148 case SIG_SF_FEATD: 02149 return "SF (Tone) with Feature Group D (DTMF)"; 02150 case SIG_SF_FEATDMF: 02151 return "SF (Tone) with Feature Group D (MF)"; 02152 case SIG_SF_FEATB: 02153 return "SF (Tone) with Feature Group B (MF)"; 02154 case SIG_GR303FXOKS: 02155 return "GR-303 with FXOKS"; 02156 case SIG_GR303FXSKS: 02157 return "GR-303 with FXSKS"; 02158 case 0: 02159 return "Pseudo"; 02160 default: 02161 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 02162 return buf; 02163 } 02164 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 11933 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, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
11934 { 11935 struct dahdi_pvt *p; 11936 retry: 11937 ast_mutex_lock(&iflock); 11938 for (p = iflist; p; p = p->next) { 11939 ast_mutex_lock(&p->lock); 11940 if (p->owner && !p->restartpending) { 11941 if (ast_channel_trylock(p->owner)) { 11942 if (option_debug > 2) 11943 ast_verbose("Avoiding deadlock\n"); 11944 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 11945 ast_mutex_unlock(&p->lock); 11946 ast_mutex_unlock(&iflock); 11947 goto retry; 11948 } 11949 if (option_debug > 2) 11950 ast_verbose("Softhanging up on %s\n", p->owner->name); 11951 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 11952 p->restartpending = 1; 11953 num_restart_pending++; 11954 ast_channel_unlock(p->owner); 11955 } 11956 ast_mutex_unlock(&p->lock); 11957 } 11958 ast_mutex_unlock(&iflock); 11959 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2385 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().
02386 { 02387 int x; 02388 int res; 02389 if (p && p->echocancel && p->echotraining) { 02390 x = p->echotraining; 02391 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02392 if (res) 02393 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02394 else { 02395 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 02396 } 02397 } else 02398 ast_log(LOG_DEBUG, "No echo training requested\n"); 02399 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4255 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().
04256 { 04257 /* Unlink a specific slave or all slaves/masters from a given master */ 04258 int x; 04259 int hasslaves; 04260 if (!master) 04261 return; 04262 if (needlock) { 04263 ast_mutex_lock(&master->lock); 04264 if (slave) { 04265 while (ast_mutex_trylock(&slave->lock)) { 04266 DEADLOCK_AVOIDANCE(&master->lock); 04267 } 04268 } 04269 } 04270 hasslaves = 0; 04271 for (x = 0; x < MAX_SLAVES; x++) { 04272 if (master->slaves[x]) { 04273 if (!slave || (master->slaves[x] == slave)) { 04274 /* Take slave out of the conference */ 04275 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04276 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04277 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04278 master->slaves[x]->master = NULL; 04279 master->slaves[x] = NULL; 04280 } else 04281 hasslaves = 1; 04282 } 04283 if (!hasslaves) 04284 master->inconference = 0; 04285 } 04286 if (!slave) { 04287 if (master->master) { 04288 /* Take master out of the conference */ 04289 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04290 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04291 hasslaves = 0; 04292 for (x = 0; x < MAX_SLAVES; x++) { 04293 if (master->master->slaves[x] == master) 04294 master->master->slaves[x] = NULL; 04295 else if (master->master->slaves[x]) 04296 hasslaves = 1; 04297 } 04298 if (!hasslaves) 04299 master->master->inconference = 0; 04300 } 04301 master->master = NULL; 04302 } 04303 update_conf(master); 04304 if (needlock) { 04305 if (slave) 04306 ast_mutex_unlock(&slave->lock); 04307 ast_mutex_unlock(&master->lock); 04308 } 04309 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 281 of file chan_dahdi.c.
Referenced by ss_thread().
00282 { 00283 int i, j = 0; 00284 i = DAHDI_IOMUX_SIGEVENT; 00285 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00286 return -1; 00287 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00288 return -1; 00289 return j; 00290 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 6739 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06740 { 06741 int j; 06742 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 06743 for (;;) 06744 { 06745 /* set bits of interest */ 06746 j = DAHDI_IOMUX_SIGEVENT; 06747 /* wait for some happening */ 06748 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06749 /* exit loop if we have it */ 06750 if (j & DAHDI_IOMUX_SIGEVENT) break; 06751 } 06752 /* get the event info */ 06753 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06754 return 0; 06755 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6252 of file chan_dahdi.c.
References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, errno, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, my_dahdi_write(), ast_channel::name, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
06253 { 06254 struct dahdi_pvt *p = ast->tech_pvt; 06255 int res; 06256 int index; 06257 index = dahdi_get_index(ast, p, 0); 06258 if (index < 0) { 06259 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06260 return -1; 06261 } 06262 06263 #if 0 06264 #ifdef HAVE_PRI 06265 ast_mutex_lock(&p->lock); 06266 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06267 if (p->pri->pri) { 06268 if (!pri_grab(p, p->pri)) { 06269 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06270 pri_rel(p->pri); 06271 } else 06272 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06273 } 06274 p->proceeding=1; 06275 } 06276 ast_mutex_unlock(&p->lock); 06277 #endif 06278 #endif 06279 /* Write a frame of (presumably voice) data */ 06280 if (frame->frametype != AST_FRAME_VOICE) { 06281 if (frame->frametype != AST_FRAME_IMAGE) 06282 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06283 return 0; 06284 } 06285 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06286 (frame->subclass != AST_FORMAT_ULAW) && 06287 (frame->subclass != AST_FORMAT_ALAW)) { 06288 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06289 return -1; 06290 } 06291 if (p->dialing) { 06292 if (option_debug) 06293 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06294 return 0; 06295 } 06296 if (!p->owner) { 06297 if (option_debug) 06298 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 06299 return 0; 06300 } 06301 if (p->cidspill) { 06302 if (option_debug) 06303 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 06304 return 0; 06305 } 06306 /* Return if it's not valid data */ 06307 if (!frame->data || !frame->datalen) 06308 return 0; 06309 06310 if (frame->subclass == AST_FORMAT_SLINEAR) { 06311 if (!p->subs[index].linear) { 06312 p->subs[index].linear = 1; 06313 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06314 if (res) 06315 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06316 } 06317 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06318 } else { 06319 /* x-law already */ 06320 if (p->subs[index].linear) { 06321 p->subs[index].linear = 0; 06322 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06323 if (res) 06324 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06325 } 06326 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06327 } 06328 if (res < 0) { 06329 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06330 return -1; 06331 } 06332 return 0; 06333 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3256 of file chan_dahdi.c.
References ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cidspill, destroy_dahdi_pvt(), iflist, iflock, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.
Referenced by __unload_module(), and dahdi_restart().
03257 { 03258 int x; 03259 struct dahdi_pvt *p, *pl; 03260 03261 while (num_restart_pending) { 03262 usleep(1); 03263 } 03264 03265 ast_mutex_lock(&iflock); 03266 /* Destroy all the interfaces and free their memory */ 03267 p = iflist; 03268 while (p) { 03269 /* Free any callerid */ 03270 if (p->cidspill) 03271 ast_free(p->cidspill); 03272 pl = p; 03273 p = p->next; 03274 x = pl->channel; 03275 /* Free associated memory */ 03276 if (pl) 03277 destroy_dahdi_pvt(&pl); 03278 if (option_verbose > 2) 03279 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03280 } 03281 iflist = NULL; 03282 ifcount = 0; 03283 ast_mutex_unlock(&iflock); 03284 }
Definition at line 3206 of file chan_dahdi.c.
References destroy_dahdi_pvt(), 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().
03207 { 03208 int owned = 0; 03209 int i = 0; 03210 03211 if (!now) { 03212 if (cur->owner) { 03213 owned = 1; 03214 } 03215 03216 for (i = 0; i < 3; i++) { 03217 if (cur->subs[i].owner) { 03218 owned = 1; 03219 } 03220 } 03221 if (!owned) { 03222 if (prev) { 03223 prev->next = cur->next; 03224 if (prev->next) 03225 prev->next->prev = prev; 03226 else 03227 ifend = prev; 03228 } else { 03229 iflist = cur->next; 03230 if (iflist) 03231 iflist->prev = NULL; 03232 else 03233 ifend = NULL; 03234 } 03235 destroy_dahdi_pvt(&cur); 03236 } 03237 } else { 03238 if (prev) { 03239 prev->next = cur->next; 03240 if (prev->next) 03241 prev->next->prev = prev; 03242 else 03243 ifend = prev; 03244 } else { 03245 iflist = cur->next; 03246 if (iflist) 03247 iflist->prev = NULL; 03248 else 03249 ifend = NULL; 03250 } 03251 destroy_dahdi_pvt(&cur); 03252 } 03253 return 0; 03254 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3188 of file chan_dahdi.c.
References ast_mutex_destroy(), ast_smdi_interface_unref(), 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().
03189 { 03190 struct dahdi_pvt *p = *pvt; 03191 /* Remove channel from the list */ 03192 if (p->prev) 03193 p->prev->next = p->next; 03194 if (p->next) 03195 p->next->prev = p->prev; 03196 if (p->use_smdi) 03197 ast_smdi_interface_unref(p->smdi_iface); 03198 ast_mutex_destroy(&p->lock); 03199 dahdi_close_sub(p, SUB_REAL); 03200 if (p->owner) 03201 p->owner->tech_pvt = NULL; 03202 free(p); 03203 *pvt = NULL; 03204 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2095 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
02096 { 02097 if (dialplan == -1) { 02098 return("Dynamically set dialplan in ISDN"); 02099 } 02100 return (pri_plan2str(dialplan)); 02101 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1928 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01929 { 01930 if (isdigit(digit)) 01931 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01932 else if (digit >= 'A' && digit <= 'D') 01933 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01934 else if (digit >= 'a' && digit <= 'd') 01935 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01936 else if (digit == '*') 01937 return DAHDI_TONE_DTMF_s; 01938 else if (digit == '#') 01939 return DAHDI_TONE_DTMF_p; 01940 else 01941 return -1; 01942 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4334 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().
04335 { 04336 #ifdef DAHDI_TONEDETECT 04337 int val; 04338 #endif 04339 04340 p->ignoredtmf = 1; 04341 04342 #ifdef DAHDI_TONEDETECT 04343 val = 0; 04344 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04345 #endif 04346 if (!p->hardwaredtmf && p->dsp) { 04347 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04348 ast_dsp_set_features(p->dsp, p->dsp_features); 04349 } 04350 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 9804 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().
09805 { 09806 struct ast_channel *chan = vchan; 09807 struct dahdi_pvt *pvt = chan->tech_pvt; 09808 struct ast_frame *f; 09809 char ex[80]; 09810 /* Wait up to 30 seconds for an answer */ 09811 int newms, ms = 30000; 09812 if (option_verbose > 2) 09813 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 09814 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 09815 if (ast_call(chan, ex, 0)) { 09816 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 09817 ast_hangup(chan); 09818 return NULL; 09819 } 09820 while ((newms = ast_waitfor(chan, ms)) > 0) { 09821 f = ast_read(chan); 09822 if (!f) { 09823 /* Got hangup */ 09824 break; 09825 } 09826 if (f->frametype == AST_FRAME_CONTROL) { 09827 switch (f->subclass) { 09828 case AST_CONTROL_ANSWER: 09829 /* Launch the PBX */ 09830 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 09831 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 09832 chan->priority = 1; 09833 if (option_verbose > 3) 09834 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 09835 ast_pbx_run(chan); 09836 /* It's already hungup, return immediately */ 09837 return NULL; 09838 case AST_CONTROL_BUSY: 09839 if (option_verbose > 3) 09840 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 09841 break; 09842 case AST_CONTROL_CONGESTION: 09843 if (option_verbose > 3) 09844 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 09845 break; 09846 }; 09847 } 09848 ast_frfree(f); 09849 ms = newms; 09850 } 09851 /* Hangup the channel since nothing happend */ 09852 ast_hangup(chan); 09853 return NULL; 09854 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8165 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, 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().
08166 { 08167 int count, res, res2, spoint, pollres=0; 08168 struct dahdi_pvt *i; 08169 struct dahdi_pvt *last = NULL; 08170 struct dahdi_pvt *doomed; 08171 time_t thispass = 0, lastpass = 0; 08172 int found; 08173 char buf[1024]; 08174 struct pollfd *pfds=NULL; 08175 int lastalloc = -1; 08176 /* This thread monitors all the frame relay interfaces which are not yet in use 08177 (and thus do not have a separate thread) indefinitely */ 08178 /* From here on out, we die whenever asked */ 08179 #if 0 08180 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08181 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08182 return NULL; 08183 } 08184 ast_log(LOG_DEBUG, "Monitor starting...\n"); 08185 #endif 08186 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08187 08188 for (;;) { 08189 /* Lock the interface list */ 08190 ast_mutex_lock(&iflock); 08191 if (!pfds || (lastalloc != ifcount)) { 08192 if (pfds) { 08193 free(pfds); 08194 pfds = NULL; 08195 } 08196 if (ifcount) { 08197 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08198 ast_mutex_unlock(&iflock); 08199 return NULL; 08200 } 08201 } 08202 lastalloc = ifcount; 08203 } 08204 /* Build the stuff we're going to poll on, that is the socket of every 08205 dahdi_pvt that does not have an associated owner channel */ 08206 count = 0; 08207 i = iflist; 08208 while (i) { 08209 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 08210 if (!i->owner && !i->subs[SUB_REAL].owner) { 08211 /* This needs to be watched, as it lacks an owner */ 08212 pfds[count].fd = i->subs[SUB_REAL].dfd; 08213 pfds[count].events = POLLPRI; 08214 pfds[count].revents = 0; 08215 /* Message waiting or r2 channels also get watched for reading */ 08216 if (i->cidspill || 08217 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 08218 pfds[count].events |= POLLIN; 08219 } 08220 count++; 08221 } 08222 } 08223 i = i->next; 08224 } 08225 /* Okay, now that we know what to do, release the interface lock */ 08226 ast_mutex_unlock(&iflock); 08227 08228 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08229 pthread_testcancel(); 08230 /* Wait at least a second for something to happen */ 08231 res = poll(pfds, count, 1000); 08232 pthread_testcancel(); 08233 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08234 08235 /* Okay, poll has finished. Let's see what happened. */ 08236 if (res < 0) { 08237 if ((errno != EAGAIN) && (errno != EINTR)) 08238 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08239 continue; 08240 } 08241 /* Alright, lock the interface list again, and let's look and see what has 08242 happened */ 08243 ast_mutex_lock(&iflock); 08244 found = 0; 08245 spoint = 0; 08246 lastpass = thispass; 08247 thispass = time(NULL); 08248 doomed = NULL; 08249 for (i = iflist;; i = i->next) { 08250 if (doomed) { 08251 int res; 08252 res = dahdi_destroy_channel_bynum(doomed->channel); 08253 if (!res) { 08254 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08255 } 08256 doomed = NULL; 08257 } 08258 if (!i) { 08259 break; 08260 } 08261 if (thispass != lastpass) { 08262 if (!found && ((i == last) || ((i == iflist) && !last))) { 08263 last = i; 08264 if (last) { 08265 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 08266 (last->sig & __DAHDI_SIG_FXO)) { 08267 res = ast_app_has_voicemail(last->mailbox, NULL); 08268 if (last->msgstate != res) { 08269 int x; 08270 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08271 x = DAHDI_FLUSH_BOTH; 08272 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08273 if (res2) 08274 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 08275 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08276 /* Turn on on hook transfer for 4 seconds */ 08277 x = 4000; 08278 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08279 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08280 last->cidpos = 0; 08281 last->msgstate = res; 08282 last->onhooktime = thispass; 08283 } 08284 found ++; 08285 } 08286 } 08287 last = last->next; 08288 } 08289 } 08290 } 08291 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08292 if (i->radio && !i->owner) 08293 { 08294 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08295 if (res) 08296 { 08297 if (option_debug) 08298 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08299 /* Don't hold iflock while handling init events */ 08300 ast_mutex_unlock(&iflock); 08301 doomed = handle_init_event(i, res); 08302 ast_mutex_lock(&iflock); 08303 } 08304 continue; 08305 } 08306 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08307 if (pollres & POLLIN) { 08308 if (i->owner || i->subs[SUB_REAL].owner) { 08309 #ifdef HAVE_PRI 08310 if (!i->pri) 08311 #endif 08312 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08313 continue; 08314 } 08315 // if (!i->cidspill) { 08316 // ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08317 // continue; 08318 //} 08319 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08320 if (res > 0) { 08321 /* We read some number of bytes. Write an equal amount of data */ 08322 /* if (res > i->cidlen - i->cidpos) */ 08323 /* res = i->cidlen - i->cidpos; */ 08324 /* res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); */ 08325 /* if (res2 > 0) { */ 08326 /* i->cidpos += res2; */ 08327 /* if (i->cidpos >= i->cidlen) { */ 08328 /* free(i->cidspill); */ 08329 /* i->cidspill = 0; */ 08330 /* i->cidpos = 0; */ 08331 /* i->cidlen = 0; */ 08332 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 08333 if (i->cid_start == CID_START_DTMF_NOALERT) { 08334 int energy; 08335 struct timeval now; 08336 /* State machine dtmfcid_holdoff_state allows for the line to settle 08337 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 08338 */ 08339 if (1 == i->dtmfcid_holdoff_state) { 08340 gettimeofday(&i->dtmfcid_delay, NULL); 08341 i->dtmfcid_holdoff_state = 2; 08342 } else if (2 == i->dtmfcid_holdoff_state) { 08343 gettimeofday(&now, NULL); 08344 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 08345 i->dtmfcid_holdoff_state = 0; 08346 } 08347 } else { 08348 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 08349 if (energy > dtmfcid_level) { 08350 pthread_t threadid; 08351 struct ast_channel *chan; 08352 ast_mutex_unlock(&iflock); 08353 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08354 if (!chan) { 08355 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08356 } else { 08357 pthread_attr_t attr; 08358 pthread_attr_init(&attr); 08359 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08360 res = ast_pthread_create(&threadid, &attr, ss_thread, chan); 08361 if (res) { 08362 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08363 } else { 08364 i->dtmfcid_holdoff_state = 1; 08365 } 08366 } 08367 ast_mutex_lock(&iflock); 08368 } 08369 } 08370 /* } else { */ 08371 /* ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); */ 08372 /* i->msgstate = -1; */ 08373 } 08374 } else { 08375 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08376 } 08377 } 08378 if (pollres & POLLPRI) { 08379 if (i->owner || i->subs[SUB_REAL].owner) { 08380 #ifdef HAVE_PRI 08381 if (!i->pri) 08382 #endif 08383 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08384 continue; 08385 } 08386 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08387 if (option_debug) 08388 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08389 /* Don't hold iflock while handling init events */ 08390 ast_mutex_unlock(&iflock); 08391 doomed = handle_init_event(i, res); 08392 ast_mutex_lock(&iflock); 08393 } 08394 } 08395 } 08396 ast_mutex_unlock(&iflock); 08397 } 08398 /* Never reached */ 08399 return NULL; 08400 08401 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4352 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().
04353 { 04354 #ifdef DAHDI_TONEDETECT 04355 int val; 04356 #endif 04357 04358 if (p->channel == CHAN_PSEUDO) 04359 return; 04360 04361 p->ignoredtmf = 0; 04362 04363 #ifdef DAHDI_TONEDETECT 04364 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04365 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04366 #endif 04367 if (!p->hardwaredtmf && p->dsp) { 04368 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04369 ast_dsp_set_features(p->dsp, p->dsp_features); 04370 } 04371 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 2085 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
02086 { 02087 static char buf[256]; 02088 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 02089 return events[event]; 02090 sprintf(buf, "Event %d", event); /* safe */ 02091 return buf; 02092 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2450 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02451 { 02452 int j; 02453 int k; 02454 float linear_gain = pow(10.0, gain / 20.0); 02455 02456 switch (law) { 02457 case DAHDI_LAW_ALAW: 02458 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02459 if (gain) { 02460 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02461 if (k > 32767) k = 32767; 02462 if (k < -32767) k = -32767; 02463 g->rxgain[j] = AST_LIN2A(k); 02464 } else { 02465 g->rxgain[j] = j; 02466 } 02467 } 02468 break; 02469 case DAHDI_LAW_MULAW: 02470 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02471 if (gain) { 02472 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02473 if (k > 32767) k = 32767; 02474 if (k < -32767) k = -32767; 02475 g->rxgain[j] = AST_LIN2MU(k); 02476 } else { 02477 g->rxgain[j] = j; 02478 } 02479 } 02480 break; 02481 } 02482 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2416 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02417 { 02418 int j; 02419 int k; 02420 float linear_gain = pow(10.0, gain / 20.0); 02421 02422 switch (law) { 02423 case DAHDI_LAW_ALAW: 02424 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02425 if (gain) { 02426 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02427 if (k > 32767) k = 32767; 02428 if (k < -32767) k = -32767; 02429 g->txgain[j] = AST_LIN2A(k); 02430 } else { 02431 g->txgain[j] = j; 02432 } 02433 } 02434 break; 02435 case DAHDI_LAW_MULAW: 02436 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02437 if (gain) { 02438 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02439 if (k > 32767) k = 32767; 02440 if (k < -32767) k = -32767; 02441 g->txgain[j] = AST_LIN2MU(k); 02442 } else { 02443 g->txgain[j] = j; 02444 } 02445 } 02446 break; 02447 } 02448 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 12517 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().
12518 { 12519 struct dahdi_pvt *p = iflist; 12520 while (p) { 12521 if (p->channel == channel) { 12522 break; 12523 } 12524 p = p->next; 12525 } 12526 return p; 12527 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4792 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().
04793 { 04794 int res; 04795 struct dahdi_spaninfo zi; 04796 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04797 /* 04798 * The conditional compilation is needed only in asterisk-1.4 for 04799 * backward compatibility with old zaptel drivers that don't have 04800 * a DAHDI_PARAMS.chan_alarms field. 04801 */ 04802 struct dahdi_params params; 04803 #endif 04804 04805 memset(&zi, 0, sizeof(zi)); 04806 zi.spanno = p->span; 04807 04808 /* First check for span alarms */ 04809 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 04810 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04811 return 0; 04812 } 04813 if (zi.alarms != DAHDI_ALARM_NONE) 04814 return zi.alarms; 04815 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04816 /* No alarms on the span. Check for channel alarms. */ 04817 memset(¶ms, 0, sizeof(params)); 04818 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04819 return params.chan_alarms; 04820 /* ioctl failed */ 04821 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04822 #endif 04823 return DAHDI_ALARM_NONE; 04824 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4908 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().
04909 { 04910 const char *alarm_str = alarm2str(alarms); 04911 04912 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04913 * doesn't know what to do with it. Don't confuse users with log messages. */ 04914 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04915 p->unknown_alarm = 1; 04916 return; 04917 } else { 04918 p->unknown_alarm = 0; 04919 } 04920 04921 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04922 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04923 "Alarm: %s\r\n" 04924 "Channel: %d\r\n", 04925 alarm_str, p->channel); 04926 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12332 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
12333 { 12334 int i, j; 12335 for (i = 0; i < num_cadence; i++) { 12336 char output[1024]; 12337 char tmp[16], tmp2[64]; 12338 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12339 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12340 12341 for (j = 0; j < 16; j++) { 12342 if (cadences[i].ringcadence[j] == 0) 12343 break; 12344 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12345 if (cidrings[i] * 2 - 1 == j) 12346 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12347 else 12348 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12349 if (j != 0) 12350 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12351 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12352 } 12353 ast_cli(fd,"%s\n",output); 12354 } 12355 return 0; 12356 }
Definition at line 7955 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::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.
07956 { 07957 int res; 07958 pthread_t threadid; 07959 pthread_attr_t attr; 07960 struct ast_channel *chan; 07961 pthread_attr_init(&attr); 07962 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07963 /* Handle an event on a given channel for the monitor thread. */ 07964 switch (event) { 07965 case DAHDI_EVENT_NONE: 07966 case DAHDI_EVENT_BITSCHANGED: 07967 break; 07968 case DAHDI_EVENT_WINKFLASH: 07969 case DAHDI_EVENT_RINGOFFHOOK: 07970 if (i->inalarm) break; 07971 if (i->radio) break; 07972 /* Got a ring/answer. What kind of channel are we? */ 07973 switch (i->sig) { 07974 case SIG_FXOLS: 07975 case SIG_FXOGS: 07976 case SIG_FXOKS: 07977 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07978 if (res && (errno == EBUSY)) 07979 break; 07980 if (i->cidspill) { 07981 /* Cancel VMWI spill */ 07982 free(i->cidspill); 07983 i->cidspill = NULL; 07984 } 07985 if (i->immediate) { 07986 dahdi_enable_ec(i); 07987 /* The channel is immediately up. Start right away */ 07988 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07989 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07990 if (!chan) { 07991 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07992 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07993 if (res < 0) 07994 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07995 } 07996 } else { 07997 /* Check for callerid, digits, etc */ 07998 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07999 if (chan) { 08000 if (has_voicemail(i)) 08001 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08002 else 08003 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08004 if (res < 0) 08005 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08006 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08007 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08008 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08009 if (res < 0) 08010 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08011 ast_hangup(chan); 08012 } 08013 } else 08014 ast_log(LOG_WARNING, "Unable to create channel\n"); 08015 } 08016 break; 08017 case SIG_FXSLS: 08018 case SIG_FXSGS: 08019 case SIG_FXSKS: 08020 i->ringt = i->ringt_base; 08021 /* Fall through */ 08022 case SIG_EMWINK: 08023 case SIG_FEATD: 08024 case SIG_FEATDMF: 08025 case SIG_FEATDMF_TA: 08026 case SIG_E911: 08027 case SIG_FGC_CAMA: 08028 case SIG_FGC_CAMAMF: 08029 case SIG_FEATB: 08030 case SIG_EM: 08031 case SIG_EM_E1: 08032 case SIG_SFWINK: 08033 case SIG_SF_FEATD: 08034 case SIG_SF_FEATDMF: 08035 case SIG_SF_FEATB: 08036 case SIG_SF: 08037 /* Check for callerid, digits, etc */ 08038 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08039 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08040 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08041 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08042 if (res < 0) 08043 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08044 ast_hangup(chan); 08045 } else if (!chan) { 08046 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08047 } 08048 break; 08049 default: 08050 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08051 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08052 if (res < 0) 08053 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08054 pthread_attr_destroy(&attr); 08055 return NULL; 08056 } 08057 break; 08058 case DAHDI_EVENT_NOALARM: 08059 i->inalarm = 0; 08060 if (!i->unknown_alarm) { 08061 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08062 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08063 "Channel: %d\r\n", i->channel); 08064 } else { 08065 i->unknown_alarm = 0; 08066 } 08067 break; 08068 case DAHDI_EVENT_ALARM: 08069 i->inalarm = 1; 08070 res = get_alarms(i); 08071 handle_alarms(i, res); 08072 /* fall thru intentionally */ 08073 case DAHDI_EVENT_ONHOOK: 08074 if (i->radio) 08075 break; 08076 /* Back on hook. Hang up. */ 08077 switch (i->sig) { 08078 case SIG_FXOLS: 08079 case SIG_FXOGS: 08080 case SIG_FEATD: 08081 case SIG_FEATDMF: 08082 case SIG_FEATDMF_TA: 08083 case SIG_E911: 08084 case SIG_FGC_CAMA: 08085 case SIG_FGC_CAMAMF: 08086 case SIG_FEATB: 08087 case SIG_EM: 08088 case SIG_EM_E1: 08089 case SIG_EMWINK: 08090 case SIG_SF_FEATD: 08091 case SIG_SF_FEATDMF: 08092 case SIG_SF_FEATB: 08093 case SIG_SF: 08094 case SIG_SFWINK: 08095 case SIG_FXSLS: 08096 case SIG_FXSGS: 08097 case SIG_FXSKS: 08098 case SIG_GR303FXSKS: 08099 dahdi_disable_ec(i); 08100 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08101 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08102 break; 08103 case SIG_GR303FXOKS: 08104 case SIG_FXOKS: 08105 dahdi_disable_ec(i); 08106 /* Diddle the battery for the zhone */ 08107 #ifdef ZHONE_HACK 08108 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08109 usleep(1); 08110 #endif 08111 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08112 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08113 break; 08114 case SIG_PRI: 08115 dahdi_disable_ec(i); 08116 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08117 break; 08118 default: 08119 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08120 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08121 pthread_attr_destroy(&attr); 08122 return NULL; 08123 } 08124 break; 08125 case DAHDI_EVENT_POLARITY: 08126 switch (i->sig) { 08127 case SIG_FXSLS: 08128 case SIG_FXSKS: 08129 case SIG_FXSGS: 08130 /* We have already got a PR before the channel was 08131 created, but it wasn't handled. We need polarity 08132 to be REV for remote hangup detection to work. 08133 At least in Spain */ 08134 if (i->hanguponpolarityswitch) 08135 i->polarity = POLARITY_REV; 08136 08137 if (i->cid_start == CID_START_POLARITY) { 08138 i->polarity = POLARITY_REV; 08139 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 08140 "CID detection on channel %d\n", 08141 i->channel); 08142 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08143 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08144 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08145 } 08146 } 08147 break; 08148 default: 08149 ast_log(LOG_WARNING, "handle_init_event detected " 08150 "polarity reversal on non-FXO (SIG_FXS) " 08151 "interface %d\n", i->channel); 08152 } 08153 break; 08154 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08155 ast_log(LOG_NOTICE, 08156 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08157 i->channel); 08158 pthread_attr_destroy(&attr); 08159 return i; 08160 } 08161 pthread_attr_destroy(&attr); 08162 return NULL; 08163 }
static int handle_mfcr2_call_files | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11740 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.
11741 { 11742 struct dahdi_pvt *p = NULL; 11743 int channo = 0; 11744 if (argc < 4) { 11745 return RESULT_SHOWUSAGE; 11746 } 11747 channo = (argc == 5) ? atoi(argv[4]) : -1; 11748 ast_mutex_lock(&iflock); 11749 p = iflist; 11750 while (p) { 11751 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11752 p = p->next; 11753 continue; 11754 } 11755 if ((channo != -1) && (p->channel != channo )) { 11756 p = p->next; 11757 continue; 11758 } 11759 if (ast_true(argv[3])) { 11760 openr2_chan_enable_call_files(p->r2chan); 11761 } else { 11762 openr2_chan_disable_call_files(p->r2chan); 11763 } 11764 if (channo != -1) { 11765 if (ast_true(argv[3])) { 11766 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 11767 } else { 11768 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 11769 } 11770 break; 11771 } else { 11772 p = p->next; 11773 } 11774 } 11775 if ((channo != -1) && !p) { 11776 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11777 } 11778 if (channo == -1) { 11779 if (ast_true(argv[3])) { 11780 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n"); 11781 } else { 11782 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n"); 11783 } 11784 } 11785 ast_mutex_unlock(&iflock); 11786 return RESULT_SUCCESS; 11787 }
static int handle_mfcr2_set_blocked | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11824 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.
11825 { 11826 struct dahdi_pvt *p = NULL; 11827 int channo = 0; 11828 channo = (argc == 4) ? atoi(argv[3]) : -1; 11829 ast_mutex_lock(&iflock); 11830 p = iflist; 11831 while (p) { 11832 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11833 p = p->next; 11834 continue; 11835 } 11836 if ((channo != -1) && (p->channel != channo )) { 11837 p = p->next; 11838 continue; 11839 } 11840 if (!openr2_chan_set_blocked(p->r2chan)) { 11841 ast_mutex_lock(&p->lock); 11842 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK; 11843 ast_mutex_unlock(&p->lock); 11844 } else { 11845 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel); 11846 } 11847 if (channo != -1) { 11848 break; 11849 } else { 11850 p = p->next; 11851 } 11852 } 11853 if ((channo != -1) && !p) { 11854 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11855 } 11856 ast_mutex_unlock(&iflock); 11857 return RESULT_SUCCESS; 11858 }
static int handle_mfcr2_set_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11681 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.
11682 { 11683 struct dahdi_pvt *p = NULL; 11684 int channo = 0; 11685 char *toklevel = NULL; 11686 char *saveptr = NULL; 11687 char *logval = NULL; 11688 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 11689 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 11690 if (argc < 4) { 11691 return RESULT_SHOWUSAGE; 11692 } 11693 channo = (argc == 5) ? atoi(argv[4]) : -1; 11694 logval = ast_strdupa(argv[3]); 11695 toklevel = strtok_r(logval, ",", &saveptr); 11696 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11697 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]); 11698 return RESULT_FAILURE; 11699 } else if (OR2_LOG_NOTHING == tmplevel) { 11700 loglevel = tmplevel; 11701 } else { 11702 loglevel |= tmplevel; 11703 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 11704 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11705 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 11706 continue; 11707 } 11708 loglevel |= tmplevel; 11709 } 11710 } 11711 ast_mutex_lock(&iflock); 11712 p = iflist; 11713 while (p) { 11714 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11715 p = p->next; 11716 continue; 11717 } 11718 if ((channo != -1) && (p->channel != channo )) { 11719 p = p->next; 11720 continue; 11721 } 11722 openr2_chan_set_log_level(p->r2chan, loglevel); 11723 if (channo != -1) { 11724 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel); 11725 break; 11726 } else { 11727 p = p->next; 11728 } 11729 } 11730 if ((channo != -1) && !p) { 11731 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11732 } 11733 if (channo == -1) { 11734 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]); 11735 } 11736 ast_mutex_unlock(&iflock); 11737 return RESULT_SUCCESS; 11738 }
static int handle_mfcr2_set_idle | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11789 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.
11790 { 11791 struct dahdi_pvt *p = NULL; 11792 int channo = 0; 11793 channo = (argc == 4) ? atoi(argv[3]) : -1; 11794 ast_mutex_lock(&iflock); 11795 p = iflist; 11796 while (p) { 11797 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11798 p = p->next; 11799 continue; 11800 } 11801 if ((channo != -1) && (p->channel != channo )) { 11802 p = p->next; 11803 continue; 11804 } 11805 if (!openr2_chan_set_idle(p->r2chan)) { 11806 ast_mutex_lock(&p->lock); 11807 p->mfcr2call = 0; 11808 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 11809 ast_mutex_unlock(&p->lock); 11810 } 11811 if (channo != -1) { 11812 break; 11813 } else { 11814 p = p->next; 11815 } 11816 } 11817 if ((channo != -1) && !p) { 11818 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11819 } 11820 ast_mutex_unlock(&iflock); 11821 return RESULT_SUCCESS; 11822 }
static int handle_mfcr2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11612 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.
11613 { 11614 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 11615 int filtertype = 0; 11616 int targetnum = 0; 11617 char channo[5]; 11618 char anino[5]; 11619 char dnisno[5]; 11620 struct dahdi_pvt *p; 11621 openr2_context_t *r2context; 11622 openr2_variant_t r2variant; 11623 if (!((argc == 3) || (argc == 5))) { 11624 return RESULT_SHOWUSAGE; 11625 } 11626 if (argc == 5) { 11627 if (!strcasecmp(argv[3], "group")) { 11628 targetnum = atoi(argv[4]); 11629 if ((targetnum < 0) || (targetnum > 63)) 11630 return RESULT_SHOWUSAGE; 11631 targetnum = 1 << targetnum; 11632 filtertype = 1; 11633 } else if (!strcasecmp(argv[3], "context")) { 11634 filtertype = 2; 11635 } else { 11636 return RESULT_SHOWUSAGE; 11637 } 11638 } 11639 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 11640 ast_mutex_lock(&iflock); 11641 p = iflist; 11642 while (p) { 11643 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11644 p = p->next; 11645 continue; 11646 } 11647 if (filtertype) { 11648 switch(filtertype) { 11649 case 1: /* mfcr2 show channels group <group> */ 11650 if (p->group != targetnum) { 11651 p = p->next; 11652 continue; 11653 } 11654 break; 11655 case 2: /* mfcr2 show channels context <context> */ 11656 if (strcasecmp(p->context, argv[4])) { 11657 p= p->next; 11658 continue; 11659 } 11660 break; 11661 default: 11662 ; 11663 } 11664 } 11665 r2context = openr2_chan_get_context(p->r2chan); 11666 r2variant = openr2_context_get_variant(r2context); 11667 snprintf(channo, sizeof(channo), "%d", p->channel); 11668 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 11669 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 11670 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 11671 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 11672 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 11673 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 11674 p = p->next; 11675 } 11676 ast_mutex_unlock(&iflock); 11677 return RESULT_SUCCESS; 11678 #undef FORMAT 11679 }
static int handle_mfcr2_show_variants | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11594 of file chan_dahdi.c.
References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.
11595 { 11596 #define FORMAT "%4s %40s\n" 11597 int numvariants = 0; 11598 int i; 11599 const openr2_variant_entry_t *variants; 11600 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 11601 ast_cli(fd, "Failed to get list of variants.\n"); 11602 return RESULT_FAILURE; 11603 } 11604 ast_cli(fd, FORMAT, "Variant Code", "Country"); 11605 for (i = 0; i < numvariants; i++) { 11606 ast_cli(fd, FORMAT, variants[i].name, variants[i].country); 11607 } 11608 return RESULT_SUCCESS; 11609 #undef FORMAT 11610 }
static int handle_mfcr2_version | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11588 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11589 { 11590 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 11591 return RESULT_SUCCESS; 11592 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11341 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11342 { 11343 int span; 11344 int x; 11345 if (argc < 4) { 11346 return RESULT_SHOWUSAGE; 11347 } 11348 span = atoi(argv[3]); 11349 if ((span < 1) || (span > NUM_SPANS)) { 11350 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 11351 return RESULT_SUCCESS; 11352 } 11353 if (!pris[span-1].pri) { 11354 ast_cli(fd, "No PRI running on span %d\n", span); 11355 return RESULT_SUCCESS; 11356 } 11357 for (x = 0; x < NUM_DCHANS; x++) { 11358 if (pris[span-1].dchans[x]) 11359 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11360 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11361 PRI_DEBUG_Q921_STATE); 11362 } 11363 ast_cli(fd, "Enabled debugging on span %d\n", span); 11364 return RESULT_SUCCESS; 11365 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11369 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11370 { 11371 int span; 11372 int x; 11373 if (argc < 5) 11374 return RESULT_SHOWUSAGE; 11375 span = atoi(argv[4]); 11376 if ((span < 1) || (span > NUM_SPANS)) { 11377 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11378 return RESULT_SUCCESS; 11379 } 11380 if (!pris[span-1].pri) { 11381 ast_cli(fd, "No PRI running on span %d\n", span); 11382 return RESULT_SUCCESS; 11383 } 11384 for (x = 0; x < NUM_DCHANS; x++) { 11385 if (pris[span-1].dchans[x]) 11386 pri_set_debug(pris[span-1].dchans[x], 0); 11387 } 11388 ast_cli(fd, "Disabled debugging on span %d\n", span); 11389 return RESULT_SUCCESS; 11390 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11392 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11393 { 11394 int span; 11395 int x; 11396 if (argc < 5) 11397 return RESULT_SHOWUSAGE; 11398 span = atoi(argv[4]); 11399 if ((span < 1) || (span > NUM_SPANS)) { 11400 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11401 return RESULT_SUCCESS; 11402 } 11403 if (!pris[span-1].pri) { 11404 ast_cli(fd, "No PRI running on span %d\n", span); 11405 return RESULT_SUCCESS; 11406 } 11407 for (x = 0; x < NUM_DCHANS; x++) { 11408 if (pris[span-1].dchans[x]) 11409 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11410 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11411 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 11412 } 11413 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 11414 return RESULT_SUCCESS; 11415 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11294 of file chan_dahdi.c.
References ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), pridebugfdlock, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11295 { 11296 int myfd; 11297 11298 if (!strncasecmp(argv[1], "set", 3)) { 11299 if (argc < 5) 11300 return RESULT_SHOWUSAGE; 11301 11302 if (ast_strlen_zero(argv[4])) 11303 return RESULT_SHOWUSAGE; 11304 11305 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 11306 if (myfd < 0) { 11307 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 11308 return RESULT_SUCCESS; 11309 } 11310 11311 ast_mutex_lock(&pridebugfdlock); 11312 11313 if (pridebugfd >= 0) 11314 close(pridebugfd); 11315 11316 pridebugfd = myfd; 11317 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 11318 11319 ast_mutex_unlock(&pridebugfdlock); 11320 11321 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 11322 } else { 11323 /* Assume it is unset */ 11324 ast_mutex_lock(&pridebugfdlock); 11325 close(pridebugfd); 11326 pridebugfd = -1; 11327 ast_cli(fd, "PRI debug output to file disabled\n"); 11328 ast_mutex_unlock(&pridebugfdlock); 11329 } 11330 11331 return RESULT_SUCCESS; 11332 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11498 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
11499 { 11500 int x; 11501 int span; 11502 int count=0; 11503 int debug=0; 11504 11505 for (span = 0; span < NUM_SPANS; span++) { 11506 if (pris[span].pri) { 11507 for (x = 0; x < NUM_DCHANS; x++) { 11508 debug = 0; 11509 if (pris[span].dchans[x]) { 11510 debug = pri_get_debug(pris[span].dchans[x]); 11511 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" ); 11512 count++; 11513 } 11514 } 11515 } 11516 11517 } 11518 ast_mutex_lock(&pridebugfdlock); 11519 if (pridebugfd >= 0) 11520 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 11521 ast_mutex_unlock(&pridebugfdlock); 11522 11523 if (!count) 11524 ast_cli(fd, "No debug set or no PRI running\n"); 11525 return RESULT_SUCCESS; 11526 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11459 of file chan_dahdi.c.
References ast_cli(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11460 { 11461 int span; 11462 int x; 11463 char status[256]; 11464 if (argc < 4) 11465 return RESULT_SHOWUSAGE; 11466 span = atoi(argv[3]); 11467 if ((span < 1) || (span > NUM_SPANS)) { 11468 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 11469 return RESULT_SUCCESS; 11470 } 11471 if (!pris[span-1].pri) { 11472 ast_cli(fd, "No PRI running on span %d\n", span); 11473 return RESULT_SUCCESS; 11474 } 11475 for (x = 0; x < NUM_DCHANS; x++) { 11476 if (pris[span-1].dchannels[x]) { 11477 #ifdef PRI_DUMP_INFO_STR 11478 char *info_str = NULL; 11479 #endif 11480 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 11481 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 11482 ast_cli(fd, "Status: %s\n", status); 11483 #ifdef PRI_DUMP_INFO_STR 11484 info_str = pri_dump_info_str(pris[span-1].pri); 11485 if (info_str) { 11486 ast_cli(fd, "%s", info_str); 11487 free(info_str); 11488 } 11489 #else 11490 pri_dump_info(pris[span-1].pri); 11491 #endif 11492 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 11493 } 11494 } 11495 return RESULT_SUCCESS; 11496 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11438 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11439 { 11440 int span; 11441 int x; 11442 char status[256]; 11443 if (argc != 3) 11444 return RESULT_SHOWUSAGE; 11445 11446 for (span = 0; span < NUM_SPANS; span++) { 11447 if (pris[span].pri) { 11448 for (x = 0; x < NUM_DCHANS; x++) { 11449 if (pris[span].dchannels[x]) { 11450 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 11451 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 11452 } 11453 } 11454 } 11455 } 11456 return RESULT_SUCCESS; 11457 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11335 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11335 { 11336 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 11337 return RESULT_SUCCESS; 11338 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2647 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().
02648 { 02649 02650 return ast_app_has_voicemail(p->mailbox, NULL); 02651 }
static void init_mfcr2_globals | ( | void | ) | [static] |
Definition at line 1266 of file chan_dahdi.c.
References AST_PTHREADT_NULL, master, NUM_SPANS, and r2links.
Referenced by dahdi_restart(), and load_module().
01267 { 01268 int r; 01269 mfcr2_cur_context_index = 0; 01270 mfcr2_cur_variant = OR2_VAR_UNKNOWN; 01271 mfcr2_cur_mfback_timeout = -1; 01272 mfcr2_cur_metering_pulse_timeout = -1; 01273 mfcr2_cur_max_ani = 10; 01274 mfcr2_cur_max_dnis = 4; 01275 mfcr2_cur_get_ani_first = -1; 01276 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 01277 mfcr2_cur_dtmf_dialing = -1; 01278 mfcr2_cur_dtmf_detection = -1; 01279 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON; 01280 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF; 01281 #endif 01282 mfcr2_cur_skip_category = -1; 01283 mfcr2_cur_call_files = 0; 01284 mfcr2_cur_allow_collect_calls = 0; 01285 mfcr2_cur_forced_release = 0; 01286 mfcr2_cur_double_answer = 0; 01287 mfcr2_cur_immediate_accept = -1; 01288 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING; 01289 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 01290 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir)); 01291 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file)); 01292 memset(r2links, 0, sizeof(r2links)); 01293 for (r = 0; r < NUM_SPANS; r++) { 01294 r2links[r].master = AST_PTHREADT_NULL; 01295 } 01296 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 2206 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
02207 { 02208 /* If they're listening to our channel, they're ours */ 02209 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 02210 return 1; 02211 /* If they're a talker on our (allocated) conference, they're ours */ 02212 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 02213 return 1; 02214 return 0; 02215 }
Definition at line 2236 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().
02237 { 02238 int x; 02239 int useslavenative; 02240 struct dahdi_pvt *slave = NULL; 02241 /* Start out optimistic */ 02242 useslavenative = 1; 02243 /* Update conference state in a stateless fashion */ 02244 for (x = 0; x < 3; x++) { 02245 /* Any three-way calling makes slave native mode *definitely* out 02246 of the question */ 02247 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 02248 useslavenative = 0; 02249 } 02250 /* If we don't have any 3-way calls, check to see if we have 02251 precisely one slave */ 02252 if (useslavenative) { 02253 for (x = 0; x < MAX_SLAVES; x++) { 02254 if (p->slaves[x]) { 02255 if (slave) { 02256 /* Whoops already have a slave! No 02257 slave native and stop right away */ 02258 slave = NULL; 02259 useslavenative = 0; 02260 break; 02261 } else { 02262 /* We have one slave so far */ 02263 slave = p->slaves[x]; 02264 } 02265 } 02266 } 02267 } 02268 /* If no slave, slave native definitely out */ 02269 if (!slave) 02270 useslavenative = 0; 02271 else if (slave->law != p->law) { 02272 useslavenative = 0; 02273 slave = NULL; 02274 } 02275 if (out) 02276 *out = slave; 02277 return useslavenative; 02278 }
static int load_module | ( | void | ) | [static] |
Definition at line 13933 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(), ast_channel_tech::type, zap_accept_r2_call_exec(), zap_send_keypad_facility_exec(), and zap_tech.
13934 { 13935 int res; 13936 13937 #ifdef HAVE_PRI 13938 int y,i; 13939 memset(pris, 0, sizeof(pris)); 13940 for (y = 0; y < NUM_SPANS; y++) { 13941 ast_mutex_init(&pris[y].lock); 13942 pris[y].offset = -1; 13943 pris[y].master = AST_PTHREADT_NULL; 13944 for (i = 0; i < NUM_DCHANS; i++) 13945 pris[y].fds[i] = -1; 13946 } 13947 pri_set_error(dahdi_pri_error); 13948 pri_set_message(dahdi_pri_message); 13949 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13950 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 13951 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 13952 } 13953 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 13954 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 13955 #endif 13956 #ifdef HAVE_OPENR2 13957 init_mfcr2_globals(); 13958 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13959 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec, 13960 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip); 13961 } 13962 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec, 13963 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip); 13964 #endif 13965 if ((res = setup_dahdi(0))) { 13966 return AST_MODULE_LOAD_DECLINE; 13967 } 13968 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13969 chan_tech = &dahdi_tech; 13970 } else { 13971 chan_tech = &zap_tech; 13972 } 13973 if (ast_channel_register(chan_tech)) { 13974 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 13975 __unload_module(); 13976 return -1; 13977 } 13978 #ifdef HAVE_PRI 13979 ast_string_field_init(&inuse, 16); 13980 ast_string_field_set(&inuse, name, "GR-303InUse"); 13981 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 13982 #endif 13983 #ifdef HAVE_OPENR2 13984 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 13985 #endif 13986 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 13987 13988 memset(round_robin, 0, sizeof(round_robin)); 13989 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 13990 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 13991 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 13992 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 13993 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 13994 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 13995 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 13996 13997 ast_cond_init(&ss_thread_complete, NULL); 13998 13999 return res; 14000 }
static struct dahdi_mfcr2* mfcr2_get_context | ( | int | id | ) | [static] |
Definition at line 8435 of file chan_dahdi.c.
References ast_log(), LOG_ERROR, and r2links.
Referenced by mkintf().
08436 { 08437 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) { 08438 ast_log(LOG_ERROR, "No more R2 links available!.\n"); 08439 return NULL; 08440 } 08441 return &r2links[id]; 08442 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 9591 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, and dahdi_pvt::r2chan.
Referenced by setup_dahdi().
09592 { 09593 struct dahdi_pvt *p; 09594 struct dahdi_mfcr2 *mfcr2 = data; 09595 /* we should be using pthread_key_create 09596 and allocate pollers dynamically. 09597 I think do_monitor() could be leaking, since it 09598 could be cancelled at any time and is not 09599 using thread keys, why?, */ 09600 struct pollfd pollers[sizeof(mfcr2->pvts)]; 09601 int maxsleep = 20; 09602 int res = 0; 09603 int i = 0; 09604 int pollsize = 0; 09605 int oldstate = 0; 09606 int was_idle = 0; 09607 int quit_loop = 0; 09608 /* now that we're ready to get calls, unblock our side and 09609 get current line state */ 09610 for (i = 0; i < mfcr2->numchans; i++) { 09611 p = mfcr2->pvts[i]; 09612 if (openr2_chan_set_idle(p->r2chan)) { 09613 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel); 09614 } else { 09615 ast_mutex_lock(&p->lock); 09616 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 09617 mfcr2->pvts[i]->mfcr2call = 0; 09618 ast_mutex_unlock(&p->lock); 09619 } 09620 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 09621 } 09622 while(1) { 09623 /* we trust here that the mfcr2 channel list will not ever change once 09624 the module is loaded */ 09625 pollsize = 0; 09626 for (i = 0; i < mfcr2->numchans; i++) { 09627 pollers[i].revents = 0; 09628 pollers[i].events = 0; 09629 if (mfcr2->pvts[i]->owner) { 09630 continue; 09631 } 09632 if (!mfcr2->pvts[i]->r2chan) { 09633 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 09634 quit_loop = 1; 09635 break; 09636 } 09637 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 09638 pollers[i].events = POLLIN | POLLPRI; 09639 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 09640 pollsize++; 09641 } 09642 if (quit_loop) { 09643 break; 09644 } 09645 09646 if (pollsize == 0) { 09647 if (!was_idle) { 09648 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n"); 09649 was_idle = 1; 09650 } 09651 poll(NULL, 0, maxsleep); 09652 continue; 09653 } 09654 was_idle = 0; 09655 09656 /* probably poll() is a valid cancel point, lets just be on the safe side 09657 by calling pthread_testcancel */ 09658 pthread_testcancel(); 09659 res = poll(pollers, pollsize, maxsleep); 09660 pthread_testcancel(); 09661 if ((res < 0) && (errno != EINTR)) { 09662 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 09663 break; 09664 } 09665 /* do we want to allow to cancel while processing events? */ 09666 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 09667 for (i = 0; i < mfcr2->numchans; i++) { 09668 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) { 09669 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 09670 } 09671 } 09672 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 09673 } 09674 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 09675 return 0; 09676 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8568 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, 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, 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_pri::overlapdial, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_resolve_span(), 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().
08569 { 08570 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08571 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08572 char fn[80]; 08573 #if 1 08574 struct dahdi_bufferinfo bi; 08575 #endif 08576 int res; 08577 int span=0; 08578 int here = 0; 08579 int x; 08580 struct dahdi_pvt **wlist; 08581 struct dahdi_pvt **wend; 08582 struct dahdi_params p; 08583 08584 wlist = &iflist; 08585 wend = &ifend; 08586 08587 #ifdef HAVE_PRI 08588 if (pri) { 08589 wlist = &pri->crvs; 08590 wend = &pri->crvend; 08591 } 08592 #endif 08593 08594 tmp2 = *wlist; 08595 prev = NULL; 08596 08597 while (tmp2) { 08598 if (!tmp2->destroy) { 08599 if (tmp2->channel == channel) { 08600 tmp = tmp2; 08601 here = 1; 08602 break; 08603 } 08604 if (tmp2->channel > channel) { 08605 break; 08606 } 08607 } 08608 prev = tmp2; 08609 tmp2 = tmp2->next; 08610 } 08611 08612 if (!here && reloading != 1) { 08613 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08614 if (tmp) 08615 free(tmp); 08616 return NULL; 08617 } 08618 ast_mutex_init(&tmp->lock); 08619 ifcount++; 08620 for (x = 0; x < 3; x++) 08621 tmp->subs[x].dfd = -1; 08622 tmp->channel = channel; 08623 tmp->priindication_oob = conf->chan.priindication_oob; 08624 } 08625 08626 if (tmp) { 08627 int chan_sig = conf->chan.sig; 08628 if (!here) { 08629 if ((channel != CHAN_PSEUDO) && !pri) { 08630 int count = 0; 08631 snprintf(fn, sizeof(fn), "%d", channel); 08632 /* Open non-blocking */ 08633 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08634 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 */ 08635 usleep(1); 08636 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08637 count++; 08638 } 08639 /* Allocate a DAHDI structure */ 08640 if (tmp->subs[SUB_REAL].dfd < 0) { 08641 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); 08642 destroy_dahdi_pvt(&tmp); 08643 return NULL; 08644 } 08645 memset(&p, 0, sizeof(p)); 08646 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08647 if (res < 0) { 08648 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08649 destroy_dahdi_pvt(&tmp); 08650 return NULL; 08651 } 08652 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 08653 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)); 08654 destroy_dahdi_pvt(&tmp); 08655 return NULL; 08656 } 08657 tmp->law = p.curlaw; 08658 tmp->span = p.spanno; 08659 span = p.spanno - 1; 08660 } else { 08661 if (channel == CHAN_PSEUDO) 08662 chan_sig = 0; 08663 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08664 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08665 return NULL; 08666 } 08667 } 08668 #ifdef HAVE_PRI 08669 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08670 int offset; 08671 int myswitchtype; 08672 int matchesdchan; 08673 int x,y; 08674 offset = 0; 08675 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08676 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08677 destroy_dahdi_pvt(&tmp); 08678 return NULL; 08679 } 08680 if (span >= NUM_SPANS) { 08681 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08682 destroy_dahdi_pvt(&tmp); 08683 return NULL; 08684 } else { 08685 struct dahdi_spaninfo si; 08686 si.spanno = 0; 08687 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08688 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08689 destroy_dahdi_pvt(&tmp); 08690 return NULL; 08691 } 08692 /* Store the logical span first based upon the real span */ 08693 tmp->logicalspan = pris[span].prilogicalspan; 08694 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08695 if (span < 0) { 08696 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08697 destroy_dahdi_pvt(&tmp); 08698 return NULL; 08699 } 08700 if (chan_sig == SIG_PRI) 08701 myswitchtype = conf->pri.switchtype; 08702 else 08703 myswitchtype = PRI_SWITCH_GR303_TMC; 08704 /* Make sure this isn't a d-channel */ 08705 matchesdchan=0; 08706 for (x = 0; x < NUM_SPANS; x++) { 08707 for (y = 0; y < NUM_DCHANS; y++) { 08708 if (pris[x].dchannels[y] == tmp->channel) { 08709 matchesdchan = 1; 08710 break; 08711 } 08712 } 08713 } 08714 offset = p.chanpos; 08715 if (!matchesdchan) { 08716 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08717 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08718 destroy_dahdi_pvt(&tmp); 08719 return NULL; 08720 } 08721 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08722 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08723 destroy_dahdi_pvt(&tmp); 08724 return NULL; 08725 } 08726 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08727 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08728 destroy_dahdi_pvt(&tmp); 08729 return NULL; 08730 } 08731 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08732 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08733 destroy_dahdi_pvt(&tmp); 08734 return NULL; 08735 } 08736 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08737 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08738 destroy_dahdi_pvt(&tmp); 08739 return NULL; 08740 } 08741 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08742 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08743 destroy_dahdi_pvt(&tmp); 08744 return NULL; 08745 } 08746 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08747 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08748 destroy_dahdi_pvt(&tmp); 08749 return NULL; 08750 } 08751 if (pris[span].numchans >= MAX_CHANNELS) { 08752 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08753 pris[span].trunkgroup); 08754 destroy_dahdi_pvt(&tmp); 08755 return NULL; 08756 } 08757 pris[span].nodetype = conf->pri.nodetype; 08758 pris[span].switchtype = myswitchtype; 08759 pris[span].nsf = conf->pri.nsf; 08760 pris[span].dialplan = conf->pri.dialplan; 08761 pris[span].localdialplan = conf->pri.localdialplan; 08762 pris[span].pvts[pris[span].numchans++] = tmp; 08763 pris[span].minunused = conf->pri.minunused; 08764 pris[span].minidle = conf->pri.minidle; 08765 pris[span].overlapdial = conf->pri.overlapdial; 08766 #ifdef HAVE_PRI_INBANDDISCONNECT 08767 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08768 #endif 08769 pris[span].facilityenable = conf->pri.facilityenable; 08770 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08771 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08772 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08773 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08774 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08775 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08776 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08777 pris[span].resetinterval = conf->pri.resetinterval; 08778 08779 tmp->pri = &pris[span]; 08780 tmp->prioffset = offset; 08781 tmp->call = NULL; 08782 } else { 08783 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08784 destroy_dahdi_pvt(&tmp); 08785 return NULL; 08786 } 08787 } 08788 } else { 08789 tmp->prioffset = 0; 08790 } 08791 #endif 08792 #ifdef HAVE_OPENR2 08793 if (chan_sig == SIG_MFCR2 && reloading != 1) { 08794 char logdir[OR2_MAX_PATH]; 08795 struct dahdi_mfcr2 *dahdi_r2; 08796 int threshold = 0; 08797 int snres = 0; 08798 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index); 08799 if (!dahdi_r2) { 08800 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 08801 } else if (!dahdi_r2->protocol_context){ 08802 char tmplogdir[] = "/tmp"; 08803 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 08804 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis); 08805 if (!dahdi_r2->protocol_context) { 08806 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 08807 destroy_dahdi_pvt(&tmp); 08808 return NULL; 08809 } 08810 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel); 08811 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first); 08812 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category); 08813 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold); 08814 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout); 08815 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout); 08816 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer); 08817 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept); 08818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 08819 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off); 08820 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection); 08821 #endif 08822 if (ast_strlen_zero(mfcr2_cur_logdir)) { 08823 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) { 08824 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08825 } 08826 } else { 08827 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir); 08828 if (snres >= sizeof(logdir)) { 08829 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 08830 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08831 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08832 } 08833 } else { 08834 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08835 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 08836 } 08837 } 08838 } 08839 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) { 08840 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) { 08841 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file); 08842 } 08843 } 08844 } 08845 if (dahdi_r2) { 08846 /* TODO: should we check numchans overflow, or is it already done by DAHDI? */ 08847 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp; 08848 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context, 08849 tmp->subs[SUB_REAL].dfd, NULL, NULL); 08850 if (!tmp->r2chan) { 08851 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context); 08852 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 08853 destroy_dahdi_pvt(&tmp); 08854 return NULL; 08855 } 08856 openr2_chan_set_client_data(tmp->r2chan, tmp); 08857 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 08858 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 08859 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel); 08860 if (mfcr2_cur_call_files) { 08861 openr2_chan_enable_call_files(tmp->r2chan); 08862 } 08863 tmp->mfcr2_category = mfcr2_cur_category; 08864 tmp->mfcr2 = dahdi_r2; 08865 tmp->mfcr2call = 0; 08866 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK; 08867 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer; 08868 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls; 08869 tmp->mfcr2_ani_index = 0; 08870 tmp->mfcr2_dnis_index = 0; 08871 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls; 08872 tmp->mfcr2_forced_release = mfcr2_cur_forced_release; 08873 } 08874 } 08875 #endif 08876 } else { 08877 chan_sig = tmp->sig; 08878 if (tmp->subs[SUB_REAL].dfd > -1) { 08879 memset(&p, 0, sizeof(p)); 08880 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08881 } 08882 } 08883 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08884 switch (chan_sig) { 08885 case SIG_FXSKS: 08886 case SIG_FXSLS: 08887 case SIG_EM: 08888 case SIG_EM_E1: 08889 case SIG_EMWINK: 08890 case SIG_FEATD: 08891 case SIG_FEATDMF: 08892 case SIG_FEATDMF_TA: 08893 case SIG_FEATB: 08894 case SIG_E911: 08895 case SIG_SF: 08896 case SIG_SFWINK: 08897 case SIG_FGC_CAMA: 08898 case SIG_FGC_CAMAMF: 08899 case SIG_SF_FEATD: 08900 case SIG_SF_FEATDMF: 08901 case SIG_SF_FEATB: 08902 p.starttime = 250; 08903 break; 08904 } 08905 08906 if (tmp->radio) { 08907 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08908 p.channo = channel; 08909 p.rxwinktime = 1; 08910 p.rxflashtime = 1; 08911 p.starttime = 1; 08912 p.debouncetime = 5; 08913 } 08914 if (!tmp->radio) { 08915 p.channo = channel; 08916 /* Override timing settings based on config file */ 08917 if (conf->timing.prewinktime >= 0) 08918 p.prewinktime = conf->timing.prewinktime; 08919 if (conf->timing.preflashtime >= 0) 08920 p.preflashtime = conf->timing.preflashtime; 08921 if (conf->timing.winktime >= 0) 08922 p.winktime = conf->timing.winktime; 08923 if (conf->timing.flashtime >= 0) 08924 p.flashtime = conf->timing.flashtime; 08925 if (conf->timing.starttime >= 0) 08926 p.starttime = conf->timing.starttime; 08927 if (conf->timing.rxwinktime >= 0) 08928 p.rxwinktime = conf->timing.rxwinktime; 08929 if (conf->timing.rxflashtime >= 0) 08930 p.rxflashtime = conf->timing.rxflashtime; 08931 if (conf->timing.debouncetime >= 0) 08932 p.debouncetime = conf->timing.debouncetime; 08933 } 08934 08935 /* dont set parms on a pseudo-channel (or CRV) */ 08936 if (tmp->subs[SUB_REAL].dfd >= 0) 08937 { 08938 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 08939 if (res < 0) { 08940 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 08941 destroy_dahdi_pvt(&tmp); 08942 return NULL; 08943 } 08944 } 08945 #if 1 08946 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 08947 memset(&bi, 0, sizeof(bi)); 08948 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08949 if (!res) { 08950 bi.txbufpolicy = conf->chan.buf_policy; 08951 bi.rxbufpolicy = conf->chan.buf_policy; 08952 bi.numbufs = conf->chan.buf_no; 08953 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08954 if (res < 0) { 08955 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 08956 } 08957 } else 08958 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 08959 } 08960 #endif 08961 tmp->immediate = conf->chan.immediate; 08962 tmp->transfertobusy = conf->chan.transfertobusy; 08963 tmp->sig = chan_sig; 08964 tmp->outsigmod = conf->chan.outsigmod; 08965 tmp->ringt_base = ringt_base; 08966 tmp->firstradio = 0; 08967 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 08968 tmp->permcallwaiting = conf->chan.callwaiting; 08969 else 08970 tmp->permcallwaiting = 0; 08971 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 08972 tmp->destroy = 0; 08973 tmp->drings = drings; 08974 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 08975 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 08976 tmp->threewaycalling = conf->chan.threewaycalling; 08977 tmp->adsi = conf->chan.adsi; 08978 tmp->use_smdi = conf->chan.use_smdi; 08979 tmp->permhidecallerid = conf->chan.hidecallerid; 08980 tmp->callreturn = conf->chan.callreturn; 08981 tmp->echocancel = conf->chan.echocancel; 08982 tmp->echotraining = conf->chan.echotraining; 08983 tmp->pulse = conf->chan.pulse; 08984 if (tmp->echocancel) 08985 tmp->echocanbridged = conf->chan.echocanbridged; 08986 else { 08987 if (conf->chan.echocanbridged) 08988 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 08989 tmp->echocanbridged = 0; 08990 } 08991 tmp->busydetect = conf->chan.busydetect; 08992 tmp->busycount = conf->chan.busycount; 08993 tmp->busycompare = conf->chan.busycompare; 08994 tmp->busytonelength = conf->chan.busytonelength; 08995 tmp->busyquietlength = conf->chan.busyquietlength; 08996 tmp->busyfuzziness = conf->chan.busyfuzziness; 08997 tmp->silencethreshold = conf->chan.silencethreshold; 08998 tmp->callprogress = conf->chan.callprogress; 08999 tmp->cancallforward = conf->chan.cancallforward; 09000 tmp->dtmfrelax = conf->chan.dtmfrelax; 09001 tmp->callwaiting = tmp->permcallwaiting; 09002 tmp->hidecallerid = tmp->permhidecallerid; 09003 tmp->channel = channel; 09004 tmp->stripmsd = conf->chan.stripmsd; 09005 tmp->use_callerid = conf->chan.use_callerid; 09006 tmp->cid_signalling = conf->chan.cid_signalling; 09007 tmp->cid_start = conf->chan.cid_start; 09008 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09009 tmp->restrictcid = conf->chan.restrictcid; 09010 tmp->use_callingpres = conf->chan.use_callingpres; 09011 tmp->priexclusive = conf->chan.priexclusive; 09012 if (tmp->usedistinctiveringdetection) { 09013 if (!tmp->use_callerid) { 09014 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09015 tmp->use_callerid = 1; 09016 } 09017 } 09018 09019 if (tmp->cid_signalling == CID_SIG_SMDI) { 09020 if (!tmp->use_smdi) { 09021 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09022 tmp->use_smdi = 1; 09023 } 09024 } 09025 if (tmp->use_smdi) { 09026 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09027 if (!(tmp->smdi_iface)) { 09028 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09029 tmp->use_smdi = 0; 09030 } 09031 } 09032 09033 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09034 tmp->amaflags = conf->chan.amaflags; 09035 if (!here) { 09036 tmp->confno = -1; 09037 tmp->propconfno = -1; 09038 } 09039 tmp->canpark = conf->chan.canpark; 09040 tmp->transfer = conf->chan.transfer; 09041 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09042 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09043 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09044 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09045 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09046 tmp->cid_ton = 0; 09047 if (chan_sig != SIG_PRI) { 09048 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09049 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09050 } else { 09051 tmp->cid_num[0] = '\0'; 09052 tmp->cid_name[0] = '\0'; 09053 } 09054 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09055 tmp->msgstate = -1; 09056 tmp->group = conf->chan.group; 09057 tmp->callgroup = conf->chan.callgroup; 09058 tmp->pickupgroup= conf->chan.pickupgroup; 09059 tmp->rxgain = conf->chan.rxgain; 09060 tmp->txgain = conf->chan.txgain; 09061 tmp->tonezone = conf->chan.tonezone; 09062 tmp->onhooktime = time(NULL); 09063 if (tmp->subs[SUB_REAL].dfd > -1) { 09064 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09065 if (tmp->dsp) 09066 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09067 update_conf(tmp); 09068 if (!here) { 09069 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2)) 09070 /* Hang it up to be sure it's good */ 09071 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09072 } 09073 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09074 #ifdef HAVE_PRI 09075 /* the dchannel is down so put the channel in alarm */ 09076 if (tmp->pri && !pri_is_up(tmp->pri)) { 09077 tmp->inalarm = 1; 09078 } 09079 #endif 09080 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09081 tmp->inalarm = 1; 09082 handle_alarms(tmp, res); 09083 } else { 09084 /* yes, this looks strange... the unknown_alarm flag is only used to 09085 control whether an 'alarm cleared' message gets generated when we 09086 get an indication that the channel is no longer in alarm status. 09087 however, the channel *could* be in an alarm status that we aren't 09088 aware of (since get_alarms() only reports span alarms, not channel 09089 alarms). setting this flag will cause any potential 'alarm cleared' 09090 message to be suppressed, but if a real alarm occurs before that 09091 happens, this flag will get cleared by it and the situation will 09092 be normal. 09093 */ 09094 tmp->unknown_alarm = 1; 09095 } 09096 } 09097 09098 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09099 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09100 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09101 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09102 09103 } 09104 if (tmp && !here) { 09105 /* nothing on the iflist */ 09106 if (!*wlist) { 09107 *wlist = tmp; 09108 tmp->prev = NULL; 09109 tmp->next = NULL; 09110 *wend = tmp; 09111 } else { 09112 /* at least one member on the iflist */ 09113 struct dahdi_pvt *working = *wlist; 09114 09115 /* check if we maybe have to put it on the begining */ 09116 if (working->channel > tmp->channel) { 09117 tmp->next = *wlist; 09118 tmp->prev = NULL; 09119 (*wlist)->prev = tmp; 09120 *wlist = tmp; 09121 } else { 09122 /* go through all the members and put the member in the right place */ 09123 while (working) { 09124 /* in the middle */ 09125 if (working->next) { 09126 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09127 tmp->next = working->next; 09128 tmp->prev = working; 09129 working->next->prev = tmp; 09130 working->next = tmp; 09131 break; 09132 } 09133 } else { 09134 /* the last */ 09135 if (working->channel < tmp->channel) { 09136 working->next = tmp; 09137 tmp->next = NULL; 09138 tmp->prev = working; 09139 *wend = tmp; 09140 break; 09141 } 09142 } 09143 working = working->next; 09144 } 09145 } 09146 } 09147 } 09148 return tmp; 09149 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 6229 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, READ_SIZE, and dahdi_pvt::subs.
Referenced by dahdi_write().
06230 { 06231 int sent=0; 06232 int size; 06233 int res; 06234 int fd; 06235 fd = p->subs[index].dfd; 06236 while (len) { 06237 size = len; 06238 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06239 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06240 res = write(fd, buf, size); 06241 if (res != size) { 06242 if (option_debug) 06243 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06244 return sent; 06245 } 06246 len -= size; 06247 buf += size; 06248 } 06249 return sent; 06250 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6720 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06721 { 06722 char c; 06723 06724 *str = 0; /* start with empty output buffer */ 06725 for (;;) 06726 { 06727 /* Wait for the first digit (up to specified ms). */ 06728 c = ast_waitfordigit(chan, ms); 06729 /* if timeout, hangup or error, return as such */ 06730 if (c < 1) 06731 return c; 06732 *str++ = c; 06733 *str = 0; 06734 if (strchr(term, c)) 06735 return 1; 06736 } 06737 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3391 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().
03392 { 03393 int x = -1; 03394 03395 for (x = 0; x < NUM_DCHANS; x++) { 03396 if ((pri->dchans[x] == pri->pri)) 03397 break; 03398 } 03399 03400 return pri->fds[x]; 03401 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3361 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().
03362 { 03363 bearer->owner = &inuse; 03364 bearer->realcall = crv; 03365 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03366 if (crv->subs[SUB_REAL].owner) 03367 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 03368 crv->bearer = bearer; 03369 crv->call = bearer->call; 03370 crv->pri = pri; 03371 return 0; 03372 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9943 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, and dahdi_pvt::resetting.
Referenced by pri_dchannel().
09944 { 09945 do { 09946 pri->resetpos++; 09947 } while ((pri->resetpos < pri->numchans) && 09948 (!pri->pvts[pri->resetpos] || 09949 pri->pvts[pri->resetpos]->call || 09950 pri->pvts[pri->resetpos]->resetting)); 09951 if (pri->resetpos < pri->numchans) { 09952 /* Mark the channel as resetting and restart it */ 09953 pri->pvts[pri->resetpos]->resetting = 1; 09954 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 09955 } else { 09956 pri->resetting = 0; 09957 time(&pri->lastreset); 09958 } 09959 return 0; 09960 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8555 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08556 { 08557 if (pris[span].mastertrunkgroup) { 08558 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); 08559 return -1; 08560 } 08561 pris[span].mastertrunkgroup = trunkgroup; 08562 pris[span].prilogicalspan = logicalspan; 08563 return 0; 08564 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8492 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().
08493 { 08494 struct dahdi_spaninfo si; 08495 struct dahdi_params p; 08496 int fd; 08497 int span; 08498 int ospan=0; 08499 int x,y; 08500 for (x = 0; x < NUM_SPANS; x++) { 08501 if (pris[x].trunkgroup == trunkgroup) { 08502 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08503 return -1; 08504 } 08505 } 08506 for (y = 0; y < NUM_DCHANS; y++) { 08507 if (!channels[y]) 08508 break; 08509 memset(&si, 0, sizeof(si)); 08510 memset(&p, 0, sizeof(p)); 08511 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 08512 if (fd < 0) { 08513 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08514 return -1; 08515 } 08516 x = channels[y]; 08517 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08518 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08519 close(fd); 08520 return -1; 08521 } 08522 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08523 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08524 return -1; 08525 } 08526 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08527 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08528 close(fd); 08529 return -1; 08530 } 08531 span = p.spanno - 1; 08532 if (pris[span].trunkgroup) { 08533 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08534 close(fd); 08535 return -1; 08536 } 08537 if (pris[span].pvts[0]) { 08538 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08539 close(fd); 08540 return -1; 08541 } 08542 if (!y) { 08543 pris[span].trunkgroup = trunkgroup; 08544 pris[span].offset = channels[y] - p.chanpos; 08545 ospan = span; 08546 } 08547 pris[ospan].dchannels[y] = channels[y]; 08548 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08549 pris[span].span = span + 1; 08550 close(fd); 08551 } 08552 return 0; 08553 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10042 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_chan_name, dahdi_hangup(), 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, 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_pvt::resetting, dahdi_pri::resetting, dahdi_pri::switchtype, and t.
10043 { 10044 struct dahdi_pri *pri = vpri; 10045 pri_event *e; 10046 struct pollfd fds[NUM_DCHANS]; 10047 int res; 10048 int chanpos = 0; 10049 int x; 10050 int haveidles; 10051 int activeidles; 10052 int nextidle = -1; 10053 struct ast_channel *c; 10054 struct timeval tv, lowest, *next; 10055 struct timeval lastidle = { 0, 0 }; 10056 int doidling=0; 10057 char *cc; 10058 char idlen[80]; 10059 struct ast_channel *idle; 10060 pthread_t p; 10061 time_t t; 10062 int i, which=-1; 10063 int numdchans; 10064 int cause=0; 10065 struct dahdi_pvt *crv; 10066 pthread_t threadid; 10067 pthread_attr_t attr; 10068 char ani2str[6]; 10069 char plancallingnum[256]; 10070 char plancallingani[256]; 10071 char calledtonstr[10]; 10072 10073 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10074 10075 gettimeofday(&lastidle, NULL); 10076 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10077 /* Need to do idle dialing, check to be sure though */ 10078 cc = strchr(pri->idleext, '@'); 10079 if (cc) { 10080 *cc = '\0'; 10081 cc++; 10082 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10083 #if 0 10084 /* Extensions may not be loaded yet */ 10085 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10086 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10087 else 10088 #endif 10089 doidling = 1; 10090 } else 10091 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10092 } 10093 for (;;) { 10094 for (i = 0; i < NUM_DCHANS; i++) { 10095 if (!pri->dchannels[i]) 10096 break; 10097 fds[i].fd = pri->fds[i]; 10098 fds[i].events = POLLIN | POLLPRI; 10099 fds[i].revents = 0; 10100 } 10101 numdchans = i; 10102 time(&t); 10103 ast_mutex_lock(&pri->lock); 10104 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10105 if (pri->resetting && pri_is_up(pri)) { 10106 if (pri->resetpos < 0) 10107 pri_check_restart(pri); 10108 } else { 10109 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10110 pri->resetting = 1; 10111 pri->resetpos = -1; 10112 } 10113 } 10114 } 10115 /* Look for any idle channels if appropriate */ 10116 if (doidling && pri_is_up(pri)) { 10117 nextidle = -1; 10118 haveidles = 0; 10119 activeidles = 0; 10120 for (x = pri->numchans; x >= 0; x--) { 10121 if (pri->pvts[x] && !pri->pvts[x]->owner && 10122 !pri->pvts[x]->call) { 10123 if (haveidles < pri->minunused) { 10124 haveidles++; 10125 } else if (!pri->pvts[x]->resetting) { 10126 nextidle = x; 10127 break; 10128 } 10129 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10130 activeidles++; 10131 } 10132 if (nextidle > -1) { 10133 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10134 /* Don't create a new idle call more than once per second */ 10135 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10136 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 10137 if (idle) { 10138 pri->pvts[nextidle]->isidlecall = 1; 10139 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10140 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10141 dahdi_hangup(idle); 10142 } 10143 } else 10144 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10145 gettimeofday(&lastidle, NULL); 10146 } 10147 } else if ((haveidles < pri->minunused) && 10148 (activeidles > pri->minidle)) { 10149 /* Mark something for hangup if there is something 10150 that can be hungup */ 10151 for (x = pri->numchans; x >= 0; x--) { 10152 /* find a candidate channel */ 10153 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10154 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10155 haveidles++; 10156 /* Stop if we have enough idle channels or 10157 can't spare any more active idle ones */ 10158 if ((haveidles >= pri->minunused) || 10159 (activeidles <= pri->minidle)) 10160 break; 10161 } 10162 } 10163 } 10164 } 10165 /* Start with reasonable max */ 10166 lowest = ast_tv(60, 0); 10167 for (i = 0; i < NUM_DCHANS; i++) { 10168 /* Find lowest available d-channel */ 10169 if (!pri->dchannels[i]) 10170 break; 10171 if ((next = pri_schedule_next(pri->dchans[i]))) { 10172 /* We need relative time here */ 10173 tv = ast_tvsub(*next, ast_tvnow()); 10174 if (tv.tv_sec < 0) { 10175 tv = ast_tv(0,0); 10176 } 10177 if (doidling || pri->resetting) { 10178 if (tv.tv_sec > 1) { 10179 tv = ast_tv(1, 0); 10180 } 10181 } else { 10182 if (tv.tv_sec > 60) { 10183 tv = ast_tv(60, 0); 10184 } 10185 } 10186 } else if (doidling || pri->resetting) { 10187 /* Make sure we stop at least once per second if we're 10188 monitoring idle channels */ 10189 tv = ast_tv(1,0); 10190 } else { 10191 /* Don't poll for more than 60 seconds */ 10192 tv = ast_tv(60, 0); 10193 } 10194 if (!i || ast_tvcmp(tv, lowest) < 0) { 10195 lowest = tv; 10196 } 10197 } 10198 ast_mutex_unlock(&pri->lock); 10199 10200 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 10201 pthread_testcancel(); 10202 e = NULL; 10203 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 10204 pthread_testcancel(); 10205 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10206 10207 ast_mutex_lock(&pri->lock); 10208 if (!res) { 10209 for (which = 0; which < NUM_DCHANS; which++) { 10210 if (!pri->dchans[which]) 10211 break; 10212 /* Just a timeout, run the scheduler */ 10213 e = pri_schedule_run(pri->dchans[which]); 10214 if (e) 10215 break; 10216 } 10217 } else if (res > -1) { 10218 for (which = 0; which < NUM_DCHANS; which++) { 10219 if (!pri->dchans[which]) 10220 break; 10221 if (fds[which].revents & POLLPRI) { 10222 /* Check for an event */ 10223 x = 0; 10224 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 10225 if (x) 10226 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); 10227 /* Keep track of alarm state */ 10228 if (x == DAHDI_EVENT_ALARM) { 10229 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 10230 pri_find_dchan(pri); 10231 } else if (x == DAHDI_EVENT_NOALARM) { 10232 pri->dchanavail[which] |= DCHAN_NOTINALARM; 10233 pri_restart(pri->dchans[which]); 10234 } 10235 10236 if (option_debug) 10237 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 10238 } else if (fds[which].revents & POLLIN) { 10239 e = pri_check_event(pri->dchans[which]); 10240 } 10241 if (e) 10242 break; 10243 } 10244 } else if (errno != EINTR) 10245 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 10246 10247 if (e) { 10248 if (pri->debug) 10249 pri_dump_event(pri->dchans[which], e); 10250 10251 if (e->e != PRI_EVENT_DCHAN_DOWN) { 10252 if (!(pri->dchanavail[which] & DCHAN_UP)) { 10253 if (option_verbose > 1) 10254 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 10255 } 10256 pri->dchanavail[which] |= DCHAN_UP; 10257 } else { 10258 if (pri->dchanavail[which] & DCHAN_UP) { 10259 if (option_verbose > 1) 10260 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 10261 } 10262 pri->dchanavail[which] &= ~DCHAN_UP; 10263 } 10264 10265 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 10266 /* Must be an NFAS group that has the secondary dchan active */ 10267 pri->pri = pri->dchans[which]; 10268 10269 switch (e->e) { 10270 case PRI_EVENT_DCHAN_UP: 10271 if (!pri->pri) pri_find_dchan(pri); 10272 10273 /* Note presense of D-channel */ 10274 time(&pri->lastreset); 10275 10276 /* Restart in 5 seconds */ 10277 if (pri->resetinterval > -1) { 10278 pri->lastreset -= pri->resetinterval; 10279 pri->lastreset += 5; 10280 } 10281 pri->resetting = 0; 10282 /* Take the channels from inalarm condition */ 10283 for (i = 0; i < pri->numchans; i++) 10284 if (pri->pvts[i]) { 10285 pri->pvts[i]->inalarm = 0; 10286 } 10287 break; 10288 case PRI_EVENT_DCHAN_DOWN: 10289 pri_find_dchan(pri); 10290 if (!pri_is_up(pri)) { 10291 pri->resetting = 0; 10292 /* Hangup active channels and put them in alarm mode */ 10293 for (i = 0; i < pri->numchans; i++) { 10294 struct dahdi_pvt *p = pri->pvts[i]; 10295 if (p) { 10296 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 10297 /* T309 is not enabled : hangup calls when alarm occurs */ 10298 if (p->call) { 10299 if (p->pri && p->pri->pri) { 10300 pri_hangup(p->pri->pri, p->call, -1); 10301 pri_destroycall(p->pri->pri, p->call); 10302 p->call = NULL; 10303 } else 10304 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 10305 } 10306 if (p->realcall) { 10307 pri_hangup_all(p->realcall, pri); 10308 } else if (p->owner) 10309 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10310 } 10311 p->inalarm = 1; 10312 } 10313 } 10314 } 10315 break; 10316 case PRI_EVENT_RESTART: 10317 if (e->restart.channel > -1) { 10318 chanpos = pri_find_principle(pri, e->restart.channel); 10319 if (chanpos < 0) 10320 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 10321 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10322 else { 10323 if (option_verbose > 2) 10324 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 10325 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10326 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10327 if (pri->pvts[chanpos]->call) { 10328 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 10329 pri->pvts[chanpos]->call = NULL; 10330 } 10331 /* Force soft hangup if appropriate */ 10332 if (pri->pvts[chanpos]->realcall) 10333 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10334 else if (pri->pvts[chanpos]->owner) 10335 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10336 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10337 } 10338 } else { 10339 if (option_verbose > 2) 10340 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 10341 for (x = 0; x < pri->numchans; x++) 10342 if (pri->pvts[x]) { 10343 ast_mutex_lock(&pri->pvts[x]->lock); 10344 if (pri->pvts[x]->call) { 10345 pri_destroycall(pri->pri, pri->pvts[x]->call); 10346 pri->pvts[x]->call = NULL; 10347 } 10348 if (pri->pvts[x]->realcall) 10349 pri_hangup_all(pri->pvts[x]->realcall, pri); 10350 else if (pri->pvts[x]->owner) 10351 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10352 ast_mutex_unlock(&pri->pvts[x]->lock); 10353 } 10354 } 10355 break; 10356 case PRI_EVENT_KEYPAD_DIGIT: 10357 chanpos = pri_find_principle(pri, e->digit.channel); 10358 if (chanpos < 0) { 10359 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 10360 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 10361 } else { 10362 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 10363 if (chanpos > -1) { 10364 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10365 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 10366 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 10367 /* how to do that */ 10368 int digitlen = strlen(e->digit.digits); 10369 char digit; 10370 int i; 10371 for (i = 0; i < digitlen; i++) { 10372 digit = e->digit.digits[i]; 10373 { 10374 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10375 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10376 } 10377 } 10378 } 10379 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10380 } 10381 } 10382 break; 10383 10384 case PRI_EVENT_INFO_RECEIVED: 10385 chanpos = pri_find_principle(pri, e->ring.channel); 10386 if (chanpos < 0) { 10387 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 10388 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10389 } else { 10390 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 10391 if (chanpos > -1) { 10392 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10393 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 10394 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 10395 /* how to do that */ 10396 int digitlen = strlen(e->ring.callednum); 10397 char digit; 10398 int i; 10399 for (i = 0; i < digitlen; i++) { 10400 digit = e->ring.callednum[i]; 10401 { 10402 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10403 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10404 } 10405 } 10406 } 10407 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10408 } 10409 } 10410 break; 10411 case PRI_EVENT_RING: 10412 crv = NULL; 10413 if (e->ring.channel == -1) 10414 chanpos = pri_find_empty_chan(pri, 1); 10415 else 10416 chanpos = pri_find_principle(pri, e->ring.channel); 10417 /* if no channel specified find one empty */ 10418 if (chanpos < 0) { 10419 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 10420 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10421 } else { 10422 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10423 if (pri->pvts[chanpos]->owner) { 10424 if (pri->pvts[chanpos]->call == e->ring.call) { 10425 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 10426 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10427 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10428 break; 10429 } else { 10430 /* This is where we handle initial glare */ 10431 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 10432 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10433 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10434 chanpos = -1; 10435 } 10436 } 10437 if (chanpos > -1) 10438 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10439 } 10440 if ((chanpos < 0) && (e->ring.flexible)) 10441 chanpos = pri_find_empty_chan(pri, 1); 10442 if (chanpos > -1) { 10443 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10444 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 10445 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 10446 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 10447 if (crv) 10448 ast_mutex_lock(&crv->lock); 10449 if (!crv || crv->owner) { 10450 pri->pvts[chanpos]->call = NULL; 10451 if (crv) { 10452 if (crv->owner) 10453 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10454 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); 10455 } else 10456 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); 10457 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 10458 if (crv) 10459 ast_mutex_unlock(&crv->lock); 10460 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10461 break; 10462 } 10463 } 10464 pri->pvts[chanpos]->call = e->ring.call; 10465 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 10466 if (pri->pvts[chanpos]->use_callerid) { 10467 ast_shrink_phone_number(plancallingnum); 10468 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 10469 #ifdef PRI_ANI 10470 if (!ast_strlen_zero(e->ring.callingani)) { 10471 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 10472 ast_shrink_phone_number(plancallingani); 10473 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 10474 } else { 10475 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10476 } 10477 #endif 10478 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 10479 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 10480 } else { 10481 pri->pvts[chanpos]->cid_num[0] = '\0'; 10482 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10483 pri->pvts[chanpos]->cid_name[0] = '\0'; 10484 pri->pvts[chanpos]->cid_ton = 0; 10485 } 10486 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 10487 e->ring.redirectingnum, e->ring.callingplanrdnis); 10488 /* If immediate=yes go to s|1 */ 10489 if (pri->pvts[chanpos]->immediate) { 10490 if (option_verbose > 2) 10491 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 10492 pri->pvts[chanpos]->exten[0] = 's'; 10493 pri->pvts[chanpos]->exten[1] = '\0'; 10494 } 10495 /* Get called number */ 10496 else if (!ast_strlen_zero(e->ring.callednum)) { 10497 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 10498 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10499 } else if (pri->overlapdial) 10500 pri->pvts[chanpos]->exten[0] = '\0'; 10501 else { 10502 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 10503 pri->pvts[chanpos]->exten[0] = 's'; 10504 pri->pvts[chanpos]->exten[1] = '\0'; 10505 } 10506 /* Set DNID on all incoming calls -- even immediate */ 10507 if (!ast_strlen_zero(e->ring.callednum)) 10508 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10509 /* No number yet, but received "sending complete"? */ 10510 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 10511 if (option_verbose > 2) 10512 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 10513 pri->pvts[chanpos]->exten[0] = 's'; 10514 pri->pvts[chanpos]->exten[1] = '\0'; 10515 } 10516 10517 /* Make sure extension exists (or in overlap dial mode, can exist) */ 10518 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 10519 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10520 /* Setup law */ 10521 int law; 10522 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 10523 /* Set to audio mode at this point */ 10524 law = 1; 10525 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 10526 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 10527 } 10528 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 10529 law = DAHDI_LAW_ALAW; 10530 else 10531 law = DAHDI_LAW_MULAW; 10532 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 10533 if (res < 0) 10534 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 10535 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 10536 if (res < 0) 10537 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 10538 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 10539 /* Just announce proceeding */ 10540 pri->pvts[chanpos]->proceeding = 1; 10541 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 10542 } else { 10543 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 10544 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10545 else 10546 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10547 } 10548 /* Get the use_callingpres state */ 10549 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 10550 10551 /* Start PBX */ 10552 if (!e->ring.complete 10553 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 10554 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10555 /* 10556 * Release the PRI lock while we create the channel 10557 * so other threads can send D channel messages. 10558 */ 10559 ast_mutex_unlock(&pri->lock); 10560 if (crv) { 10561 /* Set bearer and such */ 10562 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 10563 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10564 pri->pvts[chanpos]->owner = &inuse; 10565 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 10566 } else { 10567 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10568 } 10569 ast_mutex_lock(&pri->lock); 10570 if (c) { 10571 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10572 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10573 } 10574 if (e->ring.ani2 >= 0) { 10575 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10576 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10577 } 10578 10579 #ifdef SUPPORT_USERUSER 10580 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10581 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10582 } 10583 #endif 10584 10585 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10586 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10587 if (e->ring.redirectingreason >= 0) 10588 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10589 } 10590 10591 pthread_attr_init(&attr); 10592 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 10593 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 10594 if (option_verbose > 2) 10595 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 10596 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 10597 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10598 } else { 10599 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10600 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10601 if (c) 10602 ast_hangup(c); 10603 else { 10604 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10605 pri->pvts[chanpos]->call = NULL; 10606 } 10607 } 10608 pthread_attr_destroy(&attr); 10609 } else { 10610 /* 10611 * Release the PRI lock while we create the channel 10612 * so other threads can send D channel messages. 10613 */ 10614 ast_mutex_unlock(&pri->lock); 10615 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 10616 ast_mutex_lock(&pri->lock); 10617 if (c) { 10618 /* 10619 * It is reasonably safe to set the following 10620 * channel variables while the PRI and DAHDI private 10621 * structures are locked. The PBX has not been 10622 * started yet and it is unlikely that any other task 10623 * will do anything with the channel we have just 10624 * created. 10625 */ 10626 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10627 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10628 } 10629 if (e->ring.ani2 >= 0) { 10630 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10631 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10632 } 10633 10634 #ifdef SUPPORT_USERUSER 10635 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10636 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10637 } 10638 #endif 10639 10640 if (e->ring.redirectingreason >= 0) 10641 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10642 10643 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10644 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10645 } 10646 if (c && !ast_pbx_start(c)) { 10647 if (option_verbose > 2) 10648 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 10649 plancallingnum, pri->pvts[chanpos]->exten, 10650 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10651 10652 dahdi_enable_ec(pri->pvts[chanpos]); 10653 } else { 10654 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10655 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10656 if (c) { 10657 ast_hangup(c); 10658 } else { 10659 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10660 pri->pvts[chanpos]->call = NULL; 10661 } 10662 } 10663 } 10664 } else { 10665 if (option_verbose > 2) 10666 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 10667 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 10668 pri->pvts[chanpos]->prioffset, pri->span); 10669 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 10670 pri->pvts[chanpos]->call = NULL; 10671 pri->pvts[chanpos]->exten[0] = '\0'; 10672 } 10673 if (crv) 10674 ast_mutex_unlock(&crv->lock); 10675 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10676 } else { 10677 if (e->ring.flexible) 10678 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 10679 else 10680 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 10681 } 10682 break; 10683 case PRI_EVENT_RINGING: 10684 chanpos = pri_find_principle(pri, e->ringing.channel); 10685 if (chanpos < 0) { 10686 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 10687 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10688 } else { 10689 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 10690 if (chanpos < 0) { 10691 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 10692 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10693 } else { 10694 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10695 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10696 dahdi_enable_ec(pri->pvts[chanpos]); 10697 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 10698 pri->pvts[chanpos]->alerting = 1; 10699 } else 10700 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 10701 #ifdef PRI_PROGRESS_MASK 10702 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10703 #else 10704 if (e->ringing.progress == 8) { 10705 #endif 10706 /* Now we can do call progress detection */ 10707 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10708 /* RINGING detection isn't required because we got ALERTING signal */ 10709 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 10710 pri->pvts[chanpos]->dsp_features = 0; 10711 } 10712 } 10713 10714 #ifdef SUPPORT_USERUSER 10715 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 10716 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10717 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10718 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 10719 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10720 } 10721 #endif 10722 10723 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10724 } 10725 } 10726 break; 10727 case PRI_EVENT_PROGRESS: 10728 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 10729 chanpos = pri_find_principle(pri, e->proceeding.channel); 10730 if (chanpos > -1) { 10731 #ifdef PRI_PROGRESS_MASK 10732 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 10733 #else 10734 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 10735 #endif 10736 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10737 10738 if (e->proceeding.cause > -1) { 10739 if (option_verbose > 2) 10740 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 10741 10742 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 10743 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 10744 if (pri->pvts[chanpos]->owner) { 10745 if (option_verbose > 2) 10746 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 10747 10748 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 10749 f.subclass = AST_CONTROL_BUSY; 10750 } 10751 } 10752 } 10753 10754 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10755 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 10756 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10757 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10758 #ifdef PRI_PROGRESS_MASK 10759 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10760 #else 10761 if (e->proceeding.progress == 8) { 10762 #endif 10763 /* Now we can do call progress detection */ 10764 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10765 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10766 pri->pvts[chanpos]->dsp_features = 0; 10767 } 10768 /* Bring voice path up */ 10769 f.subclass = AST_CONTROL_PROGRESS; 10770 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10771 } 10772 pri->pvts[chanpos]->progress = 1; 10773 pri->pvts[chanpos]->dialing = 0; 10774 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10775 } 10776 } 10777 break; 10778 case PRI_EVENT_PROCEEDING: 10779 chanpos = pri_find_principle(pri, e->proceeding.channel); 10780 if (chanpos > -1) { 10781 if (!pri->pvts[chanpos]->proceeding) { 10782 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10783 10784 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10785 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 10786 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10787 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10788 #ifdef PRI_PROGRESS_MASK 10789 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10790 #else 10791 if (e->proceeding.progress == 8) { 10792 #endif 10793 /* Now we can do call progress detection */ 10794 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10795 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10796 pri->pvts[chanpos]->dsp_features = 0; 10797 } 10798 /* Bring voice path up */ 10799 f.subclass = AST_CONTROL_PROGRESS; 10800 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10801 } 10802 pri->pvts[chanpos]->proceeding = 1; 10803 pri->pvts[chanpos]->dialing = 0; 10804 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10805 } 10806 } 10807 break; 10808 case PRI_EVENT_FACNAME: 10809 chanpos = pri_find_principle(pri, e->facname.channel); 10810 if (chanpos < 0) { 10811 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 10812 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10813 } else { 10814 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 10815 if (chanpos < 0) { 10816 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 10817 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10818 } else { 10819 /* Re-use *69 field for PRI */ 10820 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10821 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 10822 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 10823 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 10824 dahdi_enable_ec(pri->pvts[chanpos]); 10825 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10826 } 10827 } 10828 break; 10829 case PRI_EVENT_ANSWER: 10830 chanpos = pri_find_principle(pri, e->answer.channel); 10831 if (chanpos < 0) { 10832 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 10833 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10834 } else { 10835 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 10836 if (chanpos < 0) { 10837 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 10838 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10839 } else { 10840 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10841 /* Now we can do call progress detection */ 10842 10843 /* We changed this so it turns on the DSP no matter what... progress or no progress. 10844 * By this time, we need DTMF detection and other features that were previously disabled 10845 * -- Matt F */ 10846 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10847 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10848 pri->pvts[chanpos]->dsp_features = 0; 10849 } 10850 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 10851 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 10852 x = DAHDI_START; 10853 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 10854 if (res < 0) { 10855 if (errno != EINPROGRESS) { 10856 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 10857 } 10858 } 10859 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10860 pri->pvts[chanpos]->dialing = 1; 10861 /* Send any "w" waited stuff */ 10862 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 10863 if (res < 0) { 10864 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 10865 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10866 } else 10867 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 10868 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10869 } else if (pri->pvts[chanpos]->confirmanswer) { 10870 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 10871 } else { 10872 pri->pvts[chanpos]->dialing = 0; 10873 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 10874 /* Enable echo cancellation if it's not on already */ 10875 dahdi_enable_ec(pri->pvts[chanpos]); 10876 } 10877 10878 #ifdef SUPPORT_USERUSER 10879 if (!ast_strlen_zero(e->answer.useruserinfo)) { 10880 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10881 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10882 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 10883 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10884 } 10885 #endif 10886 10887 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10888 } 10889 } 10890 break; 10891 case PRI_EVENT_HANGUP: 10892 chanpos = pri_find_principle(pri, e->hangup.channel); 10893 if (chanpos < 0) { 10894 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 10895 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10896 } else { 10897 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10898 if (chanpos > -1) { 10899 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10900 if (!pri->pvts[chanpos]->alreadyhungup) { 10901 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 10902 pri->pvts[chanpos]->alreadyhungup = 1; 10903 if (pri->pvts[chanpos]->realcall) 10904 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10905 else if (pri->pvts[chanpos]->owner) { 10906 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 10907 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10908 switch (pri->pvts[chanpos]->owner->_state) { 10909 case AST_STATE_BUSY: 10910 case AST_STATE_UP: 10911 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10912 break; 10913 default: 10914 switch (e->hangup.cause) { 10915 case PRI_CAUSE_USER_BUSY: 10916 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10917 break; 10918 case PRI_CAUSE_CALL_REJECTED: 10919 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10920 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10921 case PRI_CAUSE_SWITCH_CONGESTION: 10922 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10923 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10924 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10925 break; 10926 default: 10927 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10928 } 10929 break; 10930 } 10931 } 10932 if (option_verbose > 2) 10933 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 10934 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 10935 } else { 10936 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10937 pri->pvts[chanpos]->call = NULL; 10938 } 10939 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10940 if (option_verbose > 2) 10941 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 10942 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10943 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10944 pri->pvts[chanpos]->resetting = 1; 10945 } 10946 if (e->hangup.aoc_units > -1) 10947 if (option_verbose > 2) 10948 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10949 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10950 10951 #ifdef SUPPORT_USERUSER 10952 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 10953 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10954 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10955 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10956 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10957 } 10958 #endif 10959 10960 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10961 } else { 10962 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 10963 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10964 } 10965 } 10966 break; 10967 #ifndef PRI_EVENT_HANGUP_REQ 10968 #error please update libpri 10969 #endif 10970 case PRI_EVENT_HANGUP_REQ: 10971 chanpos = pri_find_principle(pri, e->hangup.channel); 10972 if (chanpos < 0) { 10973 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 10974 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10975 } else { 10976 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10977 if (chanpos > -1) { 10978 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10979 if (pri->pvts[chanpos]->realcall) 10980 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10981 else if (pri->pvts[chanpos]->owner) { 10982 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10983 switch (pri->pvts[chanpos]->owner->_state) { 10984 case AST_STATE_BUSY: 10985 case AST_STATE_UP: 10986 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10987 break; 10988 default: 10989 switch (e->hangup.cause) { 10990 case PRI_CAUSE_USER_BUSY: 10991 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10992 break; 10993 case PRI_CAUSE_CALL_REJECTED: 10994 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10995 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10996 case PRI_CAUSE_SWITCH_CONGESTION: 10997 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10998 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10999 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11000 break; 11001 default: 11002 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11003 } 11004 break; 11005 } 11006 if (option_verbose > 2) 11007 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause); 11008 if (e->hangup.aoc_units > -1) 11009 if (option_verbose > 2) 11010 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11011 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11012 } else { 11013 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11014 pri->pvts[chanpos]->call = NULL; 11015 } 11016 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11017 if (option_verbose > 2) 11018 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11019 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11020 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11021 pri->pvts[chanpos]->resetting = 1; 11022 } 11023 11024 #ifdef SUPPORT_USERUSER 11025 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11026 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11027 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11028 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11029 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11030 } 11031 #endif 11032 11033 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11034 } else { 11035 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11036 } 11037 } 11038 break; 11039 case PRI_EVENT_HANGUP_ACK: 11040 chanpos = pri_find_principle(pri, e->hangup.channel); 11041 if (chanpos < 0) { 11042 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11043 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11044 } else { 11045 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11046 if (chanpos > -1) { 11047 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11048 pri->pvts[chanpos]->call = NULL; 11049 pri->pvts[chanpos]->resetting = 0; 11050 if (pri->pvts[chanpos]->owner) { 11051 if (option_verbose > 2) 11052 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11053 } 11054 11055 #ifdef SUPPORT_USERUSER 11056 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11057 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11058 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11059 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11060 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11061 } 11062 #endif 11063 11064 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11065 } 11066 } 11067 break; 11068 case PRI_EVENT_CONFIG_ERR: 11069 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11070 break; 11071 case PRI_EVENT_RESTART_ACK: 11072 chanpos = pri_find_principle(pri, e->restartack.channel); 11073 if (chanpos < 0) { 11074 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11075 channel number, so we have to figure it out... This must be why 11076 everybody resets exactly a channel at a time. */ 11077 for (x = 0; x < pri->numchans; x++) { 11078 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11079 chanpos = x; 11080 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11081 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11082 pri->pvts[chanpos]->prioffset, pri->span); 11083 if (pri->pvts[chanpos]->realcall) 11084 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11085 else if (pri->pvts[chanpos]->owner) { 11086 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11087 pri->pvts[chanpos]->prioffset, pri->span); 11088 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11089 } 11090 pri->pvts[chanpos]->resetting = 0; 11091 if (option_verbose > 2) 11092 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11093 pri->pvts[chanpos]->prioffset, pri->span); 11094 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11095 if (pri->resetting) 11096 pri_check_restart(pri); 11097 break; 11098 } 11099 } 11100 if (chanpos < 0) { 11101 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11102 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11103 } 11104 } else { 11105 if (pri->pvts[chanpos]) { 11106 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11107 if (pri->pvts[chanpos]->realcall) 11108 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11109 else if (pri->pvts[chanpos]->owner) { 11110 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11111 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11112 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11113 } 11114 pri->pvts[chanpos]->resetting = 0; 11115 if (option_verbose > 2) 11116 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11117 pri->pvts[chanpos]->prioffset, pri->span); 11118 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11119 if (pri->resetting) 11120 pri_check_restart(pri); 11121 } 11122 } 11123 break; 11124 case PRI_EVENT_SETUP_ACK: 11125 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11126 if (chanpos < 0) { 11127 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11128 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11129 } else { 11130 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11131 if (chanpos > -1) { 11132 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11133 pri->pvts[chanpos]->setup_ack = 1; 11134 /* Send any queued digits */ 11135 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11136 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11137 pri_information(pri->pri, pri->pvts[chanpos]->call, 11138 pri->pvts[chanpos]->dialdest[x]); 11139 } 11140 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11141 } else 11142 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11143 } 11144 break; 11145 case PRI_EVENT_NOTIFY: 11146 chanpos = pri_find_principle(pri, e->notify.channel); 11147 if (chanpos < 0) { 11148 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11149 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11150 } else { 11151 struct ast_frame f = { AST_FRAME_CONTROL, }; 11152 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11153 switch (e->notify.info) { 11154 case PRI_NOTIFY_REMOTE_HOLD: 11155 f.subclass = AST_CONTROL_HOLD; 11156 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11157 break; 11158 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11159 f.subclass = AST_CONTROL_UNHOLD; 11160 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11161 break; 11162 } 11163 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11164 } 11165 break; 11166 default: 11167 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 11168 } 11169 } 11170 ast_mutex_unlock(&pri->lock); 11171 } 11172 /* Never reached */ 11173 return NULL; 11174 }
Definition at line 9681 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
09682 { 09683 struct dahdi_pvt *p; 09684 p = pri->crvs; 09685 while (p) { 09686 if (p->channel == crv) 09687 return p; 09688 p = p->next; 09689 } 09690 return NULL; 09691 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3403 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03404 { 03405 int oldslot = -1; 03406 struct pri *old; 03407 int newslot = -1; 03408 int x; 03409 old = pri->pri; 03410 for (x = 0; x < NUM_DCHANS; x++) { 03411 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03412 newslot = x; 03413 if (pri->dchans[x] == old) { 03414 oldslot = x; 03415 } 03416 } 03417 if (newslot < 0) { 03418 newslot = 0; 03419 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03420 pri->dchannels[newslot]); 03421 } 03422 if (old && (oldslot != newslot)) 03423 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03424 pri->dchannels[oldslot], pri->dchannels[newslot]); 03425 pri->pri = pri->dchans[newslot]; 03426 return 0; 03427 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9304 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::inalarm, LOG_DEBUG, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::prioffset, and dahdi_pri::pvts.
Referenced by dahdi_request().
09305 { 09306 int x; 09307 if (backwards) 09308 x = pri->numchans; 09309 else 09310 x = 0; 09311 for (;;) { 09312 if (backwards && (x < 0)) 09313 break; 09314 if (!backwards && (x >= pri->numchans)) 09315 break; 09316 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09317 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 09318 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09319 return x; 09320 } 09321 if (backwards) 09322 x--; 09323 else 09324 x++; 09325 } 09326 return -1; 09327 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 9694 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, dahdi_pri::pvts, and dahdi_pvt::span.
09695 { 09696 int x; 09697 int span = PRI_SPAN(channel); 09698 int spanfd; 09699 struct dahdi_params param; 09700 int principle = -1; 09701 int explicit = PRI_EXPLICIT(channel); 09702 channel = PRI_CHANNEL(channel); 09703 09704 if (!explicit) { 09705 spanfd = pri_active_dchan_fd(pri); 09706 memset(¶m, 0, sizeof(param)); 09707 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 09708 return -1; 09709 span = pris[param.spanno - 1].prilogicalspan; 09710 } 09711 09712 for (x = 0; x < pri->numchans; x++) { 09713 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 09714 principle = x; 09715 break; 09716 } 09717 } 09718 09719 return principle; 09720 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 9722 of file chan_dahdi.c.
References ast_log(), ast_string_field_build, ast_verbose(), dahdi_pvt::call, dahdi_chan_name, name, dahdi_pri::numchans, option_verbose, dahdi_pvt::pri, dahdi_pri::pvts, SUB_REAL, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.
09723 { 09724 int x; 09725 struct dahdi_pvt *crv; 09726 if (!c) { 09727 if (principle < 0) 09728 return -1; 09729 return principle; 09730 } 09731 if ((principle > -1) && 09732 (principle < pri->numchans) && 09733 (pri->pvts[principle]) && 09734 (pri->pvts[principle]->call == c)) 09735 return principle; 09736 /* First, check for other bearers */ 09737 for (x = 0; x < pri->numchans; x++) { 09738 if (!pri->pvts[x]) 09739 continue; 09740 if (pri->pvts[x]->call == c) { 09741 /* Found our call */ 09742 if (principle != x) { 09743 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 09744 09745 if (option_verbose > 2) 09746 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 09747 old->channel, new->channel); 09748 if (new->owner) { 09749 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 09750 old->channel, new->channel, new->channel); 09751 return -1; 09752 } 09753 /* Fix it all up now */ 09754 new->owner = old->owner; 09755 old->owner = NULL; 09756 if (new->owner) { 09757 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 09758 new->owner->tech_pvt = new; 09759 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 09760 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 09761 old->subs[SUB_REAL].owner = NULL; 09762 } else 09763 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); 09764 new->call = old->call; 09765 old->call = NULL; 09766 09767 /* Copy any DSP that may be present */ 09768 new->dsp = old->dsp; 09769 new->dsp_features = old->dsp_features; 09770 old->dsp = NULL; 09771 old->dsp_features = 0; 09772 } 09773 return principle; 09774 } 09775 } 09776 /* Now check for a CRV with no bearer */ 09777 crv = pri->crvs; 09778 while (crv) { 09779 if (crv->call == c) { 09780 /* This is our match... Perform some basic checks */ 09781 if (crv->bearer) 09782 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 09783 else if (pri->pvts[principle]->owner) 09784 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 09785 else { 09786 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 09787 wakeup the potential sleeper */ 09788 dahdi_close_sub(crv, SUB_REAL); 09789 pri->pvts[principle]->call = crv->call; 09790 pri_assign_bearer(crv, pri, pri->pvts[principle]); 09791 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 09792 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 09793 pri->trunkgroup, crv->channel); 09794 wakeup_sub(crv, SUB_REAL, pri); 09795 } 09796 return principle; 09797 } 09798 crv = crv->next; 09799 } 09800 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 09801 return -1; 09802 }
Definition at line 1145 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(), dahdi_write(), and send_keypad_facility_exec().
01146 { 01147 int res; 01148 /* Grab the lock first */ 01149 do { 01150 res = ast_mutex_trylock(&pri->lock); 01151 if (res) { 01152 DEADLOCK_AVOIDANCE(&pvt->lock); 01153 } 01154 } while (res); 01155 /* Then break the poll */ 01156 if (pri->master != AST_PTHREADT_NULL) 01157 pthread_kill(pri->master, SIGURG); 01158 return 0; 01159 }
Definition at line 9962 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.
09963 { 09964 int x; 09965 int redo; 09966 ast_mutex_unlock(&pri->lock); 09967 ast_mutex_lock(&p->lock); 09968 do { 09969 redo = 0; 09970 for (x = 0; x < 3; x++) { 09971 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 09972 redo++; 09973 DEADLOCK_AVOIDANCE(&p->lock); 09974 } 09975 if (p->subs[x].owner) { 09976 ast_queue_hangup(p->subs[x].owner); 09977 ast_mutex_unlock(&p->subs[x].owner->lock); 09978 } 09979 } 09980 } while (redo); 09981 ast_mutex_unlock(&p->lock); 09982 ast_mutex_lock(&pri->lock); 09983 return 0; 09984 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3351 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03352 { 03353 int x; 03354 for (x = 0; x < NUM_DCHANS; x++) { 03355 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03356 return 1; 03357 } 03358 return 0; 03359 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3374 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03375 { 03376 switch (level) { 03377 case 0: 03378 return "Primary"; 03379 case 1: 03380 return "Secondary"; 03381 case 2: 03382 return "Tertiary"; 03383 case 3: 03384 return "Quaternary"; 03385 default: 03386 return "<Unknown>"; 03387 } 03388 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 416 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(), dahdi_write(), and send_keypad_facility_exec().
00417 { 00418 ast_mutex_unlock(&pri->lock); 00419 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8446 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().
08447 { 08448 int x; 08449 int trunkgroup; 08450 /* Get appropriate trunk group if there is one */ 08451 trunkgroup = pris[*span].mastertrunkgroup; 08452 if (trunkgroup) { 08453 /* Select a specific trunk group */ 08454 for (x = 0; x < NUM_SPANS; x++) { 08455 if (pris[x].trunkgroup == trunkgroup) { 08456 *span = x; 08457 return 0; 08458 } 08459 } 08460 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08461 *span = -1; 08462 } else { 08463 if (pris[*span].trunkgroup) { 08464 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08465 *span = -1; 08466 } else if (pris[*span].mastertrunkgroup) { 08467 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08468 *span = -1; 08469 } else { 08470 if (si->totalchans == 31) { 08471 /* E1 */ 08472 pris[*span].dchannels[0] = 16 + offset; 08473 } else if (si->totalchans == 24) { 08474 /* T1 or J1 */ 08475 pris[*span].dchannels[0] = 24 + offset; 08476 } else if (si->totalchans == 3) { 08477 /* BRI */ 08478 pris[*span].dchannels[0] = 3 + offset; 08479 } else { 08480 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); 08481 *span = -1; 08482 return 0; 08483 } 08484 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08485 pris[*span].offset = offset; 08486 pris[*span].span = *span + 1; 08487 } 08488 } 08489 return 0; 08490 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 12945 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, 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, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, 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, 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, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, 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, ast_variable::value, and VERBOSE_PREFIX_3.
Referenced by setup_dahdi().
12946 { 12947 struct dahdi_pvt *tmp; 12948 int y; 12949 int found_pseudo = 0; 12950 char dahdichan[MAX_CHANLIST_LEN] = {}; 12951 12952 for (; v; v = v->next) { 12953 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 12954 continue; 12955 12956 /* Create the interface list */ 12957 if (!strcasecmp(v->name, "channel") 12958 #ifdef HAVE_PRI 12959 || !strcasecmp(v->name, "crv") 12960 #endif 12961 ) { 12962 int iscrv; 12963 if (skipchannels) 12964 continue; 12965 iscrv = !strcasecmp(v->name, "crv"); 12966 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 12967 return -1; 12968 } else if (!strcasecmp(v->name, "buffers")) { 12969 int res; 12970 char policy[21] = ""; 12971 12972 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 12973 if (res != 2) { 12974 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 12975 confp->chan.buf_no = numbufs; 12976 continue; 12977 } 12978 if (confp->chan.buf_no < 0) 12979 confp->chan.buf_no = numbufs; 12980 if (!strcasecmp(policy, "full")) { 12981 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 12982 } else if (!strcasecmp(policy, "immediate")) { 12983 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 12984 } else { 12985 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 12986 } 12987 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 12988 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 12989 if (v->name[0] == 'z' || v->name[0] == 'Z') { 12990 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 12991 } 12992 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 12993 if (ast_true(v->value)) 12994 confp->chan.usedistinctiveringdetection = 1; 12995 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 12996 if (ast_true(v->value)) 12997 distinctiveringaftercid = 1; 12998 } else if (!strcasecmp(v->name, "dring1context")) { 12999 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 13000 } else if (!strcasecmp(v->name, "dring2context")) { 13001 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 13002 } else if (!strcasecmp(v->name, "dring3context")) { 13003 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 13004 } else if (!strcasecmp(v->name, "dring1")) { 13005 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 13006 } else if (!strcasecmp(v->name, "dring2")) { 13007 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 13008 } else if (!strcasecmp(v->name, "dring3")) { 13009 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 13010 } else if (!strcasecmp(v->name, "usecallerid")) { 13011 confp->chan.use_callerid = ast_true(v->value); 13012 } else if (!strcasecmp(v->name, "cidsignalling")) { 13013 if (!strcasecmp(v->value, "bell")) 13014 confp->chan.cid_signalling = CID_SIG_BELL; 13015 else if (!strcasecmp(v->value, "v23")) 13016 confp->chan.cid_signalling = CID_SIG_V23; 13017 else if (!strcasecmp(v->value, "dtmf")) 13018 confp->chan.cid_signalling = CID_SIG_DTMF; 13019 else if (!strcasecmp(v->value, "smdi")) 13020 confp->chan.cid_signalling = CID_SIG_SMDI; 13021 else if (!strcasecmp(v->value, "v23_jp")) 13022 confp->chan.cid_signalling = CID_SIG_V23_JP; 13023 else if (ast_true(v->value)) 13024 confp->chan.cid_signalling = CID_SIG_BELL; 13025 } else if (!strcasecmp(v->name, "cidstart")) { 13026 if (!strcasecmp(v->value, "ring")) 13027 confp->chan.cid_start = CID_START_RING; 13028 else if (!strcasecmp(v->value, "polarity")) 13029 confp->chan.cid_start = CID_START_POLARITY; 13030 else if (!strcasecmp(v->value, "dtmf")) 13031 confp->chan.cid_start = CID_START_DTMF_NOALERT; 13032 else if (ast_true(v->value)) 13033 confp->chan.cid_start = CID_START_RING; 13034 } else if (!strcasecmp(v->name, "threewaycalling")) { 13035 confp->chan.threewaycalling = ast_true(v->value); 13036 } else if (!strcasecmp(v->name, "cancallforward")) { 13037 confp->chan.cancallforward = ast_true(v->value); 13038 } else if (!strcasecmp(v->name, "relaxdtmf")) { 13039 if (ast_true(v->value)) 13040 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 13041 else 13042 confp->chan.dtmfrelax = 0; 13043 } else if (!strcasecmp(v->name, "mailbox")) { 13044 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 13045 } else if (!strcasecmp(v->name, "hasvoicemail")) { 13046 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 13047 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 13048 } 13049 } else if (!strcasecmp(v->name, "adsi")) { 13050 confp->chan.adsi = ast_true(v->value); 13051 } else if (!strcasecmp(v->name, "usesmdi")) { 13052 confp->chan.use_smdi = ast_true(v->value); 13053 } else if (!strcasecmp(v->name, "smdiport")) { 13054 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 13055 } else if (!strcasecmp(v->name, "transfer")) { 13056 confp->chan.transfer = ast_true(v->value); 13057 } else if (!strcasecmp(v->name, "canpark")) { 13058 confp->chan.canpark = ast_true(v->value); 13059 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 13060 confp->chan.echocanbridged = ast_true(v->value); 13061 } else if (!strcasecmp(v->name, "busydetect")) { 13062 confp->chan.busydetect = ast_true(v->value); 13063 } else if (!strcasecmp(v->name, "busycount")) { 13064 confp->chan.busycount = atoi(v->value); 13065 } else if (!strcasecmp(v->name, "silencethreshold")) { 13066 confp->chan.silencethreshold = atoi(v->value); 13067 } else if (!strcasecmp(v->name, "busycompare")) { 13068 confp->chan.busycompare = ast_true(v->value); 13069 } else if (!strcasecmp(v->name, "busypattern")) { 13070 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 13071 if (count == 1) 13072 confp->chan.busyquietlength = 0; 13073 else if (count < 1) 13074 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 13075 } else if (!strcasecmp(v->name, "busyfuzziness")) { 13076 confp->chan.busyfuzziness = atoi(v->value); 13077 } else if (!strcasecmp(v->name, "callprogress")) { 13078 if (ast_true(v->value)) 13079 confp->chan.callprogress |= 1; 13080 else 13081 confp->chan.callprogress &= ~1; 13082 } else if (!strcasecmp(v->name, "faxdetect")) { 13083 if (!strcasecmp(v->value, "incoming")) { 13084 confp->chan.callprogress |= 4; 13085 confp->chan.callprogress &= ~2; 13086 } else if (!strcasecmp(v->value, "outgoing")) { 13087 confp->chan.callprogress &= ~4; 13088 confp->chan.callprogress |= 2; 13089 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 13090 confp->chan.callprogress |= 6; 13091 else 13092 confp->chan.callprogress &= ~6; 13093 } else if (!strcasecmp(v->name, "echocancel")) { 13094 if (!ast_strlen_zero(v->value)) { 13095 y = atoi(v->value); 13096 } else 13097 y = 0; 13098 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 13099 confp->chan.echocancel = y; 13100 else { 13101 confp->chan.echocancel = ast_true(v->value); 13102 if (confp->chan.echocancel) 13103 confp->chan.echocancel=128; 13104 } 13105 } else if (!strcasecmp(v->name, "echotraining")) { 13106 if (sscanf(v->value, "%30d", &y) == 1) { 13107 if ((y < 10) || (y > 4000)) { 13108 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 13109 } else { 13110 confp->chan.echotraining = y; 13111 } 13112 } else if (ast_true(v->value)) { 13113 confp->chan.echotraining = 400; 13114 } else 13115 confp->chan.echotraining = 0; 13116 } else if (!strcasecmp(v->name, "hidecallerid")) { 13117 confp->chan.hidecallerid = ast_true(v->value); 13118 } else if (!strcasecmp(v->name, "hidecalleridname")) { 13119 confp->chan.hidecalleridname = ast_true(v->value); 13120 } else if (!strcasecmp(v->name, "pulsedial")) { 13121 confp->chan.pulse = ast_true(v->value); 13122 } else if (!strcasecmp(v->name, "callreturn")) { 13123 confp->chan.callreturn = ast_true(v->value); 13124 } else if (!strcasecmp(v->name, "callwaiting")) { 13125 confp->chan.callwaiting = ast_true(v->value); 13126 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 13127 confp->chan.callwaitingcallerid = ast_true(v->value); 13128 } else if (!strcasecmp(v->name, "context")) { 13129 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 13130 } else if (!strcasecmp(v->name, "language")) { 13131 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 13132 } else if (!strcasecmp(v->name, "progzone")) { 13133 ast_copy_string(progzone, v->value, sizeof(progzone)); 13134 } else if (!strcasecmp(v->name, "mohinterpret") 13135 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 13136 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 13137 } else if (!strcasecmp(v->name, "mohsuggest")) { 13138 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 13139 } else if (!strcasecmp(v->name, "stripmsd")) { 13140 confp->chan.stripmsd = atoi(v->value); 13141 } else if (!strcasecmp(v->name, "jitterbuffers")) { 13142 numbufs = atoi(v->value); 13143 } else if (!strcasecmp(v->name, "group")) { 13144 confp->chan.group = ast_get_group(v->value); 13145 } else if (!strcasecmp(v->name, "callgroup")) { 13146 confp->chan.callgroup = ast_get_group(v->value); 13147 } else if (!strcasecmp(v->name, "pickupgroup")) { 13148 confp->chan.pickupgroup = ast_get_group(v->value); 13149 } else if (!strcasecmp(v->name, "immediate")) { 13150 confp->chan.immediate = ast_true(v->value); 13151 } else if (!strcasecmp(v->name, "transfertobusy")) { 13152 confp->chan.transfertobusy = ast_true(v->value); 13153 } else if (!strcasecmp(v->name, "rxgain")) { 13154 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 13155 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 13156 } 13157 } else if (!strcasecmp(v->name, "txgain")) { 13158 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 13159 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 13160 } 13161 } else if (!strcasecmp(v->name, "tonezone")) { 13162 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 13163 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 13164 } 13165 } else if (!strcasecmp(v->name, "callerid")) { 13166 if (!strcasecmp(v->value, "asreceived")) { 13167 confp->chan.cid_num[0] = '\0'; 13168 confp->chan.cid_name[0] = '\0'; 13169 } else { 13170 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 13171 } 13172 } else if (!strcasecmp(v->name, "fullname")) { 13173 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 13174 } else if (!strcasecmp(v->name, "cid_number")) { 13175 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 13176 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 13177 confp->chan.dahditrcallerid = ast_true(v->value); 13178 if (strstr(v->name, "zap")) { 13179 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 13180 } 13181 } else if (!strcasecmp(v->name, "restrictcid")) { 13182 confp->chan.restrictcid = ast_true(v->value); 13183 } else if (!strcasecmp(v->name, "usecallingpres")) { 13184 confp->chan.use_callingpres = ast_true(v->value); 13185 } else if (!strcasecmp(v->name, "accountcode")) { 13186 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 13187 } else if (!strcasecmp(v->name, "amaflags")) { 13188 y = ast_cdr_amaflags2int(v->value); 13189 if (y < 0) 13190 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 13191 else 13192 confp->chan.amaflags = y; 13193 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 13194 confp->chan.polarityonanswerdelay = atoi(v->value); 13195 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 13196 confp->chan.answeronpolarityswitch = ast_true(v->value); 13197 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 13198 confp->chan.hanguponpolarityswitch = ast_true(v->value); 13199 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 13200 confp->chan.sendcalleridafter = atoi(v->value); 13201 } else if (reload != 1) { 13202 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 13203 confp->chan.outsigmod = -1; 13204 if (!strcasecmp(v->value, "em")) { 13205 confp->chan.sig = SIG_EM; 13206 } else if (!strcasecmp(v->value, "em_e1")) { 13207 confp->chan.sig = SIG_EM_E1; 13208 } else if (!strcasecmp(v->value, "em_w")) { 13209 confp->chan.sig = SIG_EMWINK; 13210 confp->chan.radio = 0; 13211 } else if (!strcasecmp(v->value, "fxs_ls")) { 13212 confp->chan.sig = SIG_FXSLS; 13213 confp->chan.radio = 0; 13214 } else if (!strcasecmp(v->value, "fxs_gs")) { 13215 confp->chan.sig = SIG_FXSGS; 13216 confp->chan.radio = 0; 13217 } else if (!strcasecmp(v->value, "fxs_ks")) { 13218 confp->chan.sig = SIG_FXSKS; 13219 confp->chan.radio = 0; 13220 } else if (!strcasecmp(v->value, "fxo_ls")) { 13221 confp->chan.sig = SIG_FXOLS; 13222 confp->chan.radio = 0; 13223 } else if (!strcasecmp(v->value, "fxo_gs")) { 13224 confp->chan.sig = SIG_FXOGS; 13225 confp->chan.radio = 0; 13226 } else if (!strcasecmp(v->value, "fxo_ks")) { 13227 confp->chan.sig = SIG_FXOKS; 13228 confp->chan.radio = 0; 13229 } else if (!strcasecmp(v->value, "fxs_rx")) { 13230 confp->chan.sig = SIG_FXSKS; 13231 confp->chan.radio = 1; 13232 } else if (!strcasecmp(v->value, "fxo_rx")) { 13233 confp->chan.sig = SIG_FXOLS; 13234 confp->chan.radio = 1; 13235 } else if (!strcasecmp(v->value, "fxs_tx")) { 13236 confp->chan.sig = SIG_FXSLS; 13237 confp->chan.radio = 1; 13238 } else if (!strcasecmp(v->value, "fxo_tx")) { 13239 confp->chan.sig = SIG_FXOGS; 13240 confp->chan.radio = 1; 13241 } else if (!strcasecmp(v->value, "em_rx")) { 13242 confp->chan.sig = SIG_EM; 13243 confp->chan.radio = 1; 13244 } else if (!strcasecmp(v->value, "em_tx")) { 13245 confp->chan.sig = SIG_EM; 13246 confp->chan.radio = 1; 13247 } else if (!strcasecmp(v->value, "em_rxtx")) { 13248 confp->chan.sig = SIG_EM; 13249 confp->chan.radio = 2; 13250 } else if (!strcasecmp(v->value, "em_txrx")) { 13251 confp->chan.sig = SIG_EM; 13252 confp->chan.radio = 2; 13253 } else if (!strcasecmp(v->value, "sf")) { 13254 confp->chan.sig = SIG_SF; 13255 confp->chan.radio = 0; 13256 } else if (!strcasecmp(v->value, "sf_w")) { 13257 confp->chan.sig = SIG_SFWINK; 13258 confp->chan.radio = 0; 13259 } else if (!strcasecmp(v->value, "sf_featd")) { 13260 confp->chan.sig = SIG_FEATD; 13261 confp->chan.radio = 0; 13262 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13263 confp->chan.sig = SIG_FEATDMF; 13264 confp->chan.radio = 0; 13265 } else if (!strcasecmp(v->value, "sf_featb")) { 13266 confp->chan.sig = SIG_SF_FEATB; 13267 confp->chan.radio = 0; 13268 } else if (!strcasecmp(v->value, "sf")) { 13269 confp->chan.sig = SIG_SF; 13270 confp->chan.radio = 0; 13271 } else if (!strcasecmp(v->value, "sf_rx")) { 13272 confp->chan.sig = SIG_SF; 13273 confp->chan.radio = 1; 13274 } else if (!strcasecmp(v->value, "sf_tx")) { 13275 confp->chan.sig = SIG_SF; 13276 confp->chan.radio = 1; 13277 } else if (!strcasecmp(v->value, "sf_rxtx")) { 13278 confp->chan.sig = SIG_SF; 13279 confp->chan.radio = 2; 13280 } else if (!strcasecmp(v->value, "sf_txrx")) { 13281 confp->chan.sig = SIG_SF; 13282 confp->chan.radio = 2; 13283 } else if (!strcasecmp(v->value, "featd")) { 13284 confp->chan.sig = SIG_FEATD; 13285 confp->chan.radio = 0; 13286 } else if (!strcasecmp(v->value, "featdmf")) { 13287 confp->chan.sig = SIG_FEATDMF; 13288 confp->chan.radio = 0; 13289 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13290 confp->chan.sig = SIG_FEATDMF_TA; 13291 confp->chan.radio = 0; 13292 } else if (!strcasecmp(v->value, "e911")) { 13293 confp->chan.sig = SIG_E911; 13294 confp->chan.radio = 0; 13295 } else if (!strcasecmp(v->value, "fgccama")) { 13296 confp->chan.sig = SIG_FGC_CAMA; 13297 confp->chan.radio = 0; 13298 } else if (!strcasecmp(v->value, "fgccamamf")) { 13299 confp->chan.sig = SIG_FGC_CAMAMF; 13300 confp->chan.radio = 0; 13301 } else if (!strcasecmp(v->value, "featb")) { 13302 confp->chan.sig = SIG_FEATB; 13303 confp->chan.radio = 0; 13304 #ifdef HAVE_OPENR2 13305 } else if (!strcasecmp(v->value, "mfcr2")) { 13306 confp->chan.sig = SIG_MFCR2; 13307 #endif 13308 #ifdef HAVE_PRI 13309 } else if (!strcasecmp(v->value, "pri_net")) { 13310 confp->chan.radio = 0; 13311 confp->chan.sig = SIG_PRI; 13312 confp->pri.nodetype = PRI_NETWORK; 13313 } else if (!strcasecmp(v->value, "pri_cpe")) { 13314 confp->chan.sig = SIG_PRI; 13315 confp->chan.radio = 0; 13316 confp->pri.nodetype = PRI_CPE; 13317 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 13318 confp->chan.sig = SIG_GR303FXOKS; 13319 confp->chan.radio = 0; 13320 confp->pri.nodetype = PRI_NETWORK; 13321 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 13322 confp->chan.sig = SIG_GR303FXSKS; 13323 confp->chan.radio = 0; 13324 confp->pri.nodetype = PRI_CPE; 13325 #endif 13326 } else { 13327 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13328 } 13329 } else if (!strcasecmp(v->name, "outsignalling")) { 13330 if (!strcasecmp(v->value, "em")) { 13331 confp->chan.outsigmod = SIG_EM; 13332 } else if (!strcasecmp(v->value, "em_e1")) { 13333 confp->chan.outsigmod = SIG_EM_E1; 13334 } else if (!strcasecmp(v->value, "em_w")) { 13335 confp->chan.outsigmod = SIG_EMWINK; 13336 } else if (!strcasecmp(v->value, "sf")) { 13337 confp->chan.outsigmod = SIG_SF; 13338 } else if (!strcasecmp(v->value, "sf_w")) { 13339 confp->chan.outsigmod = SIG_SFWINK; 13340 } else if (!strcasecmp(v->value, "sf_featd")) { 13341 confp->chan.outsigmod = SIG_FEATD; 13342 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13343 confp->chan.outsigmod = SIG_FEATDMF; 13344 } else if (!strcasecmp(v->value, "sf_featb")) { 13345 confp->chan.outsigmod = SIG_SF_FEATB; 13346 } else if (!strcasecmp(v->value, "sf")) { 13347 confp->chan.outsigmod = SIG_SF; 13348 } else if (!strcasecmp(v->value, "featd")) { 13349 confp->chan.outsigmod = SIG_FEATD; 13350 } else if (!strcasecmp(v->value, "featdmf")) { 13351 confp->chan.outsigmod = SIG_FEATDMF; 13352 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13353 confp->chan.outsigmod = SIG_FEATDMF_TA; 13354 } else if (!strcasecmp(v->value, "e911")) { 13355 confp->chan.outsigmod = SIG_E911; 13356 } else if (!strcasecmp(v->value, "fgccama")) { 13357 confp->chan.outsigmod = SIG_FGC_CAMA; 13358 } else if (!strcasecmp(v->value, "fgccamamf")) { 13359 confp->chan.outsigmod = SIG_FGC_CAMAMF; 13360 } else if (!strcasecmp(v->value, "featb")) { 13361 confp->chan.outsigmod = SIG_FEATB; 13362 } else { 13363 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13364 } 13365 #ifdef HAVE_PRI 13366 } else if (!strcasecmp(v->name, "pridialplan")) { 13367 if (!strcasecmp(v->value, "national")) { 13368 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 13369 } else if (!strcasecmp(v->value, "unknown")) { 13370 confp->pri.dialplan = PRI_UNKNOWN + 1; 13371 } else if (!strcasecmp(v->value, "private")) { 13372 confp->pri.dialplan = PRI_PRIVATE + 1; 13373 } else if (!strcasecmp(v->value, "international")) { 13374 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 13375 } else if (!strcasecmp(v->value, "local")) { 13376 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 13377 } else if (!strcasecmp(v->value, "dynamic")) { 13378 confp->pri.dialplan = -1; 13379 } else { 13380 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13381 } 13382 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 13383 if (!strcasecmp(v->value, "national")) { 13384 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 13385 } else if (!strcasecmp(v->value, "unknown")) { 13386 confp->pri.localdialplan = PRI_UNKNOWN + 1; 13387 } else if (!strcasecmp(v->value, "private")) { 13388 confp->pri.localdialplan = PRI_PRIVATE + 1; 13389 } else if (!strcasecmp(v->value, "international")) { 13390 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 13391 } else if (!strcasecmp(v->value, "local")) { 13392 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 13393 } else if (!strcasecmp(v->value, "dynamic")) { 13394 confp->pri.localdialplan = -1; 13395 } else { 13396 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13397 } 13398 } else if (!strcasecmp(v->name, "switchtype")) { 13399 if (!strcasecmp(v->value, "national")) 13400 confp->pri.switchtype = PRI_SWITCH_NI2; 13401 else if (!strcasecmp(v->value, "ni1")) 13402 confp->pri.switchtype = PRI_SWITCH_NI1; 13403 else if (!strcasecmp(v->value, "dms100")) 13404 confp->pri.switchtype = PRI_SWITCH_DMS100; 13405 else if (!strcasecmp(v->value, "4ess")) 13406 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 13407 else if (!strcasecmp(v->value, "5ess")) 13408 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 13409 else if (!strcasecmp(v->value, "euroisdn")) 13410 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 13411 else if (!strcasecmp(v->value, "qsig")) 13412 confp->pri.switchtype = PRI_SWITCH_QSIG; 13413 else { 13414 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 13415 return -1; 13416 } 13417 } else if (!strcasecmp(v->name, "nsf")) { 13418 if (!strcasecmp(v->value, "sdn")) 13419 confp->pri.nsf = PRI_NSF_SDN; 13420 else if (!strcasecmp(v->value, "megacom")) 13421 confp->pri.nsf = PRI_NSF_MEGACOM; 13422 else if (!strcasecmp(v->value, "tollfreemegacom")) 13423 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 13424 else if (!strcasecmp(v->value, "accunet")) 13425 confp->pri.nsf = PRI_NSF_ACCUNET; 13426 else if (!strcasecmp(v->value, "none")) 13427 confp->pri.nsf = PRI_NSF_NONE; 13428 else { 13429 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 13430 confp->pri.nsf = PRI_NSF_NONE; 13431 } 13432 } else if (!strcasecmp(v->name, "priindication")) { 13433 if (!strcasecmp(v->value, "outofband")) 13434 confp->chan.priindication_oob = 1; 13435 else if (!strcasecmp(v->value, "inband")) 13436 confp->chan.priindication_oob = 0; 13437 else 13438 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 13439 v->value, v->lineno); 13440 } else if (!strcasecmp(v->name, "priexclusive")) { 13441 confp->chan.priexclusive = ast_true(v->value); 13442 } else if (!strcasecmp(v->name, "internationalprefix")) { 13443 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 13444 } else if (!strcasecmp(v->name, "nationalprefix")) { 13445 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 13446 } else if (!strcasecmp(v->name, "localprefix")) { 13447 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 13448 } else if (!strcasecmp(v->name, "privateprefix")) { 13449 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 13450 } else if (!strcasecmp(v->name, "unknownprefix")) { 13451 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 13452 } else if (!strcasecmp(v->name, "resetinterval")) { 13453 if (!strcasecmp(v->value, "never")) 13454 confp->pri.resetinterval = -1; 13455 else if (atoi(v->value) >= 60) 13456 confp->pri.resetinterval = atoi(v->value); 13457 else 13458 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 13459 v->value, v->lineno); 13460 } else if (!strcasecmp(v->name, "minunused")) { 13461 confp->pri.minunused = atoi(v->value); 13462 } else if (!strcasecmp(v->name, "minidle")) { 13463 confp->pri.minidle = atoi(v->value); 13464 } else if (!strcasecmp(v->name, "idleext")) { 13465 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 13466 } else if (!strcasecmp(v->name, "idledial")) { 13467 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 13468 } else if (!strcasecmp(v->name, "overlapdial")) { 13469 if (ast_true(v->value)) { 13470 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13471 } else if (!strcasecmp(v->value, "incoming")) { 13472 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 13473 } else if (!strcasecmp(v->value, "outgoing")) { 13474 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 13475 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 13476 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13477 } else { 13478 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 13479 } 13480 #ifdef HAVE_PRI_INBANDDISCONNECT 13481 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 13482 confp->pri.inbanddisconnect = ast_true(v->value); 13483 #endif 13484 } else if (!strcasecmp(v->name, "pritimer")) { 13485 #ifdef PRI_GETSET_TIMERS 13486 char tmp[20]; 13487 char *timerc; 13488 char *c; 13489 int timer; 13490 int timeridx; 13491 13492 ast_copy_string(tmp, v->value, sizeof(tmp)); 13493 c = tmp; 13494 timerc = strsep(&c, ","); 13495 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 13496 timeridx = pri_timer2idx(timerc); 13497 timer = atoi(c); 13498 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 13499 ast_log(LOG_WARNING, 13500 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 13501 v->lineno); 13502 } else if (!timer) { 13503 ast_log(LOG_WARNING, 13504 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 13505 c, timerc, v->lineno); 13506 } else { 13507 pritimers[timeridx] = timer; 13508 } 13509 } else { 13510 ast_log(LOG_WARNING, 13511 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 13512 v->value, v->lineno); 13513 } 13514 #endif /* PRI_GETSET_TIMERS */ 13515 } else if (!strcasecmp(v->name, "facilityenable")) { 13516 confp->pri.facilityenable = ast_true(v->value); 13517 #endif /* HAVE_PRI */ 13518 #ifdef HAVE_OPENR2 13519 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 13520 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file)); 13521 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); 13522 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 13523 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir)); 13524 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 13525 mfcr2_cur_variant = openr2_proto_get_variant(v->value); 13526 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) { 13527 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno); 13528 } 13529 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 13530 mfcr2_cur_mfback_timeout = atoi(v->value); 13531 if (!mfcr2_cur_mfback_timeout) { 13532 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 13533 mfcr2_cur_mfback_timeout = -1; 13534 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) { 13535 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 13536 } 13537 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 13538 mfcr2_cur_metering_pulse_timeout = atoi(v->value); 13539 if (mfcr2_cur_metering_pulse_timeout > 500) { 13540 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n"); 13541 } 13542 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 13543 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) { 13544 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0; 13545 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) { 13546 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0; 13547 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) { 13548 mfcr2_cur_dtmf_time_on = atoi(v->value); 13549 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) { 13550 mfcr2_cur_dtmf_time_off = atoi(v->value); 13551 #endif 13552 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 13553 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0; 13554 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 13555 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0; 13556 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 13557 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0; 13558 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 13559 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0; 13560 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 13561 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0; 13562 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 13563 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0; 13564 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 13565 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0; 13566 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 13567 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0; 13568 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 13569 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0; 13570 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 13571 mfcr2_cur_max_ani = atoi(v->value); 13572 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) { 13573 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1; 13574 } 13575 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 13576 mfcr2_cur_max_dnis = atoi(v->value); 13577 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) { 13578 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1; 13579 } 13580 } else if (!strcasecmp(v->name, "mfcr2_category")) { 13581 mfcr2_cur_category = openr2_proto_get_category(v->value); 13582 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) { 13583 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 13584 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 13585 v->value, v->lineno); 13586 } 13587 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 13588 openr2_log_level_t tmplevel; 13589 char *toklevel = NULL; 13590 char *saveptr = NULL; 13591 char *logval = ast_strdupa(v->value); 13592 toklevel = strtok_r(logval, ",", &saveptr); 13593 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13594 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno); 13595 } else if (OR2_LOG_NOTHING == tmplevel) { 13596 mfcr2_cur_loglevel = tmplevel; 13597 } else { 13598 mfcr2_cur_loglevel |= tmplevel; 13599 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 13600 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13601 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno); 13602 continue; 13603 } 13604 mfcr2_cur_loglevel |= tmplevel; 13605 } 13606 } 13607 #endif /* HAVE_OPENR2 */ 13608 13609 } else if (!strcasecmp(v->name, "cadence")) { 13610 /* setup to scan our argument */ 13611 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 13612 int i; 13613 struct dahdi_ring_cadence new_cadence; 13614 int cid_location = -1; 13615 int firstcadencepos = 0; 13616 char original_args[80]; 13617 int cadence_is_ok = 1; 13618 13619 ast_copy_string(original_args, v->value, sizeof(original_args)); 13620 /* 16 cadences allowed (8 pairs) */ 13621 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]); 13622 13623 /* Cadence must be even (on/off) */ 13624 if (element_count % 2 == 1) { 13625 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 13626 cadence_is_ok = 0; 13627 } 13628 13629 /* Ring cadences cannot be negative */ 13630 for (i = 0; i < element_count; i++) { 13631 if (c[i] == 0) { 13632 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 13633 cadence_is_ok = 0; 13634 break; 13635 } else if (c[i] < 0) { 13636 if (i % 2 == 1) { 13637 /* Silence duration, negative possibly okay */ 13638 if (cid_location == -1) { 13639 cid_location = i; 13640 c[i] *= -1; 13641 } else { 13642 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 13643 cadence_is_ok = 0; 13644 break; 13645 } 13646 } else { 13647 if (firstcadencepos == 0) { 13648 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 13649 /* duration will be passed negative to the DAHDI driver */ 13650 } else { 13651 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 13652 cadence_is_ok = 0; 13653 break; 13654 } 13655 } 13656 } 13657 } 13658 13659 /* Substitute our scanned cadence */ 13660 for (i = 0; i < 16; i++) { 13661 new_cadence.ringcadence[i] = c[i]; 13662 } 13663 13664 if (cadence_is_ok) { 13665 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 13666 if (element_count < 2) { 13667 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 13668 } else { 13669 if (cid_location == -1) { 13670 /* user didn't say; default to first pause */ 13671 cid_location = 1; 13672 } else { 13673 /* convert element_index to cidrings value */ 13674 cid_location = (cid_location + 1) / 2; 13675 } 13676 /* ---we like their cadence; try to install it--- */ 13677 if (!user_has_defined_cadences++) 13678 /* this is the first user-defined cadence; clear the default user cadences */ 13679 num_cadence = 0; 13680 if ((num_cadence+1) >= NUM_CADENCE_MAX) 13681 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 13682 else { 13683 cadences[num_cadence] = new_cadence; 13684 cidrings[num_cadence++] = cid_location; 13685 if (option_verbose > 2) 13686 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 13687 } 13688 } 13689 } 13690 } else if (!strcasecmp(v->name, "ringtimeout")) { 13691 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 13692 } else if (!strcasecmp(v->name, "prewink")) { 13693 confp->timing.prewinktime = atoi(v->value); 13694 } else if (!strcasecmp(v->name, "preflash")) { 13695 confp->timing.preflashtime = atoi(v->value); 13696 } else if (!strcasecmp(v->name, "wink")) { 13697 confp->timing.winktime = atoi(v->value); 13698 } else if (!strcasecmp(v->name, "flash")) { 13699 confp->timing.flashtime = atoi(v->value); 13700 } else if (!strcasecmp(v->name, "start")) { 13701 confp->timing.starttime = atoi(v->value); 13702 } else if (!strcasecmp(v->name, "rxwink")) { 13703 confp->timing.rxwinktime = atoi(v->value); 13704 } else if (!strcasecmp(v->name, "rxflash")) { 13705 confp->timing.rxflashtime = atoi(v->value); 13706 } else if (!strcasecmp(v->name, "debounce")) { 13707 confp->timing.debouncetime = atoi(v->value); 13708 } else if (!strcasecmp(v->name, "toneduration")) { 13709 int toneduration; 13710 int ctlfd; 13711 int res; 13712 struct dahdi_dialparams dps; 13713 13714 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 13715 13716 if (ctlfd == -1) { 13717 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 13718 return -1; 13719 } 13720 13721 toneduration = atoi(v->value); 13722 if (toneduration > -1) { 13723 memset(&dps, 0, sizeof(dps)); 13724 13725 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 13726 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 13727 if (res < 0) { 13728 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 13729 return -1; 13730 } 13731 } 13732 close(ctlfd); 13733 } else if (!strcasecmp(v->name, "defaultcic")) { 13734 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 13735 } else if (!strcasecmp(v->name, "defaultozz")) { 13736 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 13737 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 13738 dtmfcid_level = atoi(v->value); 13739 } 13740 } else if (!skipchannels) 13741 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 13742 } 13743 if (dahdichan[0]) { 13744 /* The user has set 'dahdichan' */ 13745 /*< \todo pass proper line number instead of 0 */ 13746 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 13747 return -1; 13748 } 13749 } 13750 /*< \todo why check for the pseudo in the per-channel section. 13751 * Any actual use for manual setup of the pseudo channel? */ 13752 if (!found_pseudo && reload != 1) { 13753 /* use the default configuration for a channel, so 13754 that any settings from real configured channels 13755 don't "leak" into the pseudo channel config 13756 */ 13757 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13758 13759 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 13760 13761 if (tmp) { 13762 if (option_verbose > 2) 13763 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 13764 } else { 13765 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 13766 } 13767 } 13768 return 0; 13769 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 9986 of file chan_dahdi.c.
Referenced by __oh323_new().
09987 { 09988 switch (redirectingreason) { 09989 case 0: 09990 return "UNKNOWN"; 09991 case 1: 09992 return "BUSY"; 09993 case 2: 09994 return "NO_REPLY"; 09995 case 0xF: 09996 return "UNCONDITIONAL"; 09997 default: 09998 return "NOREDIRECT"; 09999 } 10000 }
static int reload | ( | void | ) | [static] |
Definition at line 14103 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
14104 { 14105 int res = 0; 14106 14107 res = setup_dahdi(1); 14108 if (res) { 14109 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 14110 return -1; 14111 } 14112 return 0; 14113 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2280 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().
02281 { 02282 p->confno = -1; 02283 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 02284 if (p->subs[SUB_REAL].dfd > -1) { 02285 struct dahdi_confinfo zi; 02286 02287 memset(&zi, 0, sizeof(zi)); 02288 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 02289 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 02290 } 02291 return 0; 02292 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8403 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and 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().
08404 { 08405 pthread_attr_t attr; 08406 pthread_attr_init(&attr); 08407 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08408 /* If we're supposed to be stopped -- stay stopped */ 08409 if (monitor_thread == AST_PTHREADT_STOP) 08410 return 0; 08411 ast_mutex_lock(&monlock); 08412 if (monitor_thread == pthread_self()) { 08413 ast_mutex_unlock(&monlock); 08414 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08415 return -1; 08416 } 08417 if (monitor_thread != AST_PTHREADT_NULL) { 08418 /* Wake up the thread */ 08419 pthread_kill(monitor_thread, SIGURG); 08420 } else { 08421 /* Start a new monitor */ 08422 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 08423 ast_mutex_unlock(&monlock); 08424 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08425 pthread_attr_destroy(&attr); 08426 return -1; 08427 } 08428 } 08429 ast_mutex_unlock(&monlock); 08430 pthread_attr_destroy(&attr); 08431 return 0; 08432 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2613 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(), dahdi_read(), and send_callerid().
02614 { 02615 int res; 02616 if (p->saveconf.confmode) { 02617 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02618 p->saveconf.confmode = 0; 02619 if (res) { 02620 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02621 return -1; 02622 } 02623 } 02624 if (option_debug) 02625 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02626 return 0; 02627 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2540 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().
02541 { 02542 int res; 02543 02544 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02545 if (res) { 02546 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02547 return -1; 02548 } 02549 02550 return 0; 02551 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2586 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().
02587 { 02588 struct dahdi_confinfo c; 02589 int res; 02590 if (p->saveconf.confmode) { 02591 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02592 return -1; 02593 } 02594 p->saveconf.chan = 0; 02595 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02596 if (res) { 02597 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02598 p->saveconf.confmode = 0; 02599 return -1; 02600 } 02601 memset(&c, 0, sizeof(c)); 02602 c.confmode = DAHDI_CONF_NORMAL; 02603 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02604 if (res) { 02605 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02606 return -1; 02607 } 02608 if (option_debug) 02609 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02610 return 0; 02611 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2653 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::callwaitcas, 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(), dahdi_read(), and send_cwcidspill().
02654 { 02655 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02656 int res; 02657 /* Take out of linear mode if necessary */ 02658 if (p->subs[SUB_REAL].linear) { 02659 p->subs[SUB_REAL].linear = 0; 02660 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02661 } 02662 while (p->cidpos < p->cidlen) { 02663 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02664 if (res < 0) { 02665 if (errno == EAGAIN) 02666 return 0; 02667 else { 02668 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02669 return -1; 02670 } 02671 } 02672 if (!res) 02673 return 0; 02674 p->cidpos += res; 02675 } 02676 free(p->cidspill); 02677 p->cidspill = NULL; 02678 if (p->callwaitcas) { 02679 /* Wait for CID/CW to expire */ 02680 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02681 } else 02682 restore_conference(p); 02683 return 0; 02684 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2631 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::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_dtmfup().
02632 { 02633 p->callwaitcas = 0; 02634 p->cidcwexpire = 0; 02635 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02636 return -1; 02637 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02638 /* Make sure we account for the end */ 02639 p->cidlen += READ_SIZE * 4; 02640 p->cidpos = 0; 02641 send_callerid(p); 02642 if (option_verbose > 2) 02643 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02644 return 0; 02645 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3300 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().
03301 { 03302 /* Data will be our digit string */ 03303 struct dahdi_pvt *p; 03304 char *digits = (char *) data; 03305 03306 if (ast_strlen_zero(digits)) { 03307 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 03308 return -1; 03309 } 03310 03311 p = (struct dahdi_pvt *)chan->tech_pvt; 03312 03313 if (!p) { 03314 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 03315 return -1; 03316 } 03317 03318 ast_mutex_lock(&p->lock); 03319 03320 if (!p->pri || !p->call) { 03321 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 03322 ast_mutex_unlock(&p->lock); 03323 return -1; 03324 } 03325 03326 if (!pri_grab(p, p->pri)) { 03327 pri_keypad_facility(p->pri->pri, p->call, digits); 03328 pri_rel(p->pri); 03329 } else { 03330 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 03331 ast_mutex_unlock(&p->lock); 03332 return -1; 03333 } 03334 03335 ast_mutex_unlock(&p->lock); 03336 03337 return 0; 03338 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2521 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02522 { 02523 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02524 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2503 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
02504 { 02505 struct dahdi_gains g; 02506 int res; 02507 02508 memset(&g, 0, sizeof(g)); 02509 g.chan = chan; 02510 res = ioctl(fd, DAHDI_GETGAINS, &g); 02511 if (res) { 02512 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02513 return res; 02514 } 02515 02516 fill_rxgain(&g, gain, law); 02517 02518 return ioctl(fd, DAHDI_SETGAINS, &g); 02519 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2484 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
02485 { 02486 struct dahdi_gains g; 02487 int res; 02488 02489 memset(&g, 0, sizeof(g)); 02490 g.chan = chan; 02491 res = ioctl(fd, DAHDI_GETGAINS, &g); 02492 if (res) { 02493 if (option_debug) 02494 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02495 return res; 02496 } 02497 02498 fill_txgain(&g, gain, law); 02499 02500 return ioctl(fd, DAHDI_SETGAINS, &g); 02501 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 13771 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().
13772 { 13773 struct ast_config *cfg; 13774 struct ast_variable *v; 13775 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13776 int res; 13777 13778 #ifdef HAVE_PRI 13779 char *c; 13780 int spanno; 13781 int i, x; 13782 int logicalspan; 13783 int trunkgroup; 13784 int dchannels[NUM_DCHANS]; 13785 #endif 13786 13787 #ifdef HAVE_ZAPTEL 13788 int load_from_zapata_conf = 1; 13789 #else 13790 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 13791 #endif 13792 13793 if (load_from_zapata_conf) { 13794 if (!(cfg = ast_config_load("zapata.conf"))) { 13795 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 13796 return 0; 13797 } 13798 } else { 13799 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 13800 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 13801 return 0; 13802 } 13803 } 13804 13805 /* It's a little silly to lock it, but we mind as well just to be sure */ 13806 ast_mutex_lock(&iflock); 13807 #ifdef HAVE_PRI 13808 if (reload != 1) { 13809 /* Process trunkgroups first */ 13810 v = ast_variable_browse(cfg, "trunkgroups"); 13811 while (v) { 13812 if (!strcasecmp(v->name, "trunkgroup")) { 13813 trunkgroup = atoi(v->value); 13814 if (trunkgroup > 0) { 13815 if ((c = strchr(v->value, ','))) { 13816 i = 0; 13817 memset(dchannels, 0, sizeof(dchannels)); 13818 while (c && (i < NUM_DCHANS)) { 13819 dchannels[i] = atoi(c + 1); 13820 if (dchannels[i] < 0) { 13821 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); 13822 } else 13823 i++; 13824 c = strchr(c + 1, ','); 13825 } 13826 if (i) { 13827 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 13828 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); 13829 } else if (option_verbose > 1) 13830 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"); 13831 } else 13832 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13833 } else 13834 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13835 } else 13836 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 13837 } else if (!strcasecmp(v->name, "spanmap")) { 13838 spanno = atoi(v->value); 13839 if (spanno > 0) { 13840 if ((c = strchr(v->value, ','))) { 13841 trunkgroup = atoi(c + 1); 13842 if (trunkgroup > 0) { 13843 if ((c = strchr(c + 1, ','))) 13844 logicalspan = atoi(c + 1); 13845 else 13846 logicalspan = 0; 13847 if (logicalspan >= 0) { 13848 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 13849 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13850 } else if (option_verbose > 1) 13851 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13852 } else 13853 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); 13854 } else 13855 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 13856 } else 13857 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 13858 } else 13859 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 13860 } else { 13861 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 13862 } 13863 v = v->next; 13864 } 13865 } 13866 #endif 13867 13868 /* Copy the default jb config over global_jbconf */ 13869 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 13870 13871 v = ast_variable_browse(cfg, "channels"); 13872 res = process_dahdi(&conf, "", v, reload, 0); 13873 ast_mutex_unlock(&iflock); 13874 ast_config_destroy(cfg); 13875 if (res) 13876 return res; 13877 cfg = ast_config_load("users.conf"); 13878 if (cfg) { 13879 char *cat; 13880 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 13881 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 13882 if (!strcasecmp(cat, "general")) 13883 continue; 13884 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 13885 struct dahdi_chan_conf sect_conf; 13886 memcpy(§_conf, &conf, sizeof(sect_conf)); 13887 13888 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 13889 } 13890 } 13891 ast_config_destroy(cfg); 13892 } 13893 #ifdef HAVE_PRI 13894 if (reload != 1) { 13895 for (x = 0; x < NUM_SPANS; x++) { 13896 if (pris[x].pvts[0]) { 13897 if (start_pri(pris + x)) { 13898 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 13899 return -1; 13900 } else if (option_verbose > 1) 13901 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 13902 } 13903 } 13904 } 13905 #endif 13906 #ifdef HAVE_OPENR2 13907 if (reload != 1) { 13908 int x; 13909 for (x = 0; x < NUM_SPANS; x++) { 13910 if (r2links[x].protocol_context) { 13911 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) { 13912 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1); 13913 return -1; 13914 } else { 13915 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1); 13916 } 13917 } 13918 } 13919 } 13920 #endif 13921 /* And start the monitor for the first time */ 13922 restart_monitor(); 13923 return 0; 13924 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6757 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, 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_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_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, 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_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::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, free, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, 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, 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().
06758 { 06759 struct ast_channel *chan = data; 06760 struct dahdi_pvt *p = chan->tech_pvt; 06761 char exten[AST_MAX_EXTENSION] = ""; 06762 char exten2[AST_MAX_EXTENSION] = ""; 06763 unsigned char buf[256]; 06764 char dtmfcid[300]; 06765 char dtmfbuf[300]; 06766 struct callerid_state *cs = NULL; 06767 char *name = NULL, *number = NULL; 06768 int distMatches; 06769 int curRingData[3]; 06770 int receivedRingT; 06771 int counter1; 06772 int counter; 06773 int samples = 0; 06774 struct ast_smdi_md_message *smdi_msg = NULL; 06775 int flags = 0; 06776 int i; 06777 int timeout; 06778 int getforward = 0; 06779 char *s1, *s2; 06780 int len = 0; 06781 int res; 06782 int index; 06783 06784 ast_mutex_lock(&ss_thread_lock); 06785 ss_thread_count++; 06786 ast_mutex_unlock(&ss_thread_lock); 06787 /* in the bizarre case where the channel has become a zombie before we 06788 even get started here, abort safely 06789 */ 06790 if (!p) { 06791 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06792 ast_hangup(chan); 06793 goto quit; 06794 } 06795 if (option_verbose > 2) 06796 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 06797 index = dahdi_get_index(chan, p, 1); 06798 if (index < 0) { 06799 ast_log(LOG_WARNING, "Huh?\n"); 06800 ast_hangup(chan); 06801 goto quit; 06802 } 06803 if (p->dsp) 06804 ast_dsp_digitreset(p->dsp); 06805 switch (p->sig) { 06806 #ifdef HAVE_PRI 06807 case SIG_PRI: 06808 /* Now loop looking for an extension */ 06809 ast_copy_string(exten, p->exten, sizeof(exten)); 06810 len = strlen(exten); 06811 res = 0; 06812 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06813 if (len && !ast_ignore_pattern(chan->context, exten)) 06814 tone_zone_play_tone(p->subs[index].dfd, -1); 06815 else 06816 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06817 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06818 timeout = matchdigittimeout; 06819 else 06820 timeout = gendigittimeout; 06821 res = ast_waitfordigit(chan, timeout); 06822 if (res < 0) { 06823 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06824 ast_hangup(chan); 06825 goto quit; 06826 } else if (res) { 06827 exten[len++] = res; 06828 exten[len] = '\0'; 06829 } else 06830 break; 06831 } 06832 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06833 if (ast_strlen_zero(exten)) { 06834 if (option_verbose > 2) 06835 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 06836 exten[0] = 's'; 06837 exten[1] = '\0'; 06838 } 06839 tone_zone_play_tone(p->subs[index].dfd, -1); 06840 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06841 /* Start the real PBX */ 06842 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06843 if (p->dsp) ast_dsp_digitreset(p->dsp); 06844 dahdi_enable_ec(p); 06845 ast_setstate(chan, AST_STATE_RING); 06846 res = ast_pbx_run(chan); 06847 if (res) { 06848 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06849 } 06850 } else { 06851 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06852 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06853 ast_hangup(chan); 06854 p->exten[0] = '\0'; 06855 /* Since we send release complete here, we won't get one */ 06856 p->call = NULL; 06857 } 06858 goto quit; 06859 break; 06860 #endif 06861 case SIG_FEATD: 06862 case SIG_FEATDMF: 06863 case SIG_FEATDMF_TA: 06864 case SIG_E911: 06865 case SIG_FGC_CAMAMF: 06866 case SIG_FEATB: 06867 case SIG_EMWINK: 06868 case SIG_SF_FEATD: 06869 case SIG_SF_FEATDMF: 06870 case SIG_SF_FEATB: 06871 case SIG_SFWINK: 06872 if (dahdi_wink(p, index)) 06873 goto quit; 06874 /* Fall through */ 06875 case SIG_EM: 06876 case SIG_EM_E1: 06877 case SIG_SF: 06878 case SIG_FGC_CAMA: 06879 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06880 if (p->dsp) 06881 ast_dsp_digitreset(p->dsp); 06882 /* set digit mode appropriately */ 06883 if (p->dsp) { 06884 if (NEED_MFDETECT(p)) 06885 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06886 else 06887 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06888 } 06889 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06890 /* Wait for the first digit only if immediate=no */ 06891 if (!p->immediate) 06892 /* Wait for the first digit (up to 5 seconds). */ 06893 res = ast_waitfordigit(chan, 5000); 06894 else 06895 res = 0; 06896 if (res > 0) { 06897 /* save first char */ 06898 dtmfbuf[0] = res; 06899 switch (p->sig) { 06900 case SIG_FEATD: 06901 case SIG_SF_FEATD: 06902 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06903 if (res > 0) 06904 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06905 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06906 break; 06907 case SIG_FEATDMF_TA: 06908 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06909 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06910 if (dahdi_wink(p, index)) goto quit; 06911 dtmfbuf[0] = 0; 06912 /* Wait for the first digit (up to 5 seconds). */ 06913 res = ast_waitfordigit(chan, 5000); 06914 if (res <= 0) break; 06915 dtmfbuf[0] = res; 06916 /* fall through intentionally */ 06917 case SIG_FEATDMF: 06918 case SIG_E911: 06919 case SIG_FGC_CAMAMF: 06920 case SIG_SF_FEATDMF: 06921 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06922 /* if international caca, do it again to get real ANO */ 06923 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06924 { 06925 if (dahdi_wink(p, index)) goto quit; 06926 dtmfbuf[0] = 0; 06927 /* Wait for the first digit (up to 5 seconds). */ 06928 res = ast_waitfordigit(chan, 5000); 06929 if (res <= 0) break; 06930 dtmfbuf[0] = res; 06931 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06932 } 06933 if (res > 0) { 06934 /* if E911, take off hook */ 06935 if (p->sig == SIG_E911) 06936 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06937 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06938 } 06939 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06940 break; 06941 case SIG_FEATB: 06942 case SIG_SF_FEATB: 06943 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06944 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06945 break; 06946 case SIG_EMWINK: 06947 /* if we received a '*', we are actually receiving Feature Group D 06948 dial syntax, so use that mode; otherwise, fall through to normal 06949 mode 06950 */ 06951 if (res == '*') { 06952 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06953 if (res > 0) 06954 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06955 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06956 break; 06957 } 06958 default: 06959 /* If we got the first digit, get the rest */ 06960 len = 1; 06961 dtmfbuf[len] = '\0'; 06962 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06963 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06964 timeout = matchdigittimeout; 06965 } else { 06966 timeout = gendigittimeout; 06967 } 06968 res = ast_waitfordigit(chan, timeout); 06969 if (res < 0) { 06970 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06971 ast_hangup(chan); 06972 goto quit; 06973 } else if (res) { 06974 dtmfbuf[len++] = res; 06975 dtmfbuf[len] = '\0'; 06976 } else { 06977 break; 06978 } 06979 } 06980 break; 06981 } 06982 } 06983 if (res == -1) { 06984 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06985 ast_hangup(chan); 06986 goto quit; 06987 } else if (res < 0) { 06988 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 06989 ast_hangup(chan); 06990 goto quit; 06991 } 06992 06993 if (p->sig == SIG_FGC_CAMA) { 06994 char anibuf[100]; 06995 06996 if (ast_safe_sleep(chan,1000) == -1) { 06997 ast_hangup(chan); 06998 goto quit; 06999 } 07000 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07001 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 07002 res = my_getsigstr(chan, anibuf, "#", 10000); 07003 if ((res > 0) && (strlen(anibuf) > 2)) { 07004 if (anibuf[strlen(anibuf) - 1] == '#') 07005 anibuf[strlen(anibuf) - 1] = 0; 07006 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07007 } 07008 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07009 } 07010 07011 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07012 if (ast_strlen_zero(exten)) 07013 ast_copy_string(exten, "s", sizeof(exten)); 07014 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07015 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07016 if (exten[0] == '*') { 07017 char *stringp=NULL; 07018 ast_copy_string(exten2, exten, sizeof(exten2)); 07019 /* Parse out extension and callerid */ 07020 stringp=exten2 +1; 07021 s1 = strsep(&stringp, "*"); 07022 s2 = strsep(&stringp, "*"); 07023 if (s2) { 07024 if (!ast_strlen_zero(p->cid_num)) 07025 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07026 else 07027 ast_set_callerid(chan, s1, NULL, s1); 07028 ast_copy_string(exten, s2, sizeof(exten)); 07029 } else 07030 ast_copy_string(exten, s1, sizeof(exten)); 07031 } else if (p->sig == SIG_FEATD) 07032 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07033 } 07034 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07035 if (exten[0] == '*') { 07036 char *stringp=NULL; 07037 ast_copy_string(exten2, exten, sizeof(exten2)); 07038 /* Parse out extension and callerid */ 07039 stringp=exten2 +1; 07040 s1 = strsep(&stringp, "#"); 07041 s2 = strsep(&stringp, "#"); 07042 if (s2) { 07043 if (!ast_strlen_zero(p->cid_num)) 07044 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07045 else 07046 if (*(s1 + 2)) 07047 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07048 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07049 } else 07050 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07051 } else 07052 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07053 } 07054 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07055 if (exten[0] == '*') { 07056 char *stringp=NULL; 07057 ast_copy_string(exten2, exten, sizeof(exten2)); 07058 /* Parse out extension and callerid */ 07059 stringp=exten2 +1; 07060 s1 = strsep(&stringp, "#"); 07061 s2 = strsep(&stringp, "#"); 07062 if (s2 && (*(s2 + 1) == '0')) { 07063 if (*(s2 + 2)) 07064 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07065 } 07066 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07067 else ast_copy_string(exten, "911", sizeof(exten)); 07068 } else 07069 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 07070 } 07071 if (p->sig == SIG_FEATB) { 07072 if (exten[0] == '*') { 07073 char *stringp=NULL; 07074 ast_copy_string(exten2, exten, sizeof(exten2)); 07075 /* Parse out extension and callerid */ 07076 stringp=exten2 +1; 07077 s1 = strsep(&stringp, "#"); 07078 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 07079 } else 07080 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 07081 } 07082 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07083 dahdi_wink(p, index); 07084 /* some switches require a minimum guard time between 07085 the last FGD wink and something that answers 07086 immediately. This ensures it */ 07087 if (ast_safe_sleep(chan,100)) goto quit; 07088 } 07089 dahdi_enable_ec(p); 07090 if (NEED_MFDETECT(p)) { 07091 if (p->dsp) { 07092 if (!p->hardwaredtmf) 07093 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07094 else { 07095 ast_dsp_free(p->dsp); 07096 p->dsp = NULL; 07097 } 07098 } 07099 } 07100 07101 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 07102 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07103 if (p->dsp) ast_dsp_digitreset(p->dsp); 07104 res = ast_pbx_run(chan); 07105 if (res) { 07106 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07107 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07108 } 07109 goto quit; 07110 } else { 07111 if (option_verbose > 2) 07112 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 07113 sleep(2); 07114 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 07115 if (res < 0) 07116 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 07117 else 07118 sleep(1); 07119 res = ast_streamfile(chan, "ss-noservice", chan->language); 07120 if (res >= 0) 07121 ast_waitstream(chan, ""); 07122 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07123 ast_hangup(chan); 07124 goto quit; 07125 } 07126 break; 07127 case SIG_FXOLS: 07128 case SIG_FXOGS: 07129 case SIG_FXOKS: 07130 /* Read the first digit */ 07131 timeout = firstdigittimeout; 07132 /* If starting a threeway call, never timeout on the first digit so someone 07133 can use flash-hook as a "hold" feature */ 07134 if (p->subs[SUB_THREEWAY].owner) 07135 timeout = 999999; 07136 while (len < AST_MAX_EXTENSION-1) { 07137 /* Read digit unless it's supposed to be immediate, in which case the 07138 only answer is 's' */ 07139 if (p->immediate) 07140 res = 's'; 07141 else 07142 res = ast_waitfordigit(chan, timeout); 07143 timeout = 0; 07144 if (res < 0) { 07145 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07146 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07147 ast_hangup(chan); 07148 goto quit; 07149 } else if (res) { 07150 exten[len++]=res; 07151 exten[len] = '\0'; 07152 } 07153 if (!ast_ignore_pattern(chan->context, exten)) 07154 tone_zone_play_tone(p->subs[index].dfd, -1); 07155 else 07156 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07157 if (!strcmp(exten,ast_pickup_ext())) { 07158 /* Scan all channels and see if there are any 07159 * ringing channels that have call groups 07160 * that equal this channels pickup group 07161 */ 07162 if (index == SUB_REAL) { 07163 /* Switch us from Third call to Call Wait */ 07164 if (p->subs[SUB_THREEWAY].owner) { 07165 /* If you make a threeway call and the *8# a call, it should actually 07166 look like a callwait */ 07167 alloc_sub(p, SUB_CALLWAIT); 07168 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07169 unalloc_sub(p, SUB_THREEWAY); 07170 } 07171 dahdi_enable_ec(p); 07172 if (ast_pickup_call(chan)) { 07173 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 07174 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07175 dahdi_wait_event(p->subs[index].dfd); 07176 } 07177 ast_hangup(chan); 07178 goto quit; 07179 } else { 07180 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07181 ast_hangup(chan); 07182 goto quit; 07183 } 07184 07185 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 07186 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07187 if (getforward) { 07188 /* Record this as the forwarding extension */ 07189 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 07190 if (option_verbose > 2) 07191 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 07192 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07193 if (res) 07194 break; 07195 usleep(500000); 07196 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07197 sleep(1); 07198 memset(exten, 0, sizeof(exten)); 07199 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07200 len = 0; 07201 getforward = 0; 07202 } else { 07203 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07204 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07205 if (!ast_strlen_zero(p->cid_num)) { 07206 if (!p->hidecallerid) 07207 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07208 else 07209 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07210 } 07211 if (!ast_strlen_zero(p->cid_name)) { 07212 if (!p->hidecallerid) 07213 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07214 } 07215 ast_setstate(chan, AST_STATE_RING); 07216 dahdi_enable_ec(p); 07217 res = ast_pbx_run(chan); 07218 if (res) { 07219 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07220 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07221 } 07222 goto quit; 07223 } 07224 } else { 07225 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07226 so just set the timeout to matchdigittimeout and wait some more */ 07227 timeout = matchdigittimeout; 07228 } 07229 } else if (res == 0) { 07230 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 07231 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07232 dahdi_wait_event(p->subs[index].dfd); 07233 ast_hangup(chan); 07234 goto quit; 07235 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07236 if (option_verbose > 2) 07237 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 07238 /* Disable call waiting if enabled */ 07239 p->callwaiting = 0; 07240 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07241 if (res) { 07242 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07243 chan->name, strerror(errno)); 07244 } 07245 len = 0; 07246 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 07247 memset(exten, 0, sizeof(exten)); 07248 timeout = firstdigittimeout; 07249 07250 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07251 if (option_verbose > 2) 07252 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 07253 /* Disable Caller*ID if enabled */ 07254 p->hidecallerid = 1; 07255 if (chan->cid.cid_num) 07256 free(chan->cid.cid_num); 07257 chan->cid.cid_num = NULL; 07258 if (chan->cid.cid_name) 07259 free(chan->cid.cid_name); 07260 chan->cid.cid_name = NULL; 07261 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07262 if (res) { 07263 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07264 chan->name, strerror(errno)); 07265 } 07266 len = 0; 07267 memset(exten, 0, sizeof(exten)); 07268 timeout = firstdigittimeout; 07269 } else if (p->callreturn && !strcmp(exten, "*69")) { 07270 res = 0; 07271 if (!ast_strlen_zero(p->lastcid_num)) { 07272 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07273 } 07274 if (!res) 07275 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07276 break; 07277 } else if (!strcmp(exten, "*78")) { 07278 /* Do not disturb */ 07279 if (option_verbose > 2) 07280 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 07281 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07282 "Channel: %s/%d\r\n" 07283 "Status: enabled\r\n", dahdi_chan_name, p->channel); 07284 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07285 p->dnd = 1; 07286 getforward = 0; 07287 memset(exten, 0, sizeof(exten)); 07288 len = 0; 07289 } else if (!strcmp(exten, "*79")) { 07290 /* Do not disturb */ 07291 if (option_verbose > 2) 07292 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 07293 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07294 "Channel: %s/%d\r\n" 07295 "Status: disabled\r\n", dahdi_chan_name, p->channel); 07296 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07297 p->dnd = 0; 07298 getforward = 0; 07299 memset(exten, 0, sizeof(exten)); 07300 len = 0; 07301 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07302 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07303 getforward = 1; 07304 memset(exten, 0, sizeof(exten)); 07305 len = 0; 07306 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07307 if (option_verbose > 2) 07308 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 07309 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07310 memset(p->call_forward, 0, sizeof(p->call_forward)); 07311 getforward = 0; 07312 memset(exten, 0, sizeof(exten)); 07313 len = 0; 07314 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07315 p->subs[SUB_THREEWAY].owner && 07316 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07317 /* This is a three way call, the main call being a real channel, 07318 and we're parking the first call. */ 07319 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07320 if (option_verbose > 2) 07321 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 07322 break; 07323 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07324 if (option_verbose > 2) 07325 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 07326 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07327 if (!res) { 07328 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07329 memset(exten, 0, sizeof(exten)); 07330 len = 0; 07331 } 07332 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07333 if (option_verbose > 2) 07334 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 07335 /* Enable Caller*ID if enabled */ 07336 p->hidecallerid = 0; 07337 if (chan->cid.cid_num) 07338 free(chan->cid.cid_num); 07339 chan->cid.cid_num = NULL; 07340 if (chan->cid.cid_name) 07341 free(chan->cid.cid_name); 07342 chan->cid.cid_name = NULL; 07343 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07344 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07345 if (res) { 07346 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07347 chan->name, strerror(errno)); 07348 } 07349 len = 0; 07350 memset(exten, 0, sizeof(exten)); 07351 timeout = firstdigittimeout; 07352 } else if (!strcmp(exten, "*0")) { 07353 struct ast_channel *nbridge = 07354 p->subs[SUB_THREEWAY].owner; 07355 struct dahdi_pvt *pbridge = NULL; 07356 /* set up the private struct of the bridged one, if any */ 07357 if (nbridge && ast_bridged_channel(nbridge)) 07358 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07359 if (nbridge && pbridge && 07360 (nbridge->tech == chan_tech) && 07361 (ast_bridged_channel(nbridge)->tech == chan_tech) && 07362 ISTRUNK(pbridge)) { 07363 int func = DAHDI_FLASH; 07364 /* Clear out the dial buffer */ 07365 p->dop.dialstr[0] = '\0'; 07366 /* flash hookswitch */ 07367 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07368 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07369 nbridge->name, strerror(errno)); 07370 } 07371 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07372 unalloc_sub(p, SUB_THREEWAY); 07373 p->owner = p->subs[SUB_REAL].owner; 07374 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07375 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07376 ast_hangup(chan); 07377 goto quit; 07378 } else { 07379 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07380 dahdi_wait_event(p->subs[index].dfd); 07381 tone_zone_play_tone(p->subs[index].dfd, -1); 07382 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07383 unalloc_sub(p, SUB_THREEWAY); 07384 p->owner = p->subs[SUB_REAL].owner; 07385 ast_hangup(chan); 07386 goto quit; 07387 } 07388 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07389 ((exten[0] != '*') || (strlen(exten) > 2))) { 07390 if (option_debug) 07391 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); 07392 break; 07393 } 07394 if (!timeout) 07395 timeout = gendigittimeout; 07396 if (len && !ast_ignore_pattern(chan->context, exten)) 07397 tone_zone_play_tone(p->subs[index].dfd, -1); 07398 } 07399 break; 07400 case SIG_FXSLS: 07401 case SIG_FXSGS: 07402 case SIG_FXSKS: 07403 #ifdef HAVE_PRI 07404 if (p->pri) { 07405 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07406 struct ast_frame *f; 07407 int res; 07408 time_t start; 07409 07410 time(&start); 07411 ast_setstate(chan, AST_STATE_RING); 07412 while (time(NULL) < start + 3) { 07413 res = ast_waitfor(chan, 1000); 07414 if (res) { 07415 f = ast_read(chan); 07416 if (!f) { 07417 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07418 ast_hangup(chan); 07419 goto quit; 07420 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07421 res = 1; 07422 } else 07423 res = 0; 07424 ast_frfree(f); 07425 if (res) { 07426 ast_log(LOG_DEBUG, "Got ring!\n"); 07427 res = 0; 07428 break; 07429 } 07430 } 07431 } 07432 } 07433 #endif 07434 /* check for SMDI messages */ 07435 if (p->use_smdi && p->smdi_iface) { 07436 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07437 07438 if (smdi_msg != NULL) { 07439 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07440 07441 if (smdi_msg->type == 'B') 07442 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07443 else if (smdi_msg->type == 'N') 07444 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07445 07446 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 07447 } else { 07448 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07449 } 07450 } 07451 07452 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07453 number = smdi_msg->calling_st; 07454 07455 /* If we want caller id, we're in a prering state due to a polarity reversal 07456 * and we're set to use a polarity reversal to trigger the start of caller id, 07457 * grab the caller id and wait for ringing to start... */ 07458 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 07459 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) { 07460 /* If set to use DTMF CID signalling, listen for DTMF */ 07461 if (p->cid_signalling == CID_SIG_DTMF) { 07462 int i = 0; 07463 cs = NULL; 07464 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 07465 "channel %s\n", chan->name); 07466 dahdi_setlinear(p->subs[index].dfd, 0); 07467 res = 2000; 07468 for (;;) { 07469 struct ast_frame *f; 07470 res = ast_waitfor(chan, res); 07471 if (res <= 0) { 07472 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07473 "Exiting simple switch\n"); 07474 ast_hangup(chan); 07475 goto quit; 07476 } 07477 f = ast_read(chan); 07478 if (!f) 07479 break; 07480 if (f->frametype == AST_FRAME_DTMF) { 07481 dtmfbuf[i++] = f->subclass; 07482 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07483 res = 2000; 07484 } 07485 ast_frfree(f); 07486 if (chan->_state == AST_STATE_RING || 07487 chan->_state == AST_STATE_RINGING) 07488 break; /* Got ring */ 07489 } 07490 dtmfbuf[i] = '\0'; 07491 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07492 /* Got cid and ring. */ 07493 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 07494 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07495 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07496 dtmfcid, flags); 07497 /* If first byte is NULL, we have no cid */ 07498 if (!ast_strlen_zero(dtmfcid)) 07499 number = dtmfcid; 07500 else 07501 number = NULL; 07502 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07503 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07504 cs = callerid_new(p->cid_signalling); 07505 if (cs) { 07506 samples = 0; 07507 #if 1 07508 bump_gains(p); 07509 #endif 07510 /* Take out of linear mode for Caller*ID processing */ 07511 dahdi_setlinear(p->subs[index].dfd, 0); 07512 07513 /* First we wait and listen for the Caller*ID */ 07514 for (;;) { 07515 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07516 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07517 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07518 callerid_free(cs); 07519 ast_hangup(chan); 07520 goto quit; 07521 } 07522 if (i & DAHDI_IOMUX_SIGEVENT) { 07523 res = dahdi_get_event(p->subs[index].dfd); 07524 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07525 07526 if (p->cid_signalling == CID_SIG_V23_JP) { 07527 #ifdef DAHDI_EVENT_RINGBEGIN 07528 if (res == DAHDI_EVENT_RINGBEGIN) { 07529 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07530 usleep(1); 07531 } 07532 #endif 07533 } else { 07534 res = 0; 07535 break; 07536 } 07537 } else if (i & DAHDI_IOMUX_READ) { 07538 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07539 if (res < 0) { 07540 if (errno != ELAST) { 07541 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07542 callerid_free(cs); 07543 ast_hangup(chan); 07544 goto quit; 07545 } 07546 break; 07547 } 07548 samples += res; 07549 07550 if (p->cid_signalling == CID_SIG_V23_JP) { 07551 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07552 } else { 07553 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07554 } 07555 07556 if (res < 0) { 07557 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07558 break; 07559 } else if (res) 07560 break; 07561 else if (samples > (8000 * 10)) 07562 break; 07563 } 07564 } 07565 if (res == 1) { 07566 callerid_get(cs, &name, &number, &flags); 07567 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07568 } 07569 07570 if (p->cid_signalling == CID_SIG_V23_JP) { 07571 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07572 usleep(1); 07573 res = 4000; 07574 } else { 07575 07576 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07577 res = 2000; 07578 } 07579 07580 for (;;) { 07581 struct ast_frame *f; 07582 res = ast_waitfor(chan, res); 07583 if (res <= 0) { 07584 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07585 "Exiting simple switch\n"); 07586 ast_hangup(chan); 07587 goto quit; 07588 } 07589 if (!(f = ast_read(chan))) { 07590 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07591 ast_hangup(chan); 07592 goto quit; 07593 } 07594 ast_frfree(f); 07595 if (chan->_state == AST_STATE_RING || 07596 chan->_state == AST_STATE_RINGING) 07597 break; /* Got ring */ 07598 } 07599 07600 /* We must have a ring by now, so, if configured, lets try to listen for 07601 * distinctive ringing */ 07602 if (p->usedistinctiveringdetection) { 07603 len = 0; 07604 distMatches = 0; 07605 /* Clear the current ring data array so we dont have old data in it. */ 07606 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07607 curRingData[receivedRingT] = 0; 07608 receivedRingT = 0; 07609 counter = 0; 07610 counter1 = 0; 07611 /* Check to see if context is what it should be, if not set to be. */ 07612 if (strcmp(p->context,p->defcontext) != 0) { 07613 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07614 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07615 } 07616 07617 for (;;) { 07618 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07619 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07620 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07621 callerid_free(cs); 07622 ast_hangup(chan); 07623 goto quit; 07624 } 07625 if (i & DAHDI_IOMUX_SIGEVENT) { 07626 res = dahdi_get_event(p->subs[index].dfd); 07627 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07628 res = 0; 07629 /* Let us detect distinctive ring */ 07630 07631 curRingData[receivedRingT] = p->ringt; 07632 07633 if (p->ringt < p->ringt_base/2) 07634 break; 07635 /* Increment the ringT counter so we can match it against 07636 values in chan_dahdi.conf for distinctive ring */ 07637 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07638 break; 07639 } else if (i & DAHDI_IOMUX_READ) { 07640 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07641 if (res < 0) { 07642 if (errno != ELAST) { 07643 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07644 callerid_free(cs); 07645 ast_hangup(chan); 07646 goto quit; 07647 } 07648 break; 07649 } 07650 if (p->ringt) 07651 p->ringt--; 07652 if (p->ringt == 1) { 07653 res = -1; 07654 break; 07655 } 07656 } 07657 } 07658 if (option_verbose > 2) 07659 /* this only shows up if you have n of the dring patterns filled in */ 07660 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07661 07662 for (counter = 0; counter < 3; counter++) { 07663 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07664 channel */ 07665 distMatches = 0; 07666 for (counter1 = 0; counter1 < 3; counter1++) { 07667 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07668 (p->drings.ringnum[counter].ring[counter1]-10)) { 07669 distMatches++; 07670 } 07671 } 07672 if (distMatches == 3) { 07673 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07674 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07675 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07676 if (option_verbose > 2) 07677 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07678 break; 07679 } 07680 } 07681 } 07682 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07683 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07684 #if 1 07685 restore_gains(p); 07686 #endif 07687 } else 07688 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07689 } else { 07690 ast_log(LOG_WARNING, "Channel %s in prering " 07691 "state, but I have nothing to do. " 07692 "Terminating simple switch, should be " 07693 "restarted by the actual ring.\n", 07694 chan->name); 07695 ast_hangup(chan); 07696 goto quit; 07697 } 07698 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07699 /* FSK Bell202 callerID */ 07700 cs = callerid_new(p->cid_signalling); 07701 if (cs) { 07702 #if 1 07703 bump_gains(p); 07704 #endif 07705 samples = 0; 07706 len = 0; 07707 distMatches = 0; 07708 /* Clear the current ring data array so we dont have old data in it. */ 07709 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07710 curRingData[receivedRingT] = 0; 07711 receivedRingT = 0; 07712 counter = 0; 07713 counter1 = 0; 07714 /* Check to see if context is what it should be, if not set to be. */ 07715 if (strcmp(p->context,p->defcontext) != 0) { 07716 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07717 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07718 } 07719 07720 /* Take out of linear mode for Caller*ID processing */ 07721 dahdi_setlinear(p->subs[index].dfd, 0); 07722 for (;;) { 07723 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07724 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07725 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07726 callerid_free(cs); 07727 ast_hangup(chan); 07728 goto quit; 07729 } 07730 if (i & DAHDI_IOMUX_SIGEVENT) { 07731 res = dahdi_get_event(p->subs[index].dfd); 07732 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07733 /* If we get a PR event, they hung up while processing calerid */ 07734 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07735 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07736 p->polarity = POLARITY_IDLE; 07737 callerid_free(cs); 07738 ast_hangup(chan); 07739 goto quit; 07740 } 07741 res = 0; 07742 /* Let us detect callerid when the telco uses distinctive ring */ 07743 07744 curRingData[receivedRingT] = p->ringt; 07745 07746 if (p->ringt < p->ringt_base/2) 07747 break; 07748 /* Increment the ringT counter so we can match it against 07749 values in chan_dahdi.conf for distinctive ring */ 07750 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07751 break; 07752 } else if (i & DAHDI_IOMUX_READ) { 07753 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07754 if (res < 0) { 07755 if (errno != ELAST) { 07756 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07757 callerid_free(cs); 07758 ast_hangup(chan); 07759 goto quit; 07760 } 07761 break; 07762 } 07763 if (p->ringt) 07764 p->ringt--; 07765 if (p->ringt == 1) { 07766 res = -1; 07767 break; 07768 } 07769 samples += res; 07770 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07771 if (res < 0) { 07772 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07773 break; 07774 } else if (res) 07775 break; 07776 else if (samples > (8000 * 10)) 07777 break; 07778 } 07779 } 07780 if (res == 1) { 07781 callerid_get(cs, &name, &number, &flags); 07782 if (option_debug) 07783 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07784 } 07785 if (distinctiveringaftercid == 1) { 07786 /* Clear the current ring data array so we dont have old data in it. */ 07787 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07788 curRingData[receivedRingT] = 0; 07789 } 07790 receivedRingT = 0; 07791 if (option_verbose > 2) 07792 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 07793 for (;;) { 07794 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07795 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07796 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07797 callerid_free(cs); 07798 ast_hangup(chan); 07799 goto quit; 07800 } 07801 if (i & DAHDI_IOMUX_SIGEVENT) { 07802 res = dahdi_get_event(p->subs[index].dfd); 07803 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07804 res = 0; 07805 /* Let us detect callerid when the telco uses distinctive ring */ 07806 07807 curRingData[receivedRingT] = p->ringt; 07808 07809 if (p->ringt < p->ringt_base/2) 07810 break; 07811 /* Increment the ringT counter so we can match it against 07812 values in chan_dahdi.conf for distinctive ring */ 07813 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07814 break; 07815 } else if (i & DAHDI_IOMUX_READ) { 07816 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07817 if (res < 0) { 07818 if (errno != ELAST) { 07819 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07820 callerid_free(cs); 07821 ast_hangup(chan); 07822 goto quit; 07823 } 07824 break; 07825 } 07826 if (p->ringt) 07827 p->ringt--; 07828 if (p->ringt == 1) { 07829 res = -1; 07830 break; 07831 } 07832 } 07833 } 07834 } 07835 if (p->usedistinctiveringdetection) { 07836 if (option_verbose > 2) 07837 /* this only shows up if you have n of the dring patterns filled in */ 07838 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07839 07840 for (counter = 0; counter < 3; counter++) { 07841 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07842 channel */ 07843 if (option_verbose > 2) 07844 /* this only shows up if you have n of the dring patterns filled in */ 07845 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 07846 p->drings.ringnum[counter].ring[0], 07847 p->drings.ringnum[counter].ring[1], 07848 p->drings.ringnum[counter].ring[2]); 07849 distMatches = 0; 07850 for (counter1 = 0; counter1 < 3; counter1++) { 07851 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07852 (p->drings.ringnum[counter].ring[counter1]-10)) { 07853 distMatches++; 07854 } 07855 } 07856 if (distMatches == 3) { 07857 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07858 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07859 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07860 if (option_verbose > 2) 07861 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07862 break; 07863 } 07864 } 07865 } 07866 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07867 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07868 #if 1 07869 restore_gains(p); 07870 #endif 07871 if (res < 0) { 07872 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07873 } 07874 } else 07875 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07876 } 07877 else 07878 cs = NULL; 07879 07880 if (number) 07881 ast_shrink_phone_number(number); 07882 ast_set_callerid(chan, number, name, number); 07883 07884 if (smdi_msg) 07885 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07886 07887 if (cs) 07888 callerid_free(cs); 07889 07890 ast_setstate(chan, AST_STATE_RING); 07891 chan->rings = 1; 07892 p->ringt = p->ringt_base; 07893 res = ast_pbx_run(chan); 07894 if (res) { 07895 ast_hangup(chan); 07896 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07897 } 07898 goto quit; 07899 default: 07900 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07901 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07902 if (res < 0) 07903 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07904 } 07905 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07906 if (res < 0) 07907 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07908 ast_hangup(chan); 07909 quit: 07910 ast_mutex_lock(&ss_thread_lock); 07911 ss_thread_count--; 07912 ast_cond_signal(&ss_thread_complete); 07913 ast_mutex_unlock(&ss_thread_lock); 07914 return NULL; 07915 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11176 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().
11177 { 11178 int res, x; 11179 struct dahdi_params p; 11180 struct dahdi_bufferinfo bi; 11181 struct dahdi_spaninfo si; 11182 int i; 11183 11184 for (i = 0; i < NUM_DCHANS; i++) { 11185 if (!pri->dchannels[i]) 11186 break; 11187 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 11188 x = pri->dchannels[i]; 11189 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11190 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11191 return -1; 11192 } 11193 memset(&p, 0, sizeof(p)); 11194 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11195 if (res) { 11196 dahdi_close_pri_fd(pri, i); 11197 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11198 return -1; 11199 } 11200 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11201 dahdi_close_pri_fd(pri, i); 11202 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 11203 return -1; 11204 } 11205 memset(&si, 0, sizeof(si)); 11206 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11207 if (res) { 11208 dahdi_close_pri_fd(pri, i); 11209 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11210 } 11211 if (!si.alarms) 11212 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11213 else 11214 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11215 memset(&bi, 0, sizeof(bi)); 11216 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 11217 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 11218 bi.numbufs = 32; 11219 bi.bufsize = 1024; 11220 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 11221 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 11222 dahdi_close_pri_fd(pri, i); 11223 return -1; 11224 } 11225 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 11226 /* Force overlap dial if we're doing GR-303! */ 11227 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 11228 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 11229 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 11230 #ifdef HAVE_PRI_INBANDDISCONNECT 11231 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 11232 #endif 11233 /* Enslave to master if appropriate */ 11234 if (i) 11235 pri_enslave(pri->dchans[0], pri->dchans[i]); 11236 if (!pri->dchans[i]) { 11237 dahdi_close_pri_fd(pri, i); 11238 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 11239 return -1; 11240 } 11241 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 11242 pri_set_nsf(pri->dchans[i], pri->nsf); 11243 #ifdef PRI_GETSET_TIMERS 11244 for (x = 0; x < PRI_MAX_TIMERS; x++) { 11245 if (pritimers[x] != 0) 11246 pri_set_timer(pri->dchans[i], x, pritimers[x]); 11247 } 11248 #endif 11249 } 11250 /* Assume primary is the one we use */ 11251 pri->pri = pri->dchans[0]; 11252 pri->resetpos = -1; 11253 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 11254 for (i = 0; i < NUM_DCHANS; i++) { 11255 if (!pri->dchannels[i]) 11256 break; 11257 dahdi_close_pri_fd(pri, i); 11258 } 11259 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 11260 return -1; 11261 } 11262 return 0; 11263 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1772 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().
01773 { 01774 int tchan; 01775 int tinthreeway; 01776 struct ast_channel *towner; 01777 01778 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 01779 01780 tchan = p->subs[a].chan; 01781 towner = p->subs[a].owner; 01782 tinthreeway = p->subs[a].inthreeway; 01783 01784 p->subs[a].chan = p->subs[b].chan; 01785 p->subs[a].owner = p->subs[b].owner; 01786 p->subs[a].inthreeway = p->subs[b].inthreeway; 01787 01788 p->subs[b].chan = tchan; 01789 p->subs[b].owner = towner; 01790 p->subs[b].inthreeway = tinthreeway; 01791 01792 if (p->subs[a].owner) 01793 p->subs[a].owner->fds[0] = p->subs[a].dfd; 01794 if (p->subs[b].owner) 01795 p->subs[b].owner->fds[0] = p->subs[b].dfd; 01796 wakeup_sub(p, a, NULL); 01797 wakeup_sub(p, b, NULL); 01798 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1911 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().
01912 { 01913 if (!x) { 01914 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01915 return -1; 01916 } 01917 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01918 dahdi_close_sub(p, x); 01919 p->subs[x].linear = 0; 01920 p->subs[x].chan = 0; 01921 p->subs[x].owner = NULL; 01922 p->subs[x].inthreeway = 0; 01923 p->polarity = POLARITY_IDLE; 01924 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01925 return 0; 01926 }
static int unload_module | ( | void | ) | [static] |
Definition at line 12837 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
12838 { 12839 #ifdef HAVE_PRI 12840 int y; 12841 for (y = 0; y < NUM_SPANS; y++) 12842 ast_mutex_destroy(&pris[y].lock); 12843 #endif 12844 return __unload_module(); 12845 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2294 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().
02295 { 02296 int needconf = 0; 02297 int x; 02298 int useslavenative; 02299 struct dahdi_pvt *slave = NULL; 02300 02301 useslavenative = isslavenative(p, &slave); 02302 /* Start with the obvious, general stuff */ 02303 for (x = 0; x < 3; x++) { 02304 /* Look for three way calls */ 02305 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 02306 conf_add(p, &p->subs[x], x, 0); 02307 needconf++; 02308 } else { 02309 conf_del(p, &p->subs[x], x); 02310 } 02311 } 02312 /* If we have a slave, add him to our conference now. or DAX 02313 if this is slave native */ 02314 for (x = 0; x < MAX_SLAVES; x++) { 02315 if (p->slaves[x]) { 02316 if (useslavenative) 02317 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02318 else { 02319 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02320 needconf++; 02321 } 02322 } 02323 } 02324 /* If we're supposed to be in there, do so now */ 02325 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02326 if (useslavenative) 02327 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02328 else { 02329 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02330 needconf++; 02331 } 02332 } 02333 /* If we have a master, add ourselves to his conference */ 02334 if (p->master) { 02335 if (isslavenative(p->master, NULL)) { 02336 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02337 } else { 02338 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02339 } 02340 } 02341 if (!needconf) { 02342 /* Nobody is left (or should be left) in our conference. 02343 Kill it. */ 02344 p->confno = -1; 02345 } 02346 if (option_debug) 02347 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02348 return 0; 02349 }
Definition at line 1208 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.
Referenced by swap_subs().
01212 { 01213 #ifdef HAVE_PRI 01214 if (pri) 01215 ast_mutex_unlock(&pri->lock); 01216 #endif 01217 for (;;) { 01218 if (p->subs[a].owner) { 01219 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 01220 DEADLOCK_AVOIDANCE(&p->lock); 01221 } else { 01222 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01223 ast_mutex_unlock(&p->subs[a].owner->lock); 01224 break; 01225 } 01226 } else 01227 break; 01228 } 01229 #ifdef HAVE_PRI 01230 if (pri) 01231 ast_mutex_lock(&pri->lock); 01232 #endif 01233 }
static int zap_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3546 of file chan_dahdi.c.
References dahdi_accept_r2_call_exec().
Referenced by load_module().
03547 { 03548 return dahdi_accept_r2_call_exec(chan, data); 03549 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12661 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12662 { 12663 return __action_dialoffhook(s, m, 1); 12664 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12561 of file chan_dahdi.c.
References __action_dnd(), and s.
12562 { 12563 return __action_dnd(s, m, 1, 0); 12564 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12551 of file chan_dahdi.c.
References __action_dnd(), and s.
12552 { 12553 return __action_dnd(s, m, 1, 1); 12554 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12740 of file chan_dahdi.c.
References __action_restart(), and s.
12741 { 12742 return __action_restart(s, m, 1); 12743 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12716 of file chan_dahdi.c.
References __action_showchannels(), and s.
12717 { 12718 return __action_showchannels(s, m, 1); 12719 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12590 of file chan_dahdi.c.
References __action_transfer(), and s.
12591 { 12592 return __action_transfer(s, m, 1); 12593 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12618 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12619 { 12620 return __action_transferhangup(s, m, 1); 12621 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3345 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
03346 { 03347 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); 03348 return send_keypad_facility_exec(chan, data); 03349 }
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 14129 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 14129 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1166 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 1134 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 1177 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_destroy_channel_deprecated [static] |
Initial value:
{ { "zap", "destroy", "channel", NULL }, dahdi_destroy_channel, NULL, NULL }
Definition at line 12457 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 12462 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 12442 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 12452 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 12447 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 12467 of file chan_dahdi.c.
char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 3431 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 3437 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 3434 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 11873 of file chan_dahdi.c.
openr2_event_interface_t dahdi_r2_event_iface [static] |
Definition at line 1732 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 11882 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 11869 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 11877 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 11866 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 1763 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 11863 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 11860 of file chan_dahdi.c.
char dahdi_restart_usage[] [static] |
Definition at line 12435 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3287 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 3293 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3290 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 12328 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 12427 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1092 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] |
Definition at line 214 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 215 of file chan_dahdi.c.
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 12431 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 219 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
int dtmfcid_level = 256 [static] |
Definition at line 222 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 234 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), and skinny_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 237 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 122 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 246 of file chan_dahdi.c.
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(), handle_request_subscribe(), 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 243 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(), handle_request_subscribe(), 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 225 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 240 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
int mfcr2_cur_accept_on_offer = 1 [static] |
Definition at line 332 of file chan_dahdi.c.
int mfcr2_cur_allow_collect_calls = 0 [static] |
Definition at line 331 of file chan_dahdi.c.
int mfcr2_cur_call_files = 0 [static] |
Definition at line 330 of file chan_dahdi.c.
openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static] |
Definition at line 347 of file chan_dahdi.c.
int mfcr2_cur_charge_calls = 1 [static] |
Definition at line 333 of file chan_dahdi.c.
int mfcr2_cur_context_index = 0 [static] |
Definition at line 329 of file chan_dahdi.c.
int mfcr2_cur_double_answer = 0 [static] |
Definition at line 335 of file chan_dahdi.c.
int mfcr2_cur_forced_release = 0 [static] |
Definition at line 334 of file chan_dahdi.c.
int mfcr2_cur_get_ani_first = -1 [static] |
Definition at line 327 of file chan_dahdi.c.
int mfcr2_cur_immediate_accept = -1 [static] |
Definition at line 336 of file chan_dahdi.c.
char mfcr2_cur_logdir[OR2_MAX_PATH] [static] |
Definition at line 344 of file chan_dahdi.c.
openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static] |
Definition at line 346 of file chan_dahdi.c.
int mfcr2_cur_max_ani = 10 [static] |
Definition at line 325 of file chan_dahdi.c.
int mfcr2_cur_max_dnis = 4 [static] |
Definition at line 326 of file chan_dahdi.c.
int mfcr2_cur_metering_pulse_timeout = -1 [static] |
Definition at line 324 of file chan_dahdi.c.
int mfcr2_cur_mfback_timeout = -1 [static] |
Definition at line 323 of file chan_dahdi.c.
char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static] |
Definition at line 345 of file chan_dahdi.c.
int mfcr2_cur_skip_category = -1 [static] |
Definition at line 328 of file chan_dahdi.c.
openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static] |
Definition at line 322 of file chan_dahdi.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 258 of file chan_dahdi.c.
Referenced by 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 254 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 2064 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1163 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 263 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 221 of file chan_dahdi.c.
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 11528 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 11532 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 11536 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 11540 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 11544 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 229 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 249 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 230 of file chan_dahdi.c.
Definition at line 408 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 217 of file chan_dahdi.c.
struct dahdi_mfcr2 r2links[NUM_SPANS] [static] |
Definition at line 321 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 310 of file chan_dahdi.c.
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 12423 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 12419 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 259 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 262 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
char* subnames[] [static] |
const char tdesc[] [static] |
Definition at line 161 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1164 of file chan_dahdi.c.
char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static] |
Definition at line 3432 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 3441 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 3435 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 3288 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 3296 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3291 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |