#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 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 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 297 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 472 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 473 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 1643 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 1642 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 301 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 1134 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 12442 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 1181 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 12472 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 12473 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 294 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 295 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 12887 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 1159 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 430 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 431 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 352 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 292 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 2163 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(), 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(), 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(), 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 426 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 425 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 427 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 14059 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 12441 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 12571 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().
12572 { 12573 struct dahdi_pvt *p = NULL; 12574 const char *channel = local_astman_header(m, "Channel", zap_mode); 12575 const char *number = astman_get_header(m, "Number"); 12576 int i; 12577 12578 if (ast_strlen_zero(channel)) { 12579 astman_send_error(s, m, "No channel specified"); 12580 return 0; 12581 } 12582 if (ast_strlen_zero(number)) { 12583 astman_send_error(s, m, "No number specified"); 12584 return 0; 12585 } 12586 if (!(p = find_channel(atoi(channel)))) { 12587 astman_send_error(s, m, "No such channel"); 12588 return 0; 12589 } 12590 if (!p->owner) { 12591 astman_send_error(s, m, "Channel does not have an owner"); 12592 return 0; 12593 } 12594 for (i = 0; i < strlen(number); i++) { 12595 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 12596 12597 dahdi_queue_frame(p, &f, NULL); 12598 } 12599 local_astman_ack(s, m, "DialOffHook", zap_mode); 12600 12601 return 0; 12602 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 12475 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().
12476 { 12477 struct dahdi_pvt *p = NULL; 12478 const char *channel = local_astman_header(m, "Channel", zap_mode); 12479 12480 if (ast_strlen_zero(channel)) { 12481 astman_send_error(s, m, "No channel specified"); 12482 return 0; 12483 } 12484 if (!(p = find_channel(atoi(channel)))) { 12485 astman_send_error(s, m, "No such channel"); 12486 return 0; 12487 } 12488 p->dnd = dnd; 12489 local_astman_ack(s, m, "DND", zap_mode); 12490 12491 return 0; 12492 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12669 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().
12670 { 12671 if (dahdi_restart() != 0) { 12672 if (zap_mode) { 12673 astman_send_error(s, m, "Failed to restart Zap"); 12674 } else { 12675 astman_send_error(s, m, "Failed to restart DAHDI"); 12676 } 12677 return 1; 12678 } 12679 local_astman_ack(s, m, "Restart: Success", zap_mode); 12680 return 0; 12681 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12614 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().
12615 { 12616 struct dahdi_pvt *tmp = NULL; 12617 const char *id = astman_get_header(m, "ActionID"); 12618 char idText[256] = ""; 12619 12620 local_astman_ack(s, m, " channel status will follow", zap_mode); 12621 if (!ast_strlen_zero(id)) 12622 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 12623 12624 ast_mutex_lock(&iflock); 12625 12626 tmp = iflist; 12627 while (tmp) { 12628 if (tmp->channel > 0) { 12629 int alarm = get_alarms(tmp); 12630 astman_append(s, 12631 "Event: %sShowChannels\r\n" 12632 "Channel: %d\r\n" 12633 "Signalling: %s\r\n" 12634 "Context: %s\r\n" 12635 "DND: %s\r\n" 12636 "Alarm: %s\r\n" 12637 "%s" 12638 "\r\n", 12639 dahdi_chan_name, 12640 tmp->channel, sig2str(tmp->sig), tmp->context, 12641 tmp->dnd ? "Enabled" : "Disabled", 12642 alarm2str(alarm), idText); 12643 } 12644 12645 tmp = tmp->next; 12646 } 12647 12648 ast_mutex_unlock(&iflock); 12649 12650 astman_append(s, 12651 "Event: %sShowChannelsComplete\r\n" 12652 "%s" 12653 "\r\n", 12654 dahdi_chan_name, 12655 idText); 12656 return 0; 12657 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12514 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().
12515 { 12516 struct dahdi_pvt *p = NULL; 12517 const char *channel = local_astman_header(m, "Channel", zap_mode); 12518 12519 if (ast_strlen_zero(channel)) { 12520 astman_send_error(s, m, "No channel specified"); 12521 return 0; 12522 } 12523 if (!(p = find_channel(atoi(channel)))) { 12524 astman_send_error(s, m, "No such channel"); 12525 return 0; 12526 } 12527 dahdi_fake_event(p,TRANSFER); 12528 local_astman_ack(s, m, "Transfer", zap_mode); 12529 12530 return 0; 12531 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12543 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().
12544 { 12545 struct dahdi_pvt *p = NULL; 12546 const char *channel = local_astman_header(m, "Channel", zap_mode); 12547 12548 if (ast_strlen_zero(channel)) { 12549 astman_send_error(s, m, "No channel specified"); 12550 return 0; 12551 } 12552 if (!(p = find_channel(atoi(channel)))) { 12553 astman_send_error(s, m, "No such channel"); 12554 return 0; 12555 } 12556 dahdi_fake_event(p, HANGUP); 12557 local_astman_ack(s, m, "Hangup", zap_mode); 12558 return 0; 12559 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5788 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().
05789 { 05790 struct dahdi_pvt *p = ast->tech_pvt; 05791 int res; 05792 int usedindex=-1; 05793 int index; 05794 struct ast_frame *f; 05795 05796 05797 index = dahdi_get_index(ast, p, 1); 05798 05799 p->subs[index].f.frametype = AST_FRAME_NULL; 05800 p->subs[index].f.datalen = 0; 05801 p->subs[index].f.samples = 0; 05802 p->subs[index].f.mallocd = 0; 05803 p->subs[index].f.offset = 0; 05804 p->subs[index].f.subclass = 0; 05805 p->subs[index].f.delivery = ast_tv(0,0); 05806 p->subs[index].f.src = "dahdi_exception"; 05807 p->subs[index].f.data = NULL; 05808 05809 05810 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05811 /* If nobody owns us, absorb the event appropriately, otherwise 05812 we loop indefinitely. This occurs when, during call waiting, the 05813 other end hangs up our channel so that it no longer exists, but we 05814 have neither FLASH'd nor ONHOOK'd to signify our desire to 05815 change to the other channel. */ 05816 if (p->fake_event) { 05817 res = p->fake_event; 05818 p->fake_event = 0; 05819 } else 05820 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05821 /* Switch to real if there is one and this isn't something really silly... */ 05822 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05823 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05824 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 05825 p->owner = p->subs[SUB_REAL].owner; 05826 if (p->owner && ast_bridged_channel(p->owner)) 05827 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05828 p->subs[SUB_REAL].needunhold = 1; 05829 } 05830 switch (res) { 05831 case DAHDI_EVENT_ONHOOK: 05832 dahdi_disable_ec(p); 05833 if (p->owner) { 05834 if (option_verbose > 2) 05835 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 05836 dahdi_ring_phone(p); 05837 p->callwaitingrepeat = 0; 05838 p->cidcwexpire = 0; 05839 } else 05840 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05841 update_conf(p); 05842 break; 05843 case DAHDI_EVENT_RINGOFFHOOK: 05844 dahdi_enable_ec(p); 05845 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05846 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05847 p->subs[SUB_REAL].needanswer = 1; 05848 p->dialing = 0; 05849 } 05850 break; 05851 case DAHDI_EVENT_HOOKCOMPLETE: 05852 case DAHDI_EVENT_RINGERON: 05853 case DAHDI_EVENT_RINGEROFF: 05854 /* Do nothing */ 05855 break; 05856 case DAHDI_EVENT_WINKFLASH: 05857 gettimeofday(&p->flashtime, NULL); 05858 if (p->owner) { 05859 if (option_verbose > 2) 05860 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05861 if (p->owner->_state != AST_STATE_UP) { 05862 /* Answer if necessary */ 05863 usedindex = dahdi_get_index(p->owner, p, 0); 05864 if (usedindex > -1) { 05865 p->subs[usedindex].needanswer = 1; 05866 } 05867 ast_setstate(p->owner, AST_STATE_UP); 05868 } 05869 p->callwaitingrepeat = 0; 05870 p->cidcwexpire = 0; 05871 if (ast_bridged_channel(p->owner)) 05872 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05873 p->subs[SUB_REAL].needunhold = 1; 05874 } else 05875 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05876 update_conf(p); 05877 break; 05878 default: 05879 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05880 } 05881 f = &p->subs[index].f; 05882 return f; 05883 } 05884 if (!(p->radio || (p->oprmode < 0)) && option_debug) 05885 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05886 /* If it's not us, return NULL immediately */ 05887 if (ast != p->owner) { 05888 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05889 f = &p->subs[index].f; 05890 return f; 05891 } 05892 f = dahdi_handle_event(ast); 05893 return f; 05894 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 14068 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 12700 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().
12701 { 12702 struct dahdi_pvt *p; 12703 #ifdef HAVE_OPENR2 12704 int r; 12705 #endif 12706 #ifdef HAVE_PRI 12707 int i, j; 12708 for (i = 0; i < NUM_SPANS; i++) { 12709 if (pris[i].master != AST_PTHREADT_NULL) 12710 pthread_cancel(pris[i].master); 12711 } 12712 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12713 12714 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12715 ast_unregister_application(dahdi_send_keypad_facility_app); 12716 } 12717 ast_unregister_application(zap_send_keypad_facility_app); 12718 #endif 12719 #ifdef HAVE_OPENR2 12720 for (r = 0; r < NUM_SPANS; r++) { 12721 if (r2links[r].master != AST_PTHREADT_NULL) { 12722 pthread_cancel(r2links[r].master); 12723 pthread_join(r2links[r].master, NULL); 12724 } 12725 } 12726 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0])); 12727 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12728 ast_unregister_application(dahdi_accept_r2_call_app); 12729 } 12730 ast_unregister_application(zap_accept_r2_call_app); 12731 #endif 12732 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12733 local_astman_unregister("DialOffHook"); 12734 local_astman_unregister("Hangup"); 12735 local_astman_unregister("Transfer"); 12736 local_astman_unregister("DNDoff"); 12737 local_astman_unregister("DNDon"); 12738 local_astman_unregister("ShowChannels"); 12739 local_astman_unregister("Restart"); 12740 ast_channel_unregister(chan_tech); 12741 ast_mutex_lock(&iflock); 12742 /* Hangup all interfaces if they have an owner */ 12743 p = iflist; 12744 while (p) { 12745 if (p->owner) 12746 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 12747 p = p->next; 12748 } 12749 ast_mutex_unlock(&iflock); 12750 ast_mutex_lock(&monlock); 12751 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12752 pthread_cancel(monitor_thread); 12753 pthread_kill(monitor_thread, SIGURG); 12754 pthread_join(monitor_thread, NULL); 12755 } 12756 monitor_thread = AST_PTHREADT_STOP; 12757 ast_mutex_unlock(&monlock); 12758 12759 destroy_all_channels(); 12760 #ifdef HAVE_PRI 12761 for (i = 0; i < NUM_SPANS; i++) { 12762 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 12763 pthread_join(pris[i].master, NULL); 12764 for (j = 0; j < NUM_DCHANS; j++) { 12765 dahdi_close_pri_fd(&(pris[i]), j); 12766 } 12767 } 12768 #endif 12769 #ifdef HAVE_OPENR2 12770 for (r = 0; r < NUM_SPANS; r++) { 12771 if (r2links[r].protocol_context) { 12772 openr2_context_delete(r2links[r].protocol_context); 12773 } 12774 } 12775 #endif 12776 ast_cond_destroy(&ss_thread_complete); 12777 return 0; 12778 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 14068 of file chan_dahdi.c.
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 2072 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
02073 { 02074 int x; 02075 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 02076 if (alarms[x].alarm & alarm) 02077 return alarms[x].name; 02078 } 02079 return alarm ? "Unknown Alarm" : "No Alarm"; 02080 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1874 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().
01875 { 01876 struct dahdi_bufferinfo bi; 01877 int res; 01878 if (p->subs[x].dfd < 0) { 01879 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 01880 if (p->subs[x].dfd > -1) { 01881 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01882 if (!res) { 01883 bi.txbufpolicy = p->buf_policy; 01884 bi.rxbufpolicy = p->buf_policy; 01885 bi.numbufs = p->buf_no; 01886 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01887 if (res < 0) { 01888 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01889 } 01890 } else 01891 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01892 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01893 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01894 dahdi_close_sub(p, x); 01895 return -1; 01896 } 01897 if (option_debug) 01898 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01899 return 0; 01900 } else 01901 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01902 return -1; 01903 } 01904 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01905 return -1; 01906 }
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 9945 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.
09946 { 09947 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 09948 if (size) { 09949 *buf = '\0'; 09950 } 09951 return; 09952 } 09953 09954 switch (plan) { 09955 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 09956 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 09957 break; 09958 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 09959 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 09960 break; 09961 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 09962 snprintf(buf, size, "%s%s", pri->localprefix, number); 09963 break; 09964 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 09965 snprintf(buf, size, "%s%s", pri->privateprefix, number); 09966 break; 09967 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 09968 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 09969 break; 09970 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 09971 snprintf(buf, size, "%s", number); 09972 break; 09973 } 09974 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4715 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().
04716 { 04717 /* In order to transfer, we need at least one of the channels to 04718 actually be in a call bridge. We can't conference two applications 04719 together (but then, why would we want to?) */ 04720 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04721 /* The three-way person we're about to transfer to could still be in MOH, so 04722 stop if now if appropriate */ 04723 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04724 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04725 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04726 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04727 } 04728 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04729 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04730 } 04731 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04732 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04733 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04734 return -1; 04735 } 04736 /* Orphan the channel after releasing the lock */ 04737 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04738 unalloc_sub(p, SUB_THREEWAY); 04739 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04740 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04741 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04742 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04743 } 04744 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04745 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04746 } 04747 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04748 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04749 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04750 return -1; 04751 } 04752 /* Three-way is now the REAL */ 04753 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04754 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 04755 unalloc_sub(p, SUB_THREEWAY); 04756 /* Tell the caller not to hangup */ 04757 return 1; 04758 } else { 04759 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04760 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04761 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04762 return -1; 04763 } 04764 return 0; 04765 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9094 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().
09095 { 09096 int res; 09097 struct dahdi_params par; 09098 09099 /* First, check group matching */ 09100 if (groupmatch) { 09101 if ((p->group & groupmatch) != groupmatch) 09102 return 0; 09103 *groupmatched = 1; 09104 } 09105 /* Check to see if we have a channel match */ 09106 if (channelmatch != -1) { 09107 if (p->channel != channelmatch) 09108 return 0; 09109 *channelmatched = 1; 09110 } 09111 /* We're at least busy at this point */ 09112 if (busy) { 09113 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09114 *busy = 1; 09115 } 09116 /* If do not disturb, definitely not */ 09117 if (p->dnd) 09118 return 0; 09119 /* If guard time, definitely not */ 09120 if (p->guardtime && (time(NULL) < p->guardtime)) 09121 return 0; 09122 09123 /* If no owner definitely available */ 09124 if (!p->owner) { 09125 #ifdef HAVE_PRI 09126 /* Trust PRI */ 09127 if (p->pri) { 09128 if (p->resetting || p->call) 09129 return 0; 09130 else 09131 return 1; 09132 } 09133 #endif 09134 #ifdef HAVE_OPENR2 09135 /* Trust MFC/R2 */ 09136 if (p->mfcr2) { 09137 if (p->mfcr2call || p->mfcr2block) 09138 return 0; 09139 else 09140 return 1; 09141 } 09142 #endif 09143 if (!(p->radio || (p->oprmode < 0))) 09144 { 09145 if (!p->sig || (p->sig == SIG_FXSLS)) 09146 return 1; 09147 /* Check hook state */ 09148 if (p->subs[SUB_REAL].dfd > -1) { 09149 memset(&par, 0, sizeof(par)); 09150 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09151 } else { 09152 /* Assume not off hook on CVRS */ 09153 res = 0; 09154 par.rxisoffhook = 0; 09155 } 09156 if (res) { 09157 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09158 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09159 /* When "onhook" that means no battery on the line, and thus 09160 it is out of service..., if it's on a TDM card... If it's a channel 09161 bank, there is no telling... */ 09162 if (par.rxbits > -1) 09163 return 1; 09164 if (par.rxisoffhook) 09165 return 1; 09166 else 09167 #ifdef DAHDI_CHECK_HOOKSTATE 09168 return 0; 09169 #else 09170 return 1; 09171 #endif 09172 } else if (par.rxisoffhook) { 09173 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 09174 /* Not available when the other end is off hook */ 09175 return 0; 09176 } 09177 } 09178 return 1; 09179 } 09180 09181 /* If it's not an FXO, forget about call wait */ 09182 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09183 return 0; 09184 09185 if (!p->callwaiting) { 09186 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09187 return 0; 09188 } 09189 09190 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09191 /* If there is already a call waiting call, then we can't take a second one */ 09192 return 0; 09193 } 09194 09195 if ((p->owner->_state != AST_STATE_UP) && 09196 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09197 /* If the current call is not up, then don't allow the call */ 09198 return 0; 09199 } 09200 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09201 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09202 return 0; 09203 } 09204 /* We're cool */ 09205 return 1; 09206 }
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 12790 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().
12791 { 12792 char *c, *chan; 12793 int x, start, finish; 12794 struct dahdi_pvt *tmp; 12795 #ifdef HAVE_PRI 12796 struct dahdi_pri *pri; 12797 int trunkgroup, y; 12798 #endif 12799 12800 if ((reload == 0) && (conf->chan.sig < 0)) { 12801 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 12802 return -1; 12803 } 12804 12805 c = ast_strdupa(value); 12806 12807 #ifdef HAVE_PRI 12808 pri = NULL; 12809 if (iscrv) { 12810 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 12811 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 12812 return -1; 12813 } 12814 if (trunkgroup < 1) { 12815 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 12816 return -1; 12817 } 12818 c += y; 12819 for (y = 0; y < NUM_SPANS; y++) { 12820 if (pris[y].trunkgroup == trunkgroup) { 12821 pri = pris + y; 12822 break; 12823 } 12824 } 12825 if (!pri) { 12826 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 12827 return -1; 12828 } 12829 } 12830 #endif 12831 12832 while ((chan = strsep(&c, ","))) { 12833 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 12834 /* Range */ 12835 } else if (sscanf(chan, "%30d", &start)) { 12836 /* Just one */ 12837 finish = start; 12838 } else if (!strcasecmp(chan, "pseudo")) { 12839 finish = start = CHAN_PSEUDO; 12840 if (found_pseudo) 12841 *found_pseudo = 1; 12842 } else { 12843 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 12844 return -1; 12845 } 12846 if (finish < start) { 12847 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 12848 x = finish; 12849 finish = start; 12850 start = x; 12851 } 12852 12853 for (x = start; x <= finish; x++) { 12854 #ifdef HAVE_PRI 12855 tmp = mkintf(x, conf, pri, reload); 12856 #else 12857 tmp = mkintf(x, conf, NULL, reload); 12858 #endif 12859 12860 if (tmp) { 12861 if (option_verbose > 2) { 12862 #ifdef HAVE_PRI 12863 if (pri) 12864 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 12865 else 12866 #endif 12867 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 12868 } 12869 } else { 12870 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 12871 (reload == 1) ? "reconfigure" : "register", value); 12872 return -1; 12873 } 12874 } 12875 #ifdef HAVE_OPENR2 12876 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) { 12877 mfcr2_cur_context_index++; 12878 } 12879 #endif 12880 } 12881 12882 return 0; 12883 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 11360 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
11361 { 11362 if (!s || len < 1) { 11363 return; 11364 } 11365 s[0] = '\0'; 11366 if (status & DCHAN_PROVISIONED) 11367 strncat(s, "Provisioned, ", len - strlen(s) - 1); 11368 if (!(status & DCHAN_NOTINALARM)) 11369 strncat(s, "In Alarm, ", len - strlen(s) - 1); 11370 if (status & DCHAN_UP) 11371 strncat(s, "Up", len - strlen(s) - 1); 11372 else 11373 strncat(s, "Down", len - strlen(s) - 1); 11374 if (active) 11375 strncat(s, ", Active", len - strlen(s) - 1); 11376 else 11377 strncat(s, ", Standby", len - strlen(s) - 1); 11378 s[len - 1] = '\0'; 11379 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2523 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().
02524 { 02525 int res; 02526 02527 /* Bump receive gain by 5.0db */ 02528 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 02529 if (res) { 02530 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02531 return -1; 02532 } 02533 02534 return 0; 02535 }
Definition at line 9208 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().
09209 { 09210 struct dahdi_pvt *p; 09211 struct dahdi_bufferinfo bi; 09212 int res; 09213 09214 if ((p = ast_malloc(sizeof(*p)))) { 09215 memcpy(p, src, sizeof(struct dahdi_pvt)); 09216 ast_mutex_init(&p->lock); 09217 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 09218 /* Allocate a DAHDI structure */ 09219 if (p->subs[SUB_REAL].dfd < 0) { 09220 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09221 destroy_dahdi_pvt(&p); 09222 return NULL; 09223 } 09224 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09225 if (!res) { 09226 bi.txbufpolicy = p->buf_policy; 09227 bi.rxbufpolicy = p->buf_policy; 09228 bi.numbufs = p->buf_no; 09229 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09230 if (res < 0) { 09231 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09232 } 09233 } else 09234 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09235 } 09236 p->destroy = 1; 09237 p->next = iflist; 09238 p->prev = NULL; 09239 iflist = p; 09240 if (iflist->next) 09241 iflist->next->prev = p; 09242 return p; 09243 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4767 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().
04768 { 04769 struct dahdi_confinfo ci; 04770 /* Fine if we already have a master, etc */ 04771 if (p->master || (p->confno > -1)) 04772 return 0; 04773 memset(&ci, 0, sizeof(ci)); 04774 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04775 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04776 return 0; 04777 } 04778 /* If we have no master and don't have a confno, then 04779 if we're in a conference, it's probably a MeetMe room or 04780 some such, so don't let us 3-way out! */ 04781 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04782 if (option_verbose > 2) 04783 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 04784 return 1; 04785 } 04786 return 0; 04787 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11227 of file chan_dahdi.c.
References complete_span_helper().
11228 { 11229 return complete_span_helper(line,word,pos,state,3); 11230 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11232 of file chan_dahdi.c.
References complete_span_helper().
11233 { 11234 return complete_span_helper(line,word,pos,state,4); 11235 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 11208 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
11209 { 11210 int which, span; 11211 char *ret = NULL; 11212 11213 if (pos != rpos) 11214 return ret; 11215 11216 for (which = span = 0; span < NUM_SPANS; span++) { 11217 if (pris[span].pri && ++which > state) { 11218 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 11219 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 11220 } 11221 break; 11222 } 11223 } 11224 return ret; 11225 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 2165 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().
02166 { 02167 /* If the conference already exists, and we're already in it 02168 don't bother doing anything */ 02169 struct dahdi_confinfo zi; 02170 02171 memset(&zi, 0, sizeof(zi)); 02172 zi.chan = 0; 02173 02174 if (slavechannel > 0) { 02175 /* If we have only one slave, do a digital mon */ 02176 zi.confmode = DAHDI_CONF_DIGITALMON; 02177 zi.confno = slavechannel; 02178 } else { 02179 if (!index) { 02180 /* Real-side and pseudo-side both participate in conference */ 02181 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 02182 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02183 } else 02184 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02185 zi.confno = p->confno; 02186 } 02187 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 02188 return 0; 02189 if (c->dfd < 0) 02190 return 0; 02191 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02192 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 02193 return -1; 02194 } 02195 if (slavechannel < 1) { 02196 p->confno = zi.confno; 02197 } 02198 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02199 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02200 return 0; 02201 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 2214 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().
02215 { 02216 struct dahdi_confinfo zi; 02217 if (/* Can't delete if there's no dfd */ 02218 (c->dfd < 0) || 02219 /* Don't delete from the conference if it's not our conference */ 02220 !isourconf(p, c) 02221 /* Don't delete if we don't think it's conferenced at all (implied) */ 02222 ) return 0; 02223 memset(&zi, 0, sizeof(zi)); 02224 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02225 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 02226 return -1; 02227 } 02228 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02229 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02230 return 0; 02231 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3442 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().
03443 { 03444 /* data is whether to accept with charge or no charge */ 03445 openr2_call_mode_t accept_mode; 03446 int res, timeout, maxloops; 03447 struct ast_frame *f; 03448 struct dahdi_pvt *p; 03449 char *parse; 03450 AST_DECLARE_APP_ARGS(args, 03451 AST_APP_ARG(charge); 03452 ); 03453 03454 if (ast_strlen_zero(data)) { 03455 ast_log(LOG_DEBUG, "No data sent to application!\n"); 03456 return -1; 03457 } 03458 03459 if (chan->tech != &dahdi_tech) { 03460 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 03461 return -1; 03462 } 03463 03464 p = (struct dahdi_pvt *)chan->tech_pvt; 03465 if (!p) { 03466 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 03467 return -1; 03468 } 03469 03470 parse = ast_strdupa(data); 03471 AST_STANDARD_APP_ARGS(args, parse); 03472 03473 if (ast_strlen_zero(args.charge)) { 03474 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 03475 return -1; 03476 } 03477 03478 ast_mutex_lock(&p->lock); 03479 if (!p->mfcr2 || !p->mfcr2call) { 03480 ast_mutex_unlock(&p->lock); 03481 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 03482 return -1; 03483 } 03484 03485 if (p->mfcr2_call_accepted) { 03486 ast_mutex_unlock(&p->lock); 03487 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 03488 return 0; 03489 } 03490 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 03491 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 03492 ast_mutex_unlock(&p->lock); 03493 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03494 return -1; 03495 } 03496 ast_mutex_unlock(&p->lock); 03497 03498 res = 0; 03499 timeout = 100; 03500 maxloops = 50; /* wait up to 5 seconds */ 03501 /* we need to read() until the call is accepted */ 03502 while (maxloops > 0) { 03503 maxloops--; 03504 if (ast_check_hangup(chan)) { 03505 break; 03506 } 03507 res = ast_waitfor(chan, timeout); 03508 if (res < 0) { 03509 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 03510 res = -1; 03511 break; 03512 } 03513 if (res == 0) { 03514 continue; 03515 } 03516 f = ast_read(chan); 03517 if (!f) { 03518 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 03519 res = -1; 03520 break; 03521 } 03522 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 03523 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 03524 ast_frfree(f); 03525 res = -1; 03526 break; 03527 } 03528 ast_frfree(f); 03529 ast_mutex_lock(&p->lock); 03530 if (p->mfcr2_call_accepted) { 03531 ast_mutex_unlock(&p->lock); 03532 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 03533 break; 03534 } 03535 ast_mutex_unlock(&p->lock); 03536 } 03537 if (res == -1) { 03538 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03539 } 03540 return res; 03541 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12609 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12610 { 12611 return __action_dialoffhook(s, m, 0); 12612 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12509 of file chan_dahdi.c.
References __action_dnd(), and s.
12510 { 12511 return __action_dnd(s, m, 0, 0); 12512 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12499 of file chan_dahdi.c.
References __action_dnd(), and s.
12500 { 12501 return __action_dnd(s, m, 0, 1); 12502 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12688 of file chan_dahdi.c.
References __action_restart(), and s.
12689 { 12690 return __action_restart(s, m, 0); 12691 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12664 of file chan_dahdi.c.
References __action_showchannels(), and s.
12665 { 12666 return __action_showchannels(s, m, 0); 12667 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12538 of file chan_dahdi.c.
References __action_transfer(), and s.
12539 { 12540 return __action_transfer(s, m, 0); 12541 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12566 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12567 { 12568 return __action_transferhangup(s, m, 0); 12569 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3943 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.
03944 { 03945 struct dahdi_pvt *p = ast->tech_pvt; 03946 int res = 0; 03947 int index; 03948 int oldstate = ast->_state; 03949 ast_setstate(ast, AST_STATE_UP); 03950 ast_mutex_lock(&p->lock); 03951 index = dahdi_get_index(ast, p, 0); 03952 if (index < 0) 03953 index = SUB_REAL; 03954 /* nothing to do if a radio channel */ 03955 if ((p->radio || (p->oprmode < 0))) { 03956 ast_mutex_unlock(&p->lock); 03957 return 0; 03958 } 03959 switch (p->sig) { 03960 case SIG_FXSLS: 03961 case SIG_FXSGS: 03962 case SIG_FXSKS: 03963 p->ringt = 0; 03964 /* Fall through */ 03965 case SIG_EM: 03966 case SIG_EM_E1: 03967 case SIG_EMWINK: 03968 case SIG_FEATD: 03969 case SIG_FEATDMF: 03970 case SIG_FEATDMF_TA: 03971 case SIG_E911: 03972 case SIG_FGC_CAMA: 03973 case SIG_FGC_CAMAMF: 03974 case SIG_FEATB: 03975 case SIG_SF: 03976 case SIG_SFWINK: 03977 case SIG_SF_FEATD: 03978 case SIG_SF_FEATDMF: 03979 case SIG_SF_FEATB: 03980 case SIG_FXOLS: 03981 case SIG_FXOGS: 03982 case SIG_FXOKS: 03983 /* Pick up the line */ 03984 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03985 if (p->hanguponpolarityswitch) { 03986 gettimeofday(&p->polaritydelaytv, NULL); 03987 } 03988 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03989 tone_zone_play_tone(p->subs[index].dfd, -1); 03990 p->dialing = 0; 03991 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03992 if (oldstate == AST_STATE_RINGING) { 03993 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03994 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03995 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03996 p->owner = p->subs[SUB_REAL].owner; 03997 } 03998 } 03999 if (p->sig & __DAHDI_SIG_FXS) { 04000 dahdi_enable_ec(p); 04001 dahdi_train_ec(p); 04002 } 04003 break; 04004 #ifdef HAVE_PRI 04005 case SIG_PRI: 04006 /* Send a pri acknowledge */ 04007 if (!pri_grab(p, p->pri)) { 04008 p->proceeding = 1; 04009 p->dialing = 0; 04010 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04011 pri_rel(p->pri); 04012 } else { 04013 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04014 res = -1; 04015 } 04016 break; 04017 #endif 04018 #ifdef HAVE_OPENR2 04019 case SIG_MFCR2: 04020 if (!p->mfcr2_accept_on_offer) { 04021 /* the call was not accepted on offer, so it must be accepted now before answering, 04022 the answer will be executed when the callback on_call_accepted is executed */ 04023 if (p->mfcr2_charge_calls) { 04024 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel); 04025 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04026 } else { 04027 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel); 04028 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04029 } 04030 } else { 04031 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04032 res = dahdi_r2_answer(p); 04033 } 04034 break; 04035 #endif 04036 case 0: 04037 ast_mutex_unlock(&p->lock); 04038 return 0; 04039 default: 04040 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04041 res = -1; 04042 } 04043 ast_mutex_unlock(&p->lock); 04044 return res; 04045 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 3548 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().
03549 { 03550 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 03551 switch (cause) { 03552 case AST_CAUSE_USER_BUSY: 03553 case AST_CAUSE_CALL_REJECTED: 03554 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 03555 r2cause = OR2_CAUSE_BUSY_NUMBER; 03556 break; 03557 03558 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 03559 case AST_CAUSE_SWITCH_CONGESTION: 03560 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 03561 break; 03562 03563 case AST_CAUSE_UNALLOCATED: 03564 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 03565 break; 03566 03567 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 03568 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 03569 r2cause = OR2_CAUSE_OUT_OF_ORDER; 03570 break; 03571 03572 case AST_CAUSE_NO_ANSWER: 03573 case AST_CAUSE_NO_USER_RESPONSE: 03574 r2cause = OR2_CAUSE_NO_ANSWER; 03575 break; 03576 03577 default: 03578 r2cause = OR2_CAUSE_NORMAL_CLEARING; 03579 break; 03580 } 03581 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 03582 r2cause, openr2_proto_get_disconnect_string(r2cause), cause); 03583 return r2cause; 03584 }
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 4370 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.
04371 { 04372 struct ast_channel *who; 04373 struct dahdi_pvt *p0, *p1, *op0, *op1; 04374 struct dahdi_pvt *master = NULL, *slave = NULL; 04375 struct ast_frame *f; 04376 int inconf = 0; 04377 int nothingok = 1; 04378 int ofd0, ofd1; 04379 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04380 int os0 = -1, os1 = -1; 04381 int priority = 0; 04382 struct ast_channel *oc0, *oc1; 04383 enum ast_bridge_result res; 04384 04385 #ifdef PRI_2BCT 04386 int triedtopribridge = 0; 04387 q931_call *q931c0 = NULL, *q931c1 = NULL; 04388 #endif 04389 04390 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04391 There is code below to handle it properly until DTMF is actually seen, 04392 but due to currently unresolved issues it's ignored... 04393 */ 04394 04395 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04396 return AST_BRIDGE_FAILED_NOWARN; 04397 04398 ast_mutex_lock(&c0->lock); 04399 while (ast_mutex_trylock(&c1->lock)) { 04400 DEADLOCK_AVOIDANCE(&c0->lock); 04401 } 04402 04403 p0 = c0->tech_pvt; 04404 p1 = c1->tech_pvt; 04405 /* cant do pseudo-channels here */ 04406 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04407 ast_mutex_unlock(&c0->lock); 04408 ast_mutex_unlock(&c1->lock); 04409 return AST_BRIDGE_FAILED_NOWARN; 04410 } 04411 04412 oi0 = dahdi_get_index(c0, p0, 0); 04413 oi1 = dahdi_get_index(c1, p1, 0); 04414 if ((oi0 < 0) || (oi1 < 0)) { 04415 ast_mutex_unlock(&c0->lock); 04416 ast_mutex_unlock(&c1->lock); 04417 return AST_BRIDGE_FAILED; 04418 } 04419 04420 op0 = p0 = c0->tech_pvt; 04421 op1 = p1 = c1->tech_pvt; 04422 ofd0 = c0->fds[0]; 04423 ofd1 = c1->fds[0]; 04424 oc0 = p0->owner; 04425 oc1 = p1->owner; 04426 04427 if (ast_mutex_trylock(&p0->lock)) { 04428 /* Don't block, due to potential for deadlock */ 04429 ast_mutex_unlock(&c0->lock); 04430 ast_mutex_unlock(&c1->lock); 04431 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04432 return AST_BRIDGE_RETRY; 04433 } 04434 if (ast_mutex_trylock(&p1->lock)) { 04435 /* Don't block, due to potential for deadlock */ 04436 ast_mutex_unlock(&p0->lock); 04437 ast_mutex_unlock(&c0->lock); 04438 ast_mutex_unlock(&c1->lock); 04439 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04440 return AST_BRIDGE_RETRY; 04441 } 04442 04443 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04444 if (p0->owner && p1->owner) { 04445 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04446 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04447 master = p0; 04448 slave = p1; 04449 inconf = 1; 04450 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04451 master = p1; 04452 slave = p0; 04453 inconf = 1; 04454 } else { 04455 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04456 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04457 p0->channel, 04458 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04459 p0->subs[SUB_REAL].inthreeway, p0->channel, 04460 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04461 p1->subs[SUB_REAL].inthreeway); 04462 } 04463 nothingok = 0; 04464 } 04465 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04466 if (p1->subs[SUB_THREEWAY].inthreeway) { 04467 master = p1; 04468 slave = p0; 04469 nothingok = 0; 04470 } 04471 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04472 if (p0->subs[SUB_THREEWAY].inthreeway) { 04473 master = p0; 04474 slave = p1; 04475 nothingok = 0; 04476 } 04477 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04478 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04479 don't put us in anything */ 04480 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04481 master = p1; 04482 slave = p0; 04483 nothingok = 0; 04484 } 04485 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04486 /* Same as previous */ 04487 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04488 master = p0; 04489 slave = p1; 04490 nothingok = 0; 04491 } 04492 } 04493 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 04494 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04495 if (master && slave) { 04496 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04497 in an active threeway call with a channel that is ringing, we should 04498 indicate ringing. */ 04499 if ((oi1 == SUB_THREEWAY) && 04500 p1->subs[SUB_THREEWAY].inthreeway && 04501 p1->subs[SUB_REAL].owner && 04502 p1->subs[SUB_REAL].inthreeway && 04503 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04504 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04505 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04506 os1 = p1->subs[SUB_REAL].owner->_state; 04507 } else { 04508 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04509 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04510 } 04511 if ((oi0 == SUB_THREEWAY) && 04512 p0->subs[SUB_THREEWAY].inthreeway && 04513 p0->subs[SUB_REAL].owner && 04514 p0->subs[SUB_REAL].inthreeway && 04515 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04516 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04517 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04518 os0 = p0->subs[SUB_REAL].owner->_state; 04519 } else { 04520 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04521 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04522 } 04523 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04524 if (!p0->echocanbridged || !p1->echocanbridged) { 04525 /* Disable echo cancellation if appropriate */ 04526 dahdi_disable_ec(p0); 04527 dahdi_disable_ec(p1); 04528 } 04529 } 04530 dahdi_link(slave, master); 04531 master->inconference = inconf; 04532 } else if (!nothingok) 04533 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04534 04535 update_conf(p0); 04536 update_conf(p1); 04537 t0 = p0->subs[SUB_REAL].inthreeway; 04538 t1 = p1->subs[SUB_REAL].inthreeway; 04539 04540 ast_mutex_unlock(&p0->lock); 04541 ast_mutex_unlock(&p1->lock); 04542 04543 ast_mutex_unlock(&c0->lock); 04544 ast_mutex_unlock(&c1->lock); 04545 04546 /* Native bridge failed */ 04547 if ((!master || !slave) && !nothingok) { 04548 dahdi_enable_ec(p0); 04549 dahdi_enable_ec(p1); 04550 return AST_BRIDGE_FAILED; 04551 } 04552 04553 if (option_verbose > 2) 04554 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 04555 04556 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04557 disable_dtmf_detect(op0); 04558 04559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04560 disable_dtmf_detect(op1); 04561 04562 for (;;) { 04563 struct ast_channel *c0_priority[2] = {c0, c1}; 04564 struct ast_channel *c1_priority[2] = {c1, c0}; 04565 04566 /* Here's our main loop... Start by locking things, looking for private parts, 04567 and then balking if anything is wrong */ 04568 ast_mutex_lock(&c0->lock); 04569 while (ast_mutex_trylock(&c1->lock)) { 04570 DEADLOCK_AVOIDANCE(&c0->lock); 04571 } 04572 04573 p0 = c0->tech_pvt; 04574 p1 = c1->tech_pvt; 04575 04576 if (op0 == p0) 04577 i0 = dahdi_get_index(c0, p0, 1); 04578 if (op1 == p1) 04579 i1 = dahdi_get_index(c1, p1, 1); 04580 ast_mutex_unlock(&c0->lock); 04581 ast_mutex_unlock(&c1->lock); 04582 04583 if (!timeoutms || 04584 (op0 != p0) || 04585 (op1 != p1) || 04586 (ofd0 != c0->fds[0]) || 04587 (ofd1 != c1->fds[0]) || 04588 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04589 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04590 (oc0 != p0->owner) || 04591 (oc1 != p1->owner) || 04592 (t0 != p0->subs[SUB_REAL].inthreeway) || 04593 (t1 != p1->subs[SUB_REAL].inthreeway) || 04594 (oi0 != i0) || 04595 (oi1 != i1)) { 04596 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04597 op0->channel, oi0, op1->channel, oi1); 04598 res = AST_BRIDGE_RETRY; 04599 goto return_from_bridge; 04600 } 04601 04602 #ifdef PRI_2BCT 04603 q931c0 = p0->call; 04604 q931c1 = p1->call; 04605 if (p0->transfer && p1->transfer 04606 && q931c0 && q931c1 04607 && !triedtopribridge) { 04608 pri_channel_bridge(q931c0, q931c1); 04609 triedtopribridge = 1; 04610 } 04611 #endif 04612 04613 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04614 if (!who) { 04615 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 04616 continue; 04617 } 04618 f = ast_read(who); 04619 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04620 *fo = f; 04621 *rc = who; 04622 res = AST_BRIDGE_COMPLETE; 04623 goto return_from_bridge; 04624 } 04625 if (f->frametype == AST_FRAME_DTMF) { 04626 if ((who == c0) && p0->pulsedial) { 04627 ast_write(c1, f); 04628 } else if ((who == c1) && p1->pulsedial) { 04629 ast_write(c0, f); 04630 } else { 04631 *fo = f; 04632 *rc = who; 04633 res = AST_BRIDGE_COMPLETE; 04634 goto return_from_bridge; 04635 } 04636 } 04637 ast_frfree(f); 04638 04639 /* Swap who gets priority */ 04640 priority = !priority; 04641 } 04642 04643 return_from_bridge: 04644 if (op0 == p0) 04645 dahdi_enable_ec(p0); 04646 04647 if (op1 == p1) 04648 dahdi_enable_ec(p1); 04649 04650 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04651 enable_dtmf_detect(op0); 04652 04653 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04654 enable_dtmf_detect(op1); 04655 04656 dahdi_unlink(slave, master, 1); 04657 04658 return res; 04659 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2711 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.
02712 { 02713 struct dahdi_pvt *p = ast->tech_pvt; 02714 int x, res, index,mysig; 02715 char *c, *n, *l; 02716 #ifdef HAVE_PRI 02717 char *s = NULL; 02718 #endif 02719 char dest[256]; /* must be same length as p->dialdest */ 02720 ast_mutex_lock(&p->lock); 02721 ast_copy_string(dest, rdest, sizeof(dest)); 02722 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02723 if ((ast->_state == AST_STATE_BUSY)) { 02724 p->subs[SUB_REAL].needbusy = 1; 02725 ast_mutex_unlock(&p->lock); 02726 return 0; 02727 } 02728 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02729 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02730 ast_mutex_unlock(&p->lock); 02731 return -1; 02732 } 02733 p->dialednone = 0; 02734 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02735 { 02736 /* Special pseudo -- automatically up */ 02737 ast_setstate(ast, AST_STATE_UP); 02738 ast_mutex_unlock(&p->lock); 02739 return 0; 02740 } 02741 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02742 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02743 if (res) 02744 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02745 p->outgoing = 1; 02746 02747 if (IS_DIGITAL(ast->transfercapability)) { 02748 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02749 } else { 02750 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02751 } 02752 02753 mysig = p->sig; 02754 if (p->outsigmod > -1) 02755 mysig = p->outsigmod; 02756 02757 switch (mysig) { 02758 case SIG_FXOLS: 02759 case SIG_FXOGS: 02760 case SIG_FXOKS: 02761 if (p->owner == ast) { 02762 /* Normal ring, on hook */ 02763 02764 /* Don't send audio while on hook, until the call is answered */ 02765 p->dialing = 1; 02766 if (p->use_callerid) { 02767 /* Generate the Caller-ID spill if desired */ 02768 if (p->cidspill) { 02769 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02770 free(p->cidspill); 02771 } 02772 p->callwaitcas = 0; 02773 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02774 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02775 p->cidpos = 0; 02776 send_callerid(p); 02777 } 02778 } 02779 /* Choose proper cadence */ 02780 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02781 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02782 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02783 p->cidrings = cidrings[p->distinctivering - 1]; 02784 } else { 02785 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02786 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02787 p->cidrings = p->sendcalleridafter; 02788 } 02789 02790 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02791 c = strchr(dest, '/'); 02792 if (c) 02793 c++; 02794 if (c && (strlen(c) < p->stripmsd)) { 02795 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02796 c = NULL; 02797 } 02798 if (c) { 02799 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02800 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02801 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02802 } else { 02803 p->dop.dialstr[0] = '\0'; 02804 } 02805 x = DAHDI_RING; 02806 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02807 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02808 ast_mutex_unlock(&p->lock); 02809 return -1; 02810 } 02811 p->dialing = 1; 02812 } else { 02813 /* Call waiting call */ 02814 p->callwaitrings = 0; 02815 if (ast->cid.cid_num) 02816 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02817 else 02818 p->callwait_num[0] = '\0'; 02819 if (ast->cid.cid_name) 02820 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02821 else 02822 p->callwait_name[0] = '\0'; 02823 /* Call waiting tone instead */ 02824 if (dahdi_callwait(ast)) { 02825 ast_mutex_unlock(&p->lock); 02826 return -1; 02827 } 02828 /* Make ring-back */ 02829 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02830 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02831 02832 } 02833 n = ast->cid.cid_name; 02834 l = ast->cid.cid_num; 02835 if (l) 02836 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02837 else 02838 p->lastcid_num[0] = '\0'; 02839 if (n) 02840 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02841 else 02842 p->lastcid_name[0] = '\0'; 02843 ast_setstate(ast, AST_STATE_RINGING); 02844 index = dahdi_get_index(ast, p, 0); 02845 if (index > -1) { 02846 p->subs[index].needringing = 1; 02847 } 02848 break; 02849 case SIG_FXSLS: 02850 case SIG_FXSGS: 02851 case SIG_FXSKS: 02852 case SIG_EMWINK: 02853 case SIG_EM: 02854 case SIG_EM_E1: 02855 case SIG_FEATD: 02856 case SIG_FEATDMF: 02857 case SIG_E911: 02858 case SIG_FGC_CAMA: 02859 case SIG_FGC_CAMAMF: 02860 case SIG_FEATB: 02861 case SIG_SFWINK: 02862 case SIG_SF: 02863 case SIG_SF_FEATD: 02864 case SIG_SF_FEATDMF: 02865 case SIG_FEATDMF_TA: 02866 case SIG_SF_FEATB: 02867 c = strchr(dest, '/'); 02868 if (c) 02869 c++; 02870 else 02871 c = ""; 02872 if (strlen(c) < p->stripmsd) { 02873 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02874 ast_mutex_unlock(&p->lock); 02875 return -1; 02876 } 02877 #ifdef HAVE_PRI 02878 /* Start the trunk, if not GR-303 */ 02879 if (!p->pri) { 02880 #endif 02881 x = DAHDI_START; 02882 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02883 if (res < 0) { 02884 if (errno != EINPROGRESS) { 02885 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02886 ast_mutex_unlock(&p->lock); 02887 return -1; 02888 } 02889 } 02890 #ifdef HAVE_PRI 02891 } 02892 #endif 02893 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02894 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02895 02896 c += p->stripmsd; 02897 02898 switch (mysig) { 02899 case SIG_FEATD: 02900 l = ast->cid.cid_num; 02901 if (l) 02902 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02903 else 02904 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02905 break; 02906 case SIG_FEATDMF: 02907 l = ast->cid.cid_num; 02908 if (l) 02909 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02910 else 02911 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02912 break; 02913 case SIG_FEATDMF_TA: 02914 { 02915 const char *cic, *ozz; 02916 02917 /* If you have to go through a Tandem Access point you need to use this */ 02918 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02919 if (!ozz) 02920 ozz = defaultozz; 02921 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02922 if (!cic) 02923 cic = defaultcic; 02924 if (!ozz || !cic) { 02925 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02926 ast_mutex_unlock(&p->lock); 02927 return -1; 02928 } 02929 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02930 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02931 p->whichwink = 0; 02932 } 02933 break; 02934 case SIG_E911: 02935 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02936 break; 02937 case SIG_FGC_CAMA: 02938 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02939 break; 02940 case SIG_FGC_CAMAMF: 02941 case SIG_FEATB: 02942 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02943 break; 02944 default: 02945 if (p->pulse) 02946 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02947 else 02948 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02949 break; 02950 } 02951 02952 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02953 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02954 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02955 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02956 p->echobreak = 1; 02957 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02958 } else 02959 p->echobreak = 0; 02960 if (!res) { 02961 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02962 int saveerr = errno; 02963 02964 x = DAHDI_ONHOOK; 02965 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02966 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02967 ast_mutex_unlock(&p->lock); 02968 return -1; 02969 } 02970 } else 02971 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res); 02972 p->dialing = 1; 02973 if (ast_strlen_zero(c)) 02974 p->dialednone = 1; 02975 ast_setstate(ast, AST_STATE_DIALING); 02976 break; 02977 case 0: 02978 /* Special pseudo -- automatically up*/ 02979 ast_setstate(ast, AST_STATE_UP); 02980 break; 02981 case SIG_PRI: 02982 case SIG_MFCR2: 02983 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02984 p->dialdest[0] = '\0'; 02985 p->dialing = 1; 02986 break; 02987 default: 02988 ast_log(LOG_DEBUG, "not yet implemented\n"); 02989 ast_mutex_unlock(&p->lock); 02990 return -1; 02991 } 02992 #ifdef HAVE_OPENR2 02993 if (p->mfcr2) { 02994 int strip = p->stripmsd; 02995 int callres = 0; 02996 c = strchr(dest, '/'); 02997 if (c) { 02998 c++; 02999 } else { 03000 c = dest; 03001 } 03002 if (!p->hidecallerid) { 03003 l = ast->cid.cid_num; 03004 } else { 03005 l = NULL; 03006 } 03007 if (strlen(c) < strip) { 03008 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip); 03009 strip = 0; 03010 } 03011 p->dialing = 1; 03012 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast)); 03013 if (-1 == callres) { 03014 ast_mutex_unlock(&p->lock); 03015 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03016 return -1; 03017 } 03018 ast_setstate(ast, AST_STATE_DIALING); 03019 } 03020 #endif /* HAVE_OPENR2 */ 03021 #ifdef HAVE_PRI 03022 if (p->pri) { 03023 struct pri_sr *sr; 03024 #ifdef SUPPORT_USERUSER 03025 const char *useruser; 03026 #endif 03027 int pridialplan; 03028 int dp_strip; 03029 int prilocaldialplan; 03030 int ldp_strip; 03031 int exclusive; 03032 const char *rr_str; 03033 int redirect_reason; 03034 03035 c = strchr(dest, '/'); 03036 if (c) { 03037 c++; 03038 } else { 03039 c = ""; 03040 } 03041 03042 l = NULL; 03043 n = NULL; 03044 if (!p->hidecallerid) { 03045 l = ast->cid.cid_num; 03046 if (!p->hidecalleridname) { 03047 n = ast->cid.cid_name; 03048 } 03049 } 03050 03051 03052 if (strlen(c) < p->stripmsd) { 03053 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03054 ast_mutex_unlock(&p->lock); 03055 return -1; 03056 } 03057 if (mysig != SIG_FXSKS) { 03058 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03059 s = strchr(c + p->stripmsd, 'w'); 03060 if (s) { 03061 if (strlen(s) > 1) 03062 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03063 else 03064 p->dop.dialstr[0] = '\0'; 03065 *s = '\0'; 03066 } else { 03067 p->dop.dialstr[0] = '\0'; 03068 } 03069 } 03070 if (pri_grab(p, p->pri)) { 03071 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03072 ast_mutex_unlock(&p->lock); 03073 return -1; 03074 } 03075 if (!(p->call = pri_new_call(p->pri->pri))) { 03076 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03077 pri_rel(p->pri); 03078 ast_mutex_unlock(&p->lock); 03079 return -1; 03080 } 03081 if (!(sr = pri_sr_new())) { 03082 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03083 pri_destroycall(p->pri->pri, p->call); 03084 p->call = NULL; 03085 pri_rel(p->pri); 03086 ast_mutex_unlock(&p->lock); 03087 return -1; 03088 } 03089 if (p->bearer || (mysig == SIG_FXSKS)) { 03090 if (p->bearer) { 03091 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); 03092 p->bearer->call = p->call; 03093 } else 03094 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 03095 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03096 } 03097 p->digital = IS_DIGITAL(ast->transfercapability); 03098 03099 /* Should the picked channel be used exclusively? */ 03100 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03101 exclusive = 1; 03102 } else { 03103 exclusive = 0; 03104 } 03105 03106 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03107 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03108 (p->digital ? -1 : 03109 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03110 if (p->pri->facilityenable) 03111 pri_facility_enable(p->pri->pri); 03112 03113 if (option_verbose > 2) 03114 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03115 dp_strip = 0; 03116 pridialplan = p->pri->dialplan - 1; 03117 if (pridialplan == -2) { /* compute dynamically */ 03118 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03119 dp_strip = strlen(p->pri->internationalprefix); 03120 pridialplan = PRI_INTERNATIONAL_ISDN; 03121 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03122 dp_strip = strlen(p->pri->nationalprefix); 03123 pridialplan = PRI_NATIONAL_ISDN; 03124 } else { 03125 pridialplan = PRI_LOCAL_ISDN; 03126 } 03127 } 03128 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03129 03130 ldp_strip = 0; 03131 prilocaldialplan = p->pri->localdialplan - 1; 03132 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 03133 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03134 ldp_strip = strlen(p->pri->internationalprefix); 03135 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03136 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03137 ldp_strip = strlen(p->pri->nationalprefix); 03138 prilocaldialplan = PRI_NATIONAL_ISDN; 03139 } else { 03140 prilocaldialplan = PRI_LOCAL_ISDN; 03141 } 03142 } 03143 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03144 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03145 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03146 if (!strcasecmp(rr_str, "UNKNOWN")) 03147 redirect_reason = 0; 03148 else if (!strcasecmp(rr_str, "BUSY")) 03149 redirect_reason = 1; 03150 else if (!strcasecmp(rr_str, "NO_REPLY")) 03151 redirect_reason = 2; 03152 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03153 redirect_reason = 15; 03154 else 03155 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03156 } else 03157 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03158 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03159 03160 #ifdef SUPPORT_USERUSER 03161 /* User-user info */ 03162 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03163 03164 if (useruser) 03165 pri_sr_set_useruser(sr, useruser); 03166 #endif 03167 03168 if (pri_setup(p->pri->pri, p->call, sr)) { 03169 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03170 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03171 pri_rel(p->pri); 03172 ast_mutex_unlock(&p->lock); 03173 pri_sr_free(sr); 03174 return -1; 03175 } 03176 pri_sr_free(sr); 03177 ast_setstate(ast, AST_STATE_DIALING); 03178 pri_rel(p->pri); 03179 } 03180 #endif 03181 ast_mutex_unlock(&p->lock); 03182 return 0; 03183 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2683 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().
02684 { 02685 struct dahdi_pvt *p = ast->tech_pvt; 02686 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02687 if (p->cidspill) { 02688 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02689 free(p->cidspill); 02690 } 02691 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02692 return -1; 02693 save_conference(p); 02694 /* Silence */ 02695 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02696 if (!p->callwaitrings && p->callwaitingcallerid) { 02697 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02698 p->callwaitcas = 1; 02699 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02700 } else { 02701 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02702 p->callwaitcas = 0; 02703 p->cidlen = 2400 + READ_SIZE * 4; 02704 } 02705 p->cidpos = 0; 02706 send_callerid(p); 02707 02708 return 0; 02709 }
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 994 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().
00994 { 00995 /* recall that if a field is not included here it is initialized 00996 * to 0 or equivalent 00997 */ 00998 struct dahdi_chan_conf conf = { 00999 #ifdef HAVE_PRI 01000 .pri = { 01001 .nsf = PRI_NSF_NONE, 01002 .switchtype = PRI_SWITCH_NI2, 01003 .dialplan = PRI_NATIONAL_ISDN + 1, 01004 .localdialplan = PRI_NATIONAL_ISDN + 1, 01005 .nodetype = PRI_CPE, 01006 01007 .minunused = 2, 01008 .idleext = "", 01009 .idledial = "", 01010 .internationalprefix = "", 01011 .nationalprefix = "", 01012 .localprefix = "", 01013 .privateprefix = "", 01014 .unknownprefix = "", 01015 01016 .resetinterval = 3600 01017 }, 01018 #endif 01019 .chan = { 01020 .context = "default", 01021 .cid_num = "", 01022 .cid_name = "", 01023 .mohinterpret = "default", 01024 .mohsuggest = "", 01025 .transfertobusy = 1, 01026 01027 .cid_signalling = CID_SIG_BELL, 01028 .cid_start = CID_START_RING, 01029 .dahditrcallerid = 0, 01030 .use_callerid = 1, 01031 .sig = -1, 01032 .outsigmod = -1, 01033 01034 .tonezone = -1, 01035 01036 .echocancel = 1, 01037 01038 .busycount = 3, 01039 .busycompare = 0, 01040 .busytonelength = 0, 01041 .busyquietlength = 0, 01042 .busyfuzziness = 0, 01043 .silencethreshold = 0, 01044 01045 .accountcode = "", 01046 01047 .mailbox = "", 01048 01049 01050 .polarityonanswerdelay = 600, 01051 01052 .sendcalleridafter = DEFAULT_CIDRINGS, 01053 01054 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01055 .buf_no = numbufs 01056 }, 01057 .timing = { 01058 .prewinktime = -1, 01059 .preflashtime = -1, 01060 .winktime = -1, 01061 .flashtime = -1, 01062 .starttime = -1, 01063 .rxwinktime = -1, 01064 .rxflashtime = -1, 01065 .debouncetime = -1 01066 }, 01067 .smdi_port = "/dev/ttyS0", 01068 }; 01069 01070 return conf; 01071 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1844 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 1857 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01858 { 01859 dahdi_close(pri->fds[fd_num]); 01860 pri->fds[fd_num] = -1; 01861 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1850 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().
01851 { 01852 dahdi_close(chan_pvt->subs[sub_num].dfd); 01853 chan_pvt->subs[sub_num].dfd = -1; 01854 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2567 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().
02568 { 02569 int x, y, res; 02570 x = muted; 02571 if (p->sig == SIG_PRI) { 02572 y = 1; 02573 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02574 if (res) 02575 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02576 } 02577 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02578 if (res < 0) 02579 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02580 return res; 02581 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11864 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
11865 { 11866 int channel; 11867 11868 if (argc != 4) 11869 return RESULT_SHOWUSAGE; 11870 11871 channel = atoi(argv[3]); 11872 11873 return dahdi_destroy_channel_bynum(channel); 11874 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7914 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().
07915 { 07916 struct dahdi_pvt *tmp = NULL; 07917 struct dahdi_pvt *prev = NULL; 07918 07919 ast_mutex_lock(&iflock); 07920 tmp = iflist; 07921 while (tmp) { 07922 if (tmp->channel == channel) { 07923 int x = DAHDI_FLASH; 07924 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 */ 07925 destroy_channel(prev, tmp, 1); 07926 ast_mutex_unlock(&iflock); 07927 ast_module_unref(ast_module_info->self); 07928 return RESULT_SUCCESS; 07929 } 07930 prev = tmp; 07931 tmp = tmp->next; 07932 } 07933 ast_mutex_unlock(&iflock); 07934 return RESULT_FAILURE; 07935 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1941 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.
01942 { 01943 struct dahdi_pvt *pvt; 01944 int index; 01945 int dtmf = -1; 01946 01947 pvt = chan->tech_pvt; 01948 01949 ast_mutex_lock(&pvt->lock); 01950 01951 index = dahdi_get_index(chan, pvt, 0); 01952 01953 if ((index != SUB_REAL) || !pvt->owner) 01954 goto out; 01955 01956 #ifdef HAVE_PRI 01957 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01958 if (pvt->setup_ack) { 01959 if (!pri_grab(pvt, pvt->pri)) { 01960 pri_information(pvt->pri->pri, pvt->call, digit); 01961 pri_rel(pvt->pri); 01962 } else 01963 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01964 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01965 int res; 01966 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01967 res = strlen(pvt->dialdest); 01968 pvt->dialdest[res++] = digit; 01969 pvt->dialdest[res] = '\0'; 01970 } 01971 goto out; 01972 } 01973 #endif 01974 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01975 goto out; 01976 01977 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01978 int res; 01979 struct dahdi_dialoperation zo = { 01980 .op = DAHDI_DIAL_OP_APPEND, 01981 .dialstr[0] = 'T', 01982 .dialstr[1] = digit, 01983 .dialstr[2] = 0, 01984 }; 01985 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01986 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01987 else 01988 pvt->dialing = 1; 01989 } else { 01990 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01991 pvt->dialing = 1; 01992 pvt->begindigit = digit; 01993 } 01994 01995 out: 01996 ast_mutex_unlock(&pvt->lock); 01997 01998 return 0; 01999 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2001 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.
02002 { 02003 struct dahdi_pvt *pvt; 02004 int res = 0; 02005 int index; 02006 int x; 02007 02008 pvt = chan->tech_pvt; 02009 02010 ast_mutex_lock(&pvt->lock); 02011 02012 index = dahdi_get_index(chan, pvt, 0); 02013 02014 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 02015 goto out; 02016 02017 #ifdef HAVE_PRI 02018 /* This means that the digit was already sent via PRI signalling */ 02019 if (pvt->sig == SIG_PRI && !pvt->begindigit) 02020 goto out; 02021 #endif 02022 02023 if (pvt->begindigit) { 02024 x = -1; 02025 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 02026 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 02027 pvt->dialing = 0; 02028 pvt->begindigit = 0; 02029 } 02030 02031 out: 02032 ast_mutex_unlock(&pvt->lock); 02033 02034 return res; 02035 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2398 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().
02399 { 02400 int x; 02401 int res; 02402 if (p->echocancel) { 02403 x = 0; 02404 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02405 if (res) 02406 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02407 else if (option_debug) 02408 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 02409 } 02410 p->echocanon = 0; 02411 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2348 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().
02349 { 02350 int x; 02351 int res; 02352 if (!p) 02353 return; 02354 if (p->echocanon) { 02355 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 02356 return; 02357 } 02358 if (p->digital) { 02359 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 02360 return; 02361 } 02362 if (p->echocancel) { 02363 if (p->sig == SIG_PRI) { 02364 x = 1; 02365 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02366 if (res) 02367 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02368 } 02369 x = p->echocancel; 02370 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02371 if (res) 02372 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02373 else { 02374 p->echocanon = 1; 02375 if (option_debug) 02376 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 02377 } 02378 } else if (option_debug) 02379 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 02380 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5896 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05897 { 05898 struct dahdi_pvt *p = ast->tech_pvt; 05899 struct ast_frame *f; 05900 ast_mutex_lock(&p->lock); 05901 f = __dahdi_exception(ast); 05902 ast_mutex_unlock(&p->lock); 05903 return f; 05904 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 12444 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().
12445 { 12446 if (p) { 12447 switch (mode) { 12448 case TRANSFER: 12449 p->fake_event = DAHDI_EVENT_WINKFLASH; 12450 break; 12451 case HANGUP: 12452 p->fake_event = DAHDI_EVENT_ONHOOK; 12453 break; 12454 default: 12455 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 12456 } 12457 } 12458 return 0; 12459 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4661 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.
04662 { 04663 struct dahdi_pvt *p = newchan->tech_pvt; 04664 int x; 04665 ast_mutex_lock(&p->lock); 04666 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 04667 if (p->owner == oldchan) { 04668 p->owner = newchan; 04669 } 04670 for (x = 0; x < 3; x++) 04671 if (p->subs[x].owner == oldchan) { 04672 if (!x) 04673 dahdi_unlink(NULL, p, 0); 04674 p->subs[x].owner = newchan; 04675 } 04676 if (newchan->_state == AST_STATE_RINGING) 04677 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04678 update_conf(p); 04679 ast_mutex_unlock(&p->lock); 04680 return 0; 04681 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4233 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.
04234 { 04235 struct dahdi_pvt *p = chan->tech_pvt; 04236 04237 if (!strcasecmp(data, "rxgain")) { 04238 ast_mutex_lock(&p->lock); 04239 snprintf(buf, len, "%f", p->rxgain); 04240 ast_mutex_unlock(&p->lock); 04241 } else if (!strcasecmp(data, "txgain")) { 04242 ast_mutex_lock(&p->lock); 04243 snprintf(buf, len, "%f", p->txgain); 04244 ast_mutex_unlock(&p->lock); 04245 } else { 04246 ast_copy_string(buf, "", len); 04247 } 04248 return 0; 04249 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 271 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00272 { 00273 int j; 00274 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00275 return -1; 00276 return j; 00277 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1187 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().
01188 { 01189 int res; 01190 if (p->subs[SUB_REAL].owner == ast) 01191 res = 0; 01192 else if (p->subs[SUB_CALLWAIT].owner == ast) 01193 res = 1; 01194 else if (p->subs[SUB_THREEWAY].owner == ast) 01195 res = 2; 01196 else { 01197 res = -1; 01198 if (!nullok) 01199 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01200 } 01201 return res; 01202 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4823 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().
04824 { 04825 struct dahdi_pvt *p = ast->tech_pvt; 04826 struct ast_frame *f = *dest; 04827 04828 if (option_debug) 04829 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04830 04831 if (p->confirmanswer) { 04832 if (option_debug) 04833 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04834 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04835 of a DTMF digit */ 04836 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04837 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04838 *dest = &p->subs[index].f; 04839 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04840 p->confirmanswer = 0; 04841 } else if (p->callwaitcas) { 04842 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04843 if (option_debug) 04844 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04845 if (p->cidspill) 04846 free(p->cidspill); 04847 send_cwcidspill(p); 04848 } 04849 if ((f->subclass != 'm') && (f->subclass != 'u')) 04850 p->callwaitcas = 0; 04851 p->subs[index].f.frametype = AST_FRAME_NULL; 04852 p->subs[index].f.subclass = 0; 04853 *dest = &p->subs[index].f; 04854 } else if (f->subclass == 'f') { 04855 /* Fax tone -- Handle and return NULL */ 04856 if ((p->callprogress & 0x6) && !p->faxhandled) { 04857 p->faxhandled = 1; 04858 if (strcmp(ast->exten, "fax")) { 04859 const char *target_context = S_OR(ast->macrocontext, ast->context); 04860 04861 /* We need to unlock 'ast' here because ast_exists_extension has the 04862 * potential to start autoservice on the channel. Such action is prone 04863 * to deadlock. 04864 */ 04865 ast_mutex_unlock(&p->lock); 04866 ast_channel_unlock(ast); 04867 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04868 ast_channel_lock(ast); 04869 ast_mutex_lock(&p->lock); 04870 if (option_verbose > 2) 04871 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04872 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04873 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04874 if (ast_async_goto(ast, target_context, "fax", 1)) 04875 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04876 } else { 04877 ast_channel_lock(ast); 04878 ast_mutex_lock(&p->lock); 04879 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04880 } 04881 } else if (option_debug) 04882 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04883 } else if (option_debug) 04884 ast_log(LOG_DEBUG, "Fax already handled\n"); 04885 dahdi_confmute(p, 0); 04886 p->subs[index].f.frametype = AST_FRAME_NULL; 04887 p->subs[index].f.subclass = 0; 04888 *dest = &p->subs[index].f; 04889 } else if (f->subclass == 'm') { 04890 /* Confmute request */ 04891 dahdi_confmute(p, 1); 04892 p->subs[index].f.frametype = AST_FRAME_NULL; 04893 p->subs[index].f.subclass = 0; 04894 *dest = &p->subs[index].f; 04895 } else if (f->subclass == 'u') { 04896 /* Unmute */ 04897 dahdi_confmute(p, 0); 04898 p->subs[index].f.frametype = AST_FRAME_NULL; 04899 p->subs[index].f.subclass = 0; 04900 *dest = &p->subs[index].f; 04901 } else 04902 dahdi_confmute(p, 0); 04903 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4925 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().
04926 { 04927 int res, x; 04928 int index, mysig; 04929 char *c; 04930 struct dahdi_pvt *p = ast->tech_pvt; 04931 pthread_t threadid; 04932 pthread_attr_t attr; 04933 struct ast_channel *chan; 04934 struct ast_frame *f; 04935 04936 index = dahdi_get_index(ast, p, 0); 04937 mysig = p->sig; 04938 if (p->outsigmod > -1) 04939 mysig = p->outsigmod; 04940 p->subs[index].f.frametype = AST_FRAME_NULL; 04941 p->subs[index].f.subclass = 0; 04942 p->subs[index].f.datalen = 0; 04943 p->subs[index].f.samples = 0; 04944 p->subs[index].f.mallocd = 0; 04945 p->subs[index].f.offset = 0; 04946 p->subs[index].f.src = "dahdi_handle_event"; 04947 p->subs[index].f.data = NULL; 04948 f = &p->subs[index].f; 04949 04950 if (index < 0) 04951 return &p->subs[index].f; 04952 if (p->fake_event) { 04953 res = p->fake_event; 04954 p->fake_event = 0; 04955 } else 04956 res = dahdi_get_event(p->subs[index].dfd); 04957 04958 if (option_debug) 04959 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04960 04961 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04962 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04963 04964 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04965 #ifdef HAVE_PRI 04966 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04967 /* absorb event */ 04968 } else { 04969 #endif 04970 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04971 p->subs[index].f.subclass = res & 0xff; 04972 #ifdef HAVE_PRI 04973 } 04974 #endif 04975 dahdi_handle_dtmfup(ast, index, &f); 04976 return f; 04977 } 04978 04979 if (res & DAHDI_EVENT_DTMFDOWN) { 04980 if (option_debug) 04981 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04982 /* Mute conference */ 04983 dahdi_confmute(p, 1); 04984 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04985 p->subs[index].f.subclass = res & 0xff; 04986 return &p->subs[index].f; 04987 } 04988 04989 switch (res) { 04990 #ifdef DAHDI_EVENT_EC_DISABLED 04991 case DAHDI_EVENT_EC_DISABLED: 04992 if (option_verbose > 2) 04993 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04994 p->echocanon = 0; 04995 break; 04996 #endif 04997 case DAHDI_EVENT_BITSCHANGED: 04998 #ifdef HAVE_OPENR2 04999 if (p->sig != SIG_MFCR2) { 05000 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05001 } else { 05002 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 05003 openr2_chan_handle_cas(p->r2chan); 05004 } 05005 #else 05006 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05007 #endif 05008 case DAHDI_EVENT_PULSE_START: 05009 /* Stop tone if there's a pulse start and the PBX isn't started */ 05010 if (!ast->pbx) 05011 tone_zone_play_tone(p->subs[index].dfd, -1); 05012 break; 05013 case DAHDI_EVENT_DIALCOMPLETE: 05014 #ifdef HAVE_OPENR2 05015 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05016 /* we don't need to do anything for this event for R2 signaling 05017 if the call is being setup */ 05018 break; 05019 } 05020 #endif 05021 if (p->inalarm) break; 05022 if ((p->radio || (p->oprmode < 0))) break; 05023 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 05024 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05025 return NULL; 05026 } 05027 if (!x) { /* if not still dialing in driver */ 05028 dahdi_enable_ec(p); 05029 if (p->echobreak) { 05030 dahdi_train_ec(p); 05031 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05032 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05033 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05034 p->echobreak = 0; 05035 } else { 05036 p->dialing = 0; 05037 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05038 /* if thru with dialing after offhook */ 05039 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05040 ast_setstate(ast, AST_STATE_UP); 05041 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05042 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05043 break; 05044 } else { /* if to state wait for offhook to dial rest */ 05045 /* we now wait for off hook */ 05046 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05047 } 05048 } 05049 if (ast->_state == AST_STATE_DIALING) { 05050 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05051 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 05052 } 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)))) { 05053 ast_setstate(ast, AST_STATE_RINGING); 05054 } else if (!p->answeronpolarityswitch) { 05055 ast_setstate(ast, AST_STATE_UP); 05056 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05057 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05058 /* If aops=0 and hops=1, this is necessary */ 05059 p->polarity = POLARITY_REV; 05060 } else { 05061 /* Start clean, so we can catch the change to REV polarity when party answers */ 05062 p->polarity = POLARITY_IDLE; 05063 } 05064 } 05065 } 05066 } 05067 break; 05068 case DAHDI_EVENT_ALARM: 05069 #ifdef HAVE_PRI 05070 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05071 /* T309 is not enabled : hangup calls when alarm occurs */ 05072 if (p->call) { 05073 if (p->pri && p->pri->pri) { 05074 if (!pri_grab(p, p->pri)) { 05075 pri_hangup(p->pri->pri, p->call, -1); 05076 pri_destroycall(p->pri->pri, p->call); 05077 p->call = NULL; 05078 pri_rel(p->pri); 05079 } else 05080 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 05081 } else 05082 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05083 } 05084 if (p->owner) 05085 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05086 } 05087 if (p->bearer) 05088 p->bearer->inalarm = 1; 05089 else 05090 #endif 05091 p->inalarm = 1; 05092 res = get_alarms(p); 05093 handle_alarms(p, res); 05094 #ifdef HAVE_PRI 05095 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05096 /* fall through intentionally */ 05097 } else { 05098 break; 05099 } 05100 #endif 05101 #ifdef HAVE_OPENR2 05102 if (p->sig == SIG_MFCR2) 05103 break; 05104 #endif 05105 case DAHDI_EVENT_ONHOOK: 05106 if (p->radio) { 05107 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05108 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05109 break; 05110 } 05111 if (p->oprmode < 0) 05112 { 05113 if (p->oprmode != -1) break; 05114 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05115 { 05116 /* Make sure it starts ringing */ 05117 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05118 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05119 save_conference(p->oprpeer); 05120 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05121 } 05122 break; 05123 } 05124 switch (p->sig) { 05125 case SIG_FXOLS: 05126 case SIG_FXOGS: 05127 case SIG_FXOKS: 05128 p->onhooktime = time(NULL); 05129 p->msgstate = -1; 05130 /* Check for some special conditions regarding call waiting */ 05131 if (index == SUB_REAL) { 05132 /* The normal line was hung up */ 05133 if (p->subs[SUB_CALLWAIT].owner) { 05134 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05135 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05136 if (option_verbose > 2) 05137 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05138 unalloc_sub(p, SUB_CALLWAIT); 05139 #if 0 05140 p->subs[index].needanswer = 0; 05141 p->subs[index].needringing = 0; 05142 #endif 05143 p->callwaitingrepeat = 0; 05144 p->cidcwexpire = 0; 05145 p->owner = NULL; 05146 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05147 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05148 p->dialing = 1; 05149 dahdi_ring_phone(p); 05150 } else if (p->subs[SUB_THREEWAY].owner) { 05151 unsigned int mssinceflash; 05152 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 05153 the private structure -- not especially easy or clean */ 05154 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 05155 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 05156 ast_mutex_unlock(&p->lock); 05157 DEADLOCK_AVOIDANCE(&ast->lock); 05158 /* We can grab ast and p in that order, without worry. We should make sure 05159 nothing seriously bad has happened though like some sort of bizarre double 05160 masquerade! */ 05161 ast_mutex_lock(&p->lock); 05162 if (p->owner != ast) { 05163 ast_log(LOG_WARNING, "This isn't good...\n"); 05164 return NULL; 05165 } 05166 } 05167 if (!p->subs[SUB_THREEWAY].owner) { 05168 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05169 return NULL; 05170 } 05171 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05172 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 05173 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05174 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05175 hanging up. Hangup both channels now */ 05176 if (p->subs[SUB_THREEWAY].owner) 05177 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 05178 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05179 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05180 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05181 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05182 if (p->transfer) { 05183 /* In any case this isn't a threeway call anymore */ 05184 p->subs[SUB_REAL].inthreeway = 0; 05185 p->subs[SUB_THREEWAY].inthreeway = 0; 05186 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05187 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05188 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05189 /* Swap subs and dis-own channel */ 05190 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05191 p->owner = NULL; 05192 /* Ring the phone */ 05193 dahdi_ring_phone(p); 05194 } else { 05195 if ((res = attempt_transfer(p)) < 0) { 05196 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05197 if (p->subs[SUB_THREEWAY].owner) 05198 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05199 } else if (res) { 05200 /* Don't actually hang up at this point */ 05201 if (p->subs[SUB_THREEWAY].owner) 05202 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05203 break; 05204 } 05205 } 05206 } else { 05207 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05208 if (p->subs[SUB_THREEWAY].owner) 05209 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05210 } 05211 } else { 05212 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05213 /* Swap subs and dis-own channel */ 05214 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05215 p->owner = NULL; 05216 /* Ring the phone */ 05217 dahdi_ring_phone(p); 05218 } 05219 } 05220 } else { 05221 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 05222 } 05223 /* Fall through */ 05224 default: 05225 dahdi_disable_ec(p); 05226 return NULL; 05227 } 05228 break; 05229 case DAHDI_EVENT_RINGOFFHOOK: 05230 if (p->inalarm) break; 05231 if (p->oprmode < 0) 05232 { 05233 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05234 { 05235 /* Make sure it stops ringing */ 05236 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05237 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 05238 restore_conference(p->oprpeer); 05239 } 05240 break; 05241 } 05242 if (p->radio) 05243 { 05244 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05245 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05246 break; 05247 } 05248 /* for E911, its supposed to wait for offhook then dial 05249 the second half of the dial string */ 05250 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05251 c = strchr(p->dialdest, '/'); 05252 if (c) 05253 c++; 05254 else 05255 c = p->dialdest; 05256 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05257 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05258 if (strlen(p->dop.dialstr) > 4) { 05259 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05260 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05261 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05262 p->echobreak = 1; 05263 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05264 } else 05265 p->echobreak = 0; 05266 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05267 int saveerr = errno; 05268 05269 x = DAHDI_ONHOOK; 05270 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05271 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05272 return NULL; 05273 } 05274 p->dialing = 1; 05275 return &p->subs[index].f; 05276 } 05277 switch (p->sig) { 05278 case SIG_FXOLS: 05279 case SIG_FXOGS: 05280 case SIG_FXOKS: 05281 switch (ast->_state) { 05282 case AST_STATE_RINGING: 05283 dahdi_enable_ec(p); 05284 dahdi_train_ec(p); 05285 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05286 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05287 /* Make sure it stops ringing */ 05288 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05289 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 05290 if (p->cidspill) { 05291 /* Cancel any running CallerID spill */ 05292 free(p->cidspill); 05293 p->cidspill = NULL; 05294 } 05295 p->dialing = 0; 05296 p->callwaitcas = 0; 05297 if (p->confirmanswer) { 05298 /* Ignore answer if "confirm answer" is enabled */ 05299 p->subs[index].f.frametype = AST_FRAME_NULL; 05300 p->subs[index].f.subclass = 0; 05301 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05302 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05303 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05304 if (res < 0) { 05305 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05306 p->dop.dialstr[0] = '\0'; 05307 return NULL; 05308 } else { 05309 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05310 p->subs[index].f.frametype = AST_FRAME_NULL; 05311 p->subs[index].f.subclass = 0; 05312 p->dialing = 1; 05313 } 05314 p->dop.dialstr[0] = '\0'; 05315 ast_setstate(ast, AST_STATE_DIALING); 05316 } else 05317 ast_setstate(ast, AST_STATE_UP); 05318 return &p->subs[index].f; 05319 case AST_STATE_DOWN: 05320 ast_setstate(ast, AST_STATE_RING); 05321 ast->rings = 1; 05322 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05323 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05324 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 05325 return &p->subs[index].f; 05326 case AST_STATE_UP: 05327 /* Make sure it stops ringing */ 05328 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05329 /* Okay -- probably call waiting*/ 05330 if (ast_bridged_channel(p->owner)) 05331 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05332 p->subs[index].needunhold = 1; 05333 break; 05334 case AST_STATE_RESERVED: 05335 /* Start up dialtone */ 05336 if (has_voicemail(p)) 05337 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05338 else 05339 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05340 break; 05341 default: 05342 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05343 } 05344 break; 05345 case SIG_FXSLS: 05346 case SIG_FXSGS: 05347 case SIG_FXSKS: 05348 if (ast->_state == AST_STATE_RING) { 05349 p->ringt = p->ringt_base; 05350 } 05351 05352 /* Fall through */ 05353 case SIG_EM: 05354 case SIG_EM_E1: 05355 case SIG_EMWINK: 05356 case SIG_FEATD: 05357 case SIG_FEATDMF: 05358 case SIG_FEATDMF_TA: 05359 case SIG_E911: 05360 case SIG_FGC_CAMA: 05361 case SIG_FGC_CAMAMF: 05362 case SIG_FEATB: 05363 case SIG_SF: 05364 case SIG_SFWINK: 05365 case SIG_SF_FEATD: 05366 case SIG_SF_FEATDMF: 05367 case SIG_SF_FEATB: 05368 if (ast->_state == AST_STATE_PRERING) 05369 ast_setstate(ast, AST_STATE_RING); 05370 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05371 if (option_debug) 05372 ast_log(LOG_DEBUG, "Ring detected\n"); 05373 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05374 p->subs[index].f.subclass = AST_CONTROL_RING; 05375 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05376 if (option_debug) 05377 ast_log(LOG_DEBUG, "Line answered\n"); 05378 if (p->confirmanswer) { 05379 p->subs[index].f.frametype = AST_FRAME_NULL; 05380 p->subs[index].f.subclass = 0; 05381 } else { 05382 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05383 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05384 ast_setstate(ast, AST_STATE_UP); 05385 } 05386 } else if (ast->_state != AST_STATE_RING) 05387 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05388 break; 05389 default: 05390 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05391 } 05392 break; 05393 #ifdef DAHDI_EVENT_RINGBEGIN 05394 case DAHDI_EVENT_RINGBEGIN: 05395 switch (p->sig) { 05396 case SIG_FXSLS: 05397 case SIG_FXSGS: 05398 case SIG_FXSKS: 05399 if (ast->_state == AST_STATE_RING) { 05400 p->ringt = p->ringt_base; 05401 } 05402 break; 05403 } 05404 break; 05405 #endif 05406 case DAHDI_EVENT_RINGEROFF: 05407 if (p->inalarm) break; 05408 if ((p->radio || (p->oprmode < 0))) break; 05409 ast->rings++; 05410 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05411 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05412 free(p->cidspill); 05413 p->cidspill = NULL; 05414 p->callwaitcas = 0; 05415 } 05416 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05417 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05418 break; 05419 case DAHDI_EVENT_RINGERON: 05420 break; 05421 case DAHDI_EVENT_NOALARM: 05422 p->inalarm = 0; 05423 #ifdef HAVE_PRI 05424 /* Extremely unlikely but just in case */ 05425 if (p->bearer) 05426 p->bearer->inalarm = 0; 05427 #endif 05428 if (!p->unknown_alarm) { 05429 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05430 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05431 "Channel: %d\r\n", p->channel); 05432 } else { 05433 p->unknown_alarm = 0; 05434 } 05435 break; 05436 case DAHDI_EVENT_WINKFLASH: 05437 if (p->inalarm) break; 05438 if (p->radio) break; 05439 if (p->oprmode < 0) break; 05440 if (p->oprmode > 1) 05441 { 05442 struct dahdi_params par; 05443 05444 memset(&par, 0, sizeof(par)); 05445 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05446 { 05447 if (!par.rxisoffhook) 05448 { 05449 /* Make sure it stops ringing */ 05450 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05451 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05452 save_conference(p); 05453 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05454 } 05455 } 05456 break; 05457 } 05458 /* Remember last time we got a flash-hook */ 05459 gettimeofday(&p->flashtime, NULL); 05460 switch (mysig) { 05461 case SIG_FXOLS: 05462 case SIG_FXOGS: 05463 case SIG_FXOKS: 05464 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05465 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05466 p->callwaitcas = 0; 05467 05468 if (index != SUB_REAL) { 05469 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05470 goto winkflashdone; 05471 } 05472 05473 if (p->subs[SUB_CALLWAIT].owner) { 05474 /* Swap to call-wait */ 05475 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05476 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05477 p->owner = p->subs[SUB_REAL].owner; 05478 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 05479 if (p->owner->_state == AST_STATE_RINGING) { 05480 ast_setstate(p->owner, AST_STATE_UP); 05481 p->subs[SUB_REAL].needanswer = 1; 05482 } 05483 p->callwaitingrepeat = 0; 05484 p->cidcwexpire = 0; 05485 /* Start music on hold if appropriate */ 05486 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05487 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05488 S_OR(p->mohsuggest, NULL), 05489 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05490 } 05491 p->subs[SUB_CALLWAIT].needhold = 1; 05492 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05493 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05494 S_OR(p->mohsuggest, NULL), 05495 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05496 } 05497 p->subs[SUB_REAL].needunhold = 1; 05498 } else if (!p->subs[SUB_THREEWAY].owner) { 05499 if (!p->threewaycalling) { 05500 /* Just send a flash if no 3-way calling */ 05501 p->subs[SUB_REAL].needflash = 1; 05502 goto winkflashdone; 05503 } else if (!check_for_conference(p)) { 05504 char cid_num[256]; 05505 char cid_name[256]; 05506 05507 cid_num[0] = 0; 05508 cid_name[0] = 0; 05509 if (p->dahditrcallerid && p->owner) { 05510 if (p->owner->cid.cid_num) 05511 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05512 if (p->owner->cid.cid_name) 05513 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05514 } 05515 /* XXX This section needs much more error checking!!! XXX */ 05516 /* Start a 3-way call if feasible */ 05517 if (!((ast->pbx) || 05518 (ast->_state == AST_STATE_UP) || 05519 (ast->_state == AST_STATE_RING))) { 05520 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 05521 goto winkflashdone; 05522 } 05523 if (alloc_sub(p, SUB_THREEWAY)) { 05524 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05525 goto winkflashdone; 05526 } 05527 /* Make new channel */ 05528 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05529 if (p->dahditrcallerid) { 05530 if (!p->origcid_num) 05531 p->origcid_num = ast_strdup(p->cid_num); 05532 if (!p->origcid_name) 05533 p->origcid_name = ast_strdup(p->cid_name); 05534 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05535 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05536 } 05537 /* Swap things around between the three-way and real call */ 05538 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05539 /* Disable echo canceller for better dialing */ 05540 dahdi_disable_ec(p); 05541 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05542 if (res) 05543 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05544 p->owner = chan; 05545 pthread_attr_init(&attr); 05546 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05547 if (!chan) { 05548 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05549 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 05550 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05551 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05552 dahdi_enable_ec(p); 05553 ast_hangup(chan); 05554 } else { 05555 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05556 int way3bridge = 0, cdr3way = 0; 05557 05558 if (!other) { 05559 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05560 } else 05561 way3bridge = 1; 05562 05563 if (p->subs[SUB_THREEWAY].owner->cdr) 05564 cdr3way = 1; 05565 05566 if (option_verbose > 2) 05567 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 05568 /* Start music on hold if appropriate */ 05569 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05570 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05571 S_OR(p->mohsuggest, NULL), 05572 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05573 } 05574 p->subs[SUB_THREEWAY].needhold = 1; 05575 } 05576 pthread_attr_destroy(&attr); 05577 } 05578 } else { 05579 /* Already have a 3 way call */ 05580 if (p->subs[SUB_THREEWAY].inthreeway) { 05581 /* Call is already up, drop the last person */ 05582 if (option_debug) 05583 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05584 /* If the primary call isn't answered yet, use it */ 05585 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05586 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05587 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05588 p->owner = p->subs[SUB_REAL].owner; 05589 } 05590 /* Drop the last call and stop the conference */ 05591 if (option_verbose > 2) 05592 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05593 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05594 p->subs[SUB_REAL].inthreeway = 0; 05595 p->subs[SUB_THREEWAY].inthreeway = 0; 05596 } else { 05597 /* Lets see what we're up to */ 05598 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05599 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05600 int otherindex = SUB_THREEWAY; 05601 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05602 int way3bridge = 0, cdr3way = 0; 05603 05604 if (!other) { 05605 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05606 } else 05607 way3bridge = 1; 05608 05609 if (p->subs[SUB_THREEWAY].owner->cdr) 05610 cdr3way = 1; 05611 05612 if (option_verbose > 2) 05613 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); 05614 /* Put them in the threeway, and flip */ 05615 p->subs[SUB_THREEWAY].inthreeway = 1; 05616 p->subs[SUB_REAL].inthreeway = 1; 05617 if (ast->_state == AST_STATE_UP) { 05618 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05619 otherindex = SUB_REAL; 05620 } 05621 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05622 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05623 p->subs[otherindex].needunhold = 1; 05624 p->owner = p->subs[SUB_REAL].owner; 05625 if (ast->_state == AST_STATE_RINGING) { 05626 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 05627 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05628 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05629 } 05630 } else { 05631 if (option_verbose > 2) 05632 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05633 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05634 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05635 p->owner = p->subs[SUB_REAL].owner; 05636 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05637 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05638 p->subs[SUB_REAL].needunhold = 1; 05639 dahdi_enable_ec(p); 05640 } 05641 05642 } 05643 } 05644 winkflashdone: 05645 update_conf(p); 05646 break; 05647 case SIG_EM: 05648 case SIG_EM_E1: 05649 case SIG_FEATD: 05650 case SIG_SF: 05651 case SIG_SFWINK: 05652 case SIG_SF_FEATD: 05653 case SIG_FXSLS: 05654 case SIG_FXSGS: 05655 if (p->dialing) 05656 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 05657 else 05658 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05659 break; 05660 case SIG_FEATDMF_TA: 05661 switch (p->whichwink) { 05662 case 0: 05663 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05664 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05665 break; 05666 case 1: 05667 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05668 break; 05669 case 2: 05670 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05671 return NULL; 05672 } 05673 p->whichwink++; 05674 /* Fall through */ 05675 case SIG_FEATDMF: 05676 case SIG_E911: 05677 case SIG_FGC_CAMAMF: 05678 case SIG_FGC_CAMA: 05679 case SIG_FEATB: 05680 case SIG_SF_FEATDMF: 05681 case SIG_SF_FEATB: 05682 case SIG_EMWINK: 05683 /* FGD MF and EMWINK *Must* wait for wink */ 05684 if (!ast_strlen_zero(p->dop.dialstr)) { 05685 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05686 if (res < 0) { 05687 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05688 p->dop.dialstr[0] = '\0'; 05689 return NULL; 05690 } else 05691 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05692 } 05693 p->dop.dialstr[0] = '\0'; 05694 break; 05695 default: 05696 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05697 } 05698 break; 05699 case DAHDI_EVENT_HOOKCOMPLETE: 05700 if (p->inalarm) break; 05701 if ((p->radio || (p->oprmode < 0))) break; 05702 switch (mysig) { 05703 case SIG_FXSLS: /* only interesting for FXS */ 05704 case SIG_FXSGS: 05705 case SIG_FXSKS: 05706 case SIG_EM: 05707 case SIG_EM_E1: 05708 case SIG_EMWINK: 05709 case SIG_FEATD: 05710 case SIG_SF: 05711 case SIG_SFWINK: 05712 case SIG_SF_FEATD: 05713 if (!ast_strlen_zero(p->dop.dialstr)) { 05714 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05715 if (res < 0) { 05716 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05717 p->dop.dialstr[0] = '\0'; 05718 return NULL; 05719 } else 05720 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05721 } 05722 p->dop.dialstr[0] = '\0'; 05723 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05724 break; 05725 case SIG_FEATDMF: 05726 case SIG_FEATDMF_TA: 05727 case SIG_E911: 05728 case SIG_FGC_CAMA: 05729 case SIG_FGC_CAMAMF: 05730 case SIG_FEATB: 05731 case SIG_SF_FEATDMF: 05732 case SIG_SF_FEATB: 05733 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05734 break; 05735 default: 05736 break; 05737 } 05738 break; 05739 case DAHDI_EVENT_POLARITY: 05740 /* 05741 * If we get a Polarity Switch event, check to see 05742 * if we should change the polarity state and 05743 * mark the channel as UP or if this is an indication 05744 * of remote end disconnect. 05745 */ 05746 if (p->polarity == POLARITY_IDLE) { 05747 p->polarity = POLARITY_REV; 05748 if (p->answeronpolarityswitch && 05749 ((ast->_state == AST_STATE_DIALING) || 05750 (ast->_state == AST_STATE_RINGING))) { 05751 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 05752 ast_setstate(p->owner, AST_STATE_UP); 05753 if (p->hanguponpolarityswitch) { 05754 gettimeofday(&p->polaritydelaytv, NULL); 05755 } 05756 } else 05757 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05758 } 05759 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05760 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05761 if (p->hanguponpolarityswitch && 05762 (p->polarityonanswerdelay > 0) && 05763 (p->polarity == POLARITY_REV) && 05764 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05765 /* Added log_debug information below to provide a better indication of what is going on */ 05766 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) ); 05767 05768 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05769 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05770 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05771 p->polarity = POLARITY_IDLE; 05772 } else { 05773 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); 05774 } 05775 } else { 05776 p->polarity = POLARITY_IDLE; 05777 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05778 } 05779 /* Added more log_debug information below to provide a better indication of what is going on */ 05780 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) ); 05781 break; 05782 default: 05783 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05784 } 05785 return &p->subs[index].f; 05786 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3587 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().
03588 { 03589 int res; 03590 int index,x, law; 03591 /*static int restore_gains(struct dahdi_pvt *p);*/ 03592 struct dahdi_pvt *p = ast->tech_pvt; 03593 struct dahdi_pvt *tmp = NULL; 03594 struct dahdi_pvt *prev = NULL; 03595 struct dahdi_params par; 03596 03597 if (option_debug) 03598 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 03599 if (!ast->tech_pvt) { 03600 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03601 return 0; 03602 } 03603 03604 ast_mutex_lock(&p->lock); 03605 03606 index = dahdi_get_index(ast, p, 1); 03607 03608 if (p->sig == SIG_PRI) { 03609 x = 1; 03610 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03611 p->cid_num[0] = '\0'; 03612 p->cid_name[0] = '\0'; 03613 } 03614 03615 x = 0; 03616 dahdi_confmute(p, 0); 03617 restore_gains(p); 03618 if (p->origcid_num) { 03619 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03620 free(p->origcid_num); 03621 p->origcid_num = NULL; 03622 } 03623 if (p->origcid_name) { 03624 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03625 free(p->origcid_name); 03626 p->origcid_name = NULL; 03627 } 03628 if (p->dsp) 03629 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 03630 p->exten[0] = '\0'; 03631 03632 if (option_debug) 03633 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03634 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03635 p->ignoredtmf = 0; 03636 03637 if (index > -1) { 03638 /* Real channel, do some fixup */ 03639 p->subs[index].owner = NULL; 03640 p->subs[index].needanswer = 0; 03641 p->subs[index].needflash = 0; 03642 p->subs[index].needringing = 0; 03643 p->subs[index].needbusy = 0; 03644 p->subs[index].needcongestion = 0; 03645 p->subs[index].linear = 0; 03646 p->subs[index].needcallerid = 0; 03647 p->polarity = POLARITY_IDLE; 03648 dahdi_setlinear(p->subs[index].dfd, 0); 03649 if (index == SUB_REAL) { 03650 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03651 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03652 if (p->subs[SUB_CALLWAIT].inthreeway) { 03653 /* We had flipped over to answer a callwait and now it's gone */ 03654 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 03655 /* Move to the call-wait, but un-own us until they flip back. */ 03656 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03657 unalloc_sub(p, SUB_CALLWAIT); 03658 p->owner = NULL; 03659 } else { 03660 /* The three way hung up, but we still have a call wait */ 03661 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03662 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03663 unalloc_sub(p, SUB_THREEWAY); 03664 if (p->subs[SUB_REAL].inthreeway) { 03665 /* This was part of a three way call. Immediately make way for 03666 another call */ 03667 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03668 p->owner = p->subs[SUB_REAL].owner; 03669 } else { 03670 /* This call hasn't been completed yet... Set owner to NULL */ 03671 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03672 p->owner = NULL; 03673 } 03674 p->subs[SUB_REAL].inthreeway = 0; 03675 } 03676 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03677 /* Move to the call-wait and switch back to them. */ 03678 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03679 unalloc_sub(p, SUB_CALLWAIT); 03680 p->owner = p->subs[SUB_REAL].owner; 03681 if (p->owner->_state != AST_STATE_UP) 03682 p->subs[SUB_REAL].needanswer = 1; 03683 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03684 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03685 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03686 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03687 unalloc_sub(p, SUB_THREEWAY); 03688 if (p->subs[SUB_REAL].inthreeway) { 03689 /* This was part of a three way call. Immediately make way for 03690 another call */ 03691 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03692 p->owner = p->subs[SUB_REAL].owner; 03693 } else { 03694 /* This call hasn't been completed yet... Set owner to NULL */ 03695 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03696 p->owner = NULL; 03697 } 03698 p->subs[SUB_REAL].inthreeway = 0; 03699 } 03700 } else if (index == SUB_CALLWAIT) { 03701 /* Ditch the holding callwait call, and immediately make it availabe */ 03702 if (p->subs[SUB_CALLWAIT].inthreeway) { 03703 /* This is actually part of a three way, placed on hold. Place the third part 03704 on music on hold now */ 03705 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03706 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03707 S_OR(p->mohsuggest, NULL), 03708 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03709 } 03710 p->subs[SUB_THREEWAY].inthreeway = 0; 03711 /* Make it the call wait now */ 03712 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03713 unalloc_sub(p, SUB_THREEWAY); 03714 } else 03715 unalloc_sub(p, SUB_CALLWAIT); 03716 } else if (index == SUB_THREEWAY) { 03717 if (p->subs[SUB_CALLWAIT].inthreeway) { 03718 /* The other party of the three way call is currently in a call-wait state. 03719 Start music on hold for them, and take the main guy out of the third call */ 03720 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03721 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03722 S_OR(p->mohsuggest, NULL), 03723 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03724 } 03725 p->subs[SUB_CALLWAIT].inthreeway = 0; 03726 } 03727 p->subs[SUB_REAL].inthreeway = 0; 03728 /* If this was part of a three way call index, let us make 03729 another three way call */ 03730 unalloc_sub(p, SUB_THREEWAY); 03731 } else { 03732 /* This wasn't any sort of call, but how are we an index? */ 03733 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03734 } 03735 } 03736 03737 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03738 p->owner = NULL; 03739 p->ringt = 0; 03740 p->distinctivering = 0; 03741 p->confirmanswer = 0; 03742 p->cidrings = 1; 03743 p->outgoing = 0; 03744 p->digital = 0; 03745 p->faxhandled = 0; 03746 p->pulsedial = 0; 03747 p->onhooktime = time(NULL); 03748 #ifdef HAVE_PRI 03749 p->proceeding = 0; 03750 p->dialing = 0; 03751 p->progress = 0; 03752 p->alerting = 0; 03753 p->setup_ack = 0; 03754 #endif 03755 if (p->dsp) { 03756 ast_dsp_free(p->dsp); 03757 p->dsp = NULL; 03758 } 03759 03760 law = DAHDI_LAW_DEFAULT; 03761 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03762 if (res < 0) 03763 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03764 /* Perform low level hangup if no owner left */ 03765 #ifdef HAVE_OPENR2 03766 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 03767 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 03768 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause); 03769 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 03770 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 03771 } else { 03772 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE"); 03773 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 03774 openr2_call_disconnect_cause_t r2cause = r2cause_user 03775 ? dahdi_ast_cause_to_r2_cause(r2cause_user) 03776 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 03777 dahdi_r2_disconnect_call(p, r2cause); 03778 } 03779 } else if (p->mfcr2call) { 03780 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 03781 p->mfcr2call = 0; 03782 } 03783 #endif 03784 #ifdef HAVE_PRI 03785 if (p->pri) { 03786 #ifdef SUPPORT_USERUSER 03787 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03788 #endif 03789 03790 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03791 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03792 if (!pri_grab(p, p->pri)) { 03793 if (p->alreadyhungup) { 03794 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03795 03796 #ifdef SUPPORT_USERUSER 03797 pri_call_set_useruser(p->call, useruser); 03798 #endif 03799 03800 pri_hangup(p->pri->pri, p->call, -1); 03801 p->call = NULL; 03802 if (p->bearer) 03803 p->bearer->call = NULL; 03804 } else { 03805 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03806 int icause = ast->hangupcause ? ast->hangupcause : -1; 03807 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03808 03809 #ifdef SUPPORT_USERUSER 03810 pri_call_set_useruser(p->call, useruser); 03811 #endif 03812 03813 p->alreadyhungup = 1; 03814 if (p->bearer) 03815 p->bearer->alreadyhungup = 1; 03816 if (cause) { 03817 if (atoi(cause)) 03818 icause = atoi(cause); 03819 } 03820 pri_hangup(p->pri->pri, p->call, icause); 03821 } 03822 if (res < 0) 03823 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03824 pri_rel(p->pri); 03825 } else { 03826 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03827 res = -1; 03828 } 03829 } else { 03830 if (p->bearer) 03831 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03832 p->call = NULL; 03833 res = 0; 03834 } 03835 } 03836 #endif 03837 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2)) 03838 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03839 if (res < 0) { 03840 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03841 } 03842 switch (p->sig) { 03843 case SIG_FXOGS: 03844 case SIG_FXOLS: 03845 case SIG_FXOKS: 03846 memset(&par, 0, sizeof(par)); 03847 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03848 if (!res) { 03849 #if 0 03850 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03851 #endif 03852 /* If they're off hook, try playing congestion */ 03853 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03854 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03855 else 03856 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03857 } 03858 break; 03859 case SIG_FXSGS: 03860 case SIG_FXSLS: 03861 case SIG_FXSKS: 03862 /* Make sure we're not made available for at least two seconds assuming 03863 we were actually used for an inbound or outbound call. */ 03864 if (ast->_state != AST_STATE_RESERVED) { 03865 time(&p->guardtime); 03866 p->guardtime += 2; 03867 } 03868 break; 03869 default: 03870 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03871 } 03872 if (p->cidspill) 03873 free(p->cidspill); 03874 if (p->sig) 03875 dahdi_disable_ec(p); 03876 x = 0; 03877 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03878 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03879 p->didtdd = 0; 03880 p->cidspill = NULL; 03881 p->callwaitcas = 0; 03882 p->callwaiting = p->permcallwaiting; 03883 p->hidecallerid = p->permhidecallerid; 03884 p->dialing = 0; 03885 p->rdnis[0] = '\0'; 03886 update_conf(p); 03887 reset_conf(p); 03888 /* Restore data mode */ 03889 if (p->sig == SIG_PRI) { 03890 x = 0; 03891 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03892 } 03893 #ifdef HAVE_PRI 03894 if (p->bearer) { 03895 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03896 /* Free up the bearer channel as well, and 03897 don't use its file descriptor anymore */ 03898 update_conf(p->bearer); 03899 reset_conf(p->bearer); 03900 p->bearer->owner = NULL; 03901 p->bearer->realcall = NULL; 03902 p->bearer = NULL; 03903 p->subs[SUB_REAL].dfd = -1; 03904 p->pri = NULL; 03905 } 03906 #endif 03907 if (num_restart_pending == 0) 03908 restart_monitor(); 03909 } 03910 03911 p->callwaitingrepeat = 0; 03912 p->cidcwexpire = 0; 03913 p->oprmode = 0; 03914 ast->tech_pvt = NULL; 03915 ast_mutex_unlock(&p->lock); 03916 ast_module_unref(ast_module_info->self); 03917 if (option_verbose > 2) 03918 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03919 03920 ast_mutex_lock(&iflock); 03921 03922 if (p->restartpending) { 03923 num_restart_pending--; 03924 } 03925 03926 tmp = iflist; 03927 prev = NULL; 03928 if (p->destroy) { 03929 while (tmp) { 03930 if (tmp == p) { 03931 destroy_channel(prev, tmp, 0); 03932 break; 03933 } else { 03934 prev = tmp; 03935 tmp = tmp->next; 03936 } 03937 } 03938 } 03939 ast_mutex_unlock(&iflock); 03940 return 0; 03941 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6332 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.
06333 { 06334 struct dahdi_pvt *p = chan->tech_pvt; 06335 int res=-1; 06336 int index; 06337 int func = DAHDI_FLASH; 06338 ast_mutex_lock(&p->lock); 06339 index = dahdi_get_index(chan, p, 0); 06340 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 06341 #ifdef HAVE_OPENR2 06342 if (p->mfcr2 && !p->mfcr2_call_accepted) { 06343 ast_mutex_unlock(&p->lock); 06344 /* if this an R2 call and the call is not yet accepted we don't want the 06345 tone indications to mess up with the MF tones */ 06346 return 0; 06347 } 06348 #endif 06349 if (index == SUB_REAL) { 06350 switch (condition) { 06351 case AST_CONTROL_BUSY: 06352 #ifdef HAVE_PRI 06353 if (p->priindication_oob && p->sig == SIG_PRI) { 06354 chan->hangupcause = AST_CAUSE_USER_BUSY; 06355 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06356 res = 0; 06357 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06358 if (p->pri->pri) { 06359 if (!pri_grab(p, p->pri)) { 06360 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06361 pri_rel(p->pri); 06362 } 06363 else 06364 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06365 } 06366 p->progress = 1; 06367 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06368 } else 06369 #endif 06370 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06371 break; 06372 case AST_CONTROL_RINGING: 06373 #ifdef HAVE_PRI 06374 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06375 if (p->pri->pri) { 06376 if (!pri_grab(p, p->pri)) { 06377 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06378 pri_rel(p->pri); 06379 } 06380 else 06381 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06382 } 06383 p->alerting = 1; 06384 } 06385 #endif 06386 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06387 if (chan->_state != AST_STATE_UP) { 06388 if ((chan->_state != AST_STATE_RING) || 06389 ((p->sig != SIG_FXSKS) && 06390 (p->sig != SIG_FXSLS) && 06391 (p->sig != SIG_FXSGS))) 06392 ast_setstate(chan, AST_STATE_RINGING); 06393 } 06394 break; 06395 case AST_CONTROL_PROCEEDING: 06396 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06397 #ifdef HAVE_PRI 06398 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06399 if (p->pri->pri) { 06400 if (!pri_grab(p, p->pri)) { 06401 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06402 pri_rel(p->pri); 06403 } 06404 else 06405 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06406 } 06407 p->proceeding = 1; 06408 p->dialing = 0; 06409 } 06410 #endif 06411 /* don't continue in ast_indicate */ 06412 res = 0; 06413 break; 06414 case AST_CONTROL_PROGRESS: 06415 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06416 #ifdef HAVE_PRI 06417 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06418 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06419 if (p->pri->pri) { 06420 if (!pri_grab(p, p->pri)) { 06421 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06422 pri_rel(p->pri); 06423 } 06424 else 06425 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06426 } 06427 p->progress = 1; 06428 } 06429 #endif 06430 /* don't continue in ast_indicate */ 06431 res = 0; 06432 break; 06433 case AST_CONTROL_CONGESTION: 06434 chan->hangupcause = AST_CAUSE_CONGESTION; 06435 #ifdef HAVE_PRI 06436 if (p->priindication_oob && p->sig == SIG_PRI) { 06437 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06438 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06439 res = 0; 06440 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06441 if (p->pri) { 06442 if (!pri_grab(p, p->pri)) { 06443 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06444 pri_rel(p->pri); 06445 } else 06446 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06447 } 06448 p->progress = 1; 06449 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06450 } else 06451 #endif 06452 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06453 break; 06454 case AST_CONTROL_HOLD: 06455 #ifdef HAVE_PRI 06456 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06457 if (!pri_grab(p, p->pri)) { 06458 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06459 pri_rel(p->pri); 06460 } else 06461 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06462 } else 06463 #endif 06464 ast_moh_start(chan, data, p->mohinterpret); 06465 break; 06466 case AST_CONTROL_UNHOLD: 06467 #ifdef HAVE_PRI 06468 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06469 if (!pri_grab(p, p->pri)) { 06470 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06471 pri_rel(p->pri); 06472 } else 06473 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06474 } else 06475 #endif 06476 ast_moh_stop(chan); 06477 break; 06478 case AST_CONTROL_RADIO_KEY: 06479 if (p->radio) 06480 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06481 res = 0; 06482 break; 06483 case AST_CONTROL_RADIO_UNKEY: 06484 if (p->radio) 06485 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06486 res = 0; 06487 break; 06488 case AST_CONTROL_FLASH: 06489 /* flash hookswitch */ 06490 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06491 /* Clear out the dial buffer */ 06492 p->dop.dialstr[0] = '\0'; 06493 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06494 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06495 chan->name, strerror(errno)); 06496 } else 06497 res = 0; 06498 } else 06499 res = 0; 06500 break; 06501 case AST_CONTROL_SRCUPDATE: 06502 res = 0; 06503 break; 06504 case -1: 06505 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06506 break; 06507 } 06508 } else 06509 res = 0; 06510 ast_mutex_unlock(&p->lock); 06511 return res; 06512 }
Definition at line 4308 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04308 { 04309 int x; 04310 if (!slave || !master) { 04311 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04312 return; 04313 } 04314 for (x = 0; x < MAX_SLAVES; x++) { 04315 if (!master->slaves[x]) { 04316 master->slaves[x] = slave; 04317 break; 04318 } 04319 } 04320 if (x >= MAX_SLAVES) { 04321 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04322 master->slaves[MAX_SLAVES - 1] = slave; 04323 } 04324 if (slave->master) 04325 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04326 slave->master = master; 04327 04328 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04329 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | index, | |||
int | law, | |||
int | transfercapability | |||
) | [static] |
Definition at line 6514 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().
06515 { 06516 struct ast_channel *tmp; 06517 int deflaw; 06518 int res; 06519 int x,y; 06520 int features; 06521 char *b2 = NULL; 06522 struct dahdi_params ps; 06523 char chanprefix[*dahdi_chan_name_len + 4]; 06524 06525 if (i->subs[index].owner) { 06526 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 06527 return NULL; 06528 } 06529 y = 1; 06530 do { 06531 if (b2) 06532 free(b2); 06533 #ifdef HAVE_PRI 06534 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06535 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06536 else 06537 #endif 06538 if (i->channel == CHAN_PSEUDO) 06539 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 06540 else 06541 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 06542 for (x = 0; x < 3; x++) { 06543 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 06544 break; 06545 } 06546 y++; 06547 } while (x < 3); 06548 strcpy(chanprefix, dahdi_chan_name); 06549 strcat(chanprefix, "/%s"); 06550 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 06551 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 06552 free(b2); 06553 if (!tmp) 06554 return NULL; 06555 tmp->tech = chan_tech; 06556 memset(&ps, 0, sizeof(ps)); 06557 ps.channo = i->channel; 06558 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06559 if (res) { 06560 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06561 ps.curlaw = DAHDI_LAW_MULAW; 06562 } 06563 if (ps.curlaw == DAHDI_LAW_ALAW) 06564 deflaw = AST_FORMAT_ALAW; 06565 else 06566 deflaw = AST_FORMAT_ULAW; 06567 if (law) { 06568 if (law == DAHDI_LAW_ALAW) 06569 deflaw = AST_FORMAT_ALAW; 06570 else 06571 deflaw = AST_FORMAT_ULAW; 06572 } 06573 tmp->fds[0] = i->subs[index].dfd; 06574 tmp->nativeformats = deflaw; 06575 /* Start out assuming ulaw since it's smaller :) */ 06576 tmp->rawreadformat = deflaw; 06577 tmp->readformat = deflaw; 06578 tmp->rawwriteformat = deflaw; 06579 tmp->writeformat = deflaw; 06580 i->subs[index].linear = 0; 06581 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 06582 features = 0; 06583 if (index == SUB_REAL) { 06584 if (i->busydetect && CANBUSYDETECT(i)) 06585 features |= DSP_FEATURE_BUSY_DETECT; 06586 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 06587 features |= DSP_FEATURE_CALL_PROGRESS; 06588 if ((!i->outgoing && (i->callprogress & 4)) || 06589 (i->outgoing && (i->callprogress & 2))) { 06590 features |= DSP_FEATURE_FAX_DETECT; 06591 } 06592 #ifdef DAHDI_TONEDETECT 06593 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06594 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 06595 #endif 06596 i->hardwaredtmf = 0; 06597 features |= DSP_FEATURE_DTMF_DETECT; 06598 #ifdef DAHDI_TONEDETECT 06599 } else if (NEED_MFDETECT(i)) { 06600 i->hardwaredtmf = 1; 06601 features |= DSP_FEATURE_DTMF_DETECT; 06602 } 06603 #endif 06604 } 06605 if (features) { 06606 if (i->dsp) { 06607 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 06608 } else { 06609 if (i->channel != CHAN_PSEUDO) 06610 i->dsp = ast_dsp_new(); 06611 else 06612 i->dsp = NULL; 06613 if (i->dsp) { 06614 i->dsp_features = features; 06615 #ifdef HAVE_PRI 06616 /* We cannot do progress detection until receives PROGRESS message */ 06617 if (i->outgoing && (i->sig == SIG_PRI)) { 06618 /* Remember requested DSP features, don't treat 06619 talking as ANSWER */ 06620 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06621 features = 0; 06622 } 06623 #endif 06624 ast_dsp_set_features(i->dsp, features); 06625 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06626 if (!ast_strlen_zero(progzone)) 06627 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06628 if (i->busydetect && CANBUSYDETECT(i)) { 06629 if(i->silencethreshold > 0) 06630 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06631 ast_dsp_set_busy_count(i->dsp, i->busycount); 06632 if(i->busytonelength > 0) 06633 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06634 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06635 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06636 } 06637 } 06638 } 06639 } 06640 06641 if (state == AST_STATE_RING) 06642 tmp->rings = 1; 06643 tmp->tech_pvt = i; 06644 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06645 /* Only FXO signalled stuff can be picked up */ 06646 tmp->callgroup = i->callgroup; 06647 tmp->pickupgroup = i->pickupgroup; 06648 } 06649 if (!ast_strlen_zero(i->language)) 06650 ast_string_field_set(tmp, language, i->language); 06651 if (!i->owner) 06652 i->owner = tmp; 06653 if (!ast_strlen_zero(i->accountcode)) 06654 ast_string_field_set(tmp, accountcode, i->accountcode); 06655 if (i->amaflags) 06656 tmp->amaflags = i->amaflags; 06657 i->subs[index].owner = tmp; 06658 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06659 ast_string_field_set(tmp, call_forward, i->call_forward); 06660 /* If we've been told "no ADSI" then enforce it */ 06661 if (!i->adsi) 06662 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06663 if (!ast_strlen_zero(i->exten)) 06664 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06665 if (!ast_strlen_zero(i->rdnis)) 06666 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06667 if (!ast_strlen_zero(i->dnid)) 06668 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06669 06670 /* Don't use ast_set_callerid() here because it will 06671 * generate a needless NewCallerID event */ 06672 #ifdef PRI_ANI 06673 if (!ast_strlen_zero(i->cid_ani)) 06674 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06675 else 06676 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06677 #else 06678 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06679 #endif 06680 tmp->cid.cid_pres = i->callingpres; 06681 tmp->cid.cid_ton = i->cid_ton; 06682 #ifdef HAVE_PRI 06683 tmp->transfercapability = transfercapability; 06684 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06685 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 06686 i->digital = 1; 06687 /* Assume calls are not idle calls unless we're told differently */ 06688 i->isidlecall = 0; 06689 i->alreadyhungup = 0; 06690 #endif 06691 /* clear the fake event in case we posted one before we had ast_channel */ 06692 i->fake_event = 0; 06693 /* Assure there is no confmute on this channel */ 06694 dahdi_confmute(i, 0); 06695 /* Configure the new channel jb */ 06696 ast_jb_configure(tmp, &global_jbconf); 06697 if (startpbx) { 06698 #ifdef HAVE_OPENR2 06699 if (i->mfcr2call) { 06700 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 06701 } 06702 #endif 06703 if (ast_pbx_start(tmp)) { 06704 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06705 ast_hangup(tmp); 06706 i->owner = NULL; 06707 return NULL; 06708 } 06709 } 06710 06711 ast_module_ref(ast_module_info->self); 06712 06713 return tmp; 06714 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1797 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01798 { 01799 int fd; 01800 int isnum; 01801 int chan = 0; 01802 int bs; 01803 int x; 01804 isnum = 1; 01805 for (x = 0; x < strlen(fn); x++) { 01806 if (!isdigit(fn[x])) { 01807 isnum = 0; 01808 break; 01809 } 01810 } 01811 if (isnum) { 01812 chan = atoi(fn); 01813 if (chan < 1) { 01814 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01815 return -1; 01816 } 01817 fn = DAHDI_FILE_CHANNEL; 01818 } 01819 fd = open(fn, O_RDWR | O_NONBLOCK); 01820 if (fd < 0) { 01821 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01822 return -1; 01823 } 01824 if (chan) { 01825 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01826 x = errno; 01827 close(fd); 01828 errno = x; 01829 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01830 return -1; 01831 } 01832 } 01833 bs = READ_SIZE; 01834 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01835 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01836 x = errno; 01837 close(fd); 01838 errno = x; 01839 return -1; 01840 } 01841 return fd; 01842 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9844 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().
09845 { 09846 int x, y; 09847 int dchan = -1, span = -1; 09848 int dchancount = 0; 09849 09850 if (pri) { 09851 for (x = 0; x < NUM_SPANS; x++) { 09852 for (y = 0; y < NUM_DCHANS; y++) { 09853 if (pris[x].dchans[y]) 09854 dchancount++; 09855 09856 if (pris[x].dchans[y] == pri) 09857 dchan = y; 09858 } 09859 if (dchan >= 0) { 09860 span = x; 09861 break; 09862 } 09863 dchancount = 0; 09864 } 09865 if ((dchan >= 0) && (span >= 0)) { 09866 if (dchancount > 1) 09867 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 09868 else 09869 ast_log(LOG_ERROR, "%s", s); 09870 } else 09871 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09872 } else 09873 ast_log(LOG_ERROR, "%s", s); 09874 09875 ast_mutex_lock(&pridebugfdlock); 09876 09877 if (pridebugfd >= 0) { 09878 if (write(pridebugfd, s, strlen(s)) < 0) { 09879 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09880 } 09881 } 09882 09883 ast_mutex_unlock(&pridebugfdlock); 09884 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9802 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().
09803 { 09804 int x, y; 09805 int dchan = -1, span = -1; 09806 int dchancount = 0; 09807 09808 if (pri) { 09809 for (x = 0; x < NUM_SPANS; x++) { 09810 for (y = 0; y < NUM_DCHANS; y++) { 09811 if (pris[x].dchans[y]) 09812 dchancount++; 09813 09814 if (pris[x].dchans[y] == pri) 09815 dchan = y; 09816 } 09817 if (dchan >= 0) { 09818 span = x; 09819 break; 09820 } 09821 dchancount = 0; 09822 } 09823 if ((dchan >= 0) && (span >= 0)) { 09824 if (dchancount > 1) 09825 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 09826 else 09827 ast_verbose("%s", s); 09828 } else 09829 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09830 } else 09831 ast_verbose("%s", s); 09832 09833 ast_mutex_lock(&pridebugfdlock); 09834 09835 if (pridebugfd >= 0) { 09836 if (write(pridebugfd, s, strlen(s)) < 0) { 09837 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09838 } 09839 } 09840 09841 ast_mutex_unlock(&pridebugfdlock); 09842 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 1233 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
01237 { 01238 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01239 #ifdef HAVE_PRI 01240 if (pri) 01241 ast_mutex_unlock(&pri->lock); 01242 #endif 01243 for (;;) { 01244 if (p->owner) { 01245 if (ast_mutex_trylock(&p->owner->lock)) { 01246 DEADLOCK_AVOIDANCE(&p->lock); 01247 } else { 01248 ast_queue_frame(p->owner, f); 01249 ast_mutex_unlock(&p->owner->lock); 01250 break; 01251 } 01252 } else 01253 break; 01254 } 01255 #ifdef HAVE_PRI 01256 if (pri) 01257 ast_mutex_lock(&pri->lock); 01258 #endif 01259 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 1750 of file chan_dahdi.c.
References AST_ALAW.
01751 { 01752 return AST_ALAW(sample); 01753 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1295 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().
01296 { 01297 int res = 0; 01298 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 01299 * and does not has support for openr2_chan_answer_call_with_mode 01300 * */ 01301 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01302 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 01303 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 01304 if (!double_answer) { 01305 /* this still can result in double answer if the channel context 01306 * was configured that way */ 01307 res = openr2_chan_answer_call(p->r2chan); 01308 } else if (wants_double_answer) { 01309 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 01310 } else { 01311 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 01312 } 01313 #else 01314 res = openr2_chan_answer_call(p->r2chan); 01315 #endif 01316 return res; 01317 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1408 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().
01409 { 01410 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 01411 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 01412 p->channel, openr2_proto_get_disconnect_string(cause)); 01413 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 01414 openr2_chan_set_idle(p->r2chan); 01415 ast_mutex_lock(&p->lock); 01416 p->mfcr2call = 0; 01417 ast_mutex_unlock(&p->lock); 01418 } 01419 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 1319 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().
01320 { 01321 openr2_calling_party_category_t cat; 01322 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 01323 struct dahdi_pvt *p = c->tech_pvt; 01324 if (ast_strlen_zero(catstr)) { 01325 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 01326 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01327 return p->mfcr2_category; 01328 } 01329 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 01330 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 01331 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01332 return p->mfcr2_category; 01333 } 01334 ast_log(LOG_DEBUG, "Using category %s\n", catstr); 01335 return cat; 01336 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 1755 of file chan_dahdi.c.
References AST_LIN2A.
01756 { 01757 return AST_LIN2A(sample); 01758 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1714 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
01715 { 01716 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01717 p->cid_num[p->mfcr2_ani_index] = digit; 01718 p->cid_name[p->mfcr2_ani_index] = digit; 01719 p->mfcr2_ani_index++; 01720 p->cid_num[p->mfcr2_ani_index] = 0; 01721 p->cid_name[p->mfcr2_ani_index] = 0; 01722 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1724 of file chan_dahdi.c.
References ast_log(), and LOG_NOTICE.
01725 { 01726 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 01727 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 1482 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.
01483 { 01484 struct dahdi_pvt *p = NULL; 01485 struct ast_channel *c = NULL; 01486 p = openr2_chan_get_client_data(r2chan); 01487 dahdi_enable_ec(p); 01488 p->mfcr2_call_accepted = 1; 01489 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 01490 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 01491 /* if accept on offer is not set, it means at this point the PBX thread is already 01492 launched and therefore this callback is being executed in the PBX thread rather than 01493 the monitor thread, don't launch any other thread, just disable the R2 reading and 01494 answer the call */ 01495 if (!p->mfcr2_accept_on_offer) { 01496 openr2_chan_disable_read(r2chan); 01497 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 01498 dahdi_r2_answer(p); 01499 return; 01500 } 01501 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01502 if (c) { 01503 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01504 openr2_chan_disable_read(r2chan); 01505 } else { 01506 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01507 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01508 return; 01509 } 01510 } else { 01511 ast_verbose("Call accepted on forward channel %d\n", p->channel); 01512 p->subs[SUB_REAL].needringing = 1; 01513 p->dialing = 0; 01514 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01515 openr2_chan_disable_read(r2chan); 01516 } 01517 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1519 of file chan_dahdi.c.
References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
01520 { 01521 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01522 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan)); 01523 p->subs[SUB_REAL].needanswer = 1; 01524 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1552 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.
01553 { 01554 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01555 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan)); 01556 ast_mutex_lock(&p->lock); 01557 if (p->owner) { 01558 /* when we have an owner we don't call openr2_chan_disconnect_call here, that will 01559 be done in zt_hangup */ 01560 if (p->owner->_state == AST_STATE_UP) { 01561 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01562 ast_mutex_unlock(&p->lock); 01563 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 01564 /* being the forward side we must report what happened to the call to whoever requested it */ 01565 switch (cause) { 01566 case OR2_CAUSE_BUSY_NUMBER: 01567 p->owner->hangupcause = AST_CAUSE_BUSY; 01568 p->subs[SUB_REAL].needbusy = 1; 01569 break; 01570 case OR2_CAUSE_NUMBER_CHANGED: 01571 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED; 01572 p->subs[SUB_REAL].needcongestion = 1; 01573 break; 01574 case OR2_CAUSE_NETWORK_CONGESTION: 01575 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER; 01576 p->subs[SUB_REAL].needcongestion = 1; 01577 break; 01578 case OR2_CAUSE_OUT_OF_ORDER: 01579 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01580 p->subs[SUB_REAL].needcongestion = 1; 01581 break; 01582 case OR2_CAUSE_UNALLOCATED_NUMBER: 01583 p->owner->hangupcause = AST_CAUSE_UNALLOCATED; 01584 p->subs[SUB_REAL].needcongestion = 1; 01585 break; 01586 case OR2_CAUSE_NO_ANSWER: 01587 p->owner->hangupcause = AST_CAUSE_NO_ANSWER; 01588 p->subs[SUB_REAL].needcongestion = 1; 01589 break; 01590 case OR2_CAUSE_UNSPECIFIED: 01591 p->owner->hangupcause = AST_CAUSE_NOTDEFINED; 01592 p->subs[SUB_REAL].needcongestion = 1; 01593 break; 01594 case OR2_CAUSE_NORMAL_CLEARING: 01595 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01596 p->subs[SUB_REAL].needcongestion = 1; 01597 break; 01598 default: 01599 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause); 01600 } 01601 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01602 ast_mutex_unlock(&p->lock); 01603 } else { 01604 ast_mutex_unlock(&p->lock); 01605 /* being the backward side and not UP yet, we only need to request hangup */ 01606 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 01607 ast_queue_hangup(p->owner); 01608 } 01609 } else { 01610 ast_mutex_unlock(&p->lock); 01611 /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */ 01612 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 01613 } 01614 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1472 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
01473 { 01474 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01475 ast_verbose("MFC/R2 call end on chan %d\n", p->channel); 01476 ast_mutex_lock(&p->lock); 01477 p->mfcr2call = 0; 01478 ast_mutex_unlock(&p->lock); 01479 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1338 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.
01339 { 01340 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01341 ast_mutex_lock(&p->lock); 01342 if (p->mfcr2call) { 01343 ast_mutex_unlock(&p->lock); 01344 /* TODO: This can happen when some other thread just finished zt_request requesting this very same 01345 interface but has not yet seized the line (zt_call), and the far end wins and seize the line, 01346 can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since 01347 the other end will see our seize as a forced release and drop the call, we will see an invalid 01348 pattern that will be seen and treated as protocol error. */ 01349 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 01350 return; 01351 } 01352 p->mfcr2call = 1; 01353 /* better safe than sorry ... */ 01354 p->cid_name[0] = 0; 01355 p->cid_num[0] = 0; 01356 p->rdnis[0] = 0; 01357 p->exten[0] = 0; 01358 p->mfcr2_ani_index = 0; 01359 p->mfcr2_dnis_index = 0; 01360 p->mfcr2_dnis_matched = 0; 01361 p->mfcr2_call_accepted = 0; 01362 ast_mutex_unlock(&p->lock); 01363 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 01364 }
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 1421 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.
01422 { 01423 struct dahdi_pvt *p; 01424 struct ast_channel *c; 01425 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 01426 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category)); 01427 p = openr2_chan_get_client_data(r2chan); 01428 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 01429 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel); 01430 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 01431 return; 01432 } 01433 ast_mutex_lock(&p->lock); 01434 p->mfcr2_recvd_category = category; 01435 /* if we're not supposed to use CID, clear whatever we have */ 01436 if (!p->use_callerid) { 01437 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 01438 p->cid_num[0] = 0; 01439 p->cid_name[0] = 0; 01440 } 01441 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 01442 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 01443 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 01444 p->exten[0] = 's'; 01445 p->exten[1] = 0; 01446 } 01447 ast_mutex_unlock(&p->lock); 01448 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01449 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 01450 p->channel, p->exten, p->context); 01451 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 01452 } else { 01453 /* if the user does not want to accept on offer, then we should launch the PBX thread now */ 01454 if (!p->mfcr2_accept_on_offer) { 01455 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01456 if (!c) { 01457 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01458 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01459 } 01460 /* Don't disable reading since we still need to generate MF tone to accept 01461 the call or reject it and detect the tone off condition of the other end */ 01462 } else if (p->mfcr2_charge_calls) { 01463 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel); 01464 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 01465 } else { 01466 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel); 01467 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 01468 } 01469 } 01470 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 1526 of file chan_dahdi.c.
01527 { 01528 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 01529 }
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 1675 of file chan_dahdi.c.
References dahdi_r2_write_log().
Referenced by mkintf().
01676 { 01677 char logmsg[256]; 01678 char completemsg[sizeof(logmsg)+50]; 01679 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01680 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg); 01681 dahdi_r2_write_log(level, completemsg); 01682 }
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 1664 of file chan_dahdi.c.
References dahdi_r2_write_log().
01665 { 01666 char logmsg[256]; 01667 char completemsg[sizeof(logmsg)+50]; 01668 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01669 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg); 01670 dahdi_r2_write_log(level, completemsg); 01671 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1684 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.
01685 { 01686 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01687 /* if 'immediate' is set, let's stop requesting DNIS */ 01688 if (p->immediate) { 01689 return 0; 01690 } 01691 p->exten[p->mfcr2_dnis_index] = digit; 01692 p->rdnis[p->mfcr2_dnis_index] = digit; 01693 p->mfcr2_dnis_index++; 01694 p->exten[p->mfcr2_dnis_index] = 0; 01695 p->rdnis[p->mfcr2_dnis_index] = 0; 01696 /* 01697 ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten); 01698 int ret; 01699 ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num); 01700 ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01701 ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num); 01702 ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01703 */ 01704 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 01705 if ((p->mfcr2_dnis_matched || 01706 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 01707 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01708 return 0; 01709 } 01710 /* otherwise keep going */ 01711 return 1; 01712 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 1368 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.
01369 { 01370 int res; 01371 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01372 ast_mutex_lock(&p->lock); 01373 p->inalarm = alarm ? 1 : 0; 01374 if (p->inalarm) { 01375 res = get_alarms(p); 01376 /* unknown_alarm may be set here */ 01377 handle_alarms(p, res); 01378 } else { 01379 if (!p->unknown_alarm) { 01380 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 01381 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 01382 } else { 01383 p->unknown_alarm = 0; 01384 } 01385 } 01386 ast_mutex_unlock(&p->lock); 01387 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan)); 01388 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1644 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.
01645 { 01646 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01647 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel); 01648 ast_mutex_lock(&p->lock); 01649 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK; 01650 ast_mutex_unlock(&p->lock); 01651 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1653 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.
01654 { 01655 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01656 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 01657 ast_mutex_lock(&p->lock); 01658 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK; 01659 ast_mutex_unlock(&p->lock); 01660 }
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 1395 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.
01396 { 01397 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01398 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 01399 if (p->owner) { 01400 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 01401 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01402 } 01403 ast_mutex_lock(&p->lock); 01404 p->mfcr2call = 0; 01405 ast_mutex_unlock(&p->lock); 01406 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 1616 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().
01617 { 01618 switch (level) { 01619 case OR2_LOG_NOTICE: 01620 ast_verbose("%s", logmessage); 01621 break; 01622 case OR2_LOG_WARNING: 01623 ast_log(LOG_WARNING, "%s", logmessage); 01624 break; 01625 case OR2_LOG_ERROR: 01626 ast_log(LOG_ERROR, "%s", logmessage); 01627 break; 01628 case OR2_LOG_STACK_TRACE: 01629 case OR2_LOG_MF_TRACE: 01630 case OR2_LOG_CAS_TRACE: 01631 case OR2_LOG_DEBUG: 01632 case OR2_LOG_EX_DEBUG: 01633 ast_log(LOG_DEBUG, "%s", logmessage); 01634 break; 01635 default: 01636 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 01637 ast_log(LOG_NOTICE, "%s", logmessage); 01638 break; 01639 } 01640 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5906 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.
05907 { 05908 struct dahdi_pvt *p = ast->tech_pvt; 05909 int res; 05910 int index; 05911 void *readbuf; 05912 struct ast_frame *f; 05913 05914 while (ast_mutex_trylock(&p->lock)) { 05915 DEADLOCK_AVOIDANCE(&ast->lock); 05916 } 05917 05918 index = dahdi_get_index(ast, p, 0); 05919 05920 /* Hang up if we don't really exist */ 05921 if (index < 0) { 05922 ast_log(LOG_WARNING, "We dont exist?\n"); 05923 ast_mutex_unlock(&p->lock); 05924 return NULL; 05925 } 05926 05927 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05928 ast_mutex_unlock(&p->lock); 05929 return NULL; 05930 } 05931 05932 p->subs[index].f.frametype = AST_FRAME_NULL; 05933 p->subs[index].f.datalen = 0; 05934 p->subs[index].f.samples = 0; 05935 p->subs[index].f.mallocd = 0; 05936 p->subs[index].f.offset = 0; 05937 p->subs[index].f.subclass = 0; 05938 p->subs[index].f.delivery = ast_tv(0,0); 05939 p->subs[index].f.src = "dahdi_read"; 05940 p->subs[index].f.data = NULL; 05941 05942 /* make sure it sends initial key state as first frame */ 05943 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05944 { 05945 struct dahdi_params ps; 05946 05947 memset(&ps, 0, sizeof(ps)); 05948 ps.channo = p->channel; 05949 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05950 ast_mutex_unlock(&p->lock); 05951 return NULL; 05952 } 05953 p->firstradio = 1; 05954 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05955 if (ps.rxisoffhook) 05956 { 05957 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05958 } 05959 else 05960 { 05961 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05962 } 05963 ast_mutex_unlock(&p->lock); 05964 return &p->subs[index].f; 05965 } 05966 if (p->ringt == 1) { 05967 ast_mutex_unlock(&p->lock); 05968 return NULL; 05969 } 05970 else if (p->ringt > 0) 05971 p->ringt--; 05972 05973 #ifdef HAVE_OPENR2 05974 if (p->mfcr2) { 05975 openr2_chan_process_event(p->r2chan); 05976 } 05977 #endif 05978 05979 if (p->subs[index].needringing) { 05980 /* Send ringing frame if requested */ 05981 p->subs[index].needringing = 0; 05982 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05983 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05984 ast_setstate(ast, AST_STATE_RINGING); 05985 ast_mutex_unlock(&p->lock); 05986 return &p->subs[index].f; 05987 } 05988 05989 if (p->subs[index].needbusy) { 05990 /* Send busy frame if requested */ 05991 p->subs[index].needbusy = 0; 05992 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05993 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05994 ast_mutex_unlock(&p->lock); 05995 return &p->subs[index].f; 05996 } 05997 05998 if (p->subs[index].needcongestion) { 05999 /* Send congestion frame if requested */ 06000 p->subs[index].needcongestion = 0; 06001 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06002 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 06003 ast_mutex_unlock(&p->lock); 06004 return &p->subs[index].f; 06005 } 06006 06007 if (p->subs[index].needcallerid) { 06008 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06009 S_OR(p->lastcid_name, NULL), 06010 S_OR(p->lastcid_num, NULL) 06011 ); 06012 p->subs[index].needcallerid = 0; 06013 } 06014 06015 if (p->subs[index].needanswer) { 06016 /* Send answer frame if requested */ 06017 p->subs[index].needanswer = 0; 06018 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06019 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 06020 ast_mutex_unlock(&p->lock); 06021 return &p->subs[index].f; 06022 } 06023 06024 #ifdef HAVE_OPENR2 06025 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06026 /* openr2 took care of reading and handling any event 06027 (needanswer, needbusy etc), if we continue we will read() 06028 twice, lets just return a null frame. This should only 06029 happen when openr2 is dialing out */ 06030 p->subs[index].f.frametype = AST_FRAME_NULL; 06031 p->subs[index].f.subclass = 0; 06032 p->subs[index].f.samples = 0; 06033 p->subs[index].f.mallocd = 0; 06034 p->subs[index].f.offset = 0; 06035 p->subs[index].f.data = NULL; 06036 p->subs[index].f.datalen= 0; 06037 ast_mutex_unlock(&p->lock); 06038 return &p->subs[index].f; 06039 } 06040 #endif 06041 06042 if (p->subs[index].needflash) { 06043 /* Send answer frame if requested */ 06044 p->subs[index].needflash = 0; 06045 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06046 p->subs[index].f.subclass = AST_CONTROL_FLASH; 06047 ast_mutex_unlock(&p->lock); 06048 return &p->subs[index].f; 06049 } 06050 06051 if (p->subs[index].needhold) { 06052 /* Send answer frame if requested */ 06053 p->subs[index].needhold = 0; 06054 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06055 p->subs[index].f.subclass = AST_CONTROL_HOLD; 06056 ast_mutex_unlock(&p->lock); 06057 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 06058 return &p->subs[index].f; 06059 } 06060 06061 if (p->subs[index].needunhold) { 06062 /* Send answer frame if requested */ 06063 p->subs[index].needunhold = 0; 06064 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06065 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 06066 ast_mutex_unlock(&p->lock); 06067 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 06068 return &p->subs[index].f; 06069 } 06070 06071 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06072 if (!p->subs[index].linear) { 06073 p->subs[index].linear = 1; 06074 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06075 if (res) 06076 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 06077 } 06078 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06079 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06080 if (p->subs[index].linear) { 06081 p->subs[index].linear = 0; 06082 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06083 if (res) 06084 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 06085 } 06086 } else { 06087 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06088 ast_mutex_unlock(&p->lock); 06089 return NULL; 06090 } 06091 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 06092 CHECK_BLOCKING(ast); 06093 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06094 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06095 /* Check for hangup */ 06096 if (res < 0) { 06097 f = NULL; 06098 if (res == -1) { 06099 if (errno == EAGAIN) { 06100 /* Return "NULL" frame if there is nobody there */ 06101 ast_mutex_unlock(&p->lock); 06102 return &p->subs[index].f; 06103 } else if (errno == ELAST) { 06104 f = __dahdi_exception(ast); 06105 } else 06106 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06107 } 06108 ast_mutex_unlock(&p->lock); 06109 return f; 06110 } 06111 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 06112 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06113 f = __dahdi_exception(ast); 06114 ast_mutex_unlock(&p->lock); 06115 return f; 06116 } 06117 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06118 int c; 06119 06120 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06121 if (c < 0) { 06122 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 06123 ast_mutex_unlock(&p->lock); 06124 return NULL; 06125 } 06126 if (c) { /* if a char to return */ 06127 p->subs[index].f.subclass = 0; 06128 p->subs[index].f.frametype = AST_FRAME_TEXT; 06129 p->subs[index].f.mallocd = 0; 06130 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06131 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 06132 p->subs[index].f.datalen = 1; 06133 *((char *) p->subs[index].f.data) = c; 06134 ast_mutex_unlock(&p->lock); 06135 return &p->subs[index].f; 06136 } 06137 } 06138 /* Ensure the CW timer decrements only on a single subchannel */ 06139 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 06140 p->callwaitingrepeat--; 06141 } 06142 if (p->cidcwexpire) 06143 p->cidcwexpire--; 06144 /* Repeat callwaiting */ 06145 if (p->callwaitingrepeat == 1) { 06146 p->callwaitrings++; 06147 dahdi_callwait(ast); 06148 } 06149 /* Expire CID/CW */ 06150 if (p->cidcwexpire == 1) { 06151 if (option_verbose > 2) 06152 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 06153 restore_conference(p); 06154 } 06155 if (p->subs[index].linear) { 06156 p->subs[index].f.datalen = READ_SIZE * 2; 06157 } else 06158 p->subs[index].f.datalen = READ_SIZE; 06159 06160 /* Handle CallerID Transmission */ 06161 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06162 send_callerid(p); 06163 } 06164 06165 p->subs[index].f.frametype = AST_FRAME_VOICE; 06166 p->subs[index].f.subclass = ast->rawreadformat; 06167 p->subs[index].f.samples = READ_SIZE; 06168 p->subs[index].f.mallocd = 0; 06169 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06170 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 06171 #if 0 06172 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 06173 #endif 06174 if (p->dialing || /* Transmitting something */ 06175 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06176 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06177 ) { 06178 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06179 don't send anything */ 06180 p->subs[index].f.frametype = AST_FRAME_NULL; 06181 p->subs[index].f.subclass = 0; 06182 p->subs[index].f.samples = 0; 06183 p->subs[index].f.mallocd = 0; 06184 p->subs[index].f.offset = 0; 06185 p->subs[index].f.data = NULL; 06186 p->subs[index].f.datalen= 0; 06187 } 06188 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 06189 /* Perform busy detection. etc on the dahdi line */ 06190 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 06191 if (f) { 06192 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 06193 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 06194 /* Treat this as a "hangup" instead of a "busy" on the assumption that 06195 a busy */ 06196 f = NULL; 06197 } 06198 } else if (f->frametype == AST_FRAME_DTMF) { 06199 #ifdef HAVE_PRI 06200 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial && 06201 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 06202 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 06203 /* Don't accept in-band DTMF when in overlap dial mode */ 06204 f->frametype = AST_FRAME_NULL; 06205 f->subclass = 0; 06206 } 06207 #endif 06208 /* DSP clears us of being pulse */ 06209 p->pulsedial = 0; 06210 } 06211 } 06212 } else 06213 f = &p->subs[index].f; 06214 06215 if (f && (f->frametype == AST_FRAME_DTMF)) 06216 dahdi_handle_dtmfup(ast, index, &f); 06217 06218 /* If we have a fake_event, trigger exception to handle it */ 06219 if (p->fake_event) 06220 ast_set_flag(ast, AST_FLAG_EXCEPTION); 06221 06222 ast_mutex_unlock(&p->lock); 06223 return f; 06224 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9273 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().
09274 { 09275 ast_group_t groupmatch = 0; 09276 int channelmatch = -1; 09277 int roundrobin = 0; 09278 int callwait = 0; 09279 int busy = 0; 09280 struct dahdi_pvt *p; 09281 struct ast_channel *tmp = NULL; 09282 char *dest=NULL; 09283 int x; 09284 char *s; 09285 char opt=0; 09286 int res=0, y=0; 09287 int backwards = 0; 09288 #ifdef HAVE_PRI 09289 int crv; 09290 int bearer = -1; 09291 int trunkgroup; 09292 struct dahdi_pri *pri=NULL; 09293 #endif 09294 struct dahdi_pvt *exit, *start, *end; 09295 ast_mutex_t *lock; 09296 int channelmatched = 0; 09297 int groupmatched = 0; 09298 09299 /* 09300 * data is ---v 09301 * Dial(DAHDI/pseudo[/extension]) 09302 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09303 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09304 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09305 * 09306 * g - channel group allocation search forward 09307 * G - channel group allocation search backward 09308 * r - channel group allocation round robin search forward 09309 * R - channel group allocation round robin search backward 09310 * 09311 * c - Wait for DTMF digit to confirm answer 09312 * r<cadance#> - Set distintive ring cadance number 09313 * d - Force bearer capability for ISDN call to digital. 09314 */ 09315 09316 /* Assume we're locking the iflock */ 09317 lock = &iflock; 09318 start = iflist; 09319 end = ifend; 09320 if (data) { 09321 dest = ast_strdupa((char *)data); 09322 } else { 09323 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09324 return NULL; 09325 } 09326 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09327 /* Retrieve the group number */ 09328 char *stringp; 09329 09330 stringp = dest + 1; 09331 s = strsep(&stringp, "/"); 09332 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09333 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09334 return NULL; 09335 } 09336 groupmatch = ((ast_group_t) 1 << x); 09337 if (toupper(dest[0]) == 'G') { 09338 if (dest[0] == 'G') { 09339 backwards = 1; 09340 p = ifend; 09341 } else 09342 p = iflist; 09343 } else { 09344 if (dest[0] == 'R') { 09345 backwards = 1; 09346 p = round_robin[x]?round_robin[x]->prev:ifend; 09347 if (!p) 09348 p = ifend; 09349 } else { 09350 p = round_robin[x]?round_robin[x]->next:iflist; 09351 if (!p) 09352 p = iflist; 09353 } 09354 roundrobin = 1; 09355 } 09356 } else { 09357 char *stringp; 09358 09359 stringp = dest; 09360 s = strsep(&stringp, "/"); 09361 p = iflist; 09362 if (!strcasecmp(s, "pseudo")) { 09363 /* Special case for pseudo */ 09364 x = CHAN_PSEUDO; 09365 channelmatch = x; 09366 } 09367 #ifdef HAVE_PRI 09368 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09369 if ((trunkgroup < 1) || (crv < 1)) { 09370 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09371 return NULL; 09372 } 09373 res--; 09374 for (x = 0; x < NUM_SPANS; x++) { 09375 if (pris[x].trunkgroup == trunkgroup) { 09376 pri = pris + x; 09377 lock = &pri->lock; 09378 start = pri->crvs; 09379 end = pri->crvend; 09380 break; 09381 } 09382 } 09383 if (!pri) { 09384 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09385 return NULL; 09386 } 09387 channelmatch = crv; 09388 p = pris[x].crvs; 09389 } 09390 #endif 09391 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09392 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09393 return NULL; 09394 } else { 09395 channelmatch = x; 09396 } 09397 } 09398 /* Search for an unowned channel */ 09399 ast_mutex_lock(lock); 09400 exit = p; 09401 while (p && !tmp) { 09402 if (roundrobin) 09403 round_robin[x] = p; 09404 #if 0 09405 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09406 #endif 09407 09408 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09409 if (option_debug) 09410 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 09411 if (p->inalarm) 09412 goto next; 09413 09414 callwait = (p->owner != NULL); 09415 #ifdef HAVE_PRI 09416 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09417 if (p->sig != SIG_FXSKS) { 09418 /* Gotta find an actual channel to use for this 09419 CRV if this isn't a callwait */ 09420 bearer = pri_find_empty_chan(pri, 0); 09421 if (bearer < 0) { 09422 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09423 p = NULL; 09424 break; 09425 } 09426 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09427 } else { 09428 if (alloc_sub(p, 0)) { 09429 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09430 p = NULL; 09431 break; 09432 } else 09433 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 09434 p->pri = pri; 09435 } 09436 } 09437 #endif 09438 #ifdef HAVE_OPENR2 09439 if (p->mfcr2) { 09440 ast_mutex_lock(&p->lock); 09441 if (p->mfcr2call) { 09442 ast_mutex_unlock(&p->lock); 09443 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 09444 goto next; 09445 } 09446 if (p->mfcr2block) { 09447 ast_mutex_unlock(&p->lock); 09448 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block); 09449 goto next; 09450 } 09451 p->mfcr2call = 1; 09452 ast_mutex_unlock(&p->lock); 09453 } 09454 #endif 09455 if (p->channel == CHAN_PSEUDO) { 09456 p = chandup(p); 09457 if (!p) { 09458 break; 09459 } 09460 } 09461 if (p->owner) { 09462 if (alloc_sub(p, SUB_CALLWAIT)) { 09463 p = NULL; 09464 break; 09465 } 09466 } 09467 p->outgoing = 1; 09468 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09469 if (!tmp) { 09470 p->outgoing = 0; 09471 } 09472 #ifdef HAVE_PRI 09473 if (p->bearer) { 09474 /* Log owner to bearer channel, too */ 09475 p->bearer->owner = tmp; 09476 } 09477 #endif 09478 /* Make special notes */ 09479 if (res > 1) { 09480 if (opt == 'c') { 09481 /* Confirm answer */ 09482 p->confirmanswer = 1; 09483 } else if (opt == 'r') { 09484 /* Distinctive ring */ 09485 if (res < 3) 09486 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09487 else 09488 p->distinctivering = y; 09489 } else if (opt == 'd') { 09490 /* If this is an ISDN call, make it digital */ 09491 p->digital = 1; 09492 if (tmp) 09493 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09494 } else { 09495 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09496 } 09497 } 09498 /* Note if the call is a call waiting call */ 09499 if (tmp && callwait) 09500 tmp->cdrflags |= AST_CDR_CALLWAIT; 09501 break; 09502 } 09503 next: 09504 if (backwards) { 09505 p = p->prev; 09506 if (!p) 09507 p = end; 09508 } else { 09509 p = p->next; 09510 if (!p) 09511 p = start; 09512 } 09513 /* stop when you roll to the one that we started from */ 09514 if (p == exit) 09515 break; 09516 } 09517 ast_mutex_unlock(lock); 09518 restart_monitor(); 09519 if (callwait) 09520 *cause = AST_CAUSE_BUSY; 09521 else if (!tmp) { 09522 if (channelmatched) { 09523 if (busy) 09524 *cause = AST_CAUSE_BUSY; 09525 } else if (groupmatched) { 09526 *cause = AST_CAUSE_CONGESTION; 09527 } 09528 } 09529 09530 return tmp; 09531 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 11905 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().
11906 { 11907 #ifdef HAVE_OPENR2 11908 int r; 11909 #endif 11910 #if defined(HAVE_PRI) 11911 int i, j; 11912 #endif 11913 int cancel_code; 11914 struct dahdi_pvt *p; 11915 11916 ast_mutex_lock(&restart_lock); 11917 11918 if (option_verbose) 11919 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 11920 dahdi_softhangup_all(); 11921 if (option_verbose > 3) 11922 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 11923 11924 #ifdef HAVE_OPENR2 11925 for (r = 0; r < NUM_SPANS; r++) { 11926 if (r2links[r].master != AST_PTHREADT_NULL) { 11927 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master); 11928 pthread_cancel(r2links[r].master); 11929 pthread_join(r2links[r].master, NULL); 11930 openr2_context_delete(r2links[r].protocol_context); 11931 } 11932 } 11933 init_mfcr2_globals(); 11934 #endif 11935 11936 #if defined(HAVE_PRI) 11937 for (i = 0; i < NUM_SPANS; i++) { 11938 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 11939 cancel_code = pthread_cancel(pris[i].master); 11940 pthread_kill(pris[i].master, SIGURG); 11941 if (option_debug > 3) 11942 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 11943 pthread_join(pris[i].master, NULL); 11944 if (option_debug > 3) 11945 ast_verbose("Joined thread of span %d\n", i); 11946 } 11947 } 11948 #endif 11949 11950 ast_mutex_lock(&monlock); 11951 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 11952 cancel_code = pthread_cancel(monitor_thread); 11953 pthread_kill(monitor_thread, SIGURG); 11954 if (option_debug > 3) 11955 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 11956 pthread_join(monitor_thread, NULL); 11957 if (option_debug > 3) 11958 ast_verbose("Joined monitor thread\n"); 11959 } 11960 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 11961 11962 ast_mutex_lock(&ss_thread_lock); 11963 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 11964 int x = DAHDI_FLASH; 11965 if (option_debug > 2) 11966 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 11967 11968 for (p = iflist; p; p = p->next) { 11969 if (p->owner) 11970 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 */ 11971 } 11972 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 11973 } 11974 11975 /* ensure any created channels before monitor threads were stopped are hungup */ 11976 dahdi_softhangup_all(); 11977 if (option_verbose > 3) 11978 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 11979 destroy_all_channels(); 11980 if (option_debug) 11981 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 11982 11983 ast_mutex_unlock(&monlock); 11984 11985 #ifdef HAVE_PRI 11986 for (i = 0; i < NUM_SPANS; i++) { 11987 for (j = 0; j < NUM_DCHANS; j++) 11988 dahdi_close_pri_fd(&(pris[i]), j); 11989 } 11990 11991 memset(pris, 0, sizeof(pris)); 11992 for (i = 0; i < NUM_SPANS; i++) { 11993 ast_mutex_init(&pris[i].lock); 11994 pris[i].offset = -1; 11995 pris[i].master = AST_PTHREADT_NULL; 11996 for (j = 0; j < NUM_DCHANS; j++) 11997 pris[i].fds[j] = -1; 11998 } 11999 pri_set_error(dahdi_pri_error); 12000 pri_set_message(dahdi_pri_message); 12001 #endif 12002 12003 if (setup_dahdi(2) != 0) { 12004 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12005 ast_mutex_unlock(&ss_thread_lock); 12006 return 1; 12007 } 12008 ast_mutex_unlock(&ss_thread_lock); 12009 ast_mutex_unlock(&restart_lock); 12010 return 0; 12011 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12013 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12014 { 12015 if (argc != 2) { 12016 return RESULT_SHOWUSAGE; 12017 } 12018 12019 if (dahdi_restart() != 0) 12020 return RESULT_FAILURE; 12021 return RESULT_SUCCESS; 12022 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4683 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04684 { 04685 int x; 04686 int res; 04687 /* Make sure our transmit state is on hook */ 04688 x = 0; 04689 x = DAHDI_ONHOOK; 04690 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04691 do { 04692 x = DAHDI_RING; 04693 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04694 if (res) { 04695 switch (errno) { 04696 case EBUSY: 04697 case EINTR: 04698 /* Wait just in case */ 04699 usleep(10000); 04700 continue; 04701 case EINPROGRESS: 04702 res = 0; 04703 break; 04704 default: 04705 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04706 res = 0; 04707 } 04708 } 04709 } while (res); 04710 return res; 04711 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3337 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
03338 { 03339 return send_keypad_facility_exec(chan, data); 03340 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 13941 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.
13942 { 13943 #define END_SILENCE_LEN 400 13944 #define HEADER_MS 50 13945 #define TRAILER_MS 5 13946 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 13947 #define ASCII_BYTES_PER_CHAR 80 13948 13949 unsigned char *buf,*mybuf; 13950 struct dahdi_pvt *p = c->tech_pvt; 13951 struct pollfd fds[1]; 13952 int size,res,fd,len,x; 13953 int bytes=0; 13954 /* Initial carrier (imaginary) */ 13955 float cr = 1.0; 13956 float ci = 0.0; 13957 float scont = 0.0; 13958 int index; 13959 13960 index = dahdi_get_index(c, p, 0); 13961 if (index < 0) { 13962 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 13963 return -1; 13964 } 13965 if (!text[0]) return(0); /* if nothing to send, dont */ 13966 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 13967 if (p->mate) 13968 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 13969 else 13970 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 13971 if (!buf) 13972 return -1; 13973 mybuf = buf; 13974 if (p->mate) { 13975 int codec = AST_LAW(p); 13976 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 13977 PUT_CLID_MARKMS; 13978 } 13979 /* Put actual message */ 13980 for (x = 0; text[x]; x++) { 13981 PUT_CLID(text[x]); 13982 } 13983 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 13984 PUT_CLID_MARKMS; 13985 } 13986 len = bytes; 13987 buf = mybuf; 13988 } else { 13989 len = tdd_generate(p->tdd, buf, text); 13990 if (len < 1) { 13991 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 13992 free(mybuf); 13993 return -1; 13994 } 13995 } 13996 memset(buf + len, 0x7f, END_SILENCE_LEN); 13997 len += END_SILENCE_LEN; 13998 fd = p->subs[index].dfd; 13999 while (len) { 14000 if (ast_check_hangup(c)) { 14001 free(mybuf); 14002 return -1; 14003 } 14004 size = len; 14005 if (size > READ_SIZE) 14006 size = READ_SIZE; 14007 fds[0].fd = fd; 14008 fds[0].events = POLLOUT | POLLPRI; 14009 fds[0].revents = 0; 14010 res = poll(fds, 1, -1); 14011 if (!res) { 14012 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 14013 continue; 14014 } 14015 /* if got exception */ 14016 if (fds[0].revents & POLLPRI) { 14017 ast_free(mybuf); 14018 return -1; 14019 } 14020 if (!(fds[0].revents & POLLOUT)) { 14021 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 14022 continue; 14023 } 14024 res = write(fd, buf, size); 14025 if (res != size) { 14026 if (res == -1) { 14027 free(mybuf); 14028 return -1; 14029 } 14030 if (option_debug) 14031 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 14032 break; 14033 } 14034 len -= size; 14035 buf += size; 14036 } 14037 free(mybuf); 14038 return(0); 14039 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2550 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().
02551 { 02552 int x, res; 02553 02554 x = hs; 02555 res = ioctl(fd, DAHDI_HOOK, &x); 02556 02557 if (res < 0) { 02558 if (errno == EINPROGRESS) 02559 return 0; 02560 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02561 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02562 } 02563 02564 return res; 02565 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 9976 of file chan_dahdi.c.
09977 { 09978 int res; 09979 res = ioctl(dfd, DAHDI_SETLAW, &law); 09980 if (res) 09981 return res; 09982 return 0; 09983 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1864 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01865 { 01866 int res; 01867 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01868 if (res) 01869 return res; 01870 return 0; 01871 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 4047 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.
04048 { 04049 char *cp; 04050 signed char *scp; 04051 int x; 04052 int index; 04053 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04054 struct oprmode *oprmode; 04055 04056 04057 /* all supported options require data */ 04058 if (!data || (datalen < 1)) { 04059 errno = EINVAL; 04060 return -1; 04061 } 04062 04063 switch (option) { 04064 case AST_OPTION_TXGAIN: 04065 scp = (signed char *) data; 04066 index = dahdi_get_index(chan, p, 0); 04067 if (index < 0) { 04068 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04069 return -1; 04070 } 04071 if (option_debug) 04072 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04073 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 04074 case AST_OPTION_RXGAIN: 04075 scp = (signed char *) data; 04076 index = dahdi_get_index(chan, p, 0); 04077 if (index < 0) { 04078 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04079 return -1; 04080 } 04081 if (option_debug) 04082 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04083 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 04084 case AST_OPTION_TONE_VERIFY: 04085 if (!p->dsp) 04086 break; 04087 cp = (char *) data; 04088 switch (*cp) { 04089 case 1: 04090 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04091 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04092 break; 04093 case 2: 04094 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04095 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04096 break; 04097 default: 04098 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04099 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04100 break; 04101 } 04102 break; 04103 case AST_OPTION_TDD: 04104 /* turn on or off TDD */ 04105 cp = (char *) data; 04106 p->mate = 0; 04107 if (!*cp) { /* turn it off */ 04108 if (option_debug) 04109 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04110 if (p->tdd) 04111 tdd_free(p->tdd); 04112 p->tdd = 0; 04113 break; 04114 } 04115 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 04116 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04117 dahdi_disable_ec(p); 04118 /* otherwise, turn it on */ 04119 if (!p->didtdd) { /* if havent done it yet */ 04120 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04121 unsigned char *buf; 04122 int size, res, fd, len; 04123 struct pollfd fds[1]; 04124 04125 buf = mybuf; 04126 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04127 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04128 len = 40000; 04129 index = dahdi_get_index(chan, p, 0); 04130 if (index < 0) { 04131 ast_log(LOG_WARNING, "No index in TDD?\n"); 04132 return -1; 04133 } 04134 fd = p->subs[index].dfd; 04135 while (len) { 04136 if (ast_check_hangup(chan)) 04137 return -1; 04138 size = len; 04139 if (size > READ_SIZE) 04140 size = READ_SIZE; 04141 fds[0].fd = fd; 04142 fds[0].events = POLLPRI | POLLOUT; 04143 fds[0].revents = 0; 04144 res = poll(fds, 1, -1); 04145 if (!res) { 04146 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 04147 continue; 04148 } 04149 /* if got exception */ 04150 if (fds[0].revents & POLLPRI) 04151 return -1; 04152 if (!(fds[0].revents & POLLOUT)) { 04153 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 04154 continue; 04155 } 04156 res = write(fd, buf, size); 04157 if (res != size) { 04158 if (res == -1) return -1; 04159 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04160 break; 04161 } 04162 len -= size; 04163 buf += size; 04164 } 04165 p->didtdd = 1; /* set to have done it now */ 04166 } 04167 if (*cp == 2) { /* Mate mode */ 04168 if (p->tdd) 04169 tdd_free(p->tdd); 04170 p->tdd = 0; 04171 p->mate = 1; 04172 break; 04173 } 04174 if (!p->tdd) { /* if we dont have one yet */ 04175 p->tdd = tdd_new(); /* allocate one */ 04176 } 04177 break; 04178 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04179 if (!p->dsp) 04180 break; 04181 cp = (char *) data; 04182 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04183 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04184 p->dtmfrelax = 0; 04185 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 04186 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04187 break; 04188 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04189 cp = (char *) data; 04190 if (!*cp) { 04191 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04192 x = 0; 04193 dahdi_disable_ec(p); 04194 } else { 04195 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04196 x = 1; 04197 } 04198 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04199 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04200 break; 04201 case AST_OPTION_OPRMODE: /* Operator services mode */ 04202 oprmode = (struct oprmode *) data; 04203 pp = oprmode->peer->tech_pvt; 04204 p->oprmode = pp->oprmode = 0; 04205 /* setup peers */ 04206 p->oprpeer = pp; 04207 pp->oprpeer = p; 04208 /* setup modes, if any */ 04209 if (oprmode->mode) 04210 { 04211 pp->oprmode = oprmode->mode; 04212 p->oprmode = -oprmode->mode; 04213 } 04214 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 04215 oprmode->mode, chan->name,oprmode->peer->name);; 04216 break; 04217 case AST_OPTION_ECHOCAN: 04218 cp = (char *) data; 04219 if (*cp) { 04220 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 04221 dahdi_enable_ec(p); 04222 } else { 04223 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 04224 dahdi_disable_ec(p); 04225 } 04226 break; 04227 } 04228 errno = 0; 04229 04230 return 0; 04231 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12085 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.
12086 { 12087 int channel; 12088 struct dahdi_pvt *tmp = NULL; 12089 struct dahdi_confinfo ci; 12090 struct dahdi_params ps; 12091 int x; 12092 ast_mutex_t *lock; 12093 struct dahdi_pvt *start; 12094 #ifdef HAVE_PRI 12095 char *c; 12096 int trunkgroup; 12097 struct dahdi_pri *pri=NULL; 12098 #endif 12099 12100 lock = &iflock; 12101 start = iflist; 12102 12103 if (argc != 4) 12104 return RESULT_SHOWUSAGE; 12105 #ifdef HAVE_PRI 12106 if ((c = strchr(argv[3], ':'))) { 12107 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12108 return RESULT_SHOWUSAGE; 12109 if ((trunkgroup < 1) || (channel < 1)) 12110 return RESULT_SHOWUSAGE; 12111 for (x = 0; x < NUM_SPANS; x++) { 12112 if (pris[x].trunkgroup == trunkgroup) { 12113 pri = pris + x; 12114 break; 12115 } 12116 } 12117 if (pri) { 12118 start = pri->crvs; 12119 lock = &pri->lock; 12120 } else { 12121 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12122 return RESULT_FAILURE; 12123 } 12124 } else 12125 #endif 12126 channel = atoi(argv[3]); 12127 12128 ast_mutex_lock(lock); 12129 tmp = start; 12130 while (tmp) { 12131 if (tmp->channel == channel) { 12132 #ifdef HAVE_PRI 12133 if (pri) 12134 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12135 else 12136 #endif 12137 ast_cli(fd, "Channel: %d\n", tmp->channel); 12138 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12139 ast_cli(fd, "Span: %d\n", tmp->span); 12140 ast_cli(fd, "Extension: %s\n", tmp->exten); 12141 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12142 ast_cli(fd, "Context: %s\n", tmp->context); 12143 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 12144 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 12145 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 12146 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 12147 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 12148 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12149 ast_cli(fd, "Radio: %d\n", tmp->radio); 12150 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12151 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)" : ""); 12152 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)" : ""); 12153 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)" : ""); 12154 ast_cli(fd, "Confno: %d\n", tmp->confno); 12155 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 12156 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 12157 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12158 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12159 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12160 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12161 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12162 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12163 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 12164 if (tmp->master) 12165 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 12166 for (x = 0; x < MAX_SLAVES; x++) { 12167 if (tmp->slaves[x]) 12168 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12169 } 12170 #ifdef HAVE_OPENR2 12171 if (tmp->mfcr2) { 12172 char calldir[OR2_MAX_PATH]; 12173 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 12174 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 12175 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No"); 12176 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No"); 12177 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 12178 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 12179 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 12180 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 12181 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 12182 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 12183 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 12184 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 12185 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 12186 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No"); 12187 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No"); 12188 #endif 12189 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 12190 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 12191 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 12192 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 12193 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 12194 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 12195 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 12196 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 12197 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 12198 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 12199 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 12200 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 12201 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 12202 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 12203 } 12204 #endif 12205 #ifdef HAVE_PRI 12206 if (tmp->pri) { 12207 ast_cli(fd, "PRI Flags: "); 12208 if (tmp->resetting) 12209 ast_cli(fd, "Resetting "); 12210 if (tmp->call) 12211 ast_cli(fd, "Call "); 12212 if (tmp->bearer) 12213 ast_cli(fd, "Bearer "); 12214 ast_cli(fd, "\n"); 12215 if (tmp->logicalspan) 12216 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12217 else 12218 ast_cli(fd, "PRI Logical Span: Implicit\n"); 12219 } 12220 12221 #endif 12222 memset(&ci, 0, sizeof(ci)); 12223 ps.channo = tmp->channel; 12224 if (tmp->subs[SUB_REAL].dfd > -1) { 12225 memset(&ci, 0, sizeof(ci)); 12226 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12227 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12228 } 12229 #ifdef DAHDI_GETCONFMUTE 12230 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12231 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12232 } 12233 #endif 12234 memset(&ps, 0, sizeof(ps)); 12235 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12236 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12237 } else { 12238 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12239 } 12240 } 12241 if (ISTRUNK(tmp)) { 12242 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12243 if (!ast_strlen_zero(progzone)) 12244 ast_cli(fd, "Progress Zone: %s\n", progzone); 12245 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12246 if(tmp->busydetect) { 12247 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 12248 if(tmp->busytonelength > 0) { 12249 ast_cli(fd, "Busy Pattern:\n"); 12250 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12251 if (tmp->busyquietlength > 0) 12252 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12253 else 12254 ast_cli(fd, " -- Detect Tone Only\n"); 12255 if(tmp->busyfuzziness > 0) 12256 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12257 } 12258 } 12259 } 12260 ast_mutex_unlock(lock); 12261 return RESULT_SUCCESS; 12262 } 12263 tmp = tmp->next; 12264 } 12265 12266 ast_cli(fd, "Unable to find given channel %d\n", channel); 12267 ast_mutex_unlock(lock); 12268 return RESULT_FAILURE; 12269 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12024 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.
12025 { 12026 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12027 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12028 struct dahdi_pvt *tmp = NULL; 12029 char tmps[20] = ""; 12030 ast_mutex_t *lock; 12031 struct dahdi_pvt *start; 12032 #ifdef HAVE_PRI 12033 int trunkgroup; 12034 struct dahdi_pri *pri = NULL; 12035 int x; 12036 #endif 12037 12038 lock = &iflock; 12039 start = iflist; 12040 12041 #ifdef HAVE_PRI 12042 if (argc == 4) { 12043 if ((trunkgroup = atoi(argv[3])) < 1) 12044 return RESULT_SHOWUSAGE; 12045 for (x = 0; x < NUM_SPANS; x++) { 12046 if (pris[x].trunkgroup == trunkgroup) { 12047 pri = pris + x; 12048 break; 12049 } 12050 } 12051 if (pri) { 12052 start = pri->crvs; 12053 lock = &pri->lock; 12054 } else { 12055 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12056 return RESULT_FAILURE; 12057 } 12058 } else 12059 #endif 12060 if (argc != 3) 12061 return RESULT_SHOWUSAGE; 12062 12063 ast_mutex_lock(lock); 12064 #ifdef HAVE_PRI 12065 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12066 #else 12067 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12068 #endif 12069 12070 tmp = start; 12071 while (tmp) { 12072 if (tmp->channel > 0) { 12073 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12074 } else 12075 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12076 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 12077 tmp = tmp->next; 12078 } 12079 ast_mutex_unlock(lock); 12080 return RESULT_SUCCESS; 12081 #undef FORMAT 12082 #undef FORMAT2 12083 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12302 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
12302 { 12303 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 12304 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 12305 12306 int span; 12307 int res; 12308 char alarms[50]; 12309 12310 int ctl; 12311 struct dahdi_spaninfo s; 12312 12313 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 12314 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 12315 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 12316 return RESULT_FAILURE; 12317 } 12318 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 12319 12320 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 12321 s.spanno = span; 12322 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 12323 if (res) { 12324 continue; 12325 } 12326 alarms[0] = '\0'; 12327 if (s.alarms > 0) { 12328 if (s.alarms & DAHDI_ALARM_BLUE) 12329 strcat(alarms, "BLU/"); 12330 if (s.alarms & DAHDI_ALARM_YELLOW) 12331 strcat(alarms, "YEL/"); 12332 if (s.alarms & DAHDI_ALARM_RED) 12333 strcat(alarms, "RED/"); 12334 if (s.alarms & DAHDI_ALARM_LOOPBACK) 12335 strcat(alarms, "LB/"); 12336 if (s.alarms & DAHDI_ALARM_RECOVER) 12337 strcat(alarms, "REC/"); 12338 if (s.alarms & DAHDI_ALARM_NOTOPEN) 12339 strcat(alarms, "NOP/"); 12340 if (!strlen(alarms)) 12341 strcat(alarms, "UUU/"); 12342 if (strlen(alarms)) { 12343 /* Strip trailing / */ 12344 alarms[strlen(alarms) - 1] = '\0'; 12345 } 12346 } else { 12347 if (s.numchans) 12348 strcpy(alarms, "OK"); 12349 else 12350 strcpy(alarms, "UNCONFIGURED"); 12351 } 12352 12353 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 12354 } 12355 close(ctl); 12356 12357 return RESULT_SUCCESS; 12358 #undef FORMAT 12359 #undef FORMAT2 12360 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2101 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.
02102 { 02103 static char buf[256]; 02104 switch (sig) { 02105 case SIG_EM: 02106 return "E & M Immediate"; 02107 case SIG_EMWINK: 02108 return "E & M Wink"; 02109 case SIG_EM_E1: 02110 return "E & M E1"; 02111 case SIG_FEATD: 02112 return "Feature Group D (DTMF)"; 02113 case SIG_FEATDMF: 02114 return "Feature Group D (MF)"; 02115 case SIG_FEATDMF_TA: 02116 return "Feature Groud D (MF) Tandem Access"; 02117 case SIG_FEATB: 02118 return "Feature Group B (MF)"; 02119 case SIG_E911: 02120 return "E911 (MF)"; 02121 case SIG_FGC_CAMA: 02122 return "FGC/CAMA (Dialpulse)"; 02123 case SIG_FGC_CAMAMF: 02124 return "FGC/CAMA (MF)"; 02125 case SIG_FXSLS: 02126 return "FXS Loopstart"; 02127 case SIG_FXSGS: 02128 return "FXS Groundstart"; 02129 case SIG_FXSKS: 02130 return "FXS Kewlstart"; 02131 case SIG_FXOLS: 02132 return "FXO Loopstart"; 02133 case SIG_FXOGS: 02134 return "FXO Groundstart"; 02135 case SIG_FXOKS: 02136 return "FXO Kewlstart"; 02137 case SIG_PRI: 02138 return "ISDN PRI"; 02139 case SIG_MFCR2: 02140 return "MFC/R2"; 02141 case SIG_SF: 02142 return "SF (Tone) Immediate"; 02143 case SIG_SFWINK: 02144 return "SF (Tone) Wink"; 02145 case SIG_SF_FEATD: 02146 return "SF (Tone) with Feature Group D (DTMF)"; 02147 case SIG_SF_FEATDMF: 02148 return "SF (Tone) with Feature Group D (MF)"; 02149 case SIG_SF_FEATB: 02150 return "SF (Tone) with Feature Group B (MF)"; 02151 case SIG_GR303FXOKS: 02152 return "GR-303 with FXOKS"; 02153 case SIG_GR303FXSKS: 02154 return "GR-303 with FXSKS"; 02155 case 0: 02156 return "Pseudo"; 02157 default: 02158 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 02159 return buf; 02160 } 02161 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 11876 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().
11877 { 11878 struct dahdi_pvt *p; 11879 retry: 11880 ast_mutex_lock(&iflock); 11881 for (p = iflist; p; p = p->next) { 11882 ast_mutex_lock(&p->lock); 11883 if (p->owner && !p->restartpending) { 11884 if (ast_channel_trylock(p->owner)) { 11885 if (option_debug > 2) 11886 ast_verbose("Avoiding deadlock\n"); 11887 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 11888 ast_mutex_unlock(&p->lock); 11889 ast_mutex_unlock(&iflock); 11890 goto retry; 11891 } 11892 if (option_debug > 2) 11893 ast_verbose("Softhanging up on %s\n", p->owner->name); 11894 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 11895 p->restartpending = 1; 11896 num_restart_pending++; 11897 ast_channel_unlock(p->owner); 11898 } 11899 ast_mutex_unlock(&p->lock); 11900 } 11901 ast_mutex_unlock(&iflock); 11902 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2382 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().
02383 { 02384 int x; 02385 int res; 02386 if (p && p->echocancel && p->echotraining) { 02387 x = p->echotraining; 02388 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02389 if (res) 02390 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02391 else { 02392 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 02393 } 02394 } else 02395 ast_log(LOG_DEBUG, "No echo training requested\n"); 02396 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4252 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().
04253 { 04254 /* Unlink a specific slave or all slaves/masters from a given master */ 04255 int x; 04256 int hasslaves; 04257 if (!master) 04258 return; 04259 if (needlock) { 04260 ast_mutex_lock(&master->lock); 04261 if (slave) { 04262 while (ast_mutex_trylock(&slave->lock)) { 04263 DEADLOCK_AVOIDANCE(&master->lock); 04264 } 04265 } 04266 } 04267 hasslaves = 0; 04268 for (x = 0; x < MAX_SLAVES; x++) { 04269 if (master->slaves[x]) { 04270 if (!slave || (master->slaves[x] == slave)) { 04271 /* Take slave out of the conference */ 04272 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04273 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04274 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04275 master->slaves[x]->master = NULL; 04276 master->slaves[x] = NULL; 04277 } else 04278 hasslaves = 1; 04279 } 04280 if (!hasslaves) 04281 master->inconference = 0; 04282 } 04283 if (!slave) { 04284 if (master->master) { 04285 /* Take master out of the conference */ 04286 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04287 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04288 hasslaves = 0; 04289 for (x = 0; x < MAX_SLAVES; x++) { 04290 if (master->master->slaves[x] == master) 04291 master->master->slaves[x] = NULL; 04292 else if (master->master->slaves[x]) 04293 hasslaves = 1; 04294 } 04295 if (!hasslaves) 04296 master->master->inconference = 0; 04297 } 04298 master->master = NULL; 04299 } 04300 update_conf(master); 04301 if (needlock) { 04302 if (slave) 04303 ast_mutex_unlock(&slave->lock); 04304 ast_mutex_unlock(&master->lock); 04305 } 04306 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 280 of file chan_dahdi.c.
Referenced by ss_thread().
00281 { 00282 int i, j = 0; 00283 i = DAHDI_IOMUX_SIGEVENT; 00284 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00285 return -1; 00286 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00287 return -1; 00288 return j; 00289 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 6736 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06737 { 06738 int j; 06739 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 06740 for (;;) 06741 { 06742 /* set bits of interest */ 06743 j = DAHDI_IOMUX_SIGEVENT; 06744 /* wait for some happening */ 06745 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06746 /* exit loop if we have it */ 06747 if (j & DAHDI_IOMUX_SIGEVENT) break; 06748 } 06749 /* get the event info */ 06750 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06751 return 0; 06752 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6249 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.
06250 { 06251 struct dahdi_pvt *p = ast->tech_pvt; 06252 int res; 06253 int index; 06254 index = dahdi_get_index(ast, p, 0); 06255 if (index < 0) { 06256 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06257 return -1; 06258 } 06259 06260 #if 0 06261 #ifdef HAVE_PRI 06262 ast_mutex_lock(&p->lock); 06263 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06264 if (p->pri->pri) { 06265 if (!pri_grab(p, p->pri)) { 06266 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06267 pri_rel(p->pri); 06268 } else 06269 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06270 } 06271 p->proceeding=1; 06272 } 06273 ast_mutex_unlock(&p->lock); 06274 #endif 06275 #endif 06276 /* Write a frame of (presumably voice) data */ 06277 if (frame->frametype != AST_FRAME_VOICE) { 06278 if (frame->frametype != AST_FRAME_IMAGE) 06279 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06280 return 0; 06281 } 06282 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06283 (frame->subclass != AST_FORMAT_ULAW) && 06284 (frame->subclass != AST_FORMAT_ALAW)) { 06285 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06286 return -1; 06287 } 06288 if (p->dialing) { 06289 if (option_debug) 06290 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06291 return 0; 06292 } 06293 if (!p->owner) { 06294 if (option_debug) 06295 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 06296 return 0; 06297 } 06298 if (p->cidspill) { 06299 if (option_debug) 06300 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 06301 return 0; 06302 } 06303 /* Return if it's not valid data */ 06304 if (!frame->data || !frame->datalen) 06305 return 0; 06306 06307 if (frame->subclass == AST_FORMAT_SLINEAR) { 06308 if (!p->subs[index].linear) { 06309 p->subs[index].linear = 1; 06310 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06311 if (res) 06312 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06313 } 06314 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06315 } else { 06316 /* x-law already */ 06317 if (p->subs[index].linear) { 06318 p->subs[index].linear = 0; 06319 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06320 if (res) 06321 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06322 } 06323 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06324 } 06325 if (res < 0) { 06326 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06327 return -1; 06328 } 06329 return 0; 06330 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3253 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().
03254 { 03255 int x; 03256 struct dahdi_pvt *p, *pl; 03257 03258 while (num_restart_pending) { 03259 usleep(1); 03260 } 03261 03262 ast_mutex_lock(&iflock); 03263 /* Destroy all the interfaces and free their memory */ 03264 p = iflist; 03265 while (p) { 03266 /* Free any callerid */ 03267 if (p->cidspill) 03268 ast_free(p->cidspill); 03269 pl = p; 03270 p = p->next; 03271 x = pl->channel; 03272 /* Free associated memory */ 03273 if (pl) 03274 destroy_dahdi_pvt(&pl); 03275 if (option_verbose > 2) 03276 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03277 } 03278 iflist = NULL; 03279 ifcount = 0; 03280 ast_mutex_unlock(&iflock); 03281 }
Definition at line 3203 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().
03204 { 03205 int owned = 0; 03206 int i = 0; 03207 03208 if (!now) { 03209 if (cur->owner) { 03210 owned = 1; 03211 } 03212 03213 for (i = 0; i < 3; i++) { 03214 if (cur->subs[i].owner) { 03215 owned = 1; 03216 } 03217 } 03218 if (!owned) { 03219 if (prev) { 03220 prev->next = cur->next; 03221 if (prev->next) 03222 prev->next->prev = prev; 03223 else 03224 ifend = prev; 03225 } else { 03226 iflist = cur->next; 03227 if (iflist) 03228 iflist->prev = NULL; 03229 else 03230 ifend = NULL; 03231 } 03232 destroy_dahdi_pvt(&cur); 03233 } 03234 } else { 03235 if (prev) { 03236 prev->next = cur->next; 03237 if (prev->next) 03238 prev->next->prev = prev; 03239 else 03240 ifend = prev; 03241 } else { 03242 iflist = cur->next; 03243 if (iflist) 03244 iflist->prev = NULL; 03245 else 03246 ifend = NULL; 03247 } 03248 destroy_dahdi_pvt(&cur); 03249 } 03250 return 0; 03251 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3185 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().
03186 { 03187 struct dahdi_pvt *p = *pvt; 03188 /* Remove channel from the list */ 03189 if (p->prev) 03190 p->prev->next = p->next; 03191 if (p->next) 03192 p->next->prev = p->prev; 03193 if (p->use_smdi) 03194 ast_smdi_interface_unref(p->smdi_iface); 03195 ast_mutex_destroy(&p->lock); 03196 dahdi_close_sub(p, SUB_REAL); 03197 if (p->owner) 03198 p->owner->tech_pvt = NULL; 03199 free(p); 03200 *pvt = NULL; 03201 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2092 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
02093 { 02094 if (dialplan == -1) { 02095 return("Dynamically set dialplan in ISDN"); 02096 } 02097 return (pri_plan2str(dialplan)); 02098 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1925 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01926 { 01927 if (isdigit(digit)) 01928 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01929 else if (digit >= 'A' && digit <= 'D') 01930 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01931 else if (digit >= 'a' && digit <= 'd') 01932 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01933 else if (digit == '*') 01934 return DAHDI_TONE_DTMF_s; 01935 else if (digit == '#') 01936 return DAHDI_TONE_DTMF_p; 01937 else 01938 return -1; 01939 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4331 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().
04332 { 04333 #ifdef DAHDI_TONEDETECT 04334 int val; 04335 #endif 04336 04337 p->ignoredtmf = 1; 04338 04339 #ifdef DAHDI_TONEDETECT 04340 val = 0; 04341 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04342 #endif 04343 if (!p->hardwaredtmf && p->dsp) { 04344 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04345 ast_dsp_set_features(p->dsp, p->dsp_features); 04346 } 04347 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 9747 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().
09748 { 09749 struct ast_channel *chan = vchan; 09750 struct dahdi_pvt *pvt = chan->tech_pvt; 09751 struct ast_frame *f; 09752 char ex[80]; 09753 /* Wait up to 30 seconds for an answer */ 09754 int newms, ms = 30000; 09755 if (option_verbose > 2) 09756 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 09757 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 09758 if (ast_call(chan, ex, 0)) { 09759 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 09760 ast_hangup(chan); 09761 return NULL; 09762 } 09763 while ((newms = ast_waitfor(chan, ms)) > 0) { 09764 f = ast_read(chan); 09765 if (!f) { 09766 /* Got hangup */ 09767 break; 09768 } 09769 if (f->frametype == AST_FRAME_CONTROL) { 09770 switch (f->subclass) { 09771 case AST_CONTROL_ANSWER: 09772 /* Launch the PBX */ 09773 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 09774 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 09775 chan->priority = 1; 09776 if (option_verbose > 3) 09777 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 09778 ast_pbx_run(chan); 09779 /* It's already hungup, return immediately */ 09780 return NULL; 09781 case AST_CONTROL_BUSY: 09782 if (option_verbose > 3) 09783 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 09784 break; 09785 case AST_CONTROL_CONGESTION: 09786 if (option_verbose > 3) 09787 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 09788 break; 09789 }; 09790 } 09791 ast_frfree(f); 09792 ms = newms; 09793 } 09794 /* Hangup the channel since nothing happend */ 09795 ast_hangup(chan); 09796 return NULL; 09797 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8147 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08148 { 08149 int count, res, res2, spoint, pollres=0; 08150 struct dahdi_pvt *i; 08151 struct dahdi_pvt *last = NULL; 08152 struct dahdi_pvt *doomed; 08153 time_t thispass = 0, lastpass = 0; 08154 int found; 08155 char buf[1024]; 08156 struct pollfd *pfds=NULL; 08157 int lastalloc = -1; 08158 /* This thread monitors all the frame relay interfaces which are not yet in use 08159 (and thus do not have a separate thread) indefinitely */ 08160 /* From here on out, we die whenever asked */ 08161 #if 0 08162 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08163 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08164 return NULL; 08165 } 08166 ast_log(LOG_DEBUG, "Monitor starting...\n"); 08167 #endif 08168 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08169 08170 for (;;) { 08171 /* Lock the interface list */ 08172 ast_mutex_lock(&iflock); 08173 if (!pfds || (lastalloc != ifcount)) { 08174 if (pfds) { 08175 free(pfds); 08176 pfds = NULL; 08177 } 08178 if (ifcount) { 08179 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08180 ast_mutex_unlock(&iflock); 08181 return NULL; 08182 } 08183 } 08184 lastalloc = ifcount; 08185 } 08186 /* Build the stuff we're going to poll on, that is the socket of every 08187 dahdi_pvt that does not have an associated owner channel */ 08188 count = 0; 08189 i = iflist; 08190 while (i) { 08191 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 08192 if (!i->owner && !i->subs[SUB_REAL].owner) { 08193 /* This needs to be watched, as it lacks an owner */ 08194 pfds[count].fd = i->subs[SUB_REAL].dfd; 08195 pfds[count].events = POLLPRI; 08196 pfds[count].revents = 0; 08197 /* Message waiting or r2 channels also get watched for reading */ 08198 if (i->cidspill) 08199 pfds[count].events |= POLLIN; 08200 count++; 08201 } 08202 } 08203 i = i->next; 08204 } 08205 /* Okay, now that we know what to do, release the interface lock */ 08206 ast_mutex_unlock(&iflock); 08207 08208 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08209 pthread_testcancel(); 08210 /* Wait at least a second for something to happen */ 08211 res = poll(pfds, count, 1000); 08212 pthread_testcancel(); 08213 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08214 08215 /* Okay, poll has finished. Let's see what happened. */ 08216 if (res < 0) { 08217 if ((errno != EAGAIN) && (errno != EINTR)) 08218 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08219 continue; 08220 } 08221 /* Alright, lock the interface list again, and let's look and see what has 08222 happened */ 08223 ast_mutex_lock(&iflock); 08224 found = 0; 08225 spoint = 0; 08226 lastpass = thispass; 08227 thispass = time(NULL); 08228 doomed = NULL; 08229 for (i = iflist;; i = i->next) { 08230 if (doomed) { 08231 int res; 08232 res = dahdi_destroy_channel_bynum(doomed->channel); 08233 if (!res) { 08234 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08235 } 08236 doomed = NULL; 08237 } 08238 if (!i) { 08239 break; 08240 } 08241 if (thispass != lastpass) { 08242 if (!found && ((i == last) || ((i == iflist) && !last))) { 08243 last = i; 08244 if (last) { 08245 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 08246 (last->sig & __DAHDI_SIG_FXO)) { 08247 res = ast_app_has_voicemail(last->mailbox, NULL); 08248 if (last->msgstate != res) { 08249 int x; 08250 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08251 x = DAHDI_FLUSH_BOTH; 08252 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08253 if (res2) 08254 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 08255 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08256 /* Turn on on hook transfer for 4 seconds */ 08257 x = 4000; 08258 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08259 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08260 last->cidpos = 0; 08261 last->msgstate = res; 08262 last->onhooktime = thispass; 08263 } 08264 found ++; 08265 } 08266 } 08267 last = last->next; 08268 } 08269 } 08270 } 08271 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08272 if (i->radio && !i->owner) 08273 { 08274 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08275 if (res) 08276 { 08277 if (option_debug) 08278 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08279 /* Don't hold iflock while handling init events */ 08280 ast_mutex_unlock(&iflock); 08281 doomed = handle_init_event(i, res); 08282 ast_mutex_lock(&iflock); 08283 } 08284 continue; 08285 } 08286 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08287 if (pollres & POLLIN) { 08288 if (i->owner || i->subs[SUB_REAL].owner) { 08289 #ifdef HAVE_PRI 08290 if (!i->pri) 08291 #endif 08292 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08293 continue; 08294 } 08295 if (!i->cidspill) { 08296 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08297 continue; 08298 } 08299 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08300 if (res > 0) { 08301 /* We read some number of bytes. Write an equal amount of data */ 08302 if (res > i->cidlen - i->cidpos) 08303 res = i->cidlen - i->cidpos; 08304 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 08305 if (res2 > 0) { 08306 i->cidpos += res2; 08307 if (i->cidpos >= i->cidlen) { 08308 free(i->cidspill); 08309 i->cidspill = 0; 08310 i->cidpos = 0; 08311 i->cidlen = 0; 08312 } 08313 } else { 08314 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 08315 i->msgstate = -1; 08316 } 08317 } else { 08318 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08319 } 08320 } 08321 if (pollres & POLLPRI) { 08322 if (i->owner || i->subs[SUB_REAL].owner) { 08323 #ifdef HAVE_PRI 08324 if (!i->pri) 08325 #endif 08326 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08327 continue; 08328 } 08329 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08330 if (option_debug) 08331 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08332 /* Don't hold iflock while handling init events */ 08333 ast_mutex_unlock(&iflock); 08334 doomed = handle_init_event(i, res); 08335 ast_mutex_lock(&iflock); 08336 } 08337 } 08338 } 08339 ast_mutex_unlock(&iflock); 08340 } 08341 /* Never reached */ 08342 return NULL; 08343 08344 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4349 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().
04350 { 04351 #ifdef DAHDI_TONEDETECT 04352 int val; 04353 #endif 04354 04355 if (p->channel == CHAN_PSEUDO) 04356 return; 04357 04358 p->ignoredtmf = 0; 04359 04360 #ifdef DAHDI_TONEDETECT 04361 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04362 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04363 #endif 04364 if (!p->hardwaredtmf && p->dsp) { 04365 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04366 ast_dsp_set_features(p->dsp, p->dsp_features); 04367 } 04368 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 2082 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
02083 { 02084 static char buf[256]; 02085 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 02086 return events[event]; 02087 sprintf(buf, "Event %d", event); /* safe */ 02088 return buf; 02089 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2447 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02448 { 02449 int j; 02450 int k; 02451 float linear_gain = pow(10.0, gain / 20.0); 02452 02453 switch (law) { 02454 case DAHDI_LAW_ALAW: 02455 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02456 if (gain) { 02457 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02458 if (k > 32767) k = 32767; 02459 if (k < -32767) k = -32767; 02460 g->rxgain[j] = AST_LIN2A(k); 02461 } else { 02462 g->rxgain[j] = j; 02463 } 02464 } 02465 break; 02466 case DAHDI_LAW_MULAW: 02467 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02468 if (gain) { 02469 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02470 if (k > 32767) k = 32767; 02471 if (k < -32767) k = -32767; 02472 g->rxgain[j] = AST_LIN2MU(k); 02473 } else { 02474 g->rxgain[j] = j; 02475 } 02476 } 02477 break; 02478 } 02479 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2413 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02414 { 02415 int j; 02416 int k; 02417 float linear_gain = pow(10.0, gain / 20.0); 02418 02419 switch (law) { 02420 case DAHDI_LAW_ALAW: 02421 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02422 if (gain) { 02423 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02424 if (k > 32767) k = 32767; 02425 if (k < -32767) k = -32767; 02426 g->txgain[j] = AST_LIN2A(k); 02427 } else { 02428 g->txgain[j] = j; 02429 } 02430 } 02431 break; 02432 case DAHDI_LAW_MULAW: 02433 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02434 if (gain) { 02435 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02436 if (k > 32767) k = 32767; 02437 if (k < -32767) k = -32767; 02438 g->txgain[j] = AST_LIN2MU(k); 02439 } else { 02440 g->txgain[j] = j; 02441 } 02442 } 02443 break; 02444 } 02445 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 12460 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().
12461 { 12462 struct dahdi_pvt *p = iflist; 12463 while (p) { 12464 if (p->channel == channel) { 12465 break; 12466 } 12467 p = p->next; 12468 } 12469 return p; 12470 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4789 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().
04790 { 04791 int res; 04792 struct dahdi_spaninfo zi; 04793 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04794 /* 04795 * The conditional compilation is needed only in asterisk-1.4 for 04796 * backward compatibility with old zaptel drivers that don't have 04797 * a DAHDI_PARAMS.chan_alarms field. 04798 */ 04799 struct dahdi_params params; 04800 #endif 04801 04802 memset(&zi, 0, sizeof(zi)); 04803 zi.spanno = p->span; 04804 04805 /* First check for span alarms */ 04806 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 04807 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04808 return 0; 04809 } 04810 if (zi.alarms != DAHDI_ALARM_NONE) 04811 return zi.alarms; 04812 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04813 /* No alarms on the span. Check for channel alarms. */ 04814 memset(¶ms, 0, sizeof(params)); 04815 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04816 return params.chan_alarms; 04817 /* ioctl failed */ 04818 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04819 #endif 04820 return DAHDI_ALARM_NONE; 04821 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4905 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().
04906 { 04907 const char *alarm_str = alarm2str(alarms); 04908 04909 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04910 * doesn't know what to do with it. Don't confuse users with log messages. */ 04911 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04912 p->unknown_alarm = 1; 04913 return; 04914 } else { 04915 p->unknown_alarm = 0; 04916 } 04917 04918 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04919 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04920 "Alarm: %s\r\n" 04921 "Channel: %d\r\n", 04922 alarm_str, p->channel); 04923 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12275 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
12276 { 12277 int i, j; 12278 for (i = 0; i < num_cadence; i++) { 12279 char output[1024]; 12280 char tmp[16], tmp2[64]; 12281 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12282 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12283 12284 for (j = 0; j < 16; j++) { 12285 if (cadences[i].ringcadence[j] == 0) 12286 break; 12287 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12288 if (cidrings[i] * 2 - 1 == j) 12289 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12290 else 12291 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12292 if (j != 0) 12293 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12294 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12295 } 12296 ast_cli(fd,"%s\n",output); 12297 } 12298 return 0; 12299 }
Definition at line 7937 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.
07938 { 07939 int res; 07940 pthread_t threadid; 07941 pthread_attr_t attr; 07942 struct ast_channel *chan; 07943 pthread_attr_init(&attr); 07944 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07945 /* Handle an event on a given channel for the monitor thread. */ 07946 switch (event) { 07947 case DAHDI_EVENT_NONE: 07948 case DAHDI_EVENT_BITSCHANGED: 07949 break; 07950 case DAHDI_EVENT_WINKFLASH: 07951 case DAHDI_EVENT_RINGOFFHOOK: 07952 if (i->inalarm) break; 07953 if (i->radio) break; 07954 /* Got a ring/answer. What kind of channel are we? */ 07955 switch (i->sig) { 07956 case SIG_FXOLS: 07957 case SIG_FXOGS: 07958 case SIG_FXOKS: 07959 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07960 if (res && (errno == EBUSY)) 07961 break; 07962 if (i->cidspill) { 07963 /* Cancel VMWI spill */ 07964 free(i->cidspill); 07965 i->cidspill = NULL; 07966 } 07967 if (i->immediate) { 07968 dahdi_enable_ec(i); 07969 /* The channel is immediately up. Start right away */ 07970 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07971 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07972 if (!chan) { 07973 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07974 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07975 if (res < 0) 07976 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07977 } 07978 } else { 07979 /* Check for callerid, digits, etc */ 07980 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07981 if (chan) { 07982 if (has_voicemail(i)) 07983 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07984 else 07985 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07986 if (res < 0) 07987 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 07988 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07989 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07990 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07991 if (res < 0) 07992 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07993 ast_hangup(chan); 07994 } 07995 } else 07996 ast_log(LOG_WARNING, "Unable to create channel\n"); 07997 } 07998 break; 07999 case SIG_FXSLS: 08000 case SIG_FXSGS: 08001 case SIG_FXSKS: 08002 i->ringt = i->ringt_base; 08003 /* Fall through */ 08004 case SIG_EMWINK: 08005 case SIG_FEATD: 08006 case SIG_FEATDMF: 08007 case SIG_FEATDMF_TA: 08008 case SIG_E911: 08009 case SIG_FGC_CAMA: 08010 case SIG_FGC_CAMAMF: 08011 case SIG_FEATB: 08012 case SIG_EM: 08013 case SIG_EM_E1: 08014 case SIG_SFWINK: 08015 case SIG_SF_FEATD: 08016 case SIG_SF_FEATDMF: 08017 case SIG_SF_FEATB: 08018 case SIG_SF: 08019 /* Check for callerid, digits, etc */ 08020 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08021 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08022 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08023 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08024 if (res < 0) 08025 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08026 ast_hangup(chan); 08027 } else if (!chan) { 08028 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08029 } 08030 break; 08031 default: 08032 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08033 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08034 if (res < 0) 08035 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08036 pthread_attr_destroy(&attr); 08037 return NULL; 08038 } 08039 break; 08040 case DAHDI_EVENT_NOALARM: 08041 i->inalarm = 0; 08042 if (!i->unknown_alarm) { 08043 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08044 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08045 "Channel: %d\r\n", i->channel); 08046 } else { 08047 i->unknown_alarm = 0; 08048 } 08049 break; 08050 case DAHDI_EVENT_ALARM: 08051 i->inalarm = 1; 08052 res = get_alarms(i); 08053 handle_alarms(i, res); 08054 /* fall thru intentionally */ 08055 case DAHDI_EVENT_ONHOOK: 08056 if (i->radio) 08057 break; 08058 /* Back on hook. Hang up. */ 08059 switch (i->sig) { 08060 case SIG_FXOLS: 08061 case SIG_FXOGS: 08062 case SIG_FEATD: 08063 case SIG_FEATDMF: 08064 case SIG_FEATDMF_TA: 08065 case SIG_E911: 08066 case SIG_FGC_CAMA: 08067 case SIG_FGC_CAMAMF: 08068 case SIG_FEATB: 08069 case SIG_EM: 08070 case SIG_EM_E1: 08071 case SIG_EMWINK: 08072 case SIG_SF_FEATD: 08073 case SIG_SF_FEATDMF: 08074 case SIG_SF_FEATB: 08075 case SIG_SF: 08076 case SIG_SFWINK: 08077 case SIG_FXSLS: 08078 case SIG_FXSGS: 08079 case SIG_FXSKS: 08080 case SIG_GR303FXSKS: 08081 dahdi_disable_ec(i); 08082 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08083 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08084 break; 08085 case SIG_GR303FXOKS: 08086 case SIG_FXOKS: 08087 dahdi_disable_ec(i); 08088 /* Diddle the battery for the zhone */ 08089 #ifdef ZHONE_HACK 08090 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08091 usleep(1); 08092 #endif 08093 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08094 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08095 break; 08096 case SIG_PRI: 08097 dahdi_disable_ec(i); 08098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08099 break; 08100 default: 08101 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08102 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08103 pthread_attr_destroy(&attr); 08104 return NULL; 08105 } 08106 break; 08107 case DAHDI_EVENT_POLARITY: 08108 switch (i->sig) { 08109 case SIG_FXSLS: 08110 case SIG_FXSKS: 08111 case SIG_FXSGS: 08112 /* We have already got a PR before the channel was 08113 created, but it wasn't handled. We need polarity 08114 to be REV for remote hangup detection to work. 08115 At least in Spain */ 08116 if (i->hanguponpolarityswitch) 08117 i->polarity = POLARITY_REV; 08118 08119 if (i->cid_start == CID_START_POLARITY) { 08120 i->polarity = POLARITY_REV; 08121 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 08122 "CID detection on channel %d\n", 08123 i->channel); 08124 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08125 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08126 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08127 } 08128 } 08129 break; 08130 default: 08131 ast_log(LOG_WARNING, "handle_init_event detected " 08132 "polarity reversal on non-FXO (SIG_FXS) " 08133 "interface %d\n", i->channel); 08134 } 08135 break; 08136 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08137 ast_log(LOG_NOTICE, 08138 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08139 i->channel); 08140 pthread_attr_destroy(&attr); 08141 return i; 08142 } 08143 pthread_attr_destroy(&attr); 08144 return NULL; 08145 }
static int handle_mfcr2_call_files | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11683 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.
11684 { 11685 struct dahdi_pvt *p = NULL; 11686 int channo = 0; 11687 if (argc < 4) { 11688 return RESULT_SHOWUSAGE; 11689 } 11690 channo = (argc == 5) ? atoi(argv[4]) : -1; 11691 ast_mutex_lock(&iflock); 11692 p = iflist; 11693 while (p) { 11694 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11695 p = p->next; 11696 continue; 11697 } 11698 if ((channo != -1) && (p->channel != channo )) { 11699 p = p->next; 11700 continue; 11701 } 11702 if (ast_true(argv[3])) { 11703 openr2_chan_enable_call_files(p->r2chan); 11704 } else { 11705 openr2_chan_disable_call_files(p->r2chan); 11706 } 11707 if (channo != -1) { 11708 if (ast_true(argv[3])) { 11709 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 11710 } else { 11711 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 11712 } 11713 break; 11714 } else { 11715 p = p->next; 11716 } 11717 } 11718 if ((channo != -1) && !p) { 11719 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11720 } 11721 if (channo == -1) { 11722 if (ast_true(argv[3])) { 11723 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n"); 11724 } else { 11725 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n"); 11726 } 11727 } 11728 ast_mutex_unlock(&iflock); 11729 return RESULT_SUCCESS; 11730 }
static int handle_mfcr2_set_blocked | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11767 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.
11768 { 11769 struct dahdi_pvt *p = NULL; 11770 int channo = 0; 11771 channo = (argc == 4) ? atoi(argv[3]) : -1; 11772 ast_mutex_lock(&iflock); 11773 p = iflist; 11774 while (p) { 11775 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11776 p = p->next; 11777 continue; 11778 } 11779 if ((channo != -1) && (p->channel != channo )) { 11780 p = p->next; 11781 continue; 11782 } 11783 if (!openr2_chan_set_blocked(p->r2chan)) { 11784 ast_mutex_lock(&p->lock); 11785 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK; 11786 ast_mutex_unlock(&p->lock); 11787 } else { 11788 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel); 11789 } 11790 if (channo != -1) { 11791 break; 11792 } else { 11793 p = p->next; 11794 } 11795 } 11796 if ((channo != -1) && !p) { 11797 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11798 } 11799 ast_mutex_unlock(&iflock); 11800 return RESULT_SUCCESS; 11801 }
static int handle_mfcr2_set_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11624 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.
11625 { 11626 struct dahdi_pvt *p = NULL; 11627 int channo = 0; 11628 char *toklevel = NULL; 11629 char *saveptr = NULL; 11630 char *logval = NULL; 11631 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 11632 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 11633 if (argc < 4) { 11634 return RESULT_SHOWUSAGE; 11635 } 11636 channo = (argc == 5) ? atoi(argv[4]) : -1; 11637 logval = ast_strdupa(argv[3]); 11638 toklevel = strtok_r(logval, ",", &saveptr); 11639 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11640 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]); 11641 return RESULT_FAILURE; 11642 } else if (OR2_LOG_NOTHING == tmplevel) { 11643 loglevel = tmplevel; 11644 } else { 11645 loglevel |= tmplevel; 11646 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 11647 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11648 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 11649 continue; 11650 } 11651 loglevel |= tmplevel; 11652 } 11653 } 11654 ast_mutex_lock(&iflock); 11655 p = iflist; 11656 while (p) { 11657 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11658 p = p->next; 11659 continue; 11660 } 11661 if ((channo != -1) && (p->channel != channo )) { 11662 p = p->next; 11663 continue; 11664 } 11665 openr2_chan_set_log_level(p->r2chan, loglevel); 11666 if (channo != -1) { 11667 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel); 11668 break; 11669 } else { 11670 p = p->next; 11671 } 11672 } 11673 if ((channo != -1) && !p) { 11674 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11675 } 11676 if (channo == -1) { 11677 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]); 11678 } 11679 ast_mutex_unlock(&iflock); 11680 return RESULT_SUCCESS; 11681 }
static int handle_mfcr2_set_idle | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11732 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.
11733 { 11734 struct dahdi_pvt *p = NULL; 11735 int channo = 0; 11736 channo = (argc == 4) ? atoi(argv[3]) : -1; 11737 ast_mutex_lock(&iflock); 11738 p = iflist; 11739 while (p) { 11740 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11741 p = p->next; 11742 continue; 11743 } 11744 if ((channo != -1) && (p->channel != channo )) { 11745 p = p->next; 11746 continue; 11747 } 11748 if (!openr2_chan_set_idle(p->r2chan)) { 11749 ast_mutex_lock(&p->lock); 11750 p->mfcr2call = 0; 11751 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 11752 ast_mutex_unlock(&p->lock); 11753 } 11754 if (channo != -1) { 11755 break; 11756 } else { 11757 p = p->next; 11758 } 11759 } 11760 if ((channo != -1) && !p) { 11761 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11762 } 11763 ast_mutex_unlock(&iflock); 11764 return RESULT_SUCCESS; 11765 }
static int handle_mfcr2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11555 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.
11556 { 11557 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 11558 int filtertype = 0; 11559 int targetnum = 0; 11560 char channo[5]; 11561 char anino[5]; 11562 char dnisno[5]; 11563 struct dahdi_pvt *p; 11564 openr2_context_t *r2context; 11565 openr2_variant_t r2variant; 11566 if (!((argc == 3) || (argc == 5))) { 11567 return RESULT_SHOWUSAGE; 11568 } 11569 if (argc == 5) { 11570 if (!strcasecmp(argv[3], "group")) { 11571 targetnum = atoi(argv[4]); 11572 if ((targetnum < 0) || (targetnum > 63)) 11573 return RESULT_SHOWUSAGE; 11574 targetnum = 1 << targetnum; 11575 filtertype = 1; 11576 } else if (!strcasecmp(argv[3], "context")) { 11577 filtertype = 2; 11578 } else { 11579 return RESULT_SHOWUSAGE; 11580 } 11581 } 11582 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 11583 ast_mutex_lock(&iflock); 11584 p = iflist; 11585 while (p) { 11586 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11587 p = p->next; 11588 continue; 11589 } 11590 if (filtertype) { 11591 switch(filtertype) { 11592 case 1: /* mfcr2 show channels group <group> */ 11593 if (p->group != targetnum) { 11594 p = p->next; 11595 continue; 11596 } 11597 break; 11598 case 2: /* mfcr2 show channels context <context> */ 11599 if (strcasecmp(p->context, argv[4])) { 11600 p= p->next; 11601 continue; 11602 } 11603 break; 11604 default: 11605 ; 11606 } 11607 } 11608 r2context = openr2_chan_get_context(p->r2chan); 11609 r2variant = openr2_context_get_variant(r2context); 11610 snprintf(channo, sizeof(channo), "%d", p->channel); 11611 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 11612 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 11613 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 11614 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 11615 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 11616 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 11617 p = p->next; 11618 } 11619 ast_mutex_unlock(&iflock); 11620 return RESULT_SUCCESS; 11621 #undef FORMAT 11622 }
static int handle_mfcr2_show_variants | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11537 of file chan_dahdi.c.
References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.
11538 { 11539 #define FORMAT "%4s %40s\n" 11540 int numvariants = 0; 11541 int i; 11542 const openr2_variant_entry_t *variants; 11543 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 11544 ast_cli(fd, "Failed to get list of variants.\n"); 11545 return RESULT_FAILURE; 11546 } 11547 ast_cli(fd, FORMAT, "Variant Code", "Country"); 11548 for (i = 0; i < numvariants; i++) { 11549 ast_cli(fd, FORMAT, variants[i].name, variants[i].country); 11550 } 11551 return RESULT_SUCCESS; 11552 #undef FORMAT 11553 }
static int handle_mfcr2_version | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11531 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11532 { 11533 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 11534 return RESULT_SUCCESS; 11535 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11284 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11285 { 11286 int span; 11287 int x; 11288 if (argc < 4) { 11289 return RESULT_SHOWUSAGE; 11290 } 11291 span = atoi(argv[3]); 11292 if ((span < 1) || (span > NUM_SPANS)) { 11293 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 11294 return RESULT_SUCCESS; 11295 } 11296 if (!pris[span-1].pri) { 11297 ast_cli(fd, "No PRI running on span %d\n", span); 11298 return RESULT_SUCCESS; 11299 } 11300 for (x = 0; x < NUM_DCHANS; x++) { 11301 if (pris[span-1].dchans[x]) 11302 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11303 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11304 PRI_DEBUG_Q921_STATE); 11305 } 11306 ast_cli(fd, "Enabled debugging on span %d\n", span); 11307 return RESULT_SUCCESS; 11308 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11312 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11313 { 11314 int span; 11315 int x; 11316 if (argc < 5) 11317 return RESULT_SHOWUSAGE; 11318 span = atoi(argv[4]); 11319 if ((span < 1) || (span > NUM_SPANS)) { 11320 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11321 return RESULT_SUCCESS; 11322 } 11323 if (!pris[span-1].pri) { 11324 ast_cli(fd, "No PRI running on span %d\n", span); 11325 return RESULT_SUCCESS; 11326 } 11327 for (x = 0; x < NUM_DCHANS; x++) { 11328 if (pris[span-1].dchans[x]) 11329 pri_set_debug(pris[span-1].dchans[x], 0); 11330 } 11331 ast_cli(fd, "Disabled debugging on span %d\n", span); 11332 return RESULT_SUCCESS; 11333 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11335 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11336 { 11337 int span; 11338 int x; 11339 if (argc < 5) 11340 return RESULT_SHOWUSAGE; 11341 span = atoi(argv[4]); 11342 if ((span < 1) || (span > NUM_SPANS)) { 11343 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11344 return RESULT_SUCCESS; 11345 } 11346 if (!pris[span-1].pri) { 11347 ast_cli(fd, "No PRI running on span %d\n", span); 11348 return RESULT_SUCCESS; 11349 } 11350 for (x = 0; x < NUM_DCHANS; x++) { 11351 if (pris[span-1].dchans[x]) 11352 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11353 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11354 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 11355 } 11356 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 11357 return RESULT_SUCCESS; 11358 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11237 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.
11238 { 11239 int myfd; 11240 11241 if (!strncasecmp(argv[1], "set", 3)) { 11242 if (argc < 5) 11243 return RESULT_SHOWUSAGE; 11244 11245 if (ast_strlen_zero(argv[4])) 11246 return RESULT_SHOWUSAGE; 11247 11248 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 11249 if (myfd < 0) { 11250 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 11251 return RESULT_SUCCESS; 11252 } 11253 11254 ast_mutex_lock(&pridebugfdlock); 11255 11256 if (pridebugfd >= 0) 11257 close(pridebugfd); 11258 11259 pridebugfd = myfd; 11260 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 11261 11262 ast_mutex_unlock(&pridebugfdlock); 11263 11264 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 11265 } else { 11266 /* Assume it is unset */ 11267 ast_mutex_lock(&pridebugfdlock); 11268 close(pridebugfd); 11269 pridebugfd = -1; 11270 ast_cli(fd, "PRI debug output to file disabled\n"); 11271 ast_mutex_unlock(&pridebugfdlock); 11272 } 11273 11274 return RESULT_SUCCESS; 11275 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11441 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
11442 { 11443 int x; 11444 int span; 11445 int count=0; 11446 int debug=0; 11447 11448 for (span = 0; span < NUM_SPANS; span++) { 11449 if (pris[span].pri) { 11450 for (x = 0; x < NUM_DCHANS; x++) { 11451 debug = 0; 11452 if (pris[span].dchans[x]) { 11453 debug = pri_get_debug(pris[span].dchans[x]); 11454 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" ); 11455 count++; 11456 } 11457 } 11458 } 11459 11460 } 11461 ast_mutex_lock(&pridebugfdlock); 11462 if (pridebugfd >= 0) 11463 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 11464 ast_mutex_unlock(&pridebugfdlock); 11465 11466 if (!count) 11467 ast_cli(fd, "No debug set or no PRI running\n"); 11468 return RESULT_SUCCESS; 11469 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11402 of file chan_dahdi.c.
References ast_cli(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11403 { 11404 int span; 11405 int x; 11406 char status[256]; 11407 if (argc < 4) 11408 return RESULT_SHOWUSAGE; 11409 span = atoi(argv[3]); 11410 if ((span < 1) || (span > NUM_SPANS)) { 11411 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 11412 return RESULT_SUCCESS; 11413 } 11414 if (!pris[span-1].pri) { 11415 ast_cli(fd, "No PRI running on span %d\n", span); 11416 return RESULT_SUCCESS; 11417 } 11418 for (x = 0; x < NUM_DCHANS; x++) { 11419 if (pris[span-1].dchannels[x]) { 11420 #ifdef PRI_DUMP_INFO_STR 11421 char *info_str = NULL; 11422 #endif 11423 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 11424 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 11425 ast_cli(fd, "Status: %s\n", status); 11426 #ifdef PRI_DUMP_INFO_STR 11427 info_str = pri_dump_info_str(pris[span-1].pri); 11428 if (info_str) { 11429 ast_cli(fd, "%s", info_str); 11430 free(info_str); 11431 } 11432 #else 11433 pri_dump_info(pris[span-1].pri); 11434 #endif 11435 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 11436 } 11437 } 11438 return RESULT_SUCCESS; 11439 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11381 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11382 { 11383 int span; 11384 int x; 11385 char status[256]; 11386 if (argc != 3) 11387 return RESULT_SHOWUSAGE; 11388 11389 for (span = 0; span < NUM_SPANS; span++) { 11390 if (pris[span].pri) { 11391 for (x = 0; x < NUM_DCHANS; x++) { 11392 if (pris[span].dchannels[x]) { 11393 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 11394 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 11395 } 11396 } 11397 } 11398 } 11399 return RESULT_SUCCESS; 11400 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11278 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11278 { 11279 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 11280 return RESULT_SUCCESS; 11281 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2644 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().
02645 { 02646 02647 return ast_app_has_voicemail(p->mailbox, NULL); 02648 }
static void init_mfcr2_globals | ( | void | ) | [static] |
Definition at line 1263 of file chan_dahdi.c.
References AST_PTHREADT_NULL, master, NUM_SPANS, and r2links.
Referenced by dahdi_restart(), and load_module().
01264 { 01265 int r; 01266 mfcr2_cur_context_index = 0; 01267 mfcr2_cur_variant = OR2_VAR_UNKNOWN; 01268 mfcr2_cur_mfback_timeout = -1; 01269 mfcr2_cur_metering_pulse_timeout = -1; 01270 mfcr2_cur_max_ani = 10; 01271 mfcr2_cur_max_dnis = 4; 01272 mfcr2_cur_get_ani_first = -1; 01273 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 01274 mfcr2_cur_dtmf_dialing = -1; 01275 mfcr2_cur_dtmf_detection = -1; 01276 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON; 01277 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF; 01278 #endif 01279 mfcr2_cur_skip_category = -1; 01280 mfcr2_cur_call_files = 0; 01281 mfcr2_cur_allow_collect_calls = 0; 01282 mfcr2_cur_forced_release = 0; 01283 mfcr2_cur_double_answer = 0; 01284 mfcr2_cur_immediate_accept = -1; 01285 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING; 01286 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 01287 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir)); 01288 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file)); 01289 memset(r2links, 0, sizeof(r2links)); 01290 for (r = 0; r < NUM_SPANS; r++) { 01291 r2links[r].master = AST_PTHREADT_NULL; 01292 } 01293 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 2203 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
02204 { 02205 /* If they're listening to our channel, they're ours */ 02206 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 02207 return 1; 02208 /* If they're a talker on our (allocated) conference, they're ours */ 02209 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 02210 return 1; 02211 return 0; 02212 }
Definition at line 2233 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().
02234 { 02235 int x; 02236 int useslavenative; 02237 struct dahdi_pvt *slave = NULL; 02238 /* Start out optimistic */ 02239 useslavenative = 1; 02240 /* Update conference state in a stateless fashion */ 02241 for (x = 0; x < 3; x++) { 02242 /* Any three-way calling makes slave native mode *definitely* out 02243 of the question */ 02244 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 02245 useslavenative = 0; 02246 } 02247 /* If we don't have any 3-way calls, check to see if we have 02248 precisely one slave */ 02249 if (useslavenative) { 02250 for (x = 0; x < MAX_SLAVES; x++) { 02251 if (p->slaves[x]) { 02252 if (slave) { 02253 /* Whoops already have a slave! No 02254 slave native and stop right away */ 02255 slave = NULL; 02256 useslavenative = 0; 02257 break; 02258 } else { 02259 /* We have one slave so far */ 02260 slave = p->slaves[x]; 02261 } 02262 } 02263 } 02264 } 02265 /* If no slave, slave native definitely out */ 02266 if (!slave) 02267 useslavenative = 0; 02268 else if (slave->law != p->law) { 02269 useslavenative = 0; 02270 slave = NULL; 02271 } 02272 if (out) 02273 *out = slave; 02274 return useslavenative; 02275 }
static int load_module | ( | void | ) | [static] |
Definition at line 13872 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.
13873 { 13874 int res; 13875 13876 #ifdef HAVE_PRI 13877 int y,i; 13878 memset(pris, 0, sizeof(pris)); 13879 for (y = 0; y < NUM_SPANS; y++) { 13880 ast_mutex_init(&pris[y].lock); 13881 pris[y].offset = -1; 13882 pris[y].master = AST_PTHREADT_NULL; 13883 for (i = 0; i < NUM_DCHANS; i++) 13884 pris[y].fds[i] = -1; 13885 } 13886 pri_set_error(dahdi_pri_error); 13887 pri_set_message(dahdi_pri_message); 13888 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13889 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 13890 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 13891 } 13892 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 13893 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 13894 #endif 13895 #ifdef HAVE_OPENR2 13896 init_mfcr2_globals(); 13897 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13898 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec, 13899 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip); 13900 } 13901 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec, 13902 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip); 13903 #endif 13904 if ((res = setup_dahdi(0))) { 13905 return AST_MODULE_LOAD_DECLINE; 13906 } 13907 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13908 chan_tech = &dahdi_tech; 13909 } else { 13910 chan_tech = &zap_tech; 13911 } 13912 if (ast_channel_register(chan_tech)) { 13913 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 13914 __unload_module(); 13915 return -1; 13916 } 13917 #ifdef HAVE_PRI 13918 ast_string_field_init(&inuse, 16); 13919 ast_string_field_set(&inuse, name, "GR-303InUse"); 13920 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 13921 #endif 13922 #ifdef HAVE_OPENR2 13923 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 13924 #endif 13925 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 13926 13927 memset(round_robin, 0, sizeof(round_robin)); 13928 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 13929 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 13930 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 13931 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 13932 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 13933 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 13934 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 13935 13936 ast_cond_init(&ss_thread_complete, NULL); 13937 13938 return res; 13939 }
static struct dahdi_mfcr2* mfcr2_get_context | ( | int | id | ) | [static] |
Definition at line 8378 of file chan_dahdi.c.
References ast_log(), LOG_ERROR, and r2links.
Referenced by mkintf().
08379 { 08380 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) { 08381 ast_log(LOG_ERROR, "No more R2 links available!.\n"); 08382 return NULL; 08383 } 08384 return &r2links[id]; 08385 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 9534 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().
09535 { 09536 struct dahdi_pvt *p; 09537 struct dahdi_mfcr2 *mfcr2 = data; 09538 /* we should be using pthread_key_create 09539 and allocate pollers dynamically. 09540 I think do_monitor() could be leaking, since it 09541 could be cancelled at any time and is not 09542 using thread keys, why?, */ 09543 struct pollfd pollers[sizeof(mfcr2->pvts)]; 09544 int maxsleep = 20; 09545 int res = 0; 09546 int i = 0; 09547 int pollsize = 0; 09548 int oldstate = 0; 09549 int was_idle = 0; 09550 int quit_loop = 0; 09551 /* now that we're ready to get calls, unblock our side and 09552 get current line state */ 09553 for (i = 0; i < mfcr2->numchans; i++) { 09554 p = mfcr2->pvts[i]; 09555 if (openr2_chan_set_idle(p->r2chan)) { 09556 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel); 09557 } else { 09558 ast_mutex_lock(&p->lock); 09559 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 09560 mfcr2->pvts[i]->mfcr2call = 0; 09561 ast_mutex_unlock(&p->lock); 09562 } 09563 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 09564 } 09565 while(1) { 09566 /* we trust here that the mfcr2 channel list will not ever change once 09567 the module is loaded */ 09568 pollsize = 0; 09569 for (i = 0; i < mfcr2->numchans; i++) { 09570 pollers[i].revents = 0; 09571 pollers[i].events = 0; 09572 if (mfcr2->pvts[i]->owner) { 09573 continue; 09574 } 09575 if (!mfcr2->pvts[i]->r2chan) { 09576 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 09577 quit_loop = 1; 09578 break; 09579 } 09580 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 09581 pollers[i].events = POLLIN | POLLPRI; 09582 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 09583 pollsize++; 09584 } 09585 if (quit_loop) { 09586 break; 09587 } 09588 09589 if (pollsize == 0) { 09590 if (!was_idle) { 09591 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n"); 09592 was_idle = 1; 09593 } 09594 poll(NULL, 0, maxsleep); 09595 continue; 09596 } 09597 was_idle = 0; 09598 09599 /* probably poll() is a valid cancel point, lets just be on the safe side 09600 by calling pthread_testcancel */ 09601 pthread_testcancel(); 09602 res = poll(pollers, pollsize, maxsleep); 09603 pthread_testcancel(); 09604 if ((res < 0) && (errno != EINTR)) { 09605 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 09606 break; 09607 } 09608 /* do we want to allow to cancel while processing events? */ 09609 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 09610 for (i = 0; i < mfcr2->numchans; i++) { 09611 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) { 09612 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 09613 } 09614 } 09615 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 09616 } 09617 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 09618 return 0; 09619 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8511 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().
08512 { 08513 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08514 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08515 char fn[80]; 08516 #if 1 08517 struct dahdi_bufferinfo bi; 08518 #endif 08519 int res; 08520 int span=0; 08521 int here = 0; 08522 int x; 08523 struct dahdi_pvt **wlist; 08524 struct dahdi_pvt **wend; 08525 struct dahdi_params p; 08526 08527 wlist = &iflist; 08528 wend = &ifend; 08529 08530 #ifdef HAVE_PRI 08531 if (pri) { 08532 wlist = &pri->crvs; 08533 wend = &pri->crvend; 08534 } 08535 #endif 08536 08537 tmp2 = *wlist; 08538 prev = NULL; 08539 08540 while (tmp2) { 08541 if (!tmp2->destroy) { 08542 if (tmp2->channel == channel) { 08543 tmp = tmp2; 08544 here = 1; 08545 break; 08546 } 08547 if (tmp2->channel > channel) { 08548 break; 08549 } 08550 } 08551 prev = tmp2; 08552 tmp2 = tmp2->next; 08553 } 08554 08555 if (!here && reloading != 1) { 08556 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08557 if (tmp) 08558 free(tmp); 08559 return NULL; 08560 } 08561 ast_mutex_init(&tmp->lock); 08562 ifcount++; 08563 for (x = 0; x < 3; x++) 08564 tmp->subs[x].dfd = -1; 08565 tmp->channel = channel; 08566 tmp->priindication_oob = conf->chan.priindication_oob; 08567 } 08568 08569 if (tmp) { 08570 int chan_sig = conf->chan.sig; 08571 if (!here) { 08572 if ((channel != CHAN_PSEUDO) && !pri) { 08573 int count = 0; 08574 snprintf(fn, sizeof(fn), "%d", channel); 08575 /* Open non-blocking */ 08576 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08577 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 */ 08578 usleep(1); 08579 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08580 count++; 08581 } 08582 /* Allocate a DAHDI structure */ 08583 if (tmp->subs[SUB_REAL].dfd < 0) { 08584 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); 08585 destroy_dahdi_pvt(&tmp); 08586 return NULL; 08587 } 08588 memset(&p, 0, sizeof(p)); 08589 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08590 if (res < 0) { 08591 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08592 destroy_dahdi_pvt(&tmp); 08593 return NULL; 08594 } 08595 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 08596 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)); 08597 destroy_dahdi_pvt(&tmp); 08598 return NULL; 08599 } 08600 tmp->law = p.curlaw; 08601 tmp->span = p.spanno; 08602 span = p.spanno - 1; 08603 } else { 08604 if (channel == CHAN_PSEUDO) 08605 chan_sig = 0; 08606 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08607 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08608 return NULL; 08609 } 08610 } 08611 #ifdef HAVE_PRI 08612 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08613 int offset; 08614 int myswitchtype; 08615 int matchesdchan; 08616 int x,y; 08617 offset = 0; 08618 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08619 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08620 destroy_dahdi_pvt(&tmp); 08621 return NULL; 08622 } 08623 if (span >= NUM_SPANS) { 08624 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08625 destroy_dahdi_pvt(&tmp); 08626 return NULL; 08627 } else { 08628 struct dahdi_spaninfo si; 08629 si.spanno = 0; 08630 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08631 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08632 destroy_dahdi_pvt(&tmp); 08633 return NULL; 08634 } 08635 /* Store the logical span first based upon the real span */ 08636 tmp->logicalspan = pris[span].prilogicalspan; 08637 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08638 if (span < 0) { 08639 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08640 destroy_dahdi_pvt(&tmp); 08641 return NULL; 08642 } 08643 if (chan_sig == SIG_PRI) 08644 myswitchtype = conf->pri.switchtype; 08645 else 08646 myswitchtype = PRI_SWITCH_GR303_TMC; 08647 /* Make sure this isn't a d-channel */ 08648 matchesdchan=0; 08649 for (x = 0; x < NUM_SPANS; x++) { 08650 for (y = 0; y < NUM_DCHANS; y++) { 08651 if (pris[x].dchannels[y] == tmp->channel) { 08652 matchesdchan = 1; 08653 break; 08654 } 08655 } 08656 } 08657 offset = p.chanpos; 08658 if (!matchesdchan) { 08659 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08660 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08661 destroy_dahdi_pvt(&tmp); 08662 return NULL; 08663 } 08664 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08665 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08666 destroy_dahdi_pvt(&tmp); 08667 return NULL; 08668 } 08669 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08670 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08671 destroy_dahdi_pvt(&tmp); 08672 return NULL; 08673 } 08674 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08675 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08676 destroy_dahdi_pvt(&tmp); 08677 return NULL; 08678 } 08679 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08680 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08681 destroy_dahdi_pvt(&tmp); 08682 return NULL; 08683 } 08684 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08685 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08686 destroy_dahdi_pvt(&tmp); 08687 return NULL; 08688 } 08689 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08690 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08691 destroy_dahdi_pvt(&tmp); 08692 return NULL; 08693 } 08694 if (pris[span].numchans >= MAX_CHANNELS) { 08695 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08696 pris[span].trunkgroup); 08697 destroy_dahdi_pvt(&tmp); 08698 return NULL; 08699 } 08700 pris[span].nodetype = conf->pri.nodetype; 08701 pris[span].switchtype = myswitchtype; 08702 pris[span].nsf = conf->pri.nsf; 08703 pris[span].dialplan = conf->pri.dialplan; 08704 pris[span].localdialplan = conf->pri.localdialplan; 08705 pris[span].pvts[pris[span].numchans++] = tmp; 08706 pris[span].minunused = conf->pri.minunused; 08707 pris[span].minidle = conf->pri.minidle; 08708 pris[span].overlapdial = conf->pri.overlapdial; 08709 #ifdef HAVE_PRI_INBANDDISCONNECT 08710 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08711 #endif 08712 pris[span].facilityenable = conf->pri.facilityenable; 08713 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08714 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08715 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08716 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08717 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08718 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08719 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08720 pris[span].resetinterval = conf->pri.resetinterval; 08721 08722 tmp->pri = &pris[span]; 08723 tmp->prioffset = offset; 08724 tmp->call = NULL; 08725 } else { 08726 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08727 destroy_dahdi_pvt(&tmp); 08728 return NULL; 08729 } 08730 } 08731 } else { 08732 tmp->prioffset = 0; 08733 } 08734 #endif 08735 #ifdef HAVE_OPENR2 08736 if (chan_sig == SIG_MFCR2 && reloading != 1) { 08737 char logdir[OR2_MAX_PATH]; 08738 struct dahdi_mfcr2 *dahdi_r2; 08739 int threshold = 0; 08740 int snres = 0; 08741 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index); 08742 if (!dahdi_r2) { 08743 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 08744 } else if (!dahdi_r2->protocol_context){ 08745 char tmplogdir[] = "/tmp"; 08746 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 08747 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis); 08748 if (!dahdi_r2->protocol_context) { 08749 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 08750 destroy_dahdi_pvt(&tmp); 08751 return NULL; 08752 } 08753 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel); 08754 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first); 08755 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category); 08756 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold); 08757 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout); 08758 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout); 08759 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer); 08760 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept); 08761 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 08762 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off); 08763 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection); 08764 #endif 08765 if (ast_strlen_zero(mfcr2_cur_logdir)) { 08766 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) { 08767 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08768 } 08769 } else { 08770 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir); 08771 if (snres >= sizeof(logdir)) { 08772 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 08773 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08774 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08775 } 08776 } else { 08777 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08778 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 08779 } 08780 } 08781 } 08782 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) { 08783 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) { 08784 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file); 08785 } 08786 } 08787 } 08788 if (dahdi_r2) { 08789 /* TODO: should we check numchans overflow, or is it already done by DAHDI? */ 08790 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp; 08791 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context, 08792 tmp->subs[SUB_REAL].dfd, NULL, NULL); 08793 if (!tmp->r2chan) { 08794 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context); 08795 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 08796 destroy_dahdi_pvt(&tmp); 08797 return NULL; 08798 } 08799 openr2_chan_set_client_data(tmp->r2chan, tmp); 08800 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 08801 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 08802 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel); 08803 if (mfcr2_cur_call_files) { 08804 openr2_chan_enable_call_files(tmp->r2chan); 08805 } 08806 tmp->mfcr2_category = mfcr2_cur_category; 08807 tmp->mfcr2 = dahdi_r2; 08808 tmp->mfcr2call = 0; 08809 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK; 08810 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer; 08811 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls; 08812 tmp->mfcr2_ani_index = 0; 08813 tmp->mfcr2_dnis_index = 0; 08814 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls; 08815 tmp->mfcr2_forced_release = mfcr2_cur_forced_release; 08816 } 08817 } 08818 #endif 08819 } else { 08820 chan_sig = tmp->sig; 08821 if (tmp->subs[SUB_REAL].dfd > -1) { 08822 memset(&p, 0, sizeof(p)); 08823 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08824 } 08825 } 08826 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08827 switch (chan_sig) { 08828 case SIG_FXSKS: 08829 case SIG_FXSLS: 08830 case SIG_EM: 08831 case SIG_EM_E1: 08832 case SIG_EMWINK: 08833 case SIG_FEATD: 08834 case SIG_FEATDMF: 08835 case SIG_FEATDMF_TA: 08836 case SIG_FEATB: 08837 case SIG_E911: 08838 case SIG_SF: 08839 case SIG_SFWINK: 08840 case SIG_FGC_CAMA: 08841 case SIG_FGC_CAMAMF: 08842 case SIG_SF_FEATD: 08843 case SIG_SF_FEATDMF: 08844 case SIG_SF_FEATB: 08845 p.starttime = 250; 08846 break; 08847 } 08848 08849 if (tmp->radio) { 08850 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08851 p.channo = channel; 08852 p.rxwinktime = 1; 08853 p.rxflashtime = 1; 08854 p.starttime = 1; 08855 p.debouncetime = 5; 08856 } 08857 if (!tmp->radio) { 08858 p.channo = channel; 08859 /* Override timing settings based on config file */ 08860 if (conf->timing.prewinktime >= 0) 08861 p.prewinktime = conf->timing.prewinktime; 08862 if (conf->timing.preflashtime >= 0) 08863 p.preflashtime = conf->timing.preflashtime; 08864 if (conf->timing.winktime >= 0) 08865 p.winktime = conf->timing.winktime; 08866 if (conf->timing.flashtime >= 0) 08867 p.flashtime = conf->timing.flashtime; 08868 if (conf->timing.starttime >= 0) 08869 p.starttime = conf->timing.starttime; 08870 if (conf->timing.rxwinktime >= 0) 08871 p.rxwinktime = conf->timing.rxwinktime; 08872 if (conf->timing.rxflashtime >= 0) 08873 p.rxflashtime = conf->timing.rxflashtime; 08874 if (conf->timing.debouncetime >= 0) 08875 p.debouncetime = conf->timing.debouncetime; 08876 } 08877 08878 /* dont set parms on a pseudo-channel (or CRV) */ 08879 if (tmp->subs[SUB_REAL].dfd >= 0) 08880 { 08881 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 08882 if (res < 0) { 08883 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 08884 destroy_dahdi_pvt(&tmp); 08885 return NULL; 08886 } 08887 } 08888 #if 1 08889 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 08890 memset(&bi, 0, sizeof(bi)); 08891 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08892 if (!res) { 08893 bi.txbufpolicy = conf->chan.buf_policy; 08894 bi.rxbufpolicy = conf->chan.buf_policy; 08895 bi.numbufs = conf->chan.buf_no; 08896 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08897 if (res < 0) { 08898 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 08899 } 08900 } else 08901 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 08902 } 08903 #endif 08904 tmp->immediate = conf->chan.immediate; 08905 tmp->transfertobusy = conf->chan.transfertobusy; 08906 tmp->sig = chan_sig; 08907 tmp->outsigmod = conf->chan.outsigmod; 08908 tmp->ringt_base = ringt_base; 08909 tmp->firstradio = 0; 08910 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 08911 tmp->permcallwaiting = conf->chan.callwaiting; 08912 else 08913 tmp->permcallwaiting = 0; 08914 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 08915 tmp->destroy = 0; 08916 tmp->drings = drings; 08917 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 08918 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 08919 tmp->threewaycalling = conf->chan.threewaycalling; 08920 tmp->adsi = conf->chan.adsi; 08921 tmp->use_smdi = conf->chan.use_smdi; 08922 tmp->permhidecallerid = conf->chan.hidecallerid; 08923 tmp->callreturn = conf->chan.callreturn; 08924 tmp->echocancel = conf->chan.echocancel; 08925 tmp->echotraining = conf->chan.echotraining; 08926 tmp->pulse = conf->chan.pulse; 08927 if (tmp->echocancel) 08928 tmp->echocanbridged = conf->chan.echocanbridged; 08929 else { 08930 if (conf->chan.echocanbridged) 08931 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 08932 tmp->echocanbridged = 0; 08933 } 08934 tmp->busydetect = conf->chan.busydetect; 08935 tmp->busycount = conf->chan.busycount; 08936 tmp->busycompare = conf->chan.busycompare; 08937 tmp->busytonelength = conf->chan.busytonelength; 08938 tmp->busyquietlength = conf->chan.busyquietlength; 08939 tmp->busyfuzziness = conf->chan.busyfuzziness; 08940 tmp->silencethreshold = conf->chan.silencethreshold; 08941 tmp->callprogress = conf->chan.callprogress; 08942 tmp->cancallforward = conf->chan.cancallforward; 08943 tmp->dtmfrelax = conf->chan.dtmfrelax; 08944 tmp->callwaiting = tmp->permcallwaiting; 08945 tmp->hidecallerid = tmp->permhidecallerid; 08946 tmp->channel = channel; 08947 tmp->stripmsd = conf->chan.stripmsd; 08948 tmp->use_callerid = conf->chan.use_callerid; 08949 tmp->cid_signalling = conf->chan.cid_signalling; 08950 tmp->cid_start = conf->chan.cid_start; 08951 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 08952 tmp->restrictcid = conf->chan.restrictcid; 08953 tmp->use_callingpres = conf->chan.use_callingpres; 08954 tmp->priexclusive = conf->chan.priexclusive; 08955 if (tmp->usedistinctiveringdetection) { 08956 if (!tmp->use_callerid) { 08957 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 08958 tmp->use_callerid = 1; 08959 } 08960 } 08961 08962 if (tmp->cid_signalling == CID_SIG_SMDI) { 08963 if (!tmp->use_smdi) { 08964 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 08965 tmp->use_smdi = 1; 08966 } 08967 } 08968 if (tmp->use_smdi) { 08969 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 08970 if (!(tmp->smdi_iface)) { 08971 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 08972 tmp->use_smdi = 0; 08973 } 08974 } 08975 08976 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 08977 tmp->amaflags = conf->chan.amaflags; 08978 if (!here) { 08979 tmp->confno = -1; 08980 tmp->propconfno = -1; 08981 } 08982 tmp->canpark = conf->chan.canpark; 08983 tmp->transfer = conf->chan.transfer; 08984 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 08985 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 08986 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 08987 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 08988 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 08989 tmp->cid_ton = 0; 08990 if (chan_sig != SIG_PRI) { 08991 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 08992 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 08993 } else { 08994 tmp->cid_num[0] = '\0'; 08995 tmp->cid_name[0] = '\0'; 08996 } 08997 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 08998 tmp->msgstate = -1; 08999 tmp->group = conf->chan.group; 09000 tmp->callgroup = conf->chan.callgroup; 09001 tmp->pickupgroup= conf->chan.pickupgroup; 09002 tmp->rxgain = conf->chan.rxgain; 09003 tmp->txgain = conf->chan.txgain; 09004 tmp->tonezone = conf->chan.tonezone; 09005 tmp->onhooktime = time(NULL); 09006 if (tmp->subs[SUB_REAL].dfd > -1) { 09007 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09008 if (tmp->dsp) 09009 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09010 update_conf(tmp); 09011 if (!here) { 09012 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2)) 09013 /* Hang it up to be sure it's good */ 09014 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09015 } 09016 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09017 #ifdef HAVE_PRI 09018 /* the dchannel is down so put the channel in alarm */ 09019 if (tmp->pri && !pri_is_up(tmp->pri)) { 09020 tmp->inalarm = 1; 09021 } 09022 #endif 09023 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09024 tmp->inalarm = 1; 09025 handle_alarms(tmp, res); 09026 } else { 09027 /* yes, this looks strange... the unknown_alarm flag is only used to 09028 control whether an 'alarm cleared' message gets generated when we 09029 get an indication that the channel is no longer in alarm status. 09030 however, the channel *could* be in an alarm status that we aren't 09031 aware of (since get_alarms() only reports span alarms, not channel 09032 alarms). setting this flag will cause any potential 'alarm cleared' 09033 message to be suppressed, but if a real alarm occurs before that 09034 happens, this flag will get cleared by it and the situation will 09035 be normal. 09036 */ 09037 tmp->unknown_alarm = 1; 09038 } 09039 } 09040 09041 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09042 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09043 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09044 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09045 09046 } 09047 if (tmp && !here) { 09048 /* nothing on the iflist */ 09049 if (!*wlist) { 09050 *wlist = tmp; 09051 tmp->prev = NULL; 09052 tmp->next = NULL; 09053 *wend = tmp; 09054 } else { 09055 /* at least one member on the iflist */ 09056 struct dahdi_pvt *working = *wlist; 09057 09058 /* check if we maybe have to put it on the begining */ 09059 if (working->channel > tmp->channel) { 09060 tmp->next = *wlist; 09061 tmp->prev = NULL; 09062 (*wlist)->prev = tmp; 09063 *wlist = tmp; 09064 } else { 09065 /* go through all the members and put the member in the right place */ 09066 while (working) { 09067 /* in the middle */ 09068 if (working->next) { 09069 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09070 tmp->next = working->next; 09071 tmp->prev = working; 09072 working->next->prev = tmp; 09073 working->next = tmp; 09074 break; 09075 } 09076 } else { 09077 /* the last */ 09078 if (working->channel < tmp->channel) { 09079 working->next = tmp; 09080 tmp->next = NULL; 09081 tmp->prev = working; 09082 *wend = tmp; 09083 break; 09084 } 09085 } 09086 working = working->next; 09087 } 09088 } 09089 } 09090 } 09091 return tmp; 09092 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 6226 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().
06227 { 06228 int sent=0; 06229 int size; 06230 int res; 06231 int fd; 06232 fd = p->subs[index].dfd; 06233 while (len) { 06234 size = len; 06235 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06236 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06237 res = write(fd, buf, size); 06238 if (res != size) { 06239 if (option_debug) 06240 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06241 return sent; 06242 } 06243 len -= size; 06244 buf += size; 06245 } 06246 return sent; 06247 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6717 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06718 { 06719 char c; 06720 06721 *str = 0; /* start with empty output buffer */ 06722 for (;;) 06723 { 06724 /* Wait for the first digit (up to specified ms). */ 06725 c = ast_waitfordigit(chan, ms); 06726 /* if timeout, hangup or error, return as such */ 06727 if (c < 1) 06728 return c; 06729 *str++ = c; 06730 *str = 0; 06731 if (strchr(term, c)) 06732 return 1; 06733 } 06734 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3388 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().
03389 { 03390 int x = -1; 03391 03392 for (x = 0; x < NUM_DCHANS; x++) { 03393 if ((pri->dchans[x] == pri->pri)) 03394 break; 03395 } 03396 03397 return pri->fds[x]; 03398 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3358 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().
03359 { 03360 bearer->owner = &inuse; 03361 bearer->realcall = crv; 03362 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03363 if (crv->subs[SUB_REAL].owner) 03364 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 03365 crv->bearer = bearer; 03366 crv->call = bearer->call; 03367 crv->pri = pri; 03368 return 0; 03369 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9886 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().
09887 { 09888 do { 09889 pri->resetpos++; 09890 } while ((pri->resetpos < pri->numchans) && 09891 (!pri->pvts[pri->resetpos] || 09892 pri->pvts[pri->resetpos]->call || 09893 pri->pvts[pri->resetpos]->resetting)); 09894 if (pri->resetpos < pri->numchans) { 09895 /* Mark the channel as resetting and restart it */ 09896 pri->pvts[pri->resetpos]->resetting = 1; 09897 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 09898 } else { 09899 pri->resetting = 0; 09900 time(&pri->lastreset); 09901 } 09902 return 0; 09903 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8498 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08499 { 08500 if (pris[span].mastertrunkgroup) { 08501 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); 08502 return -1; 08503 } 08504 pris[span].mastertrunkgroup = trunkgroup; 08505 pris[span].prilogicalspan = logicalspan; 08506 return 0; 08507 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8435 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().
08436 { 08437 struct dahdi_spaninfo si; 08438 struct dahdi_params p; 08439 int fd; 08440 int span; 08441 int ospan=0; 08442 int x,y; 08443 for (x = 0; x < NUM_SPANS; x++) { 08444 if (pris[x].trunkgroup == trunkgroup) { 08445 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08446 return -1; 08447 } 08448 } 08449 for (y = 0; y < NUM_DCHANS; y++) { 08450 if (!channels[y]) 08451 break; 08452 memset(&si, 0, sizeof(si)); 08453 memset(&p, 0, sizeof(p)); 08454 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 08455 if (fd < 0) { 08456 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08457 return -1; 08458 } 08459 x = channels[y]; 08460 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08461 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08462 close(fd); 08463 return -1; 08464 } 08465 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08466 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08467 return -1; 08468 } 08469 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08470 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08471 close(fd); 08472 return -1; 08473 } 08474 span = p.spanno - 1; 08475 if (pris[span].trunkgroup) { 08476 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08477 close(fd); 08478 return -1; 08479 } 08480 if (pris[span].pvts[0]) { 08481 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08482 close(fd); 08483 return -1; 08484 } 08485 if (!y) { 08486 pris[span].trunkgroup = trunkgroup; 08487 pris[span].offset = channels[y] - p.chanpos; 08488 ospan = span; 08489 } 08490 pris[ospan].dchannels[y] = channels[y]; 08491 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08492 pris[span].span = span + 1; 08493 close(fd); 08494 } 08495 return 0; 08496 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 9985 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.
09986 { 09987 struct dahdi_pri *pri = vpri; 09988 pri_event *e; 09989 struct pollfd fds[NUM_DCHANS]; 09990 int res; 09991 int chanpos = 0; 09992 int x; 09993 int haveidles; 09994 int activeidles; 09995 int nextidle = -1; 09996 struct ast_channel *c; 09997 struct timeval tv, lowest, *next; 09998 struct timeval lastidle = { 0, 0 }; 09999 int doidling=0; 10000 char *cc; 10001 char idlen[80]; 10002 struct ast_channel *idle; 10003 pthread_t p; 10004 time_t t; 10005 int i, which=-1; 10006 int numdchans; 10007 int cause=0; 10008 struct dahdi_pvt *crv; 10009 pthread_t threadid; 10010 pthread_attr_t attr; 10011 char ani2str[6]; 10012 char plancallingnum[256]; 10013 char plancallingani[256]; 10014 char calledtonstr[10]; 10015 10016 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10017 10018 gettimeofday(&lastidle, NULL); 10019 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10020 /* Need to do idle dialing, check to be sure though */ 10021 cc = strchr(pri->idleext, '@'); 10022 if (cc) { 10023 *cc = '\0'; 10024 cc++; 10025 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10026 #if 0 10027 /* Extensions may not be loaded yet */ 10028 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10029 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10030 else 10031 #endif 10032 doidling = 1; 10033 } else 10034 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10035 } 10036 for (;;) { 10037 for (i = 0; i < NUM_DCHANS; i++) { 10038 if (!pri->dchannels[i]) 10039 break; 10040 fds[i].fd = pri->fds[i]; 10041 fds[i].events = POLLIN | POLLPRI; 10042 fds[i].revents = 0; 10043 } 10044 numdchans = i; 10045 time(&t); 10046 ast_mutex_lock(&pri->lock); 10047 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10048 if (pri->resetting && pri_is_up(pri)) { 10049 if (pri->resetpos < 0) 10050 pri_check_restart(pri); 10051 } else { 10052 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10053 pri->resetting = 1; 10054 pri->resetpos = -1; 10055 } 10056 } 10057 } 10058 /* Look for any idle channels if appropriate */ 10059 if (doidling && pri_is_up(pri)) { 10060 nextidle = -1; 10061 haveidles = 0; 10062 activeidles = 0; 10063 for (x = pri->numchans; x >= 0; x--) { 10064 if (pri->pvts[x] && !pri->pvts[x]->owner && 10065 !pri->pvts[x]->call) { 10066 if (haveidles < pri->minunused) { 10067 haveidles++; 10068 } else if (!pri->pvts[x]->resetting) { 10069 nextidle = x; 10070 break; 10071 } 10072 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10073 activeidles++; 10074 } 10075 if (nextidle > -1) { 10076 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10077 /* Don't create a new idle call more than once per second */ 10078 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10079 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 10080 if (idle) { 10081 pri->pvts[nextidle]->isidlecall = 1; 10082 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10083 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10084 dahdi_hangup(idle); 10085 } 10086 } else 10087 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10088 gettimeofday(&lastidle, NULL); 10089 } 10090 } else if ((haveidles < pri->minunused) && 10091 (activeidles > pri->minidle)) { 10092 /* Mark something for hangup if there is something 10093 that can be hungup */ 10094 for (x = pri->numchans; x >= 0; x--) { 10095 /* find a candidate channel */ 10096 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10097 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10098 haveidles++; 10099 /* Stop if we have enough idle channels or 10100 can't spare any more active idle ones */ 10101 if ((haveidles >= pri->minunused) || 10102 (activeidles <= pri->minidle)) 10103 break; 10104 } 10105 } 10106 } 10107 } 10108 /* Start with reasonable max */ 10109 lowest = ast_tv(60, 0); 10110 for (i = 0; i < NUM_DCHANS; i++) { 10111 /* Find lowest available d-channel */ 10112 if (!pri->dchannels[i]) 10113 break; 10114 if ((next = pri_schedule_next(pri->dchans[i]))) { 10115 /* We need relative time here */ 10116 tv = ast_tvsub(*next, ast_tvnow()); 10117 if (tv.tv_sec < 0) { 10118 tv = ast_tv(0,0); 10119 } 10120 if (doidling || pri->resetting) { 10121 if (tv.tv_sec > 1) { 10122 tv = ast_tv(1, 0); 10123 } 10124 } else { 10125 if (tv.tv_sec > 60) { 10126 tv = ast_tv(60, 0); 10127 } 10128 } 10129 } else if (doidling || pri->resetting) { 10130 /* Make sure we stop at least once per second if we're 10131 monitoring idle channels */ 10132 tv = ast_tv(1,0); 10133 } else { 10134 /* Don't poll for more than 60 seconds */ 10135 tv = ast_tv(60, 0); 10136 } 10137 if (!i || ast_tvcmp(tv, lowest) < 0) { 10138 lowest = tv; 10139 } 10140 } 10141 ast_mutex_unlock(&pri->lock); 10142 10143 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 10144 pthread_testcancel(); 10145 e = NULL; 10146 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 10147 pthread_testcancel(); 10148 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10149 10150 ast_mutex_lock(&pri->lock); 10151 if (!res) { 10152 for (which = 0; which < NUM_DCHANS; which++) { 10153 if (!pri->dchans[which]) 10154 break; 10155 /* Just a timeout, run the scheduler */ 10156 e = pri_schedule_run(pri->dchans[which]); 10157 if (e) 10158 break; 10159 } 10160 } else if (res > -1) { 10161 for (which = 0; which < NUM_DCHANS; which++) { 10162 if (!pri->dchans[which]) 10163 break; 10164 if (fds[which].revents & POLLPRI) { 10165 /* Check for an event */ 10166 x = 0; 10167 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 10168 if (x) 10169 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); 10170 /* Keep track of alarm state */ 10171 if (x == DAHDI_EVENT_ALARM) { 10172 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 10173 pri_find_dchan(pri); 10174 } else if (x == DAHDI_EVENT_NOALARM) { 10175 pri->dchanavail[which] |= DCHAN_NOTINALARM; 10176 pri_restart(pri->dchans[which]); 10177 } 10178 10179 if (option_debug) 10180 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 10181 } else if (fds[which].revents & POLLIN) { 10182 e = pri_check_event(pri->dchans[which]); 10183 } 10184 if (e) 10185 break; 10186 } 10187 } else if (errno != EINTR) 10188 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 10189 10190 if (e) { 10191 if (pri->debug) 10192 pri_dump_event(pri->dchans[which], e); 10193 10194 if (e->e != PRI_EVENT_DCHAN_DOWN) { 10195 if (!(pri->dchanavail[which] & DCHAN_UP)) { 10196 if (option_verbose > 1) 10197 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 10198 } 10199 pri->dchanavail[which] |= DCHAN_UP; 10200 } else { 10201 if (pri->dchanavail[which] & DCHAN_UP) { 10202 if (option_verbose > 1) 10203 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 10204 } 10205 pri->dchanavail[which] &= ~DCHAN_UP; 10206 } 10207 10208 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 10209 /* Must be an NFAS group that has the secondary dchan active */ 10210 pri->pri = pri->dchans[which]; 10211 10212 switch (e->e) { 10213 case PRI_EVENT_DCHAN_UP: 10214 if (!pri->pri) pri_find_dchan(pri); 10215 10216 /* Note presense of D-channel */ 10217 time(&pri->lastreset); 10218 10219 /* Restart in 5 seconds */ 10220 if (pri->resetinterval > -1) { 10221 pri->lastreset -= pri->resetinterval; 10222 pri->lastreset += 5; 10223 } 10224 pri->resetting = 0; 10225 /* Take the channels from inalarm condition */ 10226 for (i = 0; i < pri->numchans; i++) 10227 if (pri->pvts[i]) { 10228 pri->pvts[i]->inalarm = 0; 10229 } 10230 break; 10231 case PRI_EVENT_DCHAN_DOWN: 10232 pri_find_dchan(pri); 10233 if (!pri_is_up(pri)) { 10234 pri->resetting = 0; 10235 /* Hangup active channels and put them in alarm mode */ 10236 for (i = 0; i < pri->numchans; i++) { 10237 struct dahdi_pvt *p = pri->pvts[i]; 10238 if (p) { 10239 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 10240 /* T309 is not enabled : hangup calls when alarm occurs */ 10241 if (p->call) { 10242 if (p->pri && p->pri->pri) { 10243 pri_hangup(p->pri->pri, p->call, -1); 10244 pri_destroycall(p->pri->pri, p->call); 10245 p->call = NULL; 10246 } else 10247 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 10248 } 10249 if (p->realcall) { 10250 pri_hangup_all(p->realcall, pri); 10251 } else if (p->owner) 10252 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10253 } 10254 p->inalarm = 1; 10255 } 10256 } 10257 } 10258 break; 10259 case PRI_EVENT_RESTART: 10260 if (e->restart.channel > -1) { 10261 chanpos = pri_find_principle(pri, e->restart.channel); 10262 if (chanpos < 0) 10263 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 10264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10265 else { 10266 if (option_verbose > 2) 10267 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 10268 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10269 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10270 if (pri->pvts[chanpos]->call) { 10271 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 10272 pri->pvts[chanpos]->call = NULL; 10273 } 10274 /* Force soft hangup if appropriate */ 10275 if (pri->pvts[chanpos]->realcall) 10276 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10277 else if (pri->pvts[chanpos]->owner) 10278 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10279 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10280 } 10281 } else { 10282 if (option_verbose > 2) 10283 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 10284 for (x = 0; x < pri->numchans; x++) 10285 if (pri->pvts[x]) { 10286 ast_mutex_lock(&pri->pvts[x]->lock); 10287 if (pri->pvts[x]->call) { 10288 pri_destroycall(pri->pri, pri->pvts[x]->call); 10289 pri->pvts[x]->call = NULL; 10290 } 10291 if (pri->pvts[x]->realcall) 10292 pri_hangup_all(pri->pvts[x]->realcall, pri); 10293 else if (pri->pvts[x]->owner) 10294 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10295 ast_mutex_unlock(&pri->pvts[x]->lock); 10296 } 10297 } 10298 break; 10299 case PRI_EVENT_KEYPAD_DIGIT: 10300 chanpos = pri_find_principle(pri, e->digit.channel); 10301 if (chanpos < 0) { 10302 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 10303 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 10304 } else { 10305 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 10306 if (chanpos > -1) { 10307 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10308 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 10309 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 10310 /* how to do that */ 10311 int digitlen = strlen(e->digit.digits); 10312 char digit; 10313 int i; 10314 for (i = 0; i < digitlen; i++) { 10315 digit = e->digit.digits[i]; 10316 { 10317 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10318 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10319 } 10320 } 10321 } 10322 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10323 } 10324 } 10325 break; 10326 10327 case PRI_EVENT_INFO_RECEIVED: 10328 chanpos = pri_find_principle(pri, e->ring.channel); 10329 if (chanpos < 0) { 10330 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 10331 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10332 } else { 10333 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 10334 if (chanpos > -1) { 10335 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10336 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 10337 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 10338 /* how to do that */ 10339 int digitlen = strlen(e->ring.callednum); 10340 char digit; 10341 int i; 10342 for (i = 0; i < digitlen; i++) { 10343 digit = e->ring.callednum[i]; 10344 { 10345 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10346 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10347 } 10348 } 10349 } 10350 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10351 } 10352 } 10353 break; 10354 case PRI_EVENT_RING: 10355 crv = NULL; 10356 if (e->ring.channel == -1) 10357 chanpos = pri_find_empty_chan(pri, 1); 10358 else 10359 chanpos = pri_find_principle(pri, e->ring.channel); 10360 /* if no channel specified find one empty */ 10361 if (chanpos < 0) { 10362 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 10363 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10364 } else { 10365 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10366 if (pri->pvts[chanpos]->owner) { 10367 if (pri->pvts[chanpos]->call == e->ring.call) { 10368 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 10369 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10370 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10371 break; 10372 } else { 10373 /* This is where we handle initial glare */ 10374 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 10375 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10376 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10377 chanpos = -1; 10378 } 10379 } 10380 if (chanpos > -1) 10381 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10382 } 10383 if ((chanpos < 0) && (e->ring.flexible)) 10384 chanpos = pri_find_empty_chan(pri, 1); 10385 if (chanpos > -1) { 10386 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10387 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 10388 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 10389 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 10390 if (crv) 10391 ast_mutex_lock(&crv->lock); 10392 if (!crv || crv->owner) { 10393 pri->pvts[chanpos]->call = NULL; 10394 if (crv) { 10395 if (crv->owner) 10396 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10397 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); 10398 } else 10399 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); 10400 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 10401 if (crv) 10402 ast_mutex_unlock(&crv->lock); 10403 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10404 break; 10405 } 10406 } 10407 pri->pvts[chanpos]->call = e->ring.call; 10408 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 10409 if (pri->pvts[chanpos]->use_callerid) { 10410 ast_shrink_phone_number(plancallingnum); 10411 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 10412 #ifdef PRI_ANI 10413 if (!ast_strlen_zero(e->ring.callingani)) { 10414 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 10415 ast_shrink_phone_number(plancallingani); 10416 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 10417 } else { 10418 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10419 } 10420 #endif 10421 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 10422 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 10423 } else { 10424 pri->pvts[chanpos]->cid_num[0] = '\0'; 10425 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10426 pri->pvts[chanpos]->cid_name[0] = '\0'; 10427 pri->pvts[chanpos]->cid_ton = 0; 10428 } 10429 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 10430 e->ring.redirectingnum, e->ring.callingplanrdnis); 10431 /* If immediate=yes go to s|1 */ 10432 if (pri->pvts[chanpos]->immediate) { 10433 if (option_verbose > 2) 10434 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 10435 pri->pvts[chanpos]->exten[0] = 's'; 10436 pri->pvts[chanpos]->exten[1] = '\0'; 10437 } 10438 /* Get called number */ 10439 else if (!ast_strlen_zero(e->ring.callednum)) { 10440 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 10441 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10442 } else if (pri->overlapdial) 10443 pri->pvts[chanpos]->exten[0] = '\0'; 10444 else { 10445 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 10446 pri->pvts[chanpos]->exten[0] = 's'; 10447 pri->pvts[chanpos]->exten[1] = '\0'; 10448 } 10449 /* Set DNID on all incoming calls -- even immediate */ 10450 if (!ast_strlen_zero(e->ring.callednum)) 10451 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10452 /* No number yet, but received "sending complete"? */ 10453 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 10454 if (option_verbose > 2) 10455 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 10456 pri->pvts[chanpos]->exten[0] = 's'; 10457 pri->pvts[chanpos]->exten[1] = '\0'; 10458 } 10459 10460 /* Make sure extension exists (or in overlap dial mode, can exist) */ 10461 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 10462 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10463 /* Setup law */ 10464 int law; 10465 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 10466 /* Set to audio mode at this point */ 10467 law = 1; 10468 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 10469 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 10470 } 10471 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 10472 law = DAHDI_LAW_ALAW; 10473 else 10474 law = DAHDI_LAW_MULAW; 10475 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 10476 if (res < 0) 10477 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 10478 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 10479 if (res < 0) 10480 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 10481 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 10482 /* Just announce proceeding */ 10483 pri->pvts[chanpos]->proceeding = 1; 10484 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 10485 } else { 10486 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 10487 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10488 else 10489 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10490 } 10491 /* Get the use_callingpres state */ 10492 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 10493 10494 /* Start PBX */ 10495 if (!e->ring.complete 10496 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 10497 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10498 /* 10499 * Release the PRI lock while we create the channel 10500 * so other threads can send D channel messages. 10501 */ 10502 ast_mutex_unlock(&pri->lock); 10503 if (crv) { 10504 /* Set bearer and such */ 10505 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 10506 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10507 pri->pvts[chanpos]->owner = &inuse; 10508 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 10509 } else { 10510 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10511 } 10512 ast_mutex_lock(&pri->lock); 10513 if (c) { 10514 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10515 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10516 } 10517 if (e->ring.ani2 >= 0) { 10518 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10519 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10520 } 10521 10522 #ifdef SUPPORT_USERUSER 10523 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10524 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10525 } 10526 #endif 10527 10528 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10529 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10530 if (e->ring.redirectingreason >= 0) 10531 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10532 } 10533 10534 pthread_attr_init(&attr); 10535 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 10536 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 10537 if (option_verbose > 2) 10538 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 10539 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 10540 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10541 } else { 10542 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10543 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10544 if (c) 10545 ast_hangup(c); 10546 else { 10547 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10548 pri->pvts[chanpos]->call = NULL; 10549 } 10550 } 10551 pthread_attr_destroy(&attr); 10552 } else { 10553 /* 10554 * Release the PRI lock while we create the channel 10555 * so other threads can send D channel messages. 10556 */ 10557 ast_mutex_unlock(&pri->lock); 10558 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 10559 ast_mutex_lock(&pri->lock); 10560 if (c) { 10561 /* 10562 * It is reasonably safe to set the following 10563 * channel variables while the PRI and DAHDI private 10564 * structures are locked. The PBX has not been 10565 * started yet and it is unlikely that any other task 10566 * will do anything with the channel we have just 10567 * created. 10568 */ 10569 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10570 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10571 } 10572 if (e->ring.ani2 >= 0) { 10573 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10574 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10575 } 10576 10577 #ifdef SUPPORT_USERUSER 10578 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10579 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10580 } 10581 #endif 10582 10583 if (e->ring.redirectingreason >= 0) 10584 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10585 10586 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10587 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10588 } 10589 if (c && !ast_pbx_start(c)) { 10590 if (option_verbose > 2) 10591 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 10592 plancallingnum, pri->pvts[chanpos]->exten, 10593 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10594 10595 dahdi_enable_ec(pri->pvts[chanpos]); 10596 } else { 10597 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10598 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10599 if (c) { 10600 ast_hangup(c); 10601 } else { 10602 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10603 pri->pvts[chanpos]->call = NULL; 10604 } 10605 } 10606 } 10607 } else { 10608 if (option_verbose > 2) 10609 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 10610 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 10611 pri->pvts[chanpos]->prioffset, pri->span); 10612 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 10613 pri->pvts[chanpos]->call = NULL; 10614 pri->pvts[chanpos]->exten[0] = '\0'; 10615 } 10616 if (crv) 10617 ast_mutex_unlock(&crv->lock); 10618 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10619 } else { 10620 if (e->ring.flexible) 10621 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 10622 else 10623 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 10624 } 10625 break; 10626 case PRI_EVENT_RINGING: 10627 chanpos = pri_find_principle(pri, e->ringing.channel); 10628 if (chanpos < 0) { 10629 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 10630 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10631 } else { 10632 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 10633 if (chanpos < 0) { 10634 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 10635 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10636 } else { 10637 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10638 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10639 dahdi_enable_ec(pri->pvts[chanpos]); 10640 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 10641 pri->pvts[chanpos]->alerting = 1; 10642 } else 10643 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 10644 #ifdef PRI_PROGRESS_MASK 10645 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10646 #else 10647 if (e->ringing.progress == 8) { 10648 #endif 10649 /* Now we can do call progress detection */ 10650 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10651 /* RINGING detection isn't required because we got ALERTING signal */ 10652 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 10653 pri->pvts[chanpos]->dsp_features = 0; 10654 } 10655 } 10656 10657 #ifdef SUPPORT_USERUSER 10658 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 10659 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10660 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10661 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 10662 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10663 } 10664 #endif 10665 10666 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10667 } 10668 } 10669 break; 10670 case PRI_EVENT_PROGRESS: 10671 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 10672 chanpos = pri_find_principle(pri, e->proceeding.channel); 10673 if (chanpos > -1) { 10674 #ifdef PRI_PROGRESS_MASK 10675 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 10676 #else 10677 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 10678 #endif 10679 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10680 10681 if (e->proceeding.cause > -1) { 10682 if (option_verbose > 2) 10683 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 10684 10685 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 10686 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 10687 if (pri->pvts[chanpos]->owner) { 10688 if (option_verbose > 2) 10689 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 10690 10691 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 10692 f.subclass = AST_CONTROL_BUSY; 10693 } 10694 } 10695 } 10696 10697 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10698 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 10699 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10700 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10701 #ifdef PRI_PROGRESS_MASK 10702 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10703 #else 10704 if (e->proceeding.progress == 8) { 10705 #endif 10706 /* Now we can do call progress detection */ 10707 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10708 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10709 pri->pvts[chanpos]->dsp_features = 0; 10710 } 10711 /* Bring voice path up */ 10712 f.subclass = AST_CONTROL_PROGRESS; 10713 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10714 } 10715 pri->pvts[chanpos]->progress = 1; 10716 pri->pvts[chanpos]->dialing = 0; 10717 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10718 } 10719 } 10720 break; 10721 case PRI_EVENT_PROCEEDING: 10722 chanpos = pri_find_principle(pri, e->proceeding.channel); 10723 if (chanpos > -1) { 10724 if (!pri->pvts[chanpos]->proceeding) { 10725 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10726 10727 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10728 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 10729 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10730 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10731 #ifdef PRI_PROGRESS_MASK 10732 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10733 #else 10734 if (e->proceeding.progress == 8) { 10735 #endif 10736 /* Now we can do call progress detection */ 10737 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10738 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10739 pri->pvts[chanpos]->dsp_features = 0; 10740 } 10741 /* Bring voice path up */ 10742 f.subclass = AST_CONTROL_PROGRESS; 10743 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10744 } 10745 pri->pvts[chanpos]->proceeding = 1; 10746 pri->pvts[chanpos]->dialing = 0; 10747 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10748 } 10749 } 10750 break; 10751 case PRI_EVENT_FACNAME: 10752 chanpos = pri_find_principle(pri, e->facname.channel); 10753 if (chanpos < 0) { 10754 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 10755 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10756 } else { 10757 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 10758 if (chanpos < 0) { 10759 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 10760 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10761 } else { 10762 /* Re-use *69 field for PRI */ 10763 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10764 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 10765 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 10766 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 10767 dahdi_enable_ec(pri->pvts[chanpos]); 10768 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10769 } 10770 } 10771 break; 10772 case PRI_EVENT_ANSWER: 10773 chanpos = pri_find_principle(pri, e->answer.channel); 10774 if (chanpos < 0) { 10775 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 10776 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10777 } else { 10778 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 10779 if (chanpos < 0) { 10780 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 10781 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10782 } else { 10783 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10784 /* Now we can do call progress detection */ 10785 10786 /* We changed this so it turns on the DSP no matter what... progress or no progress. 10787 * By this time, we need DTMF detection and other features that were previously disabled 10788 * -- Matt F */ 10789 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10790 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10791 pri->pvts[chanpos]->dsp_features = 0; 10792 } 10793 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 10794 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 10795 x = DAHDI_START; 10796 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 10797 if (res < 0) { 10798 if (errno != EINPROGRESS) { 10799 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 10800 } 10801 } 10802 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10803 pri->pvts[chanpos]->dialing = 1; 10804 /* Send any "w" waited stuff */ 10805 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 10806 if (res < 0) { 10807 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 10808 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10809 } else 10810 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 10811 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10812 } else if (pri->pvts[chanpos]->confirmanswer) { 10813 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 10814 } else { 10815 pri->pvts[chanpos]->dialing = 0; 10816 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 10817 /* Enable echo cancellation if it's not on already */ 10818 dahdi_enable_ec(pri->pvts[chanpos]); 10819 } 10820 10821 #ifdef SUPPORT_USERUSER 10822 if (!ast_strlen_zero(e->answer.useruserinfo)) { 10823 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10824 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10825 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 10826 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10827 } 10828 #endif 10829 10830 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10831 } 10832 } 10833 break; 10834 case PRI_EVENT_HANGUP: 10835 chanpos = pri_find_principle(pri, e->hangup.channel); 10836 if (chanpos < 0) { 10837 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 10838 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10839 } else { 10840 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10841 if (chanpos > -1) { 10842 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10843 if (!pri->pvts[chanpos]->alreadyhungup) { 10844 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 10845 pri->pvts[chanpos]->alreadyhungup = 1; 10846 if (pri->pvts[chanpos]->realcall) 10847 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10848 else if (pri->pvts[chanpos]->owner) { 10849 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 10850 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10851 switch (pri->pvts[chanpos]->owner->_state) { 10852 case AST_STATE_BUSY: 10853 case AST_STATE_UP: 10854 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10855 break; 10856 default: 10857 switch (e->hangup.cause) { 10858 case PRI_CAUSE_USER_BUSY: 10859 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10860 break; 10861 case PRI_CAUSE_CALL_REJECTED: 10862 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10863 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10864 case PRI_CAUSE_SWITCH_CONGESTION: 10865 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10866 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10867 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10868 break; 10869 default: 10870 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10871 } 10872 break; 10873 } 10874 } 10875 if (option_verbose > 2) 10876 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 10877 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 10878 } else { 10879 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10880 pri->pvts[chanpos]->call = NULL; 10881 } 10882 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10883 if (option_verbose > 2) 10884 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 10885 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10886 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10887 pri->pvts[chanpos]->resetting = 1; 10888 } 10889 if (e->hangup.aoc_units > -1) 10890 if (option_verbose > 2) 10891 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10892 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10893 10894 #ifdef SUPPORT_USERUSER 10895 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 10896 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10897 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10898 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10899 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10900 } 10901 #endif 10902 10903 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10904 } else { 10905 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 10906 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10907 } 10908 } 10909 break; 10910 #ifndef PRI_EVENT_HANGUP_REQ 10911 #error please update libpri 10912 #endif 10913 case PRI_EVENT_HANGUP_REQ: 10914 chanpos = pri_find_principle(pri, e->hangup.channel); 10915 if (chanpos < 0) { 10916 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 10917 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10918 } else { 10919 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10920 if (chanpos > -1) { 10921 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10922 if (pri->pvts[chanpos]->realcall) 10923 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10924 else if (pri->pvts[chanpos]->owner) { 10925 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10926 switch (pri->pvts[chanpos]->owner->_state) { 10927 case AST_STATE_BUSY: 10928 case AST_STATE_UP: 10929 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10930 break; 10931 default: 10932 switch (e->hangup.cause) { 10933 case PRI_CAUSE_USER_BUSY: 10934 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10935 break; 10936 case PRI_CAUSE_CALL_REJECTED: 10937 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10938 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10939 case PRI_CAUSE_SWITCH_CONGESTION: 10940 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10941 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10942 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10943 break; 10944 default: 10945 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10946 } 10947 break; 10948 } 10949 if (option_verbose > 2) 10950 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); 10951 if (e->hangup.aoc_units > -1) 10952 if (option_verbose > 2) 10953 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10954 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10955 } else { 10956 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10957 pri->pvts[chanpos]->call = NULL; 10958 } 10959 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10960 if (option_verbose > 2) 10961 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 10962 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10963 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10964 pri->pvts[chanpos]->resetting = 1; 10965 } 10966 10967 #ifdef SUPPORT_USERUSER 10968 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 10969 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10970 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10971 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10972 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10973 } 10974 #endif 10975 10976 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10977 } else { 10978 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); 10979 } 10980 } 10981 break; 10982 case PRI_EVENT_HANGUP_ACK: 10983 chanpos = pri_find_principle(pri, e->hangup.channel); 10984 if (chanpos < 0) { 10985 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 10986 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10987 } else { 10988 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10989 if (chanpos > -1) { 10990 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10991 pri->pvts[chanpos]->call = NULL; 10992 pri->pvts[chanpos]->resetting = 0; 10993 if (pri->pvts[chanpos]->owner) { 10994 if (option_verbose > 2) 10995 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); 10996 } 10997 10998 #ifdef SUPPORT_USERUSER 10999 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11000 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11001 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11002 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11003 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11004 } 11005 #endif 11006 11007 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11008 } 11009 } 11010 break; 11011 case PRI_EVENT_CONFIG_ERR: 11012 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11013 break; 11014 case PRI_EVENT_RESTART_ACK: 11015 chanpos = pri_find_principle(pri, e->restartack.channel); 11016 if (chanpos < 0) { 11017 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11018 channel number, so we have to figure it out... This must be why 11019 everybody resets exactly a channel at a time. */ 11020 for (x = 0; x < pri->numchans; x++) { 11021 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11022 chanpos = x; 11023 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11024 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11025 pri->pvts[chanpos]->prioffset, pri->span); 11026 if (pri->pvts[chanpos]->realcall) 11027 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11028 else if (pri->pvts[chanpos]->owner) { 11029 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11030 pri->pvts[chanpos]->prioffset, pri->span); 11031 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11032 } 11033 pri->pvts[chanpos]->resetting = 0; 11034 if (option_verbose > 2) 11035 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11036 pri->pvts[chanpos]->prioffset, pri->span); 11037 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11038 if (pri->resetting) 11039 pri_check_restart(pri); 11040 break; 11041 } 11042 } 11043 if (chanpos < 0) { 11044 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11045 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11046 } 11047 } else { 11048 if (pri->pvts[chanpos]) { 11049 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11050 if (pri->pvts[chanpos]->realcall) 11051 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11052 else if (pri->pvts[chanpos]->owner) { 11053 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11054 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11055 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11056 } 11057 pri->pvts[chanpos]->resetting = 0; 11058 if (option_verbose > 2) 11059 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11060 pri->pvts[chanpos]->prioffset, pri->span); 11061 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11062 if (pri->resetting) 11063 pri_check_restart(pri); 11064 } 11065 } 11066 break; 11067 case PRI_EVENT_SETUP_ACK: 11068 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11069 if (chanpos < 0) { 11070 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11071 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11072 } else { 11073 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11074 if (chanpos > -1) { 11075 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11076 pri->pvts[chanpos]->setup_ack = 1; 11077 /* Send any queued digits */ 11078 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11079 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11080 pri_information(pri->pri, pri->pvts[chanpos]->call, 11081 pri->pvts[chanpos]->dialdest[x]); 11082 } 11083 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11084 } else 11085 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11086 } 11087 break; 11088 case PRI_EVENT_NOTIFY: 11089 chanpos = pri_find_principle(pri, e->notify.channel); 11090 if (chanpos < 0) { 11091 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11092 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11093 } else { 11094 struct ast_frame f = { AST_FRAME_CONTROL, }; 11095 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11096 switch (e->notify.info) { 11097 case PRI_NOTIFY_REMOTE_HOLD: 11098 f.subclass = AST_CONTROL_HOLD; 11099 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11100 break; 11101 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11102 f.subclass = AST_CONTROL_UNHOLD; 11103 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11104 break; 11105 } 11106 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11107 } 11108 break; 11109 default: 11110 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 11111 } 11112 } 11113 ast_mutex_unlock(&pri->lock); 11114 } 11115 /* Never reached */ 11116 return NULL; 11117 }
Definition at line 9624 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
09625 { 09626 struct dahdi_pvt *p; 09627 p = pri->crvs; 09628 while (p) { 09629 if (p->channel == crv) 09630 return p; 09631 p = p->next; 09632 } 09633 return NULL; 09634 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3400 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03401 { 03402 int oldslot = -1; 03403 struct pri *old; 03404 int newslot = -1; 03405 int x; 03406 old = pri->pri; 03407 for (x = 0; x < NUM_DCHANS; x++) { 03408 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03409 newslot = x; 03410 if (pri->dchans[x] == old) { 03411 oldslot = x; 03412 } 03413 } 03414 if (newslot < 0) { 03415 newslot = 0; 03416 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03417 pri->dchannels[newslot]); 03418 } 03419 if (old && (oldslot != newslot)) 03420 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03421 pri->dchannels[oldslot], pri->dchannels[newslot]); 03422 pri->pri = pri->dchans[newslot]; 03423 return 0; 03424 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9247 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().
09248 { 09249 int x; 09250 if (backwards) 09251 x = pri->numchans; 09252 else 09253 x = 0; 09254 for (;;) { 09255 if (backwards && (x < 0)) 09256 break; 09257 if (!backwards && (x >= pri->numchans)) 09258 break; 09259 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09260 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 09261 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09262 return x; 09263 } 09264 if (backwards) 09265 x--; 09266 else 09267 x++; 09268 } 09269 return -1; 09270 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 9637 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.
09638 { 09639 int x; 09640 int span = PRI_SPAN(channel); 09641 int spanfd; 09642 struct dahdi_params param; 09643 int principle = -1; 09644 int explicit = PRI_EXPLICIT(channel); 09645 channel = PRI_CHANNEL(channel); 09646 09647 if (!explicit) { 09648 spanfd = pri_active_dchan_fd(pri); 09649 memset(¶m, 0, sizeof(param)); 09650 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 09651 return -1; 09652 span = pris[param.spanno - 1].prilogicalspan; 09653 } 09654 09655 for (x = 0; x < pri->numchans; x++) { 09656 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 09657 principle = x; 09658 break; 09659 } 09660 } 09661 09662 return principle; 09663 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 9665 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.
09666 { 09667 int x; 09668 struct dahdi_pvt *crv; 09669 if (!c) { 09670 if (principle < 0) 09671 return -1; 09672 return principle; 09673 } 09674 if ((principle > -1) && 09675 (principle < pri->numchans) && 09676 (pri->pvts[principle]) && 09677 (pri->pvts[principle]->call == c)) 09678 return principle; 09679 /* First, check for other bearers */ 09680 for (x = 0; x < pri->numchans; x++) { 09681 if (!pri->pvts[x]) 09682 continue; 09683 if (pri->pvts[x]->call == c) { 09684 /* Found our call */ 09685 if (principle != x) { 09686 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 09687 09688 if (option_verbose > 2) 09689 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 09690 old->channel, new->channel); 09691 if (new->owner) { 09692 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 09693 old->channel, new->channel, new->channel); 09694 return -1; 09695 } 09696 /* Fix it all up now */ 09697 new->owner = old->owner; 09698 old->owner = NULL; 09699 if (new->owner) { 09700 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 09701 new->owner->tech_pvt = new; 09702 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 09703 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 09704 old->subs[SUB_REAL].owner = NULL; 09705 } else 09706 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); 09707 new->call = old->call; 09708 old->call = NULL; 09709 09710 /* Copy any DSP that may be present */ 09711 new->dsp = old->dsp; 09712 new->dsp_features = old->dsp_features; 09713 old->dsp = NULL; 09714 old->dsp_features = 0; 09715 } 09716 return principle; 09717 } 09718 } 09719 /* Now check for a CRV with no bearer */ 09720 crv = pri->crvs; 09721 while (crv) { 09722 if (crv->call == c) { 09723 /* This is our match... Perform some basic checks */ 09724 if (crv->bearer) 09725 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 09726 else if (pri->pvts[principle]->owner) 09727 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 09728 else { 09729 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 09730 wakeup the potential sleeper */ 09731 dahdi_close_sub(crv, SUB_REAL); 09732 pri->pvts[principle]->call = crv->call; 09733 pri_assign_bearer(crv, pri, pri->pvts[principle]); 09734 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 09735 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 09736 pri->trunkgroup, crv->channel); 09737 wakeup_sub(crv, SUB_REAL, pri); 09738 } 09739 return principle; 09740 } 09741 crv = crv->next; 09742 } 09743 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 09744 return -1; 09745 }
Definition at line 1142 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().
01143 { 01144 int res; 01145 /* Grab the lock first */ 01146 do { 01147 res = ast_mutex_trylock(&pri->lock); 01148 if (res) { 01149 DEADLOCK_AVOIDANCE(&pvt->lock); 01150 } 01151 } while (res); 01152 /* Then break the poll */ 01153 if (pri->master != AST_PTHREADT_NULL) 01154 pthread_kill(pri->master, SIGURG); 01155 return 0; 01156 }
Definition at line 9905 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.
09906 { 09907 int x; 09908 int redo; 09909 ast_mutex_unlock(&pri->lock); 09910 ast_mutex_lock(&p->lock); 09911 do { 09912 redo = 0; 09913 for (x = 0; x < 3; x++) { 09914 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 09915 redo++; 09916 DEADLOCK_AVOIDANCE(&p->lock); 09917 } 09918 if (p->subs[x].owner) { 09919 ast_queue_hangup(p->subs[x].owner); 09920 ast_mutex_unlock(&p->subs[x].owner->lock); 09921 } 09922 } 09923 } while (redo); 09924 ast_mutex_unlock(&p->lock); 09925 ast_mutex_lock(&pri->lock); 09926 return 0; 09927 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3348 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03349 { 03350 int x; 03351 for (x = 0; x < NUM_DCHANS; x++) { 03352 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03353 return 1; 03354 } 03355 return 0; 03356 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3371 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03372 { 03373 switch (level) { 03374 case 0: 03375 return "Primary"; 03376 case 1: 03377 return "Secondary"; 03378 case 2: 03379 return "Tertiary"; 03380 case 3: 03381 return "Quaternary"; 03382 default: 03383 return "<Unknown>"; 03384 } 03385 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 415 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().
00416 { 00417 ast_mutex_unlock(&pri->lock); 00418 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8389 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().
08390 { 08391 int x; 08392 int trunkgroup; 08393 /* Get appropriate trunk group if there is one */ 08394 trunkgroup = pris[*span].mastertrunkgroup; 08395 if (trunkgroup) { 08396 /* Select a specific trunk group */ 08397 for (x = 0; x < NUM_SPANS; x++) { 08398 if (pris[x].trunkgroup == trunkgroup) { 08399 *span = x; 08400 return 0; 08401 } 08402 } 08403 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08404 *span = -1; 08405 } else { 08406 if (pris[*span].trunkgroup) { 08407 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08408 *span = -1; 08409 } else if (pris[*span].mastertrunkgroup) { 08410 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08411 *span = -1; 08412 } else { 08413 if (si->totalchans == 31) { 08414 /* E1 */ 08415 pris[*span].dchannels[0] = 16 + offset; 08416 } else if (si->totalchans == 24) { 08417 /* T1 or J1 */ 08418 pris[*span].dchannels[0] = 24 + offset; 08419 } else if (si->totalchans == 3) { 08420 /* BRI */ 08421 pris[*span].dchannels[0] = 3 + offset; 08422 } else { 08423 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); 08424 *span = -1; 08425 return 0; 08426 } 08427 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08428 pris[*span].offset = offset; 08429 pris[*span].span = *span + 1; 08430 } 08431 } 08432 return 0; 08433 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 12888 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_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().
12889 { 12890 struct dahdi_pvt *tmp; 12891 int y; 12892 int found_pseudo = 0; 12893 char dahdichan[MAX_CHANLIST_LEN] = {}; 12894 12895 for (; v; v = v->next) { 12896 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 12897 continue; 12898 12899 /* Create the interface list */ 12900 if (!strcasecmp(v->name, "channel") 12901 #ifdef HAVE_PRI 12902 || !strcasecmp(v->name, "crv") 12903 #endif 12904 ) { 12905 int iscrv; 12906 if (skipchannels) 12907 continue; 12908 iscrv = !strcasecmp(v->name, "crv"); 12909 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 12910 return -1; 12911 } else if (!strcasecmp(v->name, "buffers")) { 12912 int res; 12913 char policy[21] = ""; 12914 12915 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 12916 if (res != 2) { 12917 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 12918 confp->chan.buf_no = numbufs; 12919 continue; 12920 } 12921 if (confp->chan.buf_no < 0) 12922 confp->chan.buf_no = numbufs; 12923 if (!strcasecmp(policy, "full")) { 12924 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 12925 } else if (!strcasecmp(policy, "immediate")) { 12926 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 12927 } else { 12928 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 12929 } 12930 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 12931 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 12932 if (v->name[0] == 'z' || v->name[0] == 'Z') { 12933 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 12934 } 12935 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 12936 if (ast_true(v->value)) 12937 confp->chan.usedistinctiveringdetection = 1; 12938 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 12939 if (ast_true(v->value)) 12940 distinctiveringaftercid = 1; 12941 } else if (!strcasecmp(v->name, "dring1context")) { 12942 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 12943 } else if (!strcasecmp(v->name, "dring2context")) { 12944 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 12945 } else if (!strcasecmp(v->name, "dring3context")) { 12946 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 12947 } else if (!strcasecmp(v->name, "dring1")) { 12948 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 12949 } else if (!strcasecmp(v->name, "dring2")) { 12950 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 12951 } else if (!strcasecmp(v->name, "dring3")) { 12952 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 12953 } else if (!strcasecmp(v->name, "usecallerid")) { 12954 confp->chan.use_callerid = ast_true(v->value); 12955 } else if (!strcasecmp(v->name, "cidsignalling")) { 12956 if (!strcasecmp(v->value, "bell")) 12957 confp->chan.cid_signalling = CID_SIG_BELL; 12958 else if (!strcasecmp(v->value, "v23")) 12959 confp->chan.cid_signalling = CID_SIG_V23; 12960 else if (!strcasecmp(v->value, "dtmf")) 12961 confp->chan.cid_signalling = CID_SIG_DTMF; 12962 else if (!strcasecmp(v->value, "smdi")) 12963 confp->chan.cid_signalling = CID_SIG_SMDI; 12964 else if (!strcasecmp(v->value, "v23_jp")) 12965 confp->chan.cid_signalling = CID_SIG_V23_JP; 12966 else if (ast_true(v->value)) 12967 confp->chan.cid_signalling = CID_SIG_BELL; 12968 } else if (!strcasecmp(v->name, "cidstart")) { 12969 if (!strcasecmp(v->value, "ring")) 12970 confp->chan.cid_start = CID_START_RING; 12971 else if (!strcasecmp(v->value, "polarity")) 12972 confp->chan.cid_start = CID_START_POLARITY; 12973 else if (ast_true(v->value)) 12974 confp->chan.cid_start = CID_START_RING; 12975 } else if (!strcasecmp(v->name, "threewaycalling")) { 12976 confp->chan.threewaycalling = ast_true(v->value); 12977 } else if (!strcasecmp(v->name, "cancallforward")) { 12978 confp->chan.cancallforward = ast_true(v->value); 12979 } else if (!strcasecmp(v->name, "relaxdtmf")) { 12980 if (ast_true(v->value)) 12981 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 12982 else 12983 confp->chan.dtmfrelax = 0; 12984 } else if (!strcasecmp(v->name, "mailbox")) { 12985 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 12986 } else if (!strcasecmp(v->name, "hasvoicemail")) { 12987 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 12988 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 12989 } 12990 } else if (!strcasecmp(v->name, "adsi")) { 12991 confp->chan.adsi = ast_true(v->value); 12992 } else if (!strcasecmp(v->name, "usesmdi")) { 12993 confp->chan.use_smdi = ast_true(v->value); 12994 } else if (!strcasecmp(v->name, "smdiport")) { 12995 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 12996 } else if (!strcasecmp(v->name, "transfer")) { 12997 confp->chan.transfer = ast_true(v->value); 12998 } else if (!strcasecmp(v->name, "canpark")) { 12999 confp->chan.canpark = ast_true(v->value); 13000 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 13001 confp->chan.echocanbridged = ast_true(v->value); 13002 } else if (!strcasecmp(v->name, "busydetect")) { 13003 confp->chan.busydetect = ast_true(v->value); 13004 } else if (!strcasecmp(v->name, "busycount")) { 13005 confp->chan.busycount = atoi(v->value); 13006 } else if (!strcasecmp(v->name, "silencethreshold")) { 13007 confp->chan.silencethreshold = atoi(v->value); 13008 } else if (!strcasecmp(v->name, "busycompare")) { 13009 confp->chan.busycompare = ast_true(v->value); 13010 } else if (!strcasecmp(v->name, "busypattern")) { 13011 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 13012 if (count == 1) 13013 confp->chan.busyquietlength = 0; 13014 else if (count < 1) 13015 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 13016 } else if (!strcasecmp(v->name, "busyfuzziness")) { 13017 confp->chan.busyfuzziness = atoi(v->value); 13018 } else if (!strcasecmp(v->name, "callprogress")) { 13019 if (ast_true(v->value)) 13020 confp->chan.callprogress |= 1; 13021 else 13022 confp->chan.callprogress &= ~1; 13023 } else if (!strcasecmp(v->name, "faxdetect")) { 13024 if (!strcasecmp(v->value, "incoming")) { 13025 confp->chan.callprogress |= 4; 13026 confp->chan.callprogress &= ~2; 13027 } else if (!strcasecmp(v->value, "outgoing")) { 13028 confp->chan.callprogress &= ~4; 13029 confp->chan.callprogress |= 2; 13030 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 13031 confp->chan.callprogress |= 6; 13032 else 13033 confp->chan.callprogress &= ~6; 13034 } else if (!strcasecmp(v->name, "echocancel")) { 13035 if (!ast_strlen_zero(v->value)) { 13036 y = atoi(v->value); 13037 } else 13038 y = 0; 13039 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 13040 confp->chan.echocancel = y; 13041 else { 13042 confp->chan.echocancel = ast_true(v->value); 13043 if (confp->chan.echocancel) 13044 confp->chan.echocancel=128; 13045 } 13046 } else if (!strcasecmp(v->name, "echotraining")) { 13047 if (sscanf(v->value, "%30d", &y) == 1) { 13048 if ((y < 10) || (y > 4000)) { 13049 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 13050 } else { 13051 confp->chan.echotraining = y; 13052 } 13053 } else if (ast_true(v->value)) { 13054 confp->chan.echotraining = 400; 13055 } else 13056 confp->chan.echotraining = 0; 13057 } else if (!strcasecmp(v->name, "hidecallerid")) { 13058 confp->chan.hidecallerid = ast_true(v->value); 13059 } else if (!strcasecmp(v->name, "hidecalleridname")) { 13060 confp->chan.hidecalleridname = ast_true(v->value); 13061 } else if (!strcasecmp(v->name, "pulsedial")) { 13062 confp->chan.pulse = ast_true(v->value); 13063 } else if (!strcasecmp(v->name, "callreturn")) { 13064 confp->chan.callreturn = ast_true(v->value); 13065 } else if (!strcasecmp(v->name, "callwaiting")) { 13066 confp->chan.callwaiting = ast_true(v->value); 13067 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 13068 confp->chan.callwaitingcallerid = ast_true(v->value); 13069 } else if (!strcasecmp(v->name, "context")) { 13070 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 13071 } else if (!strcasecmp(v->name, "language")) { 13072 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 13073 } else if (!strcasecmp(v->name, "progzone")) { 13074 ast_copy_string(progzone, v->value, sizeof(progzone)); 13075 } else if (!strcasecmp(v->name, "mohinterpret") 13076 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 13077 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 13078 } else if (!strcasecmp(v->name, "mohsuggest")) { 13079 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 13080 } else if (!strcasecmp(v->name, "stripmsd")) { 13081 confp->chan.stripmsd = atoi(v->value); 13082 } else if (!strcasecmp(v->name, "jitterbuffers")) { 13083 numbufs = atoi(v->value); 13084 } else if (!strcasecmp(v->name, "group")) { 13085 confp->chan.group = ast_get_group(v->value); 13086 } else if (!strcasecmp(v->name, "callgroup")) { 13087 confp->chan.callgroup = ast_get_group(v->value); 13088 } else if (!strcasecmp(v->name, "pickupgroup")) { 13089 confp->chan.pickupgroup = ast_get_group(v->value); 13090 } else if (!strcasecmp(v->name, "immediate")) { 13091 confp->chan.immediate = ast_true(v->value); 13092 } else if (!strcasecmp(v->name, "transfertobusy")) { 13093 confp->chan.transfertobusy = ast_true(v->value); 13094 } else if (!strcasecmp(v->name, "rxgain")) { 13095 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 13096 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 13097 } 13098 } else if (!strcasecmp(v->name, "txgain")) { 13099 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 13100 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 13101 } 13102 } else if (!strcasecmp(v->name, "tonezone")) { 13103 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 13104 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 13105 } 13106 } else if (!strcasecmp(v->name, "callerid")) { 13107 if (!strcasecmp(v->value, "asreceived")) { 13108 confp->chan.cid_num[0] = '\0'; 13109 confp->chan.cid_name[0] = '\0'; 13110 } else { 13111 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 13112 } 13113 } else if (!strcasecmp(v->name, "fullname")) { 13114 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 13115 } else if (!strcasecmp(v->name, "cid_number")) { 13116 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 13117 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 13118 confp->chan.dahditrcallerid = ast_true(v->value); 13119 if (strstr(v->name, "zap")) { 13120 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 13121 } 13122 } else if (!strcasecmp(v->name, "restrictcid")) { 13123 confp->chan.restrictcid = ast_true(v->value); 13124 } else if (!strcasecmp(v->name, "usecallingpres")) { 13125 confp->chan.use_callingpres = ast_true(v->value); 13126 } else if (!strcasecmp(v->name, "accountcode")) { 13127 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 13128 } else if (!strcasecmp(v->name, "amaflags")) { 13129 y = ast_cdr_amaflags2int(v->value); 13130 if (y < 0) 13131 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 13132 else 13133 confp->chan.amaflags = y; 13134 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 13135 confp->chan.polarityonanswerdelay = atoi(v->value); 13136 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 13137 confp->chan.answeronpolarityswitch = ast_true(v->value); 13138 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 13139 confp->chan.hanguponpolarityswitch = ast_true(v->value); 13140 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 13141 confp->chan.sendcalleridafter = atoi(v->value); 13142 } else if (reload != 1) { 13143 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 13144 confp->chan.outsigmod = -1; 13145 if (!strcasecmp(v->value, "em")) { 13146 confp->chan.sig = SIG_EM; 13147 } else if (!strcasecmp(v->value, "em_e1")) { 13148 confp->chan.sig = SIG_EM_E1; 13149 } else if (!strcasecmp(v->value, "em_w")) { 13150 confp->chan.sig = SIG_EMWINK; 13151 confp->chan.radio = 0; 13152 } else if (!strcasecmp(v->value, "fxs_ls")) { 13153 confp->chan.sig = SIG_FXSLS; 13154 confp->chan.radio = 0; 13155 } else if (!strcasecmp(v->value, "fxs_gs")) { 13156 confp->chan.sig = SIG_FXSGS; 13157 confp->chan.radio = 0; 13158 } else if (!strcasecmp(v->value, "fxs_ks")) { 13159 confp->chan.sig = SIG_FXSKS; 13160 confp->chan.radio = 0; 13161 } else if (!strcasecmp(v->value, "fxo_ls")) { 13162 confp->chan.sig = SIG_FXOLS; 13163 confp->chan.radio = 0; 13164 } else if (!strcasecmp(v->value, "fxo_gs")) { 13165 confp->chan.sig = SIG_FXOGS; 13166 confp->chan.radio = 0; 13167 } else if (!strcasecmp(v->value, "fxo_ks")) { 13168 confp->chan.sig = SIG_FXOKS; 13169 confp->chan.radio = 0; 13170 } else if (!strcasecmp(v->value, "fxs_rx")) { 13171 confp->chan.sig = SIG_FXSKS; 13172 confp->chan.radio = 1; 13173 } else if (!strcasecmp(v->value, "fxo_rx")) { 13174 confp->chan.sig = SIG_FXOLS; 13175 confp->chan.radio = 1; 13176 } else if (!strcasecmp(v->value, "fxs_tx")) { 13177 confp->chan.sig = SIG_FXSLS; 13178 confp->chan.radio = 1; 13179 } else if (!strcasecmp(v->value, "fxo_tx")) { 13180 confp->chan.sig = SIG_FXOGS; 13181 confp->chan.radio = 1; 13182 } else if (!strcasecmp(v->value, "em_rx")) { 13183 confp->chan.sig = SIG_EM; 13184 confp->chan.radio = 1; 13185 } else if (!strcasecmp(v->value, "em_tx")) { 13186 confp->chan.sig = SIG_EM; 13187 confp->chan.radio = 1; 13188 } else if (!strcasecmp(v->value, "em_rxtx")) { 13189 confp->chan.sig = SIG_EM; 13190 confp->chan.radio = 2; 13191 } else if (!strcasecmp(v->value, "em_txrx")) { 13192 confp->chan.sig = SIG_EM; 13193 confp->chan.radio = 2; 13194 } else if (!strcasecmp(v->value, "sf")) { 13195 confp->chan.sig = SIG_SF; 13196 confp->chan.radio = 0; 13197 } else if (!strcasecmp(v->value, "sf_w")) { 13198 confp->chan.sig = SIG_SFWINK; 13199 confp->chan.radio = 0; 13200 } else if (!strcasecmp(v->value, "sf_featd")) { 13201 confp->chan.sig = SIG_FEATD; 13202 confp->chan.radio = 0; 13203 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13204 confp->chan.sig = SIG_FEATDMF; 13205 confp->chan.radio = 0; 13206 } else if (!strcasecmp(v->value, "sf_featb")) { 13207 confp->chan.sig = SIG_SF_FEATB; 13208 confp->chan.radio = 0; 13209 } else if (!strcasecmp(v->value, "sf")) { 13210 confp->chan.sig = SIG_SF; 13211 confp->chan.radio = 0; 13212 } else if (!strcasecmp(v->value, "sf_rx")) { 13213 confp->chan.sig = SIG_SF; 13214 confp->chan.radio = 1; 13215 } else if (!strcasecmp(v->value, "sf_tx")) { 13216 confp->chan.sig = SIG_SF; 13217 confp->chan.radio = 1; 13218 } else if (!strcasecmp(v->value, "sf_rxtx")) { 13219 confp->chan.sig = SIG_SF; 13220 confp->chan.radio = 2; 13221 } else if (!strcasecmp(v->value, "sf_txrx")) { 13222 confp->chan.sig = SIG_SF; 13223 confp->chan.radio = 2; 13224 } else if (!strcasecmp(v->value, "featd")) { 13225 confp->chan.sig = SIG_FEATD; 13226 confp->chan.radio = 0; 13227 } else if (!strcasecmp(v->value, "featdmf")) { 13228 confp->chan.sig = SIG_FEATDMF; 13229 confp->chan.radio = 0; 13230 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13231 confp->chan.sig = SIG_FEATDMF_TA; 13232 confp->chan.radio = 0; 13233 } else if (!strcasecmp(v->value, "e911")) { 13234 confp->chan.sig = SIG_E911; 13235 confp->chan.radio = 0; 13236 } else if (!strcasecmp(v->value, "fgccama")) { 13237 confp->chan.sig = SIG_FGC_CAMA; 13238 confp->chan.radio = 0; 13239 } else if (!strcasecmp(v->value, "fgccamamf")) { 13240 confp->chan.sig = SIG_FGC_CAMAMF; 13241 confp->chan.radio = 0; 13242 } else if (!strcasecmp(v->value, "featb")) { 13243 confp->chan.sig = SIG_FEATB; 13244 confp->chan.radio = 0; 13245 #ifdef HAVE_OPENR2 13246 } else if (!strcasecmp(v->value, "mfcr2")) { 13247 confp->chan.sig = SIG_MFCR2; 13248 #endif 13249 #ifdef HAVE_PRI 13250 } else if (!strcasecmp(v->value, "pri_net")) { 13251 confp->chan.radio = 0; 13252 confp->chan.sig = SIG_PRI; 13253 confp->pri.nodetype = PRI_NETWORK; 13254 } else if (!strcasecmp(v->value, "pri_cpe")) { 13255 confp->chan.sig = SIG_PRI; 13256 confp->chan.radio = 0; 13257 confp->pri.nodetype = PRI_CPE; 13258 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 13259 confp->chan.sig = SIG_GR303FXOKS; 13260 confp->chan.radio = 0; 13261 confp->pri.nodetype = PRI_NETWORK; 13262 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 13263 confp->chan.sig = SIG_GR303FXSKS; 13264 confp->chan.radio = 0; 13265 confp->pri.nodetype = PRI_CPE; 13266 #endif 13267 } else { 13268 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13269 } 13270 } else if (!strcasecmp(v->name, "outsignalling")) { 13271 if (!strcasecmp(v->value, "em")) { 13272 confp->chan.outsigmod = SIG_EM; 13273 } else if (!strcasecmp(v->value, "em_e1")) { 13274 confp->chan.outsigmod = SIG_EM_E1; 13275 } else if (!strcasecmp(v->value, "em_w")) { 13276 confp->chan.outsigmod = SIG_EMWINK; 13277 } else if (!strcasecmp(v->value, "sf")) { 13278 confp->chan.outsigmod = SIG_SF; 13279 } else if (!strcasecmp(v->value, "sf_w")) { 13280 confp->chan.outsigmod = SIG_SFWINK; 13281 } else if (!strcasecmp(v->value, "sf_featd")) { 13282 confp->chan.outsigmod = SIG_FEATD; 13283 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13284 confp->chan.outsigmod = SIG_FEATDMF; 13285 } else if (!strcasecmp(v->value, "sf_featb")) { 13286 confp->chan.outsigmod = SIG_SF_FEATB; 13287 } else if (!strcasecmp(v->value, "sf")) { 13288 confp->chan.outsigmod = SIG_SF; 13289 } else if (!strcasecmp(v->value, "featd")) { 13290 confp->chan.outsigmod = SIG_FEATD; 13291 } else if (!strcasecmp(v->value, "featdmf")) { 13292 confp->chan.outsigmod = SIG_FEATDMF; 13293 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13294 confp->chan.outsigmod = SIG_FEATDMF_TA; 13295 } else if (!strcasecmp(v->value, "e911")) { 13296 confp->chan.outsigmod = SIG_E911; 13297 } else if (!strcasecmp(v->value, "fgccama")) { 13298 confp->chan.outsigmod = SIG_FGC_CAMA; 13299 } else if (!strcasecmp(v->value, "fgccamamf")) { 13300 confp->chan.outsigmod = SIG_FGC_CAMAMF; 13301 } else if (!strcasecmp(v->value, "featb")) { 13302 confp->chan.outsigmod = SIG_FEATB; 13303 } else { 13304 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13305 } 13306 #ifdef HAVE_PRI 13307 } else if (!strcasecmp(v->name, "pridialplan")) { 13308 if (!strcasecmp(v->value, "national")) { 13309 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 13310 } else if (!strcasecmp(v->value, "unknown")) { 13311 confp->pri.dialplan = PRI_UNKNOWN + 1; 13312 } else if (!strcasecmp(v->value, "private")) { 13313 confp->pri.dialplan = PRI_PRIVATE + 1; 13314 } else if (!strcasecmp(v->value, "international")) { 13315 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 13316 } else if (!strcasecmp(v->value, "local")) { 13317 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 13318 } else if (!strcasecmp(v->value, "dynamic")) { 13319 confp->pri.dialplan = -1; 13320 } else { 13321 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13322 } 13323 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 13324 if (!strcasecmp(v->value, "national")) { 13325 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 13326 } else if (!strcasecmp(v->value, "unknown")) { 13327 confp->pri.localdialplan = PRI_UNKNOWN + 1; 13328 } else if (!strcasecmp(v->value, "private")) { 13329 confp->pri.localdialplan = PRI_PRIVATE + 1; 13330 } else if (!strcasecmp(v->value, "international")) { 13331 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 13332 } else if (!strcasecmp(v->value, "local")) { 13333 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 13334 } else if (!strcasecmp(v->value, "dynamic")) { 13335 confp->pri.localdialplan = -1; 13336 } else { 13337 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13338 } 13339 } else if (!strcasecmp(v->name, "switchtype")) { 13340 if (!strcasecmp(v->value, "national")) 13341 confp->pri.switchtype = PRI_SWITCH_NI2; 13342 else if (!strcasecmp(v->value, "ni1")) 13343 confp->pri.switchtype = PRI_SWITCH_NI1; 13344 else if (!strcasecmp(v->value, "dms100")) 13345 confp->pri.switchtype = PRI_SWITCH_DMS100; 13346 else if (!strcasecmp(v->value, "4ess")) 13347 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 13348 else if (!strcasecmp(v->value, "5ess")) 13349 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 13350 else if (!strcasecmp(v->value, "euroisdn")) 13351 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 13352 else if (!strcasecmp(v->value, "qsig")) 13353 confp->pri.switchtype = PRI_SWITCH_QSIG; 13354 else { 13355 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 13356 return -1; 13357 } 13358 } else if (!strcasecmp(v->name, "nsf")) { 13359 if (!strcasecmp(v->value, "sdn")) 13360 confp->pri.nsf = PRI_NSF_SDN; 13361 else if (!strcasecmp(v->value, "megacom")) 13362 confp->pri.nsf = PRI_NSF_MEGACOM; 13363 else if (!strcasecmp(v->value, "tollfreemegacom")) 13364 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 13365 else if (!strcasecmp(v->value, "accunet")) 13366 confp->pri.nsf = PRI_NSF_ACCUNET; 13367 else if (!strcasecmp(v->value, "none")) 13368 confp->pri.nsf = PRI_NSF_NONE; 13369 else { 13370 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 13371 confp->pri.nsf = PRI_NSF_NONE; 13372 } 13373 } else if (!strcasecmp(v->name, "priindication")) { 13374 if (!strcasecmp(v->value, "outofband")) 13375 confp->chan.priindication_oob = 1; 13376 else if (!strcasecmp(v->value, "inband")) 13377 confp->chan.priindication_oob = 0; 13378 else 13379 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 13380 v->value, v->lineno); 13381 } else if (!strcasecmp(v->name, "priexclusive")) { 13382 confp->chan.priexclusive = ast_true(v->value); 13383 } else if (!strcasecmp(v->name, "internationalprefix")) { 13384 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 13385 } else if (!strcasecmp(v->name, "nationalprefix")) { 13386 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 13387 } else if (!strcasecmp(v->name, "localprefix")) { 13388 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 13389 } else if (!strcasecmp(v->name, "privateprefix")) { 13390 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 13391 } else if (!strcasecmp(v->name, "unknownprefix")) { 13392 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 13393 } else if (!strcasecmp(v->name, "resetinterval")) { 13394 if (!strcasecmp(v->value, "never")) 13395 confp->pri.resetinterval = -1; 13396 else if (atoi(v->value) >= 60) 13397 confp->pri.resetinterval = atoi(v->value); 13398 else 13399 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 13400 v->value, v->lineno); 13401 } else if (!strcasecmp(v->name, "minunused")) { 13402 confp->pri.minunused = atoi(v->value); 13403 } else if (!strcasecmp(v->name, "minidle")) { 13404 confp->pri.minidle = atoi(v->value); 13405 } else if (!strcasecmp(v->name, "idleext")) { 13406 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 13407 } else if (!strcasecmp(v->name, "idledial")) { 13408 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 13409 } else if (!strcasecmp(v->name, "overlapdial")) { 13410 if (ast_true(v->value)) { 13411 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13412 } else if (!strcasecmp(v->value, "incoming")) { 13413 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 13414 } else if (!strcasecmp(v->value, "outgoing")) { 13415 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 13416 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 13417 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13418 } else { 13419 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 13420 } 13421 #ifdef HAVE_PRI_INBANDDISCONNECT 13422 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 13423 confp->pri.inbanddisconnect = ast_true(v->value); 13424 #endif 13425 } else if (!strcasecmp(v->name, "pritimer")) { 13426 #ifdef PRI_GETSET_TIMERS 13427 char tmp[20]; 13428 char *timerc; 13429 char *c; 13430 int timer; 13431 int timeridx; 13432 13433 ast_copy_string(tmp, v->value, sizeof(tmp)); 13434 c = tmp; 13435 timerc = strsep(&c, ","); 13436 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 13437 timeridx = pri_timer2idx(timerc); 13438 timer = atoi(c); 13439 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 13440 ast_log(LOG_WARNING, 13441 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 13442 v->lineno); 13443 } else if (!timer) { 13444 ast_log(LOG_WARNING, 13445 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 13446 c, timerc, v->lineno); 13447 } else { 13448 pritimers[timeridx] = timer; 13449 } 13450 } else { 13451 ast_log(LOG_WARNING, 13452 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 13453 v->value, v->lineno); 13454 } 13455 #endif /* PRI_GETSET_TIMERS */ 13456 } else if (!strcasecmp(v->name, "facilityenable")) { 13457 confp->pri.facilityenable = ast_true(v->value); 13458 #endif /* HAVE_PRI */ 13459 #ifdef HAVE_OPENR2 13460 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 13461 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file)); 13462 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); 13463 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 13464 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir)); 13465 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 13466 mfcr2_cur_variant = openr2_proto_get_variant(v->value); 13467 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) { 13468 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno); 13469 } 13470 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 13471 mfcr2_cur_mfback_timeout = atoi(v->value); 13472 if (!mfcr2_cur_mfback_timeout) { 13473 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 13474 mfcr2_cur_mfback_timeout = -1; 13475 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) { 13476 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 13477 } 13478 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 13479 mfcr2_cur_metering_pulse_timeout = atoi(v->value); 13480 if (mfcr2_cur_metering_pulse_timeout > 500) { 13481 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n"); 13482 } 13483 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 13484 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) { 13485 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0; 13486 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) { 13487 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0; 13488 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) { 13489 mfcr2_cur_dtmf_time_on = atoi(v->value); 13490 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) { 13491 mfcr2_cur_dtmf_time_off = atoi(v->value); 13492 #endif 13493 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 13494 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0; 13495 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 13496 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0; 13497 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 13498 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0; 13499 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 13500 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0; 13501 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 13502 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0; 13503 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 13504 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0; 13505 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 13506 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0; 13507 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 13508 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0; 13509 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 13510 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0; 13511 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 13512 mfcr2_cur_max_ani = atoi(v->value); 13513 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) { 13514 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1; 13515 } 13516 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 13517 mfcr2_cur_max_dnis = atoi(v->value); 13518 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) { 13519 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1; 13520 } 13521 } else if (!strcasecmp(v->name, "mfcr2_category")) { 13522 mfcr2_cur_category = openr2_proto_get_category(v->value); 13523 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) { 13524 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 13525 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 13526 v->value, v->lineno); 13527 } 13528 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 13529 openr2_log_level_t tmplevel; 13530 char *toklevel = NULL; 13531 char *saveptr = NULL; 13532 char *logval = ast_strdupa(v->value); 13533 toklevel = strtok_r(logval, ",", &saveptr); 13534 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13535 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno); 13536 } else if (OR2_LOG_NOTHING == tmplevel) { 13537 mfcr2_cur_loglevel = tmplevel; 13538 } else { 13539 mfcr2_cur_loglevel |= tmplevel; 13540 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 13541 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13542 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno); 13543 continue; 13544 } 13545 mfcr2_cur_loglevel |= tmplevel; 13546 } 13547 } 13548 #endif /* HAVE_OPENR2 */ 13549 13550 } else if (!strcasecmp(v->name, "cadence")) { 13551 /* setup to scan our argument */ 13552 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 13553 int i; 13554 struct dahdi_ring_cadence new_cadence; 13555 int cid_location = -1; 13556 int firstcadencepos = 0; 13557 char original_args[80]; 13558 int cadence_is_ok = 1; 13559 13560 ast_copy_string(original_args, v->value, sizeof(original_args)); 13561 /* 16 cadences allowed (8 pairs) */ 13562 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]); 13563 13564 /* Cadence must be even (on/off) */ 13565 if (element_count % 2 == 1) { 13566 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 13567 cadence_is_ok = 0; 13568 } 13569 13570 /* Ring cadences cannot be negative */ 13571 for (i = 0; i < element_count; i++) { 13572 if (c[i] == 0) { 13573 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 13574 cadence_is_ok = 0; 13575 break; 13576 } else if (c[i] < 0) { 13577 if (i % 2 == 1) { 13578 /* Silence duration, negative possibly okay */ 13579 if (cid_location == -1) { 13580 cid_location = i; 13581 c[i] *= -1; 13582 } else { 13583 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 13584 cadence_is_ok = 0; 13585 break; 13586 } 13587 } else { 13588 if (firstcadencepos == 0) { 13589 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 13590 /* duration will be passed negative to the DAHDI driver */ 13591 } else { 13592 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 13593 cadence_is_ok = 0; 13594 break; 13595 } 13596 } 13597 } 13598 } 13599 13600 /* Substitute our scanned cadence */ 13601 for (i = 0; i < 16; i++) { 13602 new_cadence.ringcadence[i] = c[i]; 13603 } 13604 13605 if (cadence_is_ok) { 13606 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 13607 if (element_count < 2) { 13608 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 13609 } else { 13610 if (cid_location == -1) { 13611 /* user didn't say; default to first pause */ 13612 cid_location = 1; 13613 } else { 13614 /* convert element_index to cidrings value */ 13615 cid_location = (cid_location + 1) / 2; 13616 } 13617 /* ---we like their cadence; try to install it--- */ 13618 if (!user_has_defined_cadences++) 13619 /* this is the first user-defined cadence; clear the default user cadences */ 13620 num_cadence = 0; 13621 if ((num_cadence+1) >= NUM_CADENCE_MAX) 13622 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 13623 else { 13624 cadences[num_cadence] = new_cadence; 13625 cidrings[num_cadence++] = cid_location; 13626 if (option_verbose > 2) 13627 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 13628 } 13629 } 13630 } 13631 } else if (!strcasecmp(v->name, "ringtimeout")) { 13632 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 13633 } else if (!strcasecmp(v->name, "prewink")) { 13634 confp->timing.prewinktime = atoi(v->value); 13635 } else if (!strcasecmp(v->name, "preflash")) { 13636 confp->timing.preflashtime = atoi(v->value); 13637 } else if (!strcasecmp(v->name, "wink")) { 13638 confp->timing.winktime = atoi(v->value); 13639 } else if (!strcasecmp(v->name, "flash")) { 13640 confp->timing.flashtime = atoi(v->value); 13641 } else if (!strcasecmp(v->name, "start")) { 13642 confp->timing.starttime = atoi(v->value); 13643 } else if (!strcasecmp(v->name, "rxwink")) { 13644 confp->timing.rxwinktime = atoi(v->value); 13645 } else if (!strcasecmp(v->name, "rxflash")) { 13646 confp->timing.rxflashtime = atoi(v->value); 13647 } else if (!strcasecmp(v->name, "debounce")) { 13648 confp->timing.debouncetime = atoi(v->value); 13649 } else if (!strcasecmp(v->name, "toneduration")) { 13650 int toneduration; 13651 int ctlfd; 13652 int res; 13653 struct dahdi_dialparams dps; 13654 13655 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 13656 13657 if (ctlfd == -1) { 13658 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 13659 return -1; 13660 } 13661 13662 toneduration = atoi(v->value); 13663 if (toneduration > -1) { 13664 memset(&dps, 0, sizeof(dps)); 13665 13666 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 13667 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 13668 if (res < 0) { 13669 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 13670 return -1; 13671 } 13672 } 13673 close(ctlfd); 13674 } else if (!strcasecmp(v->name, "defaultcic")) { 13675 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 13676 } else if (!strcasecmp(v->name, "defaultozz")) { 13677 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 13678 } 13679 } else if (!skipchannels) 13680 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 13681 } 13682 if (dahdichan[0]) { 13683 /* The user has set 'dahdichan' */ 13684 /*< \todo pass proper line number instead of 0 */ 13685 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 13686 return -1; 13687 } 13688 } 13689 /*< \todo why check for the pseudo in the per-channel section. 13690 * Any actual use for manual setup of the pseudo channel? */ 13691 if (!found_pseudo && reload != 1) { 13692 /* use the default configuration for a channel, so 13693 that any settings from real configured channels 13694 don't "leak" into the pseudo channel config 13695 */ 13696 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13697 13698 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 13699 13700 if (tmp) { 13701 if (option_verbose > 2) 13702 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 13703 } else { 13704 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 13705 } 13706 } 13707 return 0; 13708 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 9929 of file chan_dahdi.c.
Referenced by __oh323_new().
09930 { 09931 switch (redirectingreason) { 09932 case 0: 09933 return "UNKNOWN"; 09934 case 1: 09935 return "BUSY"; 09936 case 2: 09937 return "NO_REPLY"; 09938 case 0xF: 09939 return "UNCONDITIONAL"; 09940 default: 09941 return "NOREDIRECT"; 09942 } 09943 }
static int reload | ( | void | ) | [static] |
Definition at line 14042 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
14043 { 14044 int res = 0; 14045 14046 res = setup_dahdi(1); 14047 if (res) { 14048 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 14049 return -1; 14050 } 14051 return 0; 14052 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2277 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().
02278 { 02279 p->confno = -1; 02280 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 02281 if (p->subs[SUB_REAL].dfd > -1) { 02282 struct dahdi_confinfo zi; 02283 02284 memset(&zi, 0, sizeof(zi)); 02285 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 02286 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 02287 } 02288 return 0; 02289 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8346 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().
08347 { 08348 pthread_attr_t attr; 08349 pthread_attr_init(&attr); 08350 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08351 /* If we're supposed to be stopped -- stay stopped */ 08352 if (monitor_thread == AST_PTHREADT_STOP) 08353 return 0; 08354 ast_mutex_lock(&monlock); 08355 if (monitor_thread == pthread_self()) { 08356 ast_mutex_unlock(&monlock); 08357 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08358 return -1; 08359 } 08360 if (monitor_thread != AST_PTHREADT_NULL) { 08361 /* Wake up the thread */ 08362 pthread_kill(monitor_thread, SIGURG); 08363 } else { 08364 /* Start a new monitor */ 08365 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 08366 ast_mutex_unlock(&monlock); 08367 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08368 pthread_attr_destroy(&attr); 08369 return -1; 08370 } 08371 } 08372 ast_mutex_unlock(&monlock); 08373 pthread_attr_destroy(&attr); 08374 return 0; 08375 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2610 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().
02611 { 02612 int res; 02613 if (p->saveconf.confmode) { 02614 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02615 p->saveconf.confmode = 0; 02616 if (res) { 02617 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02618 return -1; 02619 } 02620 } 02621 if (option_debug) 02622 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02623 return 0; 02624 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2537 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().
02538 { 02539 int res; 02540 02541 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02542 if (res) { 02543 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02544 return -1; 02545 } 02546 02547 return 0; 02548 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2583 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().
02584 { 02585 struct dahdi_confinfo c; 02586 int res; 02587 if (p->saveconf.confmode) { 02588 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02589 return -1; 02590 } 02591 p->saveconf.chan = 0; 02592 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02593 if (res) { 02594 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02595 p->saveconf.confmode = 0; 02596 return -1; 02597 } 02598 memset(&c, 0, sizeof(c)); 02599 c.confmode = DAHDI_CONF_NORMAL; 02600 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02601 if (res) { 02602 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02603 return -1; 02604 } 02605 if (option_debug) 02606 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02607 return 0; 02608 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2650 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().
02651 { 02652 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02653 int res; 02654 /* Take out of linear mode if necessary */ 02655 if (p->subs[SUB_REAL].linear) { 02656 p->subs[SUB_REAL].linear = 0; 02657 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02658 } 02659 while (p->cidpos < p->cidlen) { 02660 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02661 if (res < 0) { 02662 if (errno == EAGAIN) 02663 return 0; 02664 else { 02665 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02666 return -1; 02667 } 02668 } 02669 if (!res) 02670 return 0; 02671 p->cidpos += res; 02672 } 02673 free(p->cidspill); 02674 p->cidspill = NULL; 02675 if (p->callwaitcas) { 02676 /* Wait for CID/CW to expire */ 02677 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02678 } else 02679 restore_conference(p); 02680 return 0; 02681 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2628 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().
02629 { 02630 p->callwaitcas = 0; 02631 p->cidcwexpire = 0; 02632 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02633 return -1; 02634 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02635 /* Make sure we account for the end */ 02636 p->cidlen += READ_SIZE * 4; 02637 p->cidpos = 0; 02638 send_callerid(p); 02639 if (option_verbose > 2) 02640 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02641 return 0; 02642 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3297 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().
03298 { 03299 /* Data will be our digit string */ 03300 struct dahdi_pvt *p; 03301 char *digits = (char *) data; 03302 03303 if (ast_strlen_zero(digits)) { 03304 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 03305 return -1; 03306 } 03307 03308 p = (struct dahdi_pvt *)chan->tech_pvt; 03309 03310 if (!p) { 03311 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 03312 return -1; 03313 } 03314 03315 ast_mutex_lock(&p->lock); 03316 03317 if (!p->pri || !p->call) { 03318 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 03319 ast_mutex_unlock(&p->lock); 03320 return -1; 03321 } 03322 03323 if (!pri_grab(p, p->pri)) { 03324 pri_keypad_facility(p->pri->pri, p->call, digits); 03325 pri_rel(p->pri); 03326 } else { 03327 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 03328 ast_mutex_unlock(&p->lock); 03329 return -1; 03330 } 03331 03332 ast_mutex_unlock(&p->lock); 03333 03334 return 0; 03335 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2518 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02519 { 02520 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02521 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2500 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
02501 { 02502 struct dahdi_gains g; 02503 int res; 02504 02505 memset(&g, 0, sizeof(g)); 02506 g.chan = chan; 02507 res = ioctl(fd, DAHDI_GETGAINS, &g); 02508 if (res) { 02509 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02510 return res; 02511 } 02512 02513 fill_rxgain(&g, gain, law); 02514 02515 return ioctl(fd, DAHDI_SETGAINS, &g); 02516 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2481 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
02482 { 02483 struct dahdi_gains g; 02484 int res; 02485 02486 memset(&g, 0, sizeof(g)); 02487 g.chan = chan; 02488 res = ioctl(fd, DAHDI_GETGAINS, &g); 02489 if (res) { 02490 if (option_debug) 02491 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02492 return res; 02493 } 02494 02495 fill_txgain(&g, gain, law); 02496 02497 return ioctl(fd, DAHDI_SETGAINS, &g); 02498 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 13710 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().
13711 { 13712 struct ast_config *cfg; 13713 struct ast_variable *v; 13714 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13715 int res; 13716 13717 #ifdef HAVE_PRI 13718 char *c; 13719 int spanno; 13720 int i, x; 13721 int logicalspan; 13722 int trunkgroup; 13723 int dchannels[NUM_DCHANS]; 13724 #endif 13725 13726 #ifdef HAVE_ZAPTEL 13727 int load_from_zapata_conf = 1; 13728 #else 13729 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 13730 #endif 13731 13732 if (load_from_zapata_conf) { 13733 if (!(cfg = ast_config_load("zapata.conf"))) { 13734 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 13735 return 0; 13736 } 13737 } else { 13738 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 13739 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 13740 return 0; 13741 } 13742 } 13743 13744 /* It's a little silly to lock it, but we mind as well just to be sure */ 13745 ast_mutex_lock(&iflock); 13746 #ifdef HAVE_PRI 13747 if (reload != 1) { 13748 /* Process trunkgroups first */ 13749 v = ast_variable_browse(cfg, "trunkgroups"); 13750 while (v) { 13751 if (!strcasecmp(v->name, "trunkgroup")) { 13752 trunkgroup = atoi(v->value); 13753 if (trunkgroup > 0) { 13754 if ((c = strchr(v->value, ','))) { 13755 i = 0; 13756 memset(dchannels, 0, sizeof(dchannels)); 13757 while (c && (i < NUM_DCHANS)) { 13758 dchannels[i] = atoi(c + 1); 13759 if (dchannels[i] < 0) { 13760 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); 13761 } else 13762 i++; 13763 c = strchr(c + 1, ','); 13764 } 13765 if (i) { 13766 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 13767 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); 13768 } else if (option_verbose > 1) 13769 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"); 13770 } else 13771 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13772 } else 13773 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13774 } else 13775 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 13776 } else if (!strcasecmp(v->name, "spanmap")) { 13777 spanno = atoi(v->value); 13778 if (spanno > 0) { 13779 if ((c = strchr(v->value, ','))) { 13780 trunkgroup = atoi(c + 1); 13781 if (trunkgroup > 0) { 13782 if ((c = strchr(c + 1, ','))) 13783 logicalspan = atoi(c + 1); 13784 else 13785 logicalspan = 0; 13786 if (logicalspan >= 0) { 13787 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 13788 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13789 } else if (option_verbose > 1) 13790 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13791 } else 13792 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); 13793 } else 13794 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 13795 } else 13796 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 13797 } else 13798 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 13799 } else { 13800 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 13801 } 13802 v = v->next; 13803 } 13804 } 13805 #endif 13806 13807 /* Copy the default jb config over global_jbconf */ 13808 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 13809 13810 v = ast_variable_browse(cfg, "channels"); 13811 res = process_dahdi(&conf, "", v, reload, 0); 13812 ast_mutex_unlock(&iflock); 13813 ast_config_destroy(cfg); 13814 if (res) 13815 return res; 13816 cfg = ast_config_load("users.conf"); 13817 if (cfg) { 13818 char *cat; 13819 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 13820 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 13821 if (!strcasecmp(cat, "general")) 13822 continue; 13823 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 13824 struct dahdi_chan_conf sect_conf; 13825 memcpy(§_conf, &conf, sizeof(sect_conf)); 13826 13827 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 13828 } 13829 } 13830 ast_config_destroy(cfg); 13831 } 13832 #ifdef HAVE_PRI 13833 if (reload != 1) { 13834 for (x = 0; x < NUM_SPANS; x++) { 13835 if (pris[x].pvts[0]) { 13836 if (start_pri(pris + x)) { 13837 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 13838 return -1; 13839 } else if (option_verbose > 1) 13840 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 13841 } 13842 } 13843 } 13844 #endif 13845 #ifdef HAVE_OPENR2 13846 if (reload != 1) { 13847 int x; 13848 for (x = 0; x < NUM_SPANS; x++) { 13849 if (r2links[x].protocol_context) { 13850 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) { 13851 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1); 13852 return -1; 13853 } else { 13854 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1); 13855 } 13856 } 13857 } 13858 } 13859 #endif 13860 /* And start the monitor for the first time */ 13861 restart_monitor(); 13862 return 0; 13863 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6754 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_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().
06755 { 06756 struct ast_channel *chan = data; 06757 struct dahdi_pvt *p = chan->tech_pvt; 06758 char exten[AST_MAX_EXTENSION] = ""; 06759 char exten2[AST_MAX_EXTENSION] = ""; 06760 unsigned char buf[256]; 06761 char dtmfcid[300]; 06762 char dtmfbuf[300]; 06763 struct callerid_state *cs = NULL; 06764 char *name = NULL, *number = NULL; 06765 int distMatches; 06766 int curRingData[3]; 06767 int receivedRingT; 06768 int counter1; 06769 int counter; 06770 int samples = 0; 06771 struct ast_smdi_md_message *smdi_msg = NULL; 06772 int flags = 0; 06773 int i; 06774 int timeout; 06775 int getforward = 0; 06776 char *s1, *s2; 06777 int len = 0; 06778 int res; 06779 int index; 06780 06781 ast_mutex_lock(&ss_thread_lock); 06782 ss_thread_count++; 06783 ast_mutex_unlock(&ss_thread_lock); 06784 /* in the bizarre case where the channel has become a zombie before we 06785 even get started here, abort safely 06786 */ 06787 if (!p) { 06788 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06789 ast_hangup(chan); 06790 goto quit; 06791 } 06792 if (option_verbose > 2) 06793 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 06794 index = dahdi_get_index(chan, p, 1); 06795 if (index < 0) { 06796 ast_log(LOG_WARNING, "Huh?\n"); 06797 ast_hangup(chan); 06798 goto quit; 06799 } 06800 if (p->dsp) 06801 ast_dsp_digitreset(p->dsp); 06802 switch (p->sig) { 06803 #ifdef HAVE_PRI 06804 case SIG_PRI: 06805 /* Now loop looking for an extension */ 06806 ast_copy_string(exten, p->exten, sizeof(exten)); 06807 len = strlen(exten); 06808 res = 0; 06809 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06810 if (len && !ast_ignore_pattern(chan->context, exten)) 06811 tone_zone_play_tone(p->subs[index].dfd, -1); 06812 else 06813 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06814 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06815 timeout = matchdigittimeout; 06816 else 06817 timeout = gendigittimeout; 06818 res = ast_waitfordigit(chan, timeout); 06819 if (res < 0) { 06820 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06821 ast_hangup(chan); 06822 goto quit; 06823 } else if (res) { 06824 exten[len++] = res; 06825 exten[len] = '\0'; 06826 } else 06827 break; 06828 } 06829 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06830 if (ast_strlen_zero(exten)) { 06831 if (option_verbose > 2) 06832 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 06833 exten[0] = 's'; 06834 exten[1] = '\0'; 06835 } 06836 tone_zone_play_tone(p->subs[index].dfd, -1); 06837 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06838 /* Start the real PBX */ 06839 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06840 if (p->dsp) ast_dsp_digitreset(p->dsp); 06841 dahdi_enable_ec(p); 06842 ast_setstate(chan, AST_STATE_RING); 06843 res = ast_pbx_run(chan); 06844 if (res) { 06845 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06846 } 06847 } else { 06848 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06849 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06850 ast_hangup(chan); 06851 p->exten[0] = '\0'; 06852 /* Since we send release complete here, we won't get one */ 06853 p->call = NULL; 06854 } 06855 goto quit; 06856 break; 06857 #endif 06858 case SIG_FEATD: 06859 case SIG_FEATDMF: 06860 case SIG_FEATDMF_TA: 06861 case SIG_E911: 06862 case SIG_FGC_CAMAMF: 06863 case SIG_FEATB: 06864 case SIG_EMWINK: 06865 case SIG_SF_FEATD: 06866 case SIG_SF_FEATDMF: 06867 case SIG_SF_FEATB: 06868 case SIG_SFWINK: 06869 if (dahdi_wink(p, index)) 06870 goto quit; 06871 /* Fall through */ 06872 case SIG_EM: 06873 case SIG_EM_E1: 06874 case SIG_SF: 06875 case SIG_FGC_CAMA: 06876 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06877 if (p->dsp) 06878 ast_dsp_digitreset(p->dsp); 06879 /* set digit mode appropriately */ 06880 if (p->dsp) { 06881 if (NEED_MFDETECT(p)) 06882 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06883 else 06884 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06885 } 06886 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06887 /* Wait for the first digit only if immediate=no */ 06888 if (!p->immediate) 06889 /* Wait for the first digit (up to 5 seconds). */ 06890 res = ast_waitfordigit(chan, 5000); 06891 else 06892 res = 0; 06893 if (res > 0) { 06894 /* save first char */ 06895 dtmfbuf[0] = res; 06896 switch (p->sig) { 06897 case SIG_FEATD: 06898 case SIG_SF_FEATD: 06899 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06900 if (res > 0) 06901 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06902 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06903 break; 06904 case SIG_FEATDMF_TA: 06905 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06906 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06907 if (dahdi_wink(p, index)) goto quit; 06908 dtmfbuf[0] = 0; 06909 /* Wait for the first digit (up to 5 seconds). */ 06910 res = ast_waitfordigit(chan, 5000); 06911 if (res <= 0) break; 06912 dtmfbuf[0] = res; 06913 /* fall through intentionally */ 06914 case SIG_FEATDMF: 06915 case SIG_E911: 06916 case SIG_FGC_CAMAMF: 06917 case SIG_SF_FEATDMF: 06918 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06919 /* if international caca, do it again to get real ANO */ 06920 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06921 { 06922 if (dahdi_wink(p, index)) goto quit; 06923 dtmfbuf[0] = 0; 06924 /* Wait for the first digit (up to 5 seconds). */ 06925 res = ast_waitfordigit(chan, 5000); 06926 if (res <= 0) break; 06927 dtmfbuf[0] = res; 06928 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06929 } 06930 if (res > 0) { 06931 /* if E911, take off hook */ 06932 if (p->sig == SIG_E911) 06933 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06934 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06935 } 06936 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06937 break; 06938 case SIG_FEATB: 06939 case SIG_SF_FEATB: 06940 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06941 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06942 break; 06943 case SIG_EMWINK: 06944 /* if we received a '*', we are actually receiving Feature Group D 06945 dial syntax, so use that mode; otherwise, fall through to normal 06946 mode 06947 */ 06948 if (res == '*') { 06949 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06950 if (res > 0) 06951 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06952 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06953 break; 06954 } 06955 default: 06956 /* If we got the first digit, get the rest */ 06957 len = 1; 06958 dtmfbuf[len] = '\0'; 06959 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06960 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06961 timeout = matchdigittimeout; 06962 } else { 06963 timeout = gendigittimeout; 06964 } 06965 res = ast_waitfordigit(chan, timeout); 06966 if (res < 0) { 06967 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06968 ast_hangup(chan); 06969 goto quit; 06970 } else if (res) { 06971 dtmfbuf[len++] = res; 06972 dtmfbuf[len] = '\0'; 06973 } else { 06974 break; 06975 } 06976 } 06977 break; 06978 } 06979 } 06980 if (res == -1) { 06981 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06982 ast_hangup(chan); 06983 goto quit; 06984 } else if (res < 0) { 06985 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 06986 ast_hangup(chan); 06987 goto quit; 06988 } 06989 06990 if (p->sig == SIG_FGC_CAMA) { 06991 char anibuf[100]; 06992 06993 if (ast_safe_sleep(chan,1000) == -1) { 06994 ast_hangup(chan); 06995 goto quit; 06996 } 06997 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06998 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06999 res = my_getsigstr(chan, anibuf, "#", 10000); 07000 if ((res > 0) && (strlen(anibuf) > 2)) { 07001 if (anibuf[strlen(anibuf) - 1] == '#') 07002 anibuf[strlen(anibuf) - 1] = 0; 07003 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07004 } 07005 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07006 } 07007 07008 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07009 if (ast_strlen_zero(exten)) 07010 ast_copy_string(exten, "s", sizeof(exten)); 07011 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07012 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07013 if (exten[0] == '*') { 07014 char *stringp=NULL; 07015 ast_copy_string(exten2, exten, sizeof(exten2)); 07016 /* Parse out extension and callerid */ 07017 stringp=exten2 +1; 07018 s1 = strsep(&stringp, "*"); 07019 s2 = strsep(&stringp, "*"); 07020 if (s2) { 07021 if (!ast_strlen_zero(p->cid_num)) 07022 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07023 else 07024 ast_set_callerid(chan, s1, NULL, s1); 07025 ast_copy_string(exten, s2, sizeof(exten)); 07026 } else 07027 ast_copy_string(exten, s1, sizeof(exten)); 07028 } else if (p->sig == SIG_FEATD) 07029 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07030 } 07031 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07032 if (exten[0] == '*') { 07033 char *stringp=NULL; 07034 ast_copy_string(exten2, exten, sizeof(exten2)); 07035 /* Parse out extension and callerid */ 07036 stringp=exten2 +1; 07037 s1 = strsep(&stringp, "#"); 07038 s2 = strsep(&stringp, "#"); 07039 if (s2) { 07040 if (!ast_strlen_zero(p->cid_num)) 07041 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07042 else 07043 if (*(s1 + 2)) 07044 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07045 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07046 } else 07047 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07048 } else 07049 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07050 } 07051 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07052 if (exten[0] == '*') { 07053 char *stringp=NULL; 07054 ast_copy_string(exten2, exten, sizeof(exten2)); 07055 /* Parse out extension and callerid */ 07056 stringp=exten2 +1; 07057 s1 = strsep(&stringp, "#"); 07058 s2 = strsep(&stringp, "#"); 07059 if (s2 && (*(s2 + 1) == '0')) { 07060 if (*(s2 + 2)) 07061 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07062 } 07063 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07064 else ast_copy_string(exten, "911", sizeof(exten)); 07065 } else 07066 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 07067 } 07068 if (p->sig == SIG_FEATB) { 07069 if (exten[0] == '*') { 07070 char *stringp=NULL; 07071 ast_copy_string(exten2, exten, sizeof(exten2)); 07072 /* Parse out extension and callerid */ 07073 stringp=exten2 +1; 07074 s1 = strsep(&stringp, "#"); 07075 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 07076 } else 07077 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 07078 } 07079 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07080 dahdi_wink(p, index); 07081 /* some switches require a minimum guard time between 07082 the last FGD wink and something that answers 07083 immediately. This ensures it */ 07084 if (ast_safe_sleep(chan,100)) goto quit; 07085 } 07086 dahdi_enable_ec(p); 07087 if (NEED_MFDETECT(p)) { 07088 if (p->dsp) { 07089 if (!p->hardwaredtmf) 07090 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07091 else { 07092 ast_dsp_free(p->dsp); 07093 p->dsp = NULL; 07094 } 07095 } 07096 } 07097 07098 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 07099 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07100 if (p->dsp) ast_dsp_digitreset(p->dsp); 07101 res = ast_pbx_run(chan); 07102 if (res) { 07103 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07104 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07105 } 07106 goto quit; 07107 } else { 07108 if (option_verbose > 2) 07109 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 07110 sleep(2); 07111 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 07112 if (res < 0) 07113 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 07114 else 07115 sleep(1); 07116 res = ast_streamfile(chan, "ss-noservice", chan->language); 07117 if (res >= 0) 07118 ast_waitstream(chan, ""); 07119 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07120 ast_hangup(chan); 07121 goto quit; 07122 } 07123 break; 07124 case SIG_FXOLS: 07125 case SIG_FXOGS: 07126 case SIG_FXOKS: 07127 /* Read the first digit */ 07128 timeout = firstdigittimeout; 07129 /* If starting a threeway call, never timeout on the first digit so someone 07130 can use flash-hook as a "hold" feature */ 07131 if (p->subs[SUB_THREEWAY].owner) 07132 timeout = 999999; 07133 while (len < AST_MAX_EXTENSION-1) { 07134 /* Read digit unless it's supposed to be immediate, in which case the 07135 only answer is 's' */ 07136 if (p->immediate) 07137 res = 's'; 07138 else 07139 res = ast_waitfordigit(chan, timeout); 07140 timeout = 0; 07141 if (res < 0) { 07142 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07143 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07144 ast_hangup(chan); 07145 goto quit; 07146 } else if (res) { 07147 exten[len++]=res; 07148 exten[len] = '\0'; 07149 } 07150 if (!ast_ignore_pattern(chan->context, exten)) 07151 tone_zone_play_tone(p->subs[index].dfd, -1); 07152 else 07153 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07154 if (!strcmp(exten,ast_pickup_ext())) { 07155 /* Scan all channels and see if there are any 07156 * ringing channels that have call groups 07157 * that equal this channels pickup group 07158 */ 07159 if (index == SUB_REAL) { 07160 /* Switch us from Third call to Call Wait */ 07161 if (p->subs[SUB_THREEWAY].owner) { 07162 /* If you make a threeway call and the *8# a call, it should actually 07163 look like a callwait */ 07164 alloc_sub(p, SUB_CALLWAIT); 07165 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07166 unalloc_sub(p, SUB_THREEWAY); 07167 } 07168 dahdi_enable_ec(p); 07169 if (ast_pickup_call(chan)) { 07170 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 07171 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07172 dahdi_wait_event(p->subs[index].dfd); 07173 } 07174 ast_hangup(chan); 07175 goto quit; 07176 } else { 07177 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07178 ast_hangup(chan); 07179 goto quit; 07180 } 07181 07182 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 07183 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07184 if (getforward) { 07185 /* Record this as the forwarding extension */ 07186 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 07187 if (option_verbose > 2) 07188 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 07189 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07190 if (res) 07191 break; 07192 usleep(500000); 07193 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07194 sleep(1); 07195 memset(exten, 0, sizeof(exten)); 07196 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07197 len = 0; 07198 getforward = 0; 07199 } else { 07200 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07201 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07202 if (!ast_strlen_zero(p->cid_num)) { 07203 if (!p->hidecallerid) 07204 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07205 else 07206 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07207 } 07208 if (!ast_strlen_zero(p->cid_name)) { 07209 if (!p->hidecallerid) 07210 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07211 } 07212 ast_setstate(chan, AST_STATE_RING); 07213 dahdi_enable_ec(p); 07214 res = ast_pbx_run(chan); 07215 if (res) { 07216 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07217 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07218 } 07219 goto quit; 07220 } 07221 } else { 07222 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07223 so just set the timeout to matchdigittimeout and wait some more */ 07224 timeout = matchdigittimeout; 07225 } 07226 } else if (res == 0) { 07227 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 07228 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07229 dahdi_wait_event(p->subs[index].dfd); 07230 ast_hangup(chan); 07231 goto quit; 07232 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07233 if (option_verbose > 2) 07234 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 07235 /* Disable call waiting if enabled */ 07236 p->callwaiting = 0; 07237 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07238 if (res) { 07239 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07240 chan->name, strerror(errno)); 07241 } 07242 len = 0; 07243 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 07244 memset(exten, 0, sizeof(exten)); 07245 timeout = firstdigittimeout; 07246 07247 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07248 if (option_verbose > 2) 07249 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 07250 /* Disable Caller*ID if enabled */ 07251 p->hidecallerid = 1; 07252 if (chan->cid.cid_num) 07253 free(chan->cid.cid_num); 07254 chan->cid.cid_num = NULL; 07255 if (chan->cid.cid_name) 07256 free(chan->cid.cid_name); 07257 chan->cid.cid_name = NULL; 07258 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07259 if (res) { 07260 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07261 chan->name, strerror(errno)); 07262 } 07263 len = 0; 07264 memset(exten, 0, sizeof(exten)); 07265 timeout = firstdigittimeout; 07266 } else if (p->callreturn && !strcmp(exten, "*69")) { 07267 res = 0; 07268 if (!ast_strlen_zero(p->lastcid_num)) { 07269 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07270 } 07271 if (!res) 07272 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07273 break; 07274 } else if (!strcmp(exten, "*78")) { 07275 /* Do not disturb */ 07276 if (option_verbose > 2) 07277 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 07278 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07279 "Channel: %s/%d\r\n" 07280 "Status: enabled\r\n", dahdi_chan_name, p->channel); 07281 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07282 p->dnd = 1; 07283 getforward = 0; 07284 memset(exten, 0, sizeof(exten)); 07285 len = 0; 07286 } else if (!strcmp(exten, "*79")) { 07287 /* Do not disturb */ 07288 if (option_verbose > 2) 07289 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 07290 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07291 "Channel: %s/%d\r\n" 07292 "Status: disabled\r\n", dahdi_chan_name, p->channel); 07293 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07294 p->dnd = 0; 07295 getforward = 0; 07296 memset(exten, 0, sizeof(exten)); 07297 len = 0; 07298 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07299 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07300 getforward = 1; 07301 memset(exten, 0, sizeof(exten)); 07302 len = 0; 07303 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07304 if (option_verbose > 2) 07305 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 07306 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07307 memset(p->call_forward, 0, sizeof(p->call_forward)); 07308 getforward = 0; 07309 memset(exten, 0, sizeof(exten)); 07310 len = 0; 07311 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07312 p->subs[SUB_THREEWAY].owner && 07313 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07314 /* This is a three way call, the main call being a real channel, 07315 and we're parking the first call. */ 07316 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07317 if (option_verbose > 2) 07318 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 07319 break; 07320 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07321 if (option_verbose > 2) 07322 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 07323 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07324 if (!res) { 07325 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07326 memset(exten, 0, sizeof(exten)); 07327 len = 0; 07328 } 07329 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07330 if (option_verbose > 2) 07331 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 07332 /* Enable Caller*ID if enabled */ 07333 p->hidecallerid = 0; 07334 if (chan->cid.cid_num) 07335 free(chan->cid.cid_num); 07336 chan->cid.cid_num = NULL; 07337 if (chan->cid.cid_name) 07338 free(chan->cid.cid_name); 07339 chan->cid.cid_name = NULL; 07340 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07341 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07342 if (res) { 07343 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07344 chan->name, strerror(errno)); 07345 } 07346 len = 0; 07347 memset(exten, 0, sizeof(exten)); 07348 timeout = firstdigittimeout; 07349 } else if (!strcmp(exten, "*0")) { 07350 struct ast_channel *nbridge = 07351 p->subs[SUB_THREEWAY].owner; 07352 struct dahdi_pvt *pbridge = NULL; 07353 /* set up the private struct of the bridged one, if any */ 07354 if (nbridge && ast_bridged_channel(nbridge)) 07355 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07356 if (nbridge && pbridge && 07357 (nbridge->tech == chan_tech) && 07358 (ast_bridged_channel(nbridge)->tech == chan_tech) && 07359 ISTRUNK(pbridge)) { 07360 int func = DAHDI_FLASH; 07361 /* Clear out the dial buffer */ 07362 p->dop.dialstr[0] = '\0'; 07363 /* flash hookswitch */ 07364 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07365 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07366 nbridge->name, strerror(errno)); 07367 } 07368 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07369 unalloc_sub(p, SUB_THREEWAY); 07370 p->owner = p->subs[SUB_REAL].owner; 07371 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07372 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07373 ast_hangup(chan); 07374 goto quit; 07375 } else { 07376 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07377 dahdi_wait_event(p->subs[index].dfd); 07378 tone_zone_play_tone(p->subs[index].dfd, -1); 07379 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07380 unalloc_sub(p, SUB_THREEWAY); 07381 p->owner = p->subs[SUB_REAL].owner; 07382 ast_hangup(chan); 07383 goto quit; 07384 } 07385 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07386 ((exten[0] != '*') || (strlen(exten) > 2))) { 07387 if (option_debug) 07388 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); 07389 break; 07390 } 07391 if (!timeout) 07392 timeout = gendigittimeout; 07393 if (len && !ast_ignore_pattern(chan->context, exten)) 07394 tone_zone_play_tone(p->subs[index].dfd, -1); 07395 } 07396 break; 07397 case SIG_FXSLS: 07398 case SIG_FXSGS: 07399 case SIG_FXSKS: 07400 #ifdef HAVE_PRI 07401 if (p->pri) { 07402 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07403 struct ast_frame *f; 07404 int res; 07405 time_t start; 07406 07407 time(&start); 07408 ast_setstate(chan, AST_STATE_RING); 07409 while (time(NULL) < start + 3) { 07410 res = ast_waitfor(chan, 1000); 07411 if (res) { 07412 f = ast_read(chan); 07413 if (!f) { 07414 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07415 ast_hangup(chan); 07416 goto quit; 07417 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07418 res = 1; 07419 } else 07420 res = 0; 07421 ast_frfree(f); 07422 if (res) { 07423 ast_log(LOG_DEBUG, "Got ring!\n"); 07424 res = 0; 07425 break; 07426 } 07427 } 07428 } 07429 } 07430 #endif 07431 /* check for SMDI messages */ 07432 if (p->use_smdi && p->smdi_iface) { 07433 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07434 07435 if (smdi_msg != NULL) { 07436 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07437 07438 if (smdi_msg->type == 'B') 07439 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07440 else if (smdi_msg->type == 'N') 07441 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07442 07443 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 07444 } else { 07445 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07446 } 07447 } 07448 07449 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07450 number = smdi_msg->calling_st; 07451 07452 /* If we want caller id, we're in a prering state due to a polarity reversal 07453 * and we're set to use a polarity reversal to trigger the start of caller id, 07454 * grab the caller id and wait for ringing to start... */ 07455 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 07456 /* If set to use DTMF CID signalling, listen for DTMF */ 07457 if (p->cid_signalling == CID_SIG_DTMF) { 07458 int i = 0; 07459 cs = NULL; 07460 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 07461 "channel %s\n", chan->name); 07462 dahdi_setlinear(p->subs[index].dfd, 0); 07463 res = 2000; 07464 for (;;) { 07465 struct ast_frame *f; 07466 res = ast_waitfor(chan, res); 07467 if (res <= 0) { 07468 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07469 "Exiting simple switch\n"); 07470 ast_hangup(chan); 07471 goto quit; 07472 } 07473 f = ast_read(chan); 07474 if (!f) 07475 break; 07476 if (f->frametype == AST_FRAME_DTMF) { 07477 dtmfbuf[i++] = f->subclass; 07478 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07479 res = 2000; 07480 } 07481 ast_frfree(f); 07482 if (chan->_state == AST_STATE_RING || 07483 chan->_state == AST_STATE_RINGING) 07484 break; /* Got ring */ 07485 } 07486 dtmfbuf[i] = '\0'; 07487 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07488 /* Got cid and ring. */ 07489 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 07490 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07491 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07492 dtmfcid, flags); 07493 /* If first byte is NULL, we have no cid */ 07494 if (!ast_strlen_zero(dtmfcid)) 07495 number = dtmfcid; 07496 else 07497 number = NULL; 07498 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07499 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07500 cs = callerid_new(p->cid_signalling); 07501 if (cs) { 07502 samples = 0; 07503 #if 1 07504 bump_gains(p); 07505 #endif 07506 /* Take out of linear mode for Caller*ID processing */ 07507 dahdi_setlinear(p->subs[index].dfd, 0); 07508 07509 /* First we wait and listen for the Caller*ID */ 07510 for (;;) { 07511 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07512 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07513 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07514 callerid_free(cs); 07515 ast_hangup(chan); 07516 goto quit; 07517 } 07518 if (i & DAHDI_IOMUX_SIGEVENT) { 07519 res = dahdi_get_event(p->subs[index].dfd); 07520 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07521 07522 if (p->cid_signalling == CID_SIG_V23_JP) { 07523 #ifdef DAHDI_EVENT_RINGBEGIN 07524 if (res == DAHDI_EVENT_RINGBEGIN) { 07525 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07526 usleep(1); 07527 } 07528 #endif 07529 } else { 07530 res = 0; 07531 break; 07532 } 07533 } else if (i & DAHDI_IOMUX_READ) { 07534 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07535 if (res < 0) { 07536 if (errno != ELAST) { 07537 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07538 callerid_free(cs); 07539 ast_hangup(chan); 07540 goto quit; 07541 } 07542 break; 07543 } 07544 samples += res; 07545 07546 if (p->cid_signalling == CID_SIG_V23_JP) { 07547 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07548 } else { 07549 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07550 } 07551 07552 if (res < 0) { 07553 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07554 break; 07555 } else if (res) 07556 break; 07557 else if (samples > (8000 * 10)) 07558 break; 07559 } 07560 } 07561 if (res == 1) { 07562 callerid_get(cs, &name, &number, &flags); 07563 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07564 } 07565 07566 if (p->cid_signalling == CID_SIG_V23_JP) { 07567 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07568 usleep(1); 07569 res = 4000; 07570 } else { 07571 07572 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07573 res = 2000; 07574 } 07575 07576 for (;;) { 07577 struct ast_frame *f; 07578 res = ast_waitfor(chan, res); 07579 if (res <= 0) { 07580 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07581 "Exiting simple switch\n"); 07582 ast_hangup(chan); 07583 goto quit; 07584 } 07585 if (!(f = ast_read(chan))) { 07586 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07587 ast_hangup(chan); 07588 goto quit; 07589 } 07590 ast_frfree(f); 07591 if (chan->_state == AST_STATE_RING || 07592 chan->_state == AST_STATE_RINGING) 07593 break; /* Got ring */ 07594 } 07595 07596 /* We must have a ring by now, so, if configured, lets try to listen for 07597 * distinctive ringing */ 07598 if (p->usedistinctiveringdetection) { 07599 len = 0; 07600 distMatches = 0; 07601 /* Clear the current ring data array so we dont have old data in it. */ 07602 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07603 curRingData[receivedRingT] = 0; 07604 receivedRingT = 0; 07605 counter = 0; 07606 counter1 = 0; 07607 /* Check to see if context is what it should be, if not set to be. */ 07608 if (strcmp(p->context,p->defcontext) != 0) { 07609 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07610 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07611 } 07612 07613 for (;;) { 07614 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07615 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07616 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07617 callerid_free(cs); 07618 ast_hangup(chan); 07619 goto quit; 07620 } 07621 if (i & DAHDI_IOMUX_SIGEVENT) { 07622 res = dahdi_get_event(p->subs[index].dfd); 07623 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07624 res = 0; 07625 /* Let us detect distinctive ring */ 07626 07627 curRingData[receivedRingT] = p->ringt; 07628 07629 if (p->ringt < p->ringt_base/2) 07630 break; 07631 /* Increment the ringT counter so we can match it against 07632 values in chan_dahdi.conf for distinctive ring */ 07633 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07634 break; 07635 } else if (i & DAHDI_IOMUX_READ) { 07636 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07637 if (res < 0) { 07638 if (errno != ELAST) { 07639 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07640 callerid_free(cs); 07641 ast_hangup(chan); 07642 goto quit; 07643 } 07644 break; 07645 } 07646 if (p->ringt) 07647 p->ringt--; 07648 if (p->ringt == 1) { 07649 res = -1; 07650 break; 07651 } 07652 } 07653 } 07654 if (option_verbose > 2) 07655 /* this only shows up if you have n of the dring patterns filled in */ 07656 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07657 07658 for (counter = 0; counter < 3; counter++) { 07659 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07660 channel */ 07661 distMatches = 0; 07662 for (counter1 = 0; counter1 < 3; counter1++) { 07663 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07664 (p->drings.ringnum[counter].ring[counter1]-10)) { 07665 distMatches++; 07666 } 07667 } 07668 if (distMatches == 3) { 07669 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07670 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07671 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07672 if (option_verbose > 2) 07673 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07674 break; 07675 } 07676 } 07677 } 07678 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07679 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07680 #if 1 07681 restore_gains(p); 07682 #endif 07683 } else 07684 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07685 } else { 07686 ast_log(LOG_WARNING, "Channel %s in prering " 07687 "state, but I have nothing to do. " 07688 "Terminating simple switch, should be " 07689 "restarted by the actual ring.\n", 07690 chan->name); 07691 ast_hangup(chan); 07692 goto quit; 07693 } 07694 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07695 /* FSK Bell202 callerID */ 07696 cs = callerid_new(p->cid_signalling); 07697 if (cs) { 07698 #if 1 07699 bump_gains(p); 07700 #endif 07701 samples = 0; 07702 len = 0; 07703 distMatches = 0; 07704 /* Clear the current ring data array so we dont have old data in it. */ 07705 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07706 curRingData[receivedRingT] = 0; 07707 receivedRingT = 0; 07708 counter = 0; 07709 counter1 = 0; 07710 /* Check to see if context is what it should be, if not set to be. */ 07711 if (strcmp(p->context,p->defcontext) != 0) { 07712 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07713 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07714 } 07715 07716 /* Take out of linear mode for Caller*ID processing */ 07717 dahdi_setlinear(p->subs[index].dfd, 0); 07718 for (;;) { 07719 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07720 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07721 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07722 callerid_free(cs); 07723 ast_hangup(chan); 07724 goto quit; 07725 } 07726 if (i & DAHDI_IOMUX_SIGEVENT) { 07727 res = dahdi_get_event(p->subs[index].dfd); 07728 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07729 /* If we get a PR event, they hung up while processing calerid */ 07730 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07731 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07732 p->polarity = POLARITY_IDLE; 07733 callerid_free(cs); 07734 ast_hangup(chan); 07735 goto quit; 07736 } 07737 res = 0; 07738 /* Let us detect callerid when the telco uses distinctive ring */ 07739 07740 curRingData[receivedRingT] = p->ringt; 07741 07742 if (p->ringt < p->ringt_base/2) 07743 break; 07744 /* Increment the ringT counter so we can match it against 07745 values in chan_dahdi.conf for distinctive ring */ 07746 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07747 break; 07748 } else if (i & DAHDI_IOMUX_READ) { 07749 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07750 if (res < 0) { 07751 if (errno != ELAST) { 07752 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07753 callerid_free(cs); 07754 ast_hangup(chan); 07755 goto quit; 07756 } 07757 break; 07758 } 07759 if (p->ringt) 07760 p->ringt--; 07761 if (p->ringt == 1) { 07762 res = -1; 07763 break; 07764 } 07765 samples += res; 07766 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07767 if (res < 0) { 07768 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07769 break; 07770 } else if (res) 07771 break; 07772 else if (samples > (8000 * 10)) 07773 break; 07774 } 07775 } 07776 if (res == 1) { 07777 callerid_get(cs, &name, &number, &flags); 07778 if (option_debug) 07779 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07780 } 07781 if (distinctiveringaftercid == 1) { 07782 /* Clear the current ring data array so we dont have old data in it. */ 07783 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07784 curRingData[receivedRingT] = 0; 07785 } 07786 receivedRingT = 0; 07787 if (option_verbose > 2) 07788 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 07789 for (;;) { 07790 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07791 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07792 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07793 callerid_free(cs); 07794 ast_hangup(chan); 07795 goto quit; 07796 } 07797 if (i & DAHDI_IOMUX_SIGEVENT) { 07798 res = dahdi_get_event(p->subs[index].dfd); 07799 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07800 res = 0; 07801 /* Let us detect callerid when the telco uses distinctive ring */ 07802 07803 curRingData[receivedRingT] = p->ringt; 07804 07805 if (p->ringt < p->ringt_base/2) 07806 break; 07807 /* Increment the ringT counter so we can match it against 07808 values in chan_dahdi.conf for distinctive ring */ 07809 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07810 break; 07811 } else if (i & DAHDI_IOMUX_READ) { 07812 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07813 if (res < 0) { 07814 if (errno != ELAST) { 07815 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07816 callerid_free(cs); 07817 ast_hangup(chan); 07818 goto quit; 07819 } 07820 break; 07821 } 07822 if (p->ringt) 07823 p->ringt--; 07824 if (p->ringt == 1) { 07825 res = -1; 07826 break; 07827 } 07828 } 07829 } 07830 } 07831 if (p->usedistinctiveringdetection) { 07832 if (option_verbose > 2) 07833 /* this only shows up if you have n of the dring patterns filled in */ 07834 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07835 07836 for (counter = 0; counter < 3; counter++) { 07837 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07838 channel */ 07839 if (option_verbose > 2) 07840 /* this only shows up if you have n of the dring patterns filled in */ 07841 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 07842 p->drings.ringnum[counter].ring[0], 07843 p->drings.ringnum[counter].ring[1], 07844 p->drings.ringnum[counter].ring[2]); 07845 distMatches = 0; 07846 for (counter1 = 0; counter1 < 3; counter1++) { 07847 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07848 (p->drings.ringnum[counter].ring[counter1]-10)) { 07849 distMatches++; 07850 } 07851 } 07852 if (distMatches == 3) { 07853 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07854 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07855 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07856 if (option_verbose > 2) 07857 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07858 break; 07859 } 07860 } 07861 } 07862 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07863 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07864 #if 1 07865 restore_gains(p); 07866 #endif 07867 if (res < 0) { 07868 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07869 } 07870 } else 07871 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07872 } 07873 else 07874 cs = NULL; 07875 07876 if (number) 07877 ast_shrink_phone_number(number); 07878 ast_set_callerid(chan, number, name, number); 07879 07880 if (smdi_msg) 07881 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07882 07883 if (cs) 07884 callerid_free(cs); 07885 07886 ast_setstate(chan, AST_STATE_RING); 07887 chan->rings = 1; 07888 p->ringt = p->ringt_base; 07889 res = ast_pbx_run(chan); 07890 if (res) { 07891 ast_hangup(chan); 07892 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07893 } 07894 goto quit; 07895 default: 07896 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07897 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07898 if (res < 0) 07899 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07900 } 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 ast_hangup(chan); 07905 quit: 07906 ast_mutex_lock(&ss_thread_lock); 07907 ss_thread_count--; 07908 ast_cond_signal(&ss_thread_complete); 07909 ast_mutex_unlock(&ss_thread_lock); 07910 return NULL; 07911 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11119 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().
11120 { 11121 int res, x; 11122 struct dahdi_params p; 11123 struct dahdi_bufferinfo bi; 11124 struct dahdi_spaninfo si; 11125 int i; 11126 11127 for (i = 0; i < NUM_DCHANS; i++) { 11128 if (!pri->dchannels[i]) 11129 break; 11130 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 11131 x = pri->dchannels[i]; 11132 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11133 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11134 return -1; 11135 } 11136 memset(&p, 0, sizeof(p)); 11137 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11138 if (res) { 11139 dahdi_close_pri_fd(pri, i); 11140 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11141 return -1; 11142 } 11143 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11144 dahdi_close_pri_fd(pri, i); 11145 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 11146 return -1; 11147 } 11148 memset(&si, 0, sizeof(si)); 11149 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11150 if (res) { 11151 dahdi_close_pri_fd(pri, i); 11152 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11153 } 11154 if (!si.alarms) 11155 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11156 else 11157 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11158 memset(&bi, 0, sizeof(bi)); 11159 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 11160 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 11161 bi.numbufs = 32; 11162 bi.bufsize = 1024; 11163 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 11164 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 11165 dahdi_close_pri_fd(pri, i); 11166 return -1; 11167 } 11168 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 11169 /* Force overlap dial if we're doing GR-303! */ 11170 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 11171 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 11172 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 11173 #ifdef HAVE_PRI_INBANDDISCONNECT 11174 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 11175 #endif 11176 /* Enslave to master if appropriate */ 11177 if (i) 11178 pri_enslave(pri->dchans[0], pri->dchans[i]); 11179 if (!pri->dchans[i]) { 11180 dahdi_close_pri_fd(pri, i); 11181 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 11182 return -1; 11183 } 11184 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 11185 pri_set_nsf(pri->dchans[i], pri->nsf); 11186 #ifdef PRI_GETSET_TIMERS 11187 for (x = 0; x < PRI_MAX_TIMERS; x++) { 11188 if (pritimers[x] != 0) 11189 pri_set_timer(pri->dchans[i], x, pritimers[x]); 11190 } 11191 #endif 11192 } 11193 /* Assume primary is the one we use */ 11194 pri->pri = pri->dchans[0]; 11195 pri->resetpos = -1; 11196 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 11197 for (i = 0; i < NUM_DCHANS; i++) { 11198 if (!pri->dchannels[i]) 11199 break; 11200 dahdi_close_pri_fd(pri, i); 11201 } 11202 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 11203 return -1; 11204 } 11205 return 0; 11206 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1769 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().
01770 { 01771 int tchan; 01772 int tinthreeway; 01773 struct ast_channel *towner; 01774 01775 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 01776 01777 tchan = p->subs[a].chan; 01778 towner = p->subs[a].owner; 01779 tinthreeway = p->subs[a].inthreeway; 01780 01781 p->subs[a].chan = p->subs[b].chan; 01782 p->subs[a].owner = p->subs[b].owner; 01783 p->subs[a].inthreeway = p->subs[b].inthreeway; 01784 01785 p->subs[b].chan = tchan; 01786 p->subs[b].owner = towner; 01787 p->subs[b].inthreeway = tinthreeway; 01788 01789 if (p->subs[a].owner) 01790 p->subs[a].owner->fds[0] = p->subs[a].dfd; 01791 if (p->subs[b].owner) 01792 p->subs[b].owner->fds[0] = p->subs[b].dfd; 01793 wakeup_sub(p, a, NULL); 01794 wakeup_sub(p, b, NULL); 01795 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1908 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().
01909 { 01910 if (!x) { 01911 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01912 return -1; 01913 } 01914 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01915 dahdi_close_sub(p, x); 01916 p->subs[x].linear = 0; 01917 p->subs[x].chan = 0; 01918 p->subs[x].owner = NULL; 01919 p->subs[x].inthreeway = 0; 01920 p->polarity = POLARITY_IDLE; 01921 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01922 return 0; 01923 }
static int unload_module | ( | void | ) | [static] |
Definition at line 12780 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
12781 { 12782 #ifdef HAVE_PRI 12783 int y; 12784 for (y = 0; y < NUM_SPANS; y++) 12785 ast_mutex_destroy(&pris[y].lock); 12786 #endif 12787 return __unload_module(); 12788 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2291 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().
02292 { 02293 int needconf = 0; 02294 int x; 02295 int useslavenative; 02296 struct dahdi_pvt *slave = NULL; 02297 02298 useslavenative = isslavenative(p, &slave); 02299 /* Start with the obvious, general stuff */ 02300 for (x = 0; x < 3; x++) { 02301 /* Look for three way calls */ 02302 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 02303 conf_add(p, &p->subs[x], x, 0); 02304 needconf++; 02305 } else { 02306 conf_del(p, &p->subs[x], x); 02307 } 02308 } 02309 /* If we have a slave, add him to our conference now. or DAX 02310 if this is slave native */ 02311 for (x = 0; x < MAX_SLAVES; x++) { 02312 if (p->slaves[x]) { 02313 if (useslavenative) 02314 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02315 else { 02316 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02317 needconf++; 02318 } 02319 } 02320 } 02321 /* If we're supposed to be in there, do so now */ 02322 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02323 if (useslavenative) 02324 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02325 else { 02326 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02327 needconf++; 02328 } 02329 } 02330 /* If we have a master, add ourselves to his conference */ 02331 if (p->master) { 02332 if (isslavenative(p->master, NULL)) { 02333 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02334 } else { 02335 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02336 } 02337 } 02338 if (!needconf) { 02339 /* Nobody is left (or should be left) in our conference. 02340 Kill it. */ 02341 p->confno = -1; 02342 } 02343 if (option_debug) 02344 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02345 return 0; 02346 }
Definition at line 1205 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().
01209 { 01210 #ifdef HAVE_PRI 01211 if (pri) 01212 ast_mutex_unlock(&pri->lock); 01213 #endif 01214 for (;;) { 01215 if (p->subs[a].owner) { 01216 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 01217 DEADLOCK_AVOIDANCE(&p->lock); 01218 } else { 01219 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01220 ast_mutex_unlock(&p->subs[a].owner->lock); 01221 break; 01222 } 01223 } else 01224 break; 01225 } 01226 #ifdef HAVE_PRI 01227 if (pri) 01228 ast_mutex_lock(&pri->lock); 01229 #endif 01230 }
static int zap_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3543 of file chan_dahdi.c.
References dahdi_accept_r2_call_exec().
Referenced by load_module().
03544 { 03545 return dahdi_accept_r2_call_exec(chan, data); 03546 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12604 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12605 { 12606 return __action_dialoffhook(s, m, 1); 12607 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12504 of file chan_dahdi.c.
References __action_dnd(), and s.
12505 { 12506 return __action_dnd(s, m, 1, 0); 12507 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12494 of file chan_dahdi.c.
References __action_dnd(), and s.
12495 { 12496 return __action_dnd(s, m, 1, 1); 12497 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12683 of file chan_dahdi.c.
References __action_restart(), and s.
12684 { 12685 return __action_restart(s, m, 1); 12686 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12659 of file chan_dahdi.c.
References __action_showchannels(), and s.
12660 { 12661 return __action_showchannels(s, m, 1); 12662 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12533 of file chan_dahdi.c.
References __action_transfer(), and s.
12534 { 12535 return __action_transfer(s, m, 1); 12536 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12561 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12562 { 12563 return __action_transferhangup(s, m, 1); 12564 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3342 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
03343 { 03344 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); 03345 return send_keypad_facility_exec(chan, data); 03346 }
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 14068 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 14068 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1163 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 1131 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 1174 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 12400 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 12405 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 12385 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 12395 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 12390 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 12410 of file chan_dahdi.c.
char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 3428 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 3434 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 3431 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 11816 of file chan_dahdi.c.
openr2_event_interface_t dahdi_r2_event_iface [static] |
Definition at line 1729 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 11825 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 11812 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 11820 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 11809 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 1760 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 11806 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 11803 of file chan_dahdi.c.
char dahdi_restart_usage[] [static] |
Definition at line 12378 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3284 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 3290 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3287 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 12271 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 12370 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1089 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 12374 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 219 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 233 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 236 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 245 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 242 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 224 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 239 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
int mfcr2_cur_accept_on_offer = 1 [static] |
Definition at line 331 of file chan_dahdi.c.
int mfcr2_cur_allow_collect_calls = 0 [static] |
Definition at line 330 of file chan_dahdi.c.
int mfcr2_cur_call_files = 0 [static] |
Definition at line 329 of file chan_dahdi.c.
openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static] |
Definition at line 346 of file chan_dahdi.c.
int mfcr2_cur_charge_calls = 1 [static] |
Definition at line 332 of file chan_dahdi.c.
int mfcr2_cur_context_index = 0 [static] |
Definition at line 328 of file chan_dahdi.c.
int mfcr2_cur_double_answer = 0 [static] |
Definition at line 334 of file chan_dahdi.c.
int mfcr2_cur_forced_release = 0 [static] |
Definition at line 333 of file chan_dahdi.c.
int mfcr2_cur_get_ani_first = -1 [static] |
Definition at line 326 of file chan_dahdi.c.
int mfcr2_cur_immediate_accept = -1 [static] |
Definition at line 335 of file chan_dahdi.c.
char mfcr2_cur_logdir[OR2_MAX_PATH] [static] |
Definition at line 343 of file chan_dahdi.c.
openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static] |
Definition at line 345 of file chan_dahdi.c.
int mfcr2_cur_max_ani = 10 [static] |
Definition at line 324 of file chan_dahdi.c.
int mfcr2_cur_max_dnis = 4 [static] |
Definition at line 325 of file chan_dahdi.c.
int mfcr2_cur_metering_pulse_timeout = -1 [static] |
Definition at line 323 of file chan_dahdi.c.
int mfcr2_cur_mfback_timeout = -1 [static] |
Definition at line 322 of file chan_dahdi.c.
char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static] |
Definition at line 344 of file chan_dahdi.c.
int mfcr2_cur_skip_category = -1 [static] |
Definition at line 327 of file chan_dahdi.c.
openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static] |
Definition at line 321 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 257 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 253 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 2061 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1160 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 262 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 11471 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 11475 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 11479 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 11483 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 11487 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 228 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 248 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 229 of file chan_dahdi.c.
Definition at line 407 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 320 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 309 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 12366 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 12362 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 258 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 261 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 1161 of file chan_dahdi.c.
char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static] |
Definition at line 3429 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 3438 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 3432 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 3285 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 3293 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3288 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |