#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 = "6989f2ec67f8497e38c12890500c525b" , .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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 12438 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 12468 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 12469 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 12883 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 14055 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 12437 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 12567 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().
12568 { 12569 struct dahdi_pvt *p = NULL; 12570 const char *channel = local_astman_header(m, "Channel", zap_mode); 12571 const char *number = astman_get_header(m, "Number"); 12572 int i; 12573 12574 if (ast_strlen_zero(channel)) { 12575 astman_send_error(s, m, "No channel specified"); 12576 return 0; 12577 } 12578 if (ast_strlen_zero(number)) { 12579 astman_send_error(s, m, "No number specified"); 12580 return 0; 12581 } 12582 if (!(p = find_channel(atoi(channel)))) { 12583 astman_send_error(s, m, "No such channel"); 12584 return 0; 12585 } 12586 if (!p->owner) { 12587 astman_send_error(s, m, "Channel does not have an owner"); 12588 return 0; 12589 } 12590 for (i = 0; i < strlen(number); i++) { 12591 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 12592 12593 dahdi_queue_frame(p, &f, NULL); 12594 } 12595 local_astman_ack(s, m, "DialOffHook", zap_mode); 12596 12597 return 0; 12598 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 12471 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().
12472 { 12473 struct dahdi_pvt *p = NULL; 12474 const char *channel = local_astman_header(m, "Channel", zap_mode); 12475 12476 if (ast_strlen_zero(channel)) { 12477 astman_send_error(s, m, "No channel specified"); 12478 return 0; 12479 } 12480 if (!(p = find_channel(atoi(channel)))) { 12481 astman_send_error(s, m, "No such channel"); 12482 return 0; 12483 } 12484 p->dnd = dnd; 12485 local_astman_ack(s, m, "DND", zap_mode); 12486 12487 return 0; 12488 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12665 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().
12666 { 12667 if (dahdi_restart() != 0) { 12668 if (zap_mode) { 12669 astman_send_error(s, m, "Failed to restart Zap"); 12670 } else { 12671 astman_send_error(s, m, "Failed to restart DAHDI"); 12672 } 12673 return 1; 12674 } 12675 local_astman_ack(s, m, "Restart: Success", zap_mode); 12676 return 0; 12677 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12610 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().
12611 { 12612 struct dahdi_pvt *tmp = NULL; 12613 const char *id = astman_get_header(m, "ActionID"); 12614 char idText[256] = ""; 12615 12616 local_astman_ack(s, m, " channel status will follow", zap_mode); 12617 if (!ast_strlen_zero(id)) 12618 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 12619 12620 ast_mutex_lock(&iflock); 12621 12622 tmp = iflist; 12623 while (tmp) { 12624 if (tmp->channel > 0) { 12625 int alarm = get_alarms(tmp); 12626 astman_append(s, 12627 "Event: %sShowChannels\r\n" 12628 "Channel: %d\r\n" 12629 "Signalling: %s\r\n" 12630 "Context: %s\r\n" 12631 "DND: %s\r\n" 12632 "Alarm: %s\r\n" 12633 "%s" 12634 "\r\n", 12635 dahdi_chan_name, 12636 tmp->channel, sig2str(tmp->sig), tmp->context, 12637 tmp->dnd ? "Enabled" : "Disabled", 12638 alarm2str(alarm), idText); 12639 } 12640 12641 tmp = tmp->next; 12642 } 12643 12644 ast_mutex_unlock(&iflock); 12645 12646 astman_append(s, 12647 "Event: %sShowChannelsComplete\r\n" 12648 "%s" 12649 "\r\n", 12650 dahdi_chan_name, 12651 idText); 12652 return 0; 12653 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12510 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().
12511 { 12512 struct dahdi_pvt *p = NULL; 12513 const char *channel = local_astman_header(m, "Channel", zap_mode); 12514 12515 if (ast_strlen_zero(channel)) { 12516 astman_send_error(s, m, "No channel specified"); 12517 return 0; 12518 } 12519 if (!(p = find_channel(atoi(channel)))) { 12520 astman_send_error(s, m, "No such channel"); 12521 return 0; 12522 } 12523 dahdi_fake_event(p,TRANSFER); 12524 local_astman_ack(s, m, "Transfer", zap_mode); 12525 12526 return 0; 12527 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12539 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().
12540 { 12541 struct dahdi_pvt *p = NULL; 12542 const char *channel = local_astman_header(m, "Channel", zap_mode); 12543 12544 if (ast_strlen_zero(channel)) { 12545 astman_send_error(s, m, "No channel specified"); 12546 return 0; 12547 } 12548 if (!(p = find_channel(atoi(channel)))) { 12549 astman_send_error(s, m, "No such channel"); 12550 return 0; 12551 } 12552 dahdi_fake_event(p, HANGUP); 12553 local_astman_ack(s, m, "Hangup", zap_mode); 12554 return 0; 12555 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5784 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().
05785 { 05786 struct dahdi_pvt *p = ast->tech_pvt; 05787 int res; 05788 int usedindex=-1; 05789 int index; 05790 struct ast_frame *f; 05791 05792 05793 index = dahdi_get_index(ast, p, 1); 05794 05795 p->subs[index].f.frametype = AST_FRAME_NULL; 05796 p->subs[index].f.datalen = 0; 05797 p->subs[index].f.samples = 0; 05798 p->subs[index].f.mallocd = 0; 05799 p->subs[index].f.offset = 0; 05800 p->subs[index].f.subclass = 0; 05801 p->subs[index].f.delivery = ast_tv(0,0); 05802 p->subs[index].f.src = "dahdi_exception"; 05803 p->subs[index].f.data = NULL; 05804 05805 05806 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05807 /* If nobody owns us, absorb the event appropriately, otherwise 05808 we loop indefinitely. This occurs when, during call waiting, the 05809 other end hangs up our channel so that it no longer exists, but we 05810 have neither FLASH'd nor ONHOOK'd to signify our desire to 05811 change to the other channel. */ 05812 if (p->fake_event) { 05813 res = p->fake_event; 05814 p->fake_event = 0; 05815 } else 05816 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05817 /* Switch to real if there is one and this isn't something really silly... */ 05818 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05819 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05820 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 05821 p->owner = p->subs[SUB_REAL].owner; 05822 if (p->owner && ast_bridged_channel(p->owner)) 05823 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05824 p->subs[SUB_REAL].needunhold = 1; 05825 } 05826 switch (res) { 05827 case DAHDI_EVENT_ONHOOK: 05828 dahdi_disable_ec(p); 05829 if (p->owner) { 05830 if (option_verbose > 2) 05831 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 05832 dahdi_ring_phone(p); 05833 p->callwaitingrepeat = 0; 05834 p->cidcwexpire = 0; 05835 } else 05836 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05837 update_conf(p); 05838 break; 05839 case DAHDI_EVENT_RINGOFFHOOK: 05840 dahdi_enable_ec(p); 05841 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05842 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05843 p->subs[SUB_REAL].needanswer = 1; 05844 p->dialing = 0; 05845 } 05846 break; 05847 case DAHDI_EVENT_HOOKCOMPLETE: 05848 case DAHDI_EVENT_RINGERON: 05849 case DAHDI_EVENT_RINGEROFF: 05850 /* Do nothing */ 05851 break; 05852 case DAHDI_EVENT_WINKFLASH: 05853 gettimeofday(&p->flashtime, NULL); 05854 if (p->owner) { 05855 if (option_verbose > 2) 05856 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05857 if (p->owner->_state != AST_STATE_UP) { 05858 /* Answer if necessary */ 05859 usedindex = dahdi_get_index(p->owner, p, 0); 05860 if (usedindex > -1) { 05861 p->subs[usedindex].needanswer = 1; 05862 } 05863 ast_setstate(p->owner, AST_STATE_UP); 05864 } 05865 p->callwaitingrepeat = 0; 05866 p->cidcwexpire = 0; 05867 if (ast_bridged_channel(p->owner)) 05868 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05869 p->subs[SUB_REAL].needunhold = 1; 05870 } else 05871 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05872 update_conf(p); 05873 break; 05874 default: 05875 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05876 } 05877 f = &p->subs[index].f; 05878 return f; 05879 } 05880 if (!(p->radio || (p->oprmode < 0)) && option_debug) 05881 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05882 /* If it's not us, return NULL immediately */ 05883 if (ast != p->owner) { 05884 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05885 f = &p->subs[index].f; 05886 return f; 05887 } 05888 f = dahdi_handle_event(ast); 05889 return f; 05890 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 14064 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 12696 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().
12697 { 12698 struct dahdi_pvt *p; 12699 #ifdef HAVE_OPENR2 12700 int r; 12701 #endif 12702 #ifdef HAVE_PRI 12703 int i, j; 12704 for (i = 0; i < NUM_SPANS; i++) { 12705 if (pris[i].master != AST_PTHREADT_NULL) 12706 pthread_cancel(pris[i].master); 12707 } 12708 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12709 12710 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12711 ast_unregister_application(dahdi_send_keypad_facility_app); 12712 } 12713 ast_unregister_application(zap_send_keypad_facility_app); 12714 #endif 12715 #ifdef HAVE_OPENR2 12716 for (r = 0; r < NUM_SPANS; r++) { 12717 if (r2links[r].master != AST_PTHREADT_NULL) { 12718 pthread_cancel(r2links[r].master); 12719 pthread_join(r2links[r].master, NULL); 12720 } 12721 } 12722 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0])); 12723 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12724 ast_unregister_application(dahdi_accept_r2_call_app); 12725 } 12726 ast_unregister_application(zap_accept_r2_call_app); 12727 #endif 12728 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12729 local_astman_unregister("DialOffHook"); 12730 local_astman_unregister("Hangup"); 12731 local_astman_unregister("Transfer"); 12732 local_astman_unregister("DNDoff"); 12733 local_astman_unregister("DNDon"); 12734 local_astman_unregister("ShowChannels"); 12735 local_astman_unregister("Restart"); 12736 ast_channel_unregister(chan_tech); 12737 ast_mutex_lock(&iflock); 12738 /* Hangup all interfaces if they have an owner */ 12739 p = iflist; 12740 while (p) { 12741 if (p->owner) 12742 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 12743 p = p->next; 12744 } 12745 ast_mutex_unlock(&iflock); 12746 ast_mutex_lock(&monlock); 12747 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12748 pthread_cancel(monitor_thread); 12749 pthread_kill(monitor_thread, SIGURG); 12750 pthread_join(monitor_thread, NULL); 12751 } 12752 monitor_thread = AST_PTHREADT_STOP; 12753 ast_mutex_unlock(&monlock); 12754 12755 destroy_all_channels(); 12756 #ifdef HAVE_PRI 12757 for (i = 0; i < NUM_SPANS; i++) { 12758 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 12759 pthread_join(pris[i].master, NULL); 12760 for (j = 0; j < NUM_DCHANS; j++) { 12761 dahdi_close_pri_fd(&(pris[i]), j); 12762 } 12763 } 12764 #endif 12765 #ifdef HAVE_OPENR2 12766 for (r = 0; r < NUM_SPANS; r++) { 12767 if (r2links[r].protocol_context) { 12768 openr2_context_delete(r2links[r].protocol_context); 12769 } 12770 } 12771 #endif 12772 ast_cond_destroy(&ss_thread_complete); 12773 return 0; 12774 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 14064 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 9941 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.
09942 { 09943 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 09944 if (size) { 09945 *buf = '\0'; 09946 } 09947 return; 09948 } 09949 09950 switch (plan) { 09951 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 09952 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 09953 break; 09954 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 09955 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 09956 break; 09957 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 09958 snprintf(buf, size, "%s%s", pri->localprefix, number); 09959 break; 09960 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 09961 snprintf(buf, size, "%s%s", pri->privateprefix, number); 09962 break; 09963 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 09964 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 09965 break; 09966 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 09967 snprintf(buf, size, "%s", number); 09968 break; 09969 } 09970 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4711 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().
04712 { 04713 /* In order to transfer, we need at least one of the channels to 04714 actually be in a call bridge. We can't conference two applications 04715 together (but then, why would we want to?) */ 04716 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04717 /* The three-way person we're about to transfer to could still be in MOH, so 04718 stop if now if appropriate */ 04719 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04720 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04721 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04722 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04723 } 04724 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04725 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04726 } 04727 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04728 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04729 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04730 return -1; 04731 } 04732 /* Orphan the channel after releasing the lock */ 04733 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04734 unalloc_sub(p, SUB_THREEWAY); 04735 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04736 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04737 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04738 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04739 } 04740 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04741 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04742 } 04743 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04744 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04745 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04746 return -1; 04747 } 04748 /* Three-way is now the REAL */ 04749 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04750 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 04751 unalloc_sub(p, SUB_THREEWAY); 04752 /* Tell the caller not to hangup */ 04753 return 1; 04754 } else { 04755 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04756 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04757 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04758 return -1; 04759 } 04760 return 0; 04761 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9090 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().
09091 { 09092 int res; 09093 struct dahdi_params par; 09094 09095 /* First, check group matching */ 09096 if (groupmatch) { 09097 if ((p->group & groupmatch) != groupmatch) 09098 return 0; 09099 *groupmatched = 1; 09100 } 09101 /* Check to see if we have a channel match */ 09102 if (channelmatch != -1) { 09103 if (p->channel != channelmatch) 09104 return 0; 09105 *channelmatched = 1; 09106 } 09107 /* We're at least busy at this point */ 09108 if (busy) { 09109 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09110 *busy = 1; 09111 } 09112 /* If do not disturb, definitely not */ 09113 if (p->dnd) 09114 return 0; 09115 /* If guard time, definitely not */ 09116 if (p->guardtime && (time(NULL) < p->guardtime)) 09117 return 0; 09118 09119 /* If no owner definitely available */ 09120 if (!p->owner) { 09121 #ifdef HAVE_PRI 09122 /* Trust PRI */ 09123 if (p->pri) { 09124 if (p->resetting || p->call) 09125 return 0; 09126 else 09127 return 1; 09128 } 09129 #endif 09130 #ifdef HAVE_OPENR2 09131 /* Trust MFC/R2 */ 09132 if (p->mfcr2) { 09133 if (p->mfcr2call || p->mfcr2block) 09134 return 0; 09135 else 09136 return 1; 09137 } 09138 #endif 09139 if (!(p->radio || (p->oprmode < 0))) 09140 { 09141 if (!p->sig || (p->sig == SIG_FXSLS)) 09142 return 1; 09143 /* Check hook state */ 09144 if (p->subs[SUB_REAL].dfd > -1) { 09145 memset(&par, 0, sizeof(par)); 09146 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09147 } else { 09148 /* Assume not off hook on CVRS */ 09149 res = 0; 09150 par.rxisoffhook = 0; 09151 } 09152 if (res) { 09153 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09154 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09155 /* When "onhook" that means no battery on the line, and thus 09156 it is out of service..., if it's on a TDM card... If it's a channel 09157 bank, there is no telling... */ 09158 if (par.rxbits > -1) 09159 return 1; 09160 if (par.rxisoffhook) 09161 return 1; 09162 else 09163 #ifdef DAHDI_CHECK_HOOKSTATE 09164 return 0; 09165 #else 09166 return 1; 09167 #endif 09168 } else if (par.rxisoffhook) { 09169 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 09170 /* Not available when the other end is off hook */ 09171 return 0; 09172 } 09173 } 09174 return 1; 09175 } 09176 09177 /* If it's not an FXO, forget about call wait */ 09178 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09179 return 0; 09180 09181 if (!p->callwaiting) { 09182 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09183 return 0; 09184 } 09185 09186 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09187 /* If there is already a call waiting call, then we can't take a second one */ 09188 return 0; 09189 } 09190 09191 if ((p->owner->_state != AST_STATE_UP) && 09192 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09193 /* If the current call is not up, then don't allow the call */ 09194 return 0; 09195 } 09196 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09197 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09198 return 0; 09199 } 09200 /* We're cool */ 09201 return 1; 09202 }
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 12786 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().
12787 { 12788 char *c, *chan; 12789 int x, start, finish; 12790 struct dahdi_pvt *tmp; 12791 #ifdef HAVE_PRI 12792 struct dahdi_pri *pri; 12793 int trunkgroup, y; 12794 #endif 12795 12796 if ((reload == 0) && (conf->chan.sig < 0)) { 12797 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 12798 return -1; 12799 } 12800 12801 c = ast_strdupa(value); 12802 12803 #ifdef HAVE_PRI 12804 pri = NULL; 12805 if (iscrv) { 12806 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 12807 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 12808 return -1; 12809 } 12810 if (trunkgroup < 1) { 12811 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 12812 return -1; 12813 } 12814 c += y; 12815 for (y = 0; y < NUM_SPANS; y++) { 12816 if (pris[y].trunkgroup == trunkgroup) { 12817 pri = pris + y; 12818 break; 12819 } 12820 } 12821 if (!pri) { 12822 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 12823 return -1; 12824 } 12825 } 12826 #endif 12827 12828 while ((chan = strsep(&c, ","))) { 12829 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 12830 /* Range */ 12831 } else if (sscanf(chan, "%30d", &start)) { 12832 /* Just one */ 12833 finish = start; 12834 } else if (!strcasecmp(chan, "pseudo")) { 12835 finish = start = CHAN_PSEUDO; 12836 if (found_pseudo) 12837 *found_pseudo = 1; 12838 } else { 12839 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 12840 return -1; 12841 } 12842 if (finish < start) { 12843 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 12844 x = finish; 12845 finish = start; 12846 start = x; 12847 } 12848 12849 for (x = start; x <= finish; x++) { 12850 #ifdef HAVE_PRI 12851 tmp = mkintf(x, conf, pri, reload); 12852 #else 12853 tmp = mkintf(x, conf, NULL, reload); 12854 #endif 12855 12856 if (tmp) { 12857 if (option_verbose > 2) { 12858 #ifdef HAVE_PRI 12859 if (pri) 12860 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 12861 else 12862 #endif 12863 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 12864 } 12865 } else { 12866 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 12867 (reload == 1) ? "reconfigure" : "register", value); 12868 return -1; 12869 } 12870 } 12871 #ifdef HAVE_OPENR2 12872 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) { 12873 mfcr2_cur_context_index++; 12874 } 12875 #endif 12876 } 12877 12878 return 0; 12879 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 11356 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
11357 { 11358 if (!s || len < 1) { 11359 return; 11360 } 11361 s[0] = '\0'; 11362 if (status & DCHAN_PROVISIONED) 11363 strncat(s, "Provisioned, ", len - strlen(s) - 1); 11364 if (!(status & DCHAN_NOTINALARM)) 11365 strncat(s, "In Alarm, ", len - strlen(s) - 1); 11366 if (status & DCHAN_UP) 11367 strncat(s, "Up", len - strlen(s) - 1); 11368 else 11369 strncat(s, "Down", len - strlen(s) - 1); 11370 if (active) 11371 strncat(s, ", Active", len - strlen(s) - 1); 11372 else 11373 strncat(s, ", Standby", len - strlen(s) - 1); 11374 s[len - 1] = '\0'; 11375 }
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 9204 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().
09205 { 09206 struct dahdi_pvt *p; 09207 struct dahdi_bufferinfo bi; 09208 int res; 09209 09210 if ((p = ast_malloc(sizeof(*p)))) { 09211 memcpy(p, src, sizeof(struct dahdi_pvt)); 09212 ast_mutex_init(&p->lock); 09213 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 09214 /* Allocate a DAHDI structure */ 09215 if (p->subs[SUB_REAL].dfd < 0) { 09216 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09217 destroy_dahdi_pvt(&p); 09218 return NULL; 09219 } 09220 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09221 if (!res) { 09222 bi.txbufpolicy = p->buf_policy; 09223 bi.rxbufpolicy = p->buf_policy; 09224 bi.numbufs = p->buf_no; 09225 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09226 if (res < 0) { 09227 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09228 } 09229 } else 09230 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09231 } 09232 p->destroy = 1; 09233 p->next = iflist; 09234 p->prev = NULL; 09235 iflist = p; 09236 if (iflist->next) 09237 iflist->next->prev = p; 09238 return p; 09239 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4763 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().
04764 { 04765 struct dahdi_confinfo ci; 04766 /* Fine if we already have a master, etc */ 04767 if (p->master || (p->confno > -1)) 04768 return 0; 04769 memset(&ci, 0, sizeof(ci)); 04770 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04771 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04772 return 0; 04773 } 04774 /* If we have no master and don't have a confno, then 04775 if we're in a conference, it's probably a MeetMe room or 04776 some such, so don't let us 3-way out! */ 04777 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04778 if (option_verbose > 2) 04779 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 04780 return 1; 04781 } 04782 return 0; 04783 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11223 of file chan_dahdi.c.
References complete_span_helper().
11224 { 11225 return complete_span_helper(line,word,pos,state,3); 11226 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11228 of file chan_dahdi.c.
References complete_span_helper().
11229 { 11230 return complete_span_helper(line,word,pos,state,4); 11231 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 11204 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
11205 { 11206 int which, span; 11207 char *ret = NULL; 11208 11209 if (pos != rpos) 11210 return ret; 11211 11212 for (which = span = 0; span < NUM_SPANS; span++) { 11213 if (pris[span].pri && ++which > state) { 11214 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 11215 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 11216 } 11217 break; 11218 } 11219 } 11220 return ret; 11221 }
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 3438 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().
03439 { 03440 /* data is whether to accept with charge or no charge */ 03441 openr2_call_mode_t accept_mode; 03442 int res, timeout, maxloops; 03443 struct ast_frame *f; 03444 struct dahdi_pvt *p; 03445 char *parse; 03446 AST_DECLARE_APP_ARGS(args, 03447 AST_APP_ARG(charge); 03448 ); 03449 03450 if (ast_strlen_zero(data)) { 03451 ast_log(LOG_DEBUG, "No data sent to application!\n"); 03452 return -1; 03453 } 03454 03455 if (chan->tech != &dahdi_tech) { 03456 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 03457 return -1; 03458 } 03459 03460 p = (struct dahdi_pvt *)chan->tech_pvt; 03461 if (!p) { 03462 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 03463 return -1; 03464 } 03465 03466 parse = ast_strdupa(data); 03467 AST_STANDARD_APP_ARGS(args, parse); 03468 03469 if (ast_strlen_zero(args.charge)) { 03470 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 03471 return -1; 03472 } 03473 03474 ast_mutex_lock(&p->lock); 03475 if (!p->mfcr2 || !p->mfcr2call) { 03476 ast_mutex_unlock(&p->lock); 03477 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 03478 return -1; 03479 } 03480 03481 if (p->mfcr2_call_accepted) { 03482 ast_mutex_unlock(&p->lock); 03483 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 03484 return 0; 03485 } 03486 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 03487 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 03488 ast_mutex_unlock(&p->lock); 03489 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03490 return -1; 03491 } 03492 ast_mutex_unlock(&p->lock); 03493 03494 res = 0; 03495 timeout = 100; 03496 maxloops = 50; /* wait up to 5 seconds */ 03497 /* we need to read() until the call is accepted */ 03498 while (maxloops > 0) { 03499 maxloops--; 03500 if (ast_check_hangup(chan)) { 03501 break; 03502 } 03503 res = ast_waitfor(chan, timeout); 03504 if (res < 0) { 03505 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 03506 res = -1; 03507 break; 03508 } 03509 if (res == 0) { 03510 continue; 03511 } 03512 f = ast_read(chan); 03513 if (!f) { 03514 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 03515 res = -1; 03516 break; 03517 } 03518 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 03519 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 03520 ast_frfree(f); 03521 res = -1; 03522 break; 03523 } 03524 ast_frfree(f); 03525 ast_mutex_lock(&p->lock); 03526 if (p->mfcr2_call_accepted) { 03527 ast_mutex_unlock(&p->lock); 03528 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 03529 break; 03530 } 03531 ast_mutex_unlock(&p->lock); 03532 } 03533 if (res == -1) { 03534 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03535 } 03536 return res; 03537 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12605 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12606 { 12607 return __action_dialoffhook(s, m, 0); 12608 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12505 of file chan_dahdi.c.
References __action_dnd(), and s.
12506 { 12507 return __action_dnd(s, m, 0, 0); 12508 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12495 of file chan_dahdi.c.
References __action_dnd(), and s.
12496 { 12497 return __action_dnd(s, m, 0, 1); 12498 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12684 of file chan_dahdi.c.
References __action_restart(), and s.
12685 { 12686 return __action_restart(s, m, 0); 12687 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12660 of file chan_dahdi.c.
References __action_showchannels(), and s.
12661 { 12662 return __action_showchannels(s, m, 0); 12663 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12534 of file chan_dahdi.c.
References __action_transfer(), and s.
12535 { 12536 return __action_transfer(s, m, 0); 12537 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12562 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12563 { 12564 return __action_transferhangup(s, m, 0); 12565 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3939 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.
03940 { 03941 struct dahdi_pvt *p = ast->tech_pvt; 03942 int res = 0; 03943 int index; 03944 int oldstate = ast->_state; 03945 ast_setstate(ast, AST_STATE_UP); 03946 ast_mutex_lock(&p->lock); 03947 index = dahdi_get_index(ast, p, 0); 03948 if (index < 0) 03949 index = SUB_REAL; 03950 /* nothing to do if a radio channel */ 03951 if ((p->radio || (p->oprmode < 0))) { 03952 ast_mutex_unlock(&p->lock); 03953 return 0; 03954 } 03955 switch (p->sig) { 03956 case SIG_FXSLS: 03957 case SIG_FXSGS: 03958 case SIG_FXSKS: 03959 p->ringt = 0; 03960 /* Fall through */ 03961 case SIG_EM: 03962 case SIG_EM_E1: 03963 case SIG_EMWINK: 03964 case SIG_FEATD: 03965 case SIG_FEATDMF: 03966 case SIG_FEATDMF_TA: 03967 case SIG_E911: 03968 case SIG_FGC_CAMA: 03969 case SIG_FGC_CAMAMF: 03970 case SIG_FEATB: 03971 case SIG_SF: 03972 case SIG_SFWINK: 03973 case SIG_SF_FEATD: 03974 case SIG_SF_FEATDMF: 03975 case SIG_SF_FEATB: 03976 case SIG_FXOLS: 03977 case SIG_FXOGS: 03978 case SIG_FXOKS: 03979 /* Pick up the line */ 03980 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03981 if (p->hanguponpolarityswitch) { 03982 gettimeofday(&p->polaritydelaytv, NULL); 03983 } 03984 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03985 tone_zone_play_tone(p->subs[index].dfd, -1); 03986 p->dialing = 0; 03987 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03988 if (oldstate == AST_STATE_RINGING) { 03989 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03990 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03991 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03992 p->owner = p->subs[SUB_REAL].owner; 03993 } 03994 } 03995 if (p->sig & __DAHDI_SIG_FXS) { 03996 dahdi_enable_ec(p); 03997 dahdi_train_ec(p); 03998 } 03999 break; 04000 #ifdef HAVE_PRI 04001 case SIG_PRI: 04002 /* Send a pri acknowledge */ 04003 if (!pri_grab(p, p->pri)) { 04004 p->proceeding = 1; 04005 p->dialing = 0; 04006 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04007 pri_rel(p->pri); 04008 } else { 04009 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04010 res = -1; 04011 } 04012 break; 04013 #endif 04014 #ifdef HAVE_OPENR2 04015 case SIG_MFCR2: 04016 if (!p->mfcr2_accept_on_offer) { 04017 /* the call was not accepted on offer, so it must be accepted now before answering, 04018 the answer will be executed when the callback on_call_accepted is executed */ 04019 if (p->mfcr2_charge_calls) { 04020 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel); 04021 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04022 } else { 04023 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel); 04024 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04025 } 04026 } else { 04027 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04028 res = dahdi_r2_answer(p); 04029 } 04030 break; 04031 #endif 04032 case 0: 04033 ast_mutex_unlock(&p->lock); 04034 return 0; 04035 default: 04036 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04037 res = -1; 04038 } 04039 ast_mutex_unlock(&p->lock); 04040 return res; 04041 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 3544 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().
03545 { 03546 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 03547 switch (cause) { 03548 case AST_CAUSE_USER_BUSY: 03549 case AST_CAUSE_CALL_REJECTED: 03550 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 03551 r2cause = OR2_CAUSE_BUSY_NUMBER; 03552 break; 03553 03554 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 03555 case AST_CAUSE_SWITCH_CONGESTION: 03556 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 03557 break; 03558 03559 case AST_CAUSE_UNALLOCATED: 03560 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 03561 break; 03562 03563 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 03564 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 03565 r2cause = OR2_CAUSE_OUT_OF_ORDER; 03566 break; 03567 03568 case AST_CAUSE_NO_ANSWER: 03569 case AST_CAUSE_NO_USER_RESPONSE: 03570 r2cause = OR2_CAUSE_NO_ANSWER; 03571 break; 03572 03573 default: 03574 r2cause = OR2_CAUSE_NORMAL_CLEARING; 03575 break; 03576 } 03577 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 03578 r2cause, openr2_proto_get_disconnect_string(r2cause), cause); 03579 return r2cause; 03580 }
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 4366 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.
04367 { 04368 struct ast_channel *who; 04369 struct dahdi_pvt *p0, *p1, *op0, *op1; 04370 struct dahdi_pvt *master = NULL, *slave = NULL; 04371 struct ast_frame *f; 04372 int inconf = 0; 04373 int nothingok = 1; 04374 int ofd0, ofd1; 04375 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04376 int os0 = -1, os1 = -1; 04377 int priority = 0; 04378 struct ast_channel *oc0, *oc1; 04379 enum ast_bridge_result res; 04380 04381 #ifdef PRI_2BCT 04382 int triedtopribridge = 0; 04383 q931_call *q931c0 = NULL, *q931c1 = NULL; 04384 #endif 04385 04386 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04387 There is code below to handle it properly until DTMF is actually seen, 04388 but due to currently unresolved issues it's ignored... 04389 */ 04390 04391 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04392 return AST_BRIDGE_FAILED_NOWARN; 04393 04394 ast_mutex_lock(&c0->lock); 04395 while (ast_mutex_trylock(&c1->lock)) { 04396 DEADLOCK_AVOIDANCE(&c0->lock); 04397 } 04398 04399 p0 = c0->tech_pvt; 04400 p1 = c1->tech_pvt; 04401 /* cant do pseudo-channels here */ 04402 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04403 ast_mutex_unlock(&c0->lock); 04404 ast_mutex_unlock(&c1->lock); 04405 return AST_BRIDGE_FAILED_NOWARN; 04406 } 04407 04408 oi0 = dahdi_get_index(c0, p0, 0); 04409 oi1 = dahdi_get_index(c1, p1, 0); 04410 if ((oi0 < 0) || (oi1 < 0)) { 04411 ast_mutex_unlock(&c0->lock); 04412 ast_mutex_unlock(&c1->lock); 04413 return AST_BRIDGE_FAILED; 04414 } 04415 04416 op0 = p0 = c0->tech_pvt; 04417 op1 = p1 = c1->tech_pvt; 04418 ofd0 = c0->fds[0]; 04419 ofd1 = c1->fds[0]; 04420 oc0 = p0->owner; 04421 oc1 = p1->owner; 04422 04423 if (ast_mutex_trylock(&p0->lock)) { 04424 /* Don't block, due to potential for deadlock */ 04425 ast_mutex_unlock(&c0->lock); 04426 ast_mutex_unlock(&c1->lock); 04427 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04428 return AST_BRIDGE_RETRY; 04429 } 04430 if (ast_mutex_trylock(&p1->lock)) { 04431 /* Don't block, due to potential for deadlock */ 04432 ast_mutex_unlock(&p0->lock); 04433 ast_mutex_unlock(&c0->lock); 04434 ast_mutex_unlock(&c1->lock); 04435 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04436 return AST_BRIDGE_RETRY; 04437 } 04438 04439 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04440 if (p0->owner && p1->owner) { 04441 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04442 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04443 master = p0; 04444 slave = p1; 04445 inconf = 1; 04446 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04447 master = p1; 04448 slave = p0; 04449 inconf = 1; 04450 } else { 04451 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04452 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04453 p0->channel, 04454 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04455 p0->subs[SUB_REAL].inthreeway, p0->channel, 04456 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04457 p1->subs[SUB_REAL].inthreeway); 04458 } 04459 nothingok = 0; 04460 } 04461 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04462 if (p1->subs[SUB_THREEWAY].inthreeway) { 04463 master = p1; 04464 slave = p0; 04465 nothingok = 0; 04466 } 04467 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04468 if (p0->subs[SUB_THREEWAY].inthreeway) { 04469 master = p0; 04470 slave = p1; 04471 nothingok = 0; 04472 } 04473 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04474 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04475 don't put us in anything */ 04476 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04477 master = p1; 04478 slave = p0; 04479 nothingok = 0; 04480 } 04481 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04482 /* Same as previous */ 04483 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04484 master = p0; 04485 slave = p1; 04486 nothingok = 0; 04487 } 04488 } 04489 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 04490 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04491 if (master && slave) { 04492 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04493 in an active threeway call with a channel that is ringing, we should 04494 indicate ringing. */ 04495 if ((oi1 == SUB_THREEWAY) && 04496 p1->subs[SUB_THREEWAY].inthreeway && 04497 p1->subs[SUB_REAL].owner && 04498 p1->subs[SUB_REAL].inthreeway && 04499 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04500 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04501 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04502 os1 = p1->subs[SUB_REAL].owner->_state; 04503 } else { 04504 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04505 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04506 } 04507 if ((oi0 == SUB_THREEWAY) && 04508 p0->subs[SUB_THREEWAY].inthreeway && 04509 p0->subs[SUB_REAL].owner && 04510 p0->subs[SUB_REAL].inthreeway && 04511 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04512 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04513 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04514 os0 = p0->subs[SUB_REAL].owner->_state; 04515 } else { 04516 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04517 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04518 } 04519 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04520 if (!p0->echocanbridged || !p1->echocanbridged) { 04521 /* Disable echo cancellation if appropriate */ 04522 dahdi_disable_ec(p0); 04523 dahdi_disable_ec(p1); 04524 } 04525 } 04526 dahdi_link(slave, master); 04527 master->inconference = inconf; 04528 } else if (!nothingok) 04529 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04530 04531 update_conf(p0); 04532 update_conf(p1); 04533 t0 = p0->subs[SUB_REAL].inthreeway; 04534 t1 = p1->subs[SUB_REAL].inthreeway; 04535 04536 ast_mutex_unlock(&p0->lock); 04537 ast_mutex_unlock(&p1->lock); 04538 04539 ast_mutex_unlock(&c0->lock); 04540 ast_mutex_unlock(&c1->lock); 04541 04542 /* Native bridge failed */ 04543 if ((!master || !slave) && !nothingok) { 04544 dahdi_enable_ec(p0); 04545 dahdi_enable_ec(p1); 04546 return AST_BRIDGE_FAILED; 04547 } 04548 04549 if (option_verbose > 2) 04550 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 04551 04552 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04553 disable_dtmf_detect(op0); 04554 04555 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04556 disable_dtmf_detect(op1); 04557 04558 for (;;) { 04559 struct ast_channel *c0_priority[2] = {c0, c1}; 04560 struct ast_channel *c1_priority[2] = {c1, c0}; 04561 04562 /* Here's our main loop... Start by locking things, looking for private parts, 04563 and then balking if anything is wrong */ 04564 ast_mutex_lock(&c0->lock); 04565 while (ast_mutex_trylock(&c1->lock)) { 04566 DEADLOCK_AVOIDANCE(&c0->lock); 04567 } 04568 04569 p0 = c0->tech_pvt; 04570 p1 = c1->tech_pvt; 04571 04572 if (op0 == p0) 04573 i0 = dahdi_get_index(c0, p0, 1); 04574 if (op1 == p1) 04575 i1 = dahdi_get_index(c1, p1, 1); 04576 ast_mutex_unlock(&c0->lock); 04577 ast_mutex_unlock(&c1->lock); 04578 04579 if (!timeoutms || 04580 (op0 != p0) || 04581 (op1 != p1) || 04582 (ofd0 != c0->fds[0]) || 04583 (ofd1 != c1->fds[0]) || 04584 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04585 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04586 (oc0 != p0->owner) || 04587 (oc1 != p1->owner) || 04588 (t0 != p0->subs[SUB_REAL].inthreeway) || 04589 (t1 != p1->subs[SUB_REAL].inthreeway) || 04590 (oi0 != i0) || 04591 (oi1 != i1)) { 04592 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04593 op0->channel, oi0, op1->channel, oi1); 04594 res = AST_BRIDGE_RETRY; 04595 goto return_from_bridge; 04596 } 04597 04598 #ifdef PRI_2BCT 04599 q931c0 = p0->call; 04600 q931c1 = p1->call; 04601 if (p0->transfer && p1->transfer 04602 && q931c0 && q931c1 04603 && !triedtopribridge) { 04604 pri_channel_bridge(q931c0, q931c1); 04605 triedtopribridge = 1; 04606 } 04607 #endif 04608 04609 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04610 if (!who) { 04611 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 04612 continue; 04613 } 04614 f = ast_read(who); 04615 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04616 *fo = f; 04617 *rc = who; 04618 res = AST_BRIDGE_COMPLETE; 04619 goto return_from_bridge; 04620 } 04621 if (f->frametype == AST_FRAME_DTMF) { 04622 if ((who == c0) && p0->pulsedial) { 04623 ast_write(c1, f); 04624 } else if ((who == c1) && p1->pulsedial) { 04625 ast_write(c0, f); 04626 } else { 04627 *fo = f; 04628 *rc = who; 04629 res = AST_BRIDGE_COMPLETE; 04630 goto return_from_bridge; 04631 } 04632 } 04633 ast_frfree(f); 04634 04635 /* Swap who gets priority */ 04636 priority = !priority; 04637 } 04638 04639 return_from_bridge: 04640 if (op0 == p0) 04641 dahdi_enable_ec(p0); 04642 04643 if (op1 == p1) 04644 dahdi_enable_ec(p1); 04645 04646 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04647 enable_dtmf_detect(op0); 04648 04649 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04650 enable_dtmf_detect(op1); 04651 04652 dahdi_unlink(slave, master, 1); 04653 04654 return res; 04655 }
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 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02748 02749 mysig = p->sig; 02750 if (p->outsigmod > -1) 02751 mysig = p->outsigmod; 02752 02753 switch (mysig) { 02754 case SIG_FXOLS: 02755 case SIG_FXOGS: 02756 case SIG_FXOKS: 02757 if (p->owner == ast) { 02758 /* Normal ring, on hook */ 02759 02760 /* Don't send audio while on hook, until the call is answered */ 02761 p->dialing = 1; 02762 if (p->use_callerid) { 02763 /* Generate the Caller-ID spill if desired */ 02764 if (p->cidspill) { 02765 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02766 free(p->cidspill); 02767 } 02768 p->callwaitcas = 0; 02769 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02770 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02771 p->cidpos = 0; 02772 send_callerid(p); 02773 } 02774 } 02775 /* Choose proper cadence */ 02776 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02777 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02778 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02779 p->cidrings = cidrings[p->distinctivering - 1]; 02780 } else { 02781 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02782 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02783 p->cidrings = p->sendcalleridafter; 02784 } 02785 02786 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02787 c = strchr(dest, '/'); 02788 if (c) 02789 c++; 02790 if (c && (strlen(c) < p->stripmsd)) { 02791 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02792 c = NULL; 02793 } 02794 if (c) { 02795 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02796 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02797 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02798 } else { 02799 p->dop.dialstr[0] = '\0'; 02800 } 02801 x = DAHDI_RING; 02802 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02803 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02804 ast_mutex_unlock(&p->lock); 02805 return -1; 02806 } 02807 p->dialing = 1; 02808 } else { 02809 /* Call waiting call */ 02810 p->callwaitrings = 0; 02811 if (ast->cid.cid_num) 02812 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02813 else 02814 p->callwait_num[0] = '\0'; 02815 if (ast->cid.cid_name) 02816 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02817 else 02818 p->callwait_name[0] = '\0'; 02819 /* Call waiting tone instead */ 02820 if (dahdi_callwait(ast)) { 02821 ast_mutex_unlock(&p->lock); 02822 return -1; 02823 } 02824 /* Make ring-back */ 02825 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02826 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02827 02828 } 02829 n = ast->cid.cid_name; 02830 l = ast->cid.cid_num; 02831 if (l) 02832 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02833 else 02834 p->lastcid_num[0] = '\0'; 02835 if (n) 02836 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02837 else 02838 p->lastcid_name[0] = '\0'; 02839 ast_setstate(ast, AST_STATE_RINGING); 02840 index = dahdi_get_index(ast, p, 0); 02841 if (index > -1) { 02842 p->subs[index].needringing = 1; 02843 } 02844 break; 02845 case SIG_FXSLS: 02846 case SIG_FXSGS: 02847 case SIG_FXSKS: 02848 case SIG_EMWINK: 02849 case SIG_EM: 02850 case SIG_EM_E1: 02851 case SIG_FEATD: 02852 case SIG_FEATDMF: 02853 case SIG_E911: 02854 case SIG_FGC_CAMA: 02855 case SIG_FGC_CAMAMF: 02856 case SIG_FEATB: 02857 case SIG_SFWINK: 02858 case SIG_SF: 02859 case SIG_SF_FEATD: 02860 case SIG_SF_FEATDMF: 02861 case SIG_FEATDMF_TA: 02862 case SIG_SF_FEATB: 02863 c = strchr(dest, '/'); 02864 if (c) 02865 c++; 02866 else 02867 c = ""; 02868 if (strlen(c) < p->stripmsd) { 02869 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02870 ast_mutex_unlock(&p->lock); 02871 return -1; 02872 } 02873 #ifdef HAVE_PRI 02874 /* Start the trunk, if not GR-303 */ 02875 if (!p->pri) { 02876 #endif 02877 x = DAHDI_START; 02878 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02879 if (res < 0) { 02880 if (errno != EINPROGRESS) { 02881 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02882 ast_mutex_unlock(&p->lock); 02883 return -1; 02884 } 02885 } 02886 #ifdef HAVE_PRI 02887 } 02888 #endif 02889 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02890 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02891 02892 c += p->stripmsd; 02893 02894 switch (mysig) { 02895 case SIG_FEATD: 02896 l = ast->cid.cid_num; 02897 if (l) 02898 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02899 else 02900 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02901 break; 02902 case SIG_FEATDMF: 02903 l = ast->cid.cid_num; 02904 if (l) 02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02906 else 02907 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02908 break; 02909 case SIG_FEATDMF_TA: 02910 { 02911 const char *cic, *ozz; 02912 02913 /* If you have to go through a Tandem Access point you need to use this */ 02914 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02915 if (!ozz) 02916 ozz = defaultozz; 02917 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02918 if (!cic) 02919 cic = defaultcic; 02920 if (!ozz || !cic) { 02921 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02922 ast_mutex_unlock(&p->lock); 02923 return -1; 02924 } 02925 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02926 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02927 p->whichwink = 0; 02928 } 02929 break; 02930 case SIG_E911: 02931 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02932 break; 02933 case SIG_FGC_CAMA: 02934 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02935 break; 02936 case SIG_FGC_CAMAMF: 02937 case SIG_FEATB: 02938 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02939 break; 02940 default: 02941 if (p->pulse) 02942 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02943 else 02944 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02945 break; 02946 } 02947 02948 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02949 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02950 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02951 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02952 p->echobreak = 1; 02953 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02954 } else 02955 p->echobreak = 0; 02956 if (!res) { 02957 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02958 int saveerr = errno; 02959 02960 x = DAHDI_ONHOOK; 02961 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02962 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02963 ast_mutex_unlock(&p->lock); 02964 return -1; 02965 } 02966 } else 02967 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res); 02968 p->dialing = 1; 02969 if (ast_strlen_zero(c)) 02970 p->dialednone = 1; 02971 ast_setstate(ast, AST_STATE_DIALING); 02972 break; 02973 case 0: 02974 /* Special pseudo -- automatically up*/ 02975 ast_setstate(ast, AST_STATE_UP); 02976 break; 02977 case SIG_PRI: 02978 case SIG_MFCR2: 02979 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02980 p->dialdest[0] = '\0'; 02981 p->dialing = 1; 02982 break; 02983 default: 02984 ast_log(LOG_DEBUG, "not yet implemented\n"); 02985 ast_mutex_unlock(&p->lock); 02986 return -1; 02987 } 02988 #ifdef HAVE_OPENR2 02989 if (p->mfcr2) { 02990 int strip = p->stripmsd; 02991 int callres = 0; 02992 c = strchr(dest, '/'); 02993 if (c) { 02994 c++; 02995 } else { 02996 c = dest; 02997 } 02998 if (!p->hidecallerid) { 02999 l = ast->cid.cid_num; 03000 } else { 03001 l = NULL; 03002 } 03003 if (strlen(c) < strip) { 03004 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip); 03005 strip = 0; 03006 } 03007 p->dialing = 1; 03008 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast)); 03009 if (-1 == callres) { 03010 ast_mutex_unlock(&p->lock); 03011 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03012 return -1; 03013 } 03014 ast_setstate(ast, AST_STATE_DIALING); 03015 } 03016 #endif /* HAVE_OPENR2 */ 03017 #ifdef HAVE_PRI 03018 if (p->pri) { 03019 struct pri_sr *sr; 03020 #ifdef SUPPORT_USERUSER 03021 const char *useruser; 03022 #endif 03023 int pridialplan; 03024 int dp_strip; 03025 int prilocaldialplan; 03026 int ldp_strip; 03027 int exclusive; 03028 const char *rr_str; 03029 int redirect_reason; 03030 03031 c = strchr(dest, '/'); 03032 if (c) { 03033 c++; 03034 } else { 03035 c = ""; 03036 } 03037 03038 l = NULL; 03039 n = NULL; 03040 if (!p->hidecallerid) { 03041 l = ast->cid.cid_num; 03042 if (!p->hidecalleridname) { 03043 n = ast->cid.cid_name; 03044 } 03045 } 03046 03047 03048 if (strlen(c) < p->stripmsd) { 03049 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03050 ast_mutex_unlock(&p->lock); 03051 return -1; 03052 } 03053 if (mysig != SIG_FXSKS) { 03054 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03055 s = strchr(c + p->stripmsd, 'w'); 03056 if (s) { 03057 if (strlen(s) > 1) 03058 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03059 else 03060 p->dop.dialstr[0] = '\0'; 03061 *s = '\0'; 03062 } else { 03063 p->dop.dialstr[0] = '\0'; 03064 } 03065 } 03066 if (pri_grab(p, p->pri)) { 03067 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03068 ast_mutex_unlock(&p->lock); 03069 return -1; 03070 } 03071 if (!(p->call = pri_new_call(p->pri->pri))) { 03072 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03073 pri_rel(p->pri); 03074 ast_mutex_unlock(&p->lock); 03075 return -1; 03076 } 03077 if (!(sr = pri_sr_new())) { 03078 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03079 pri_destroycall(p->pri->pri, p->call); 03080 p->call = NULL; 03081 pri_rel(p->pri); 03082 ast_mutex_unlock(&p->lock); 03083 return -1; 03084 } 03085 if (p->bearer || (mysig == SIG_FXSKS)) { 03086 if (p->bearer) { 03087 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); 03088 p->bearer->call = p->call; 03089 } else 03090 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 03091 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03092 } 03093 p->digital = IS_DIGITAL(ast->transfercapability); 03094 03095 /* Should the picked channel be used exclusively? */ 03096 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03097 exclusive = 1; 03098 } else { 03099 exclusive = 0; 03100 } 03101 03102 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03103 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03104 (p->digital ? -1 : 03105 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03106 if (p->pri->facilityenable) 03107 pri_facility_enable(p->pri->pri); 03108 03109 if (option_verbose > 2) 03110 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03111 dp_strip = 0; 03112 pridialplan = p->pri->dialplan - 1; 03113 if (pridialplan == -2) { /* compute dynamically */ 03114 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03115 dp_strip = strlen(p->pri->internationalprefix); 03116 pridialplan = PRI_INTERNATIONAL_ISDN; 03117 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03118 dp_strip = strlen(p->pri->nationalprefix); 03119 pridialplan = PRI_NATIONAL_ISDN; 03120 } else { 03121 pridialplan = PRI_LOCAL_ISDN; 03122 } 03123 } 03124 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03125 03126 ldp_strip = 0; 03127 prilocaldialplan = p->pri->localdialplan - 1; 03128 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 03129 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03130 ldp_strip = strlen(p->pri->internationalprefix); 03131 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03132 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03133 ldp_strip = strlen(p->pri->nationalprefix); 03134 prilocaldialplan = PRI_NATIONAL_ISDN; 03135 } else { 03136 prilocaldialplan = PRI_LOCAL_ISDN; 03137 } 03138 } 03139 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03140 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03141 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03142 if (!strcasecmp(rr_str, "UNKNOWN")) 03143 redirect_reason = 0; 03144 else if (!strcasecmp(rr_str, "BUSY")) 03145 redirect_reason = 1; 03146 else if (!strcasecmp(rr_str, "NO_REPLY")) 03147 redirect_reason = 2; 03148 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03149 redirect_reason = 15; 03150 else 03151 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03152 } else 03153 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03154 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03155 03156 #ifdef SUPPORT_USERUSER 03157 /* User-user info */ 03158 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03159 03160 if (useruser) 03161 pri_sr_set_useruser(sr, useruser); 03162 #endif 03163 03164 if (pri_setup(p->pri->pri, p->call, sr)) { 03165 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03166 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03167 pri_rel(p->pri); 03168 ast_mutex_unlock(&p->lock); 03169 pri_sr_free(sr); 03170 return -1; 03171 } 03172 pri_sr_free(sr); 03173 ast_setstate(ast, AST_STATE_DIALING); 03174 pri_rel(p->pri); 03175 } 03176 #endif 03177 ast_mutex_unlock(&p->lock); 03178 return 0; 03179 }
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 11860 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
11861 { 11862 int channel; 11863 11864 if (argc != 4) 11865 return RESULT_SHOWUSAGE; 11866 11867 channel = atoi(argv[3]); 11868 11869 return dahdi_destroy_channel_bynum(channel); 11870 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7910 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().
07911 { 07912 struct dahdi_pvt *tmp = NULL; 07913 struct dahdi_pvt *prev = NULL; 07914 07915 ast_mutex_lock(&iflock); 07916 tmp = iflist; 07917 while (tmp) { 07918 if (tmp->channel == channel) { 07919 int x = DAHDI_FLASH; 07920 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 */ 07921 destroy_channel(prev, tmp, 1); 07922 ast_mutex_unlock(&iflock); 07923 ast_module_unref(ast_module_info->self); 07924 return RESULT_SUCCESS; 07925 } 07926 prev = tmp; 07927 tmp = tmp->next; 07928 } 07929 ast_mutex_unlock(&iflock); 07930 return RESULT_FAILURE; 07931 }
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 5892 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock, ast_mutex_unlock, f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05893 { 05894 struct dahdi_pvt *p = ast->tech_pvt; 05895 struct ast_frame *f; 05896 ast_mutex_lock(&p->lock); 05897 f = __dahdi_exception(ast); 05898 ast_mutex_unlock(&p->lock); 05899 return f; 05900 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 12440 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().
12441 { 12442 if (p) { 12443 switch (mode) { 12444 case TRANSFER: 12445 p->fake_event = DAHDI_EVENT_WINKFLASH; 12446 break; 12447 case HANGUP: 12448 p->fake_event = DAHDI_EVENT_ONHOOK; 12449 break; 12450 default: 12451 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 12452 } 12453 } 12454 return 0; 12455 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4657 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.
04658 { 04659 struct dahdi_pvt *p = newchan->tech_pvt; 04660 int x; 04661 ast_mutex_lock(&p->lock); 04662 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 04663 if (p->owner == oldchan) { 04664 p->owner = newchan; 04665 } 04666 for (x = 0; x < 3; x++) 04667 if (p->subs[x].owner == oldchan) { 04668 if (!x) 04669 dahdi_unlink(NULL, p, 0); 04670 p->subs[x].owner = newchan; 04671 } 04672 if (newchan->_state == AST_STATE_RINGING) 04673 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04674 update_conf(p); 04675 ast_mutex_unlock(&p->lock); 04676 return 0; 04677 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4229 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.
04230 { 04231 struct dahdi_pvt *p = chan->tech_pvt; 04232 04233 if (!strcasecmp(data, "rxgain")) { 04234 ast_mutex_lock(&p->lock); 04235 snprintf(buf, len, "%f", p->rxgain); 04236 ast_mutex_unlock(&p->lock); 04237 } else if (!strcasecmp(data, "txgain")) { 04238 ast_mutex_lock(&p->lock); 04239 snprintf(buf, len, "%f", p->txgain); 04240 ast_mutex_unlock(&p->lock); 04241 } else { 04242 ast_copy_string(buf, "", len); 04243 } 04244 return 0; 04245 }
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 4819 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().
04820 { 04821 struct dahdi_pvt *p = ast->tech_pvt; 04822 struct ast_frame *f = *dest; 04823 04824 if (option_debug) 04825 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04826 04827 if (p->confirmanswer) { 04828 if (option_debug) 04829 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04830 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04831 of a DTMF digit */ 04832 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04833 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04834 *dest = &p->subs[index].f; 04835 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04836 p->confirmanswer = 0; 04837 } else if (p->callwaitcas) { 04838 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04839 if (option_debug) 04840 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04841 if (p->cidspill) 04842 free(p->cidspill); 04843 send_cwcidspill(p); 04844 } 04845 if ((f->subclass != 'm') && (f->subclass != 'u')) 04846 p->callwaitcas = 0; 04847 p->subs[index].f.frametype = AST_FRAME_NULL; 04848 p->subs[index].f.subclass = 0; 04849 *dest = &p->subs[index].f; 04850 } else if (f->subclass == 'f') { 04851 /* Fax tone -- Handle and return NULL */ 04852 if ((p->callprogress & 0x6) && !p->faxhandled) { 04853 p->faxhandled = 1; 04854 if (strcmp(ast->exten, "fax")) { 04855 const char *target_context = S_OR(ast->macrocontext, ast->context); 04856 04857 /* We need to unlock 'ast' here because ast_exists_extension has the 04858 * potential to start autoservice on the channel. Such action is prone 04859 * to deadlock. 04860 */ 04861 ast_mutex_unlock(&p->lock); 04862 ast_channel_unlock(ast); 04863 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04864 ast_channel_lock(ast); 04865 ast_mutex_lock(&p->lock); 04866 if (option_verbose > 2) 04867 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04868 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04869 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04870 if (ast_async_goto(ast, target_context, "fax", 1)) 04871 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04872 } else { 04873 ast_channel_lock(ast); 04874 ast_mutex_lock(&p->lock); 04875 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04876 } 04877 } else if (option_debug) 04878 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04879 } else if (option_debug) 04880 ast_log(LOG_DEBUG, "Fax already handled\n"); 04881 dahdi_confmute(p, 0); 04882 p->subs[index].f.frametype = AST_FRAME_NULL; 04883 p->subs[index].f.subclass = 0; 04884 *dest = &p->subs[index].f; 04885 } else if (f->subclass == 'm') { 04886 /* Confmute request */ 04887 dahdi_confmute(p, 1); 04888 p->subs[index].f.frametype = AST_FRAME_NULL; 04889 p->subs[index].f.subclass = 0; 04890 *dest = &p->subs[index].f; 04891 } else if (f->subclass == 'u') { 04892 /* Unmute */ 04893 dahdi_confmute(p, 0); 04894 p->subs[index].f.frametype = AST_FRAME_NULL; 04895 p->subs[index].f.subclass = 0; 04896 *dest = &p->subs[index].f; 04897 } else 04898 dahdi_confmute(p, 0); 04899 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4921 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().
04922 { 04923 int res, x; 04924 int index, mysig; 04925 char *c; 04926 struct dahdi_pvt *p = ast->tech_pvt; 04927 pthread_t threadid; 04928 pthread_attr_t attr; 04929 struct ast_channel *chan; 04930 struct ast_frame *f; 04931 04932 index = dahdi_get_index(ast, p, 0); 04933 mysig = p->sig; 04934 if (p->outsigmod > -1) 04935 mysig = p->outsigmod; 04936 p->subs[index].f.frametype = AST_FRAME_NULL; 04937 p->subs[index].f.subclass = 0; 04938 p->subs[index].f.datalen = 0; 04939 p->subs[index].f.samples = 0; 04940 p->subs[index].f.mallocd = 0; 04941 p->subs[index].f.offset = 0; 04942 p->subs[index].f.src = "dahdi_handle_event"; 04943 p->subs[index].f.data = NULL; 04944 f = &p->subs[index].f; 04945 04946 if (index < 0) 04947 return &p->subs[index].f; 04948 if (p->fake_event) { 04949 res = p->fake_event; 04950 p->fake_event = 0; 04951 } else 04952 res = dahdi_get_event(p->subs[index].dfd); 04953 04954 if (option_debug) 04955 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04956 04957 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04958 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04959 04960 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04961 #ifdef HAVE_PRI 04962 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04963 /* absorb event */ 04964 } else { 04965 #endif 04966 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04967 p->subs[index].f.subclass = res & 0xff; 04968 #ifdef HAVE_PRI 04969 } 04970 #endif 04971 dahdi_handle_dtmfup(ast, index, &f); 04972 return f; 04973 } 04974 04975 if (res & DAHDI_EVENT_DTMFDOWN) { 04976 if (option_debug) 04977 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04978 /* Mute conference */ 04979 dahdi_confmute(p, 1); 04980 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04981 p->subs[index].f.subclass = res & 0xff; 04982 return &p->subs[index].f; 04983 } 04984 04985 switch (res) { 04986 #ifdef DAHDI_EVENT_EC_DISABLED 04987 case DAHDI_EVENT_EC_DISABLED: 04988 if (option_verbose > 2) 04989 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04990 p->echocanon = 0; 04991 break; 04992 #endif 04993 case DAHDI_EVENT_BITSCHANGED: 04994 #ifdef HAVE_OPENR2 04995 if (p->sig != SIG_MFCR2) { 04996 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 04997 } else { 04998 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 04999 openr2_chan_handle_cas(p->r2chan); 05000 } 05001 #else 05002 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05003 #endif 05004 case DAHDI_EVENT_PULSE_START: 05005 /* Stop tone if there's a pulse start and the PBX isn't started */ 05006 if (!ast->pbx) 05007 tone_zone_play_tone(p->subs[index].dfd, -1); 05008 break; 05009 case DAHDI_EVENT_DIALCOMPLETE: 05010 #ifdef HAVE_OPENR2 05011 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05012 /* we don't need to do anything for this event for R2 signaling 05013 if the call is being setup */ 05014 break; 05015 } 05016 #endif 05017 if (p->inalarm) break; 05018 if ((p->radio || (p->oprmode < 0))) break; 05019 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 05020 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05021 return NULL; 05022 } 05023 if (!x) { /* if not still dialing in driver */ 05024 dahdi_enable_ec(p); 05025 if (p->echobreak) { 05026 dahdi_train_ec(p); 05027 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05028 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05029 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05030 p->echobreak = 0; 05031 } else { 05032 p->dialing = 0; 05033 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05034 /* if thru with dialing after offhook */ 05035 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05036 ast_setstate(ast, AST_STATE_UP); 05037 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05038 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05039 break; 05040 } else { /* if to state wait for offhook to dial rest */ 05041 /* we now wait for off hook */ 05042 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05043 } 05044 } 05045 if (ast->_state == AST_STATE_DIALING) { 05046 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05047 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 05048 } 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)))) { 05049 ast_setstate(ast, AST_STATE_RINGING); 05050 } else if (!p->answeronpolarityswitch) { 05051 ast_setstate(ast, AST_STATE_UP); 05052 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05053 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05054 /* If aops=0 and hops=1, this is necessary */ 05055 p->polarity = POLARITY_REV; 05056 } else { 05057 /* Start clean, so we can catch the change to REV polarity when party answers */ 05058 p->polarity = POLARITY_IDLE; 05059 } 05060 } 05061 } 05062 } 05063 break; 05064 case DAHDI_EVENT_ALARM: 05065 #ifdef HAVE_PRI 05066 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05067 /* T309 is not enabled : hangup calls when alarm occurs */ 05068 if (p->call) { 05069 if (p->pri && p->pri->pri) { 05070 if (!pri_grab(p, p->pri)) { 05071 pri_hangup(p->pri->pri, p->call, -1); 05072 pri_destroycall(p->pri->pri, p->call); 05073 p->call = NULL; 05074 pri_rel(p->pri); 05075 } else 05076 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 05077 } else 05078 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05079 } 05080 if (p->owner) 05081 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05082 } 05083 if (p->bearer) 05084 p->bearer->inalarm = 1; 05085 else 05086 #endif 05087 p->inalarm = 1; 05088 res = get_alarms(p); 05089 handle_alarms(p, res); 05090 #ifdef HAVE_PRI 05091 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05092 /* fall through intentionally */ 05093 } else { 05094 break; 05095 } 05096 #endif 05097 #ifdef HAVE_OPENR2 05098 if (p->sig == SIG_MFCR2) 05099 break; 05100 #endif 05101 case DAHDI_EVENT_ONHOOK: 05102 if (p->radio) { 05103 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05104 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05105 break; 05106 } 05107 if (p->oprmode < 0) 05108 { 05109 if (p->oprmode != -1) break; 05110 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05111 { 05112 /* Make sure it starts ringing */ 05113 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05114 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05115 save_conference(p->oprpeer); 05116 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05117 } 05118 break; 05119 } 05120 switch (p->sig) { 05121 case SIG_FXOLS: 05122 case SIG_FXOGS: 05123 case SIG_FXOKS: 05124 p->onhooktime = time(NULL); 05125 p->msgstate = -1; 05126 /* Check for some special conditions regarding call waiting */ 05127 if (index == SUB_REAL) { 05128 /* The normal line was hung up */ 05129 if (p->subs[SUB_CALLWAIT].owner) { 05130 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05131 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05132 if (option_verbose > 2) 05133 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05134 unalloc_sub(p, SUB_CALLWAIT); 05135 #if 0 05136 p->subs[index].needanswer = 0; 05137 p->subs[index].needringing = 0; 05138 #endif 05139 p->callwaitingrepeat = 0; 05140 p->cidcwexpire = 0; 05141 p->owner = NULL; 05142 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05143 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05144 p->dialing = 1; 05145 dahdi_ring_phone(p); 05146 } else if (p->subs[SUB_THREEWAY].owner) { 05147 unsigned int mssinceflash; 05148 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 05149 the private structure -- not especially easy or clean */ 05150 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 05151 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 05152 ast_mutex_unlock(&p->lock); 05153 DEADLOCK_AVOIDANCE(&ast->lock); 05154 /* We can grab ast and p in that order, without worry. We should make sure 05155 nothing seriously bad has happened though like some sort of bizarre double 05156 masquerade! */ 05157 ast_mutex_lock(&p->lock); 05158 if (p->owner != ast) { 05159 ast_log(LOG_WARNING, "This isn't good...\n"); 05160 return NULL; 05161 } 05162 } 05163 if (!p->subs[SUB_THREEWAY].owner) { 05164 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05165 return NULL; 05166 } 05167 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05168 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 05169 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05170 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05171 hanging up. Hangup both channels now */ 05172 if (p->subs[SUB_THREEWAY].owner) 05173 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 05174 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05175 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05176 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05177 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05178 if (p->transfer) { 05179 /* In any case this isn't a threeway call anymore */ 05180 p->subs[SUB_REAL].inthreeway = 0; 05181 p->subs[SUB_THREEWAY].inthreeway = 0; 05182 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05183 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05184 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05185 /* Swap subs and dis-own channel */ 05186 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05187 p->owner = NULL; 05188 /* Ring the phone */ 05189 dahdi_ring_phone(p); 05190 } else { 05191 if ((res = attempt_transfer(p)) < 0) { 05192 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05193 if (p->subs[SUB_THREEWAY].owner) 05194 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05195 } else if (res) { 05196 /* Don't actually hang up at this point */ 05197 if (p->subs[SUB_THREEWAY].owner) 05198 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05199 break; 05200 } 05201 } 05202 } else { 05203 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05204 if (p->subs[SUB_THREEWAY].owner) 05205 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05206 } 05207 } else { 05208 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05209 /* Swap subs and dis-own channel */ 05210 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05211 p->owner = NULL; 05212 /* Ring the phone */ 05213 dahdi_ring_phone(p); 05214 } 05215 } 05216 } else { 05217 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 05218 } 05219 /* Fall through */ 05220 default: 05221 dahdi_disable_ec(p); 05222 return NULL; 05223 } 05224 break; 05225 case DAHDI_EVENT_RINGOFFHOOK: 05226 if (p->inalarm) break; 05227 if (p->oprmode < 0) 05228 { 05229 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05230 { 05231 /* Make sure it stops ringing */ 05232 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05233 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 05234 restore_conference(p->oprpeer); 05235 } 05236 break; 05237 } 05238 if (p->radio) 05239 { 05240 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05241 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05242 break; 05243 } 05244 /* for E911, its supposed to wait for offhook then dial 05245 the second half of the dial string */ 05246 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05247 c = strchr(p->dialdest, '/'); 05248 if (c) 05249 c++; 05250 else 05251 c = p->dialdest; 05252 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05253 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05254 if (strlen(p->dop.dialstr) > 4) { 05255 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05256 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05257 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05258 p->echobreak = 1; 05259 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05260 } else 05261 p->echobreak = 0; 05262 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05263 int saveerr = errno; 05264 05265 x = DAHDI_ONHOOK; 05266 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05267 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05268 return NULL; 05269 } 05270 p->dialing = 1; 05271 return &p->subs[index].f; 05272 } 05273 switch (p->sig) { 05274 case SIG_FXOLS: 05275 case SIG_FXOGS: 05276 case SIG_FXOKS: 05277 switch (ast->_state) { 05278 case AST_STATE_RINGING: 05279 dahdi_enable_ec(p); 05280 dahdi_train_ec(p); 05281 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05282 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05283 /* Make sure it stops ringing */ 05284 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05285 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 05286 if (p->cidspill) { 05287 /* Cancel any running CallerID spill */ 05288 free(p->cidspill); 05289 p->cidspill = NULL; 05290 } 05291 p->dialing = 0; 05292 p->callwaitcas = 0; 05293 if (p->confirmanswer) { 05294 /* Ignore answer if "confirm answer" is enabled */ 05295 p->subs[index].f.frametype = AST_FRAME_NULL; 05296 p->subs[index].f.subclass = 0; 05297 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05298 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05299 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05300 if (res < 0) { 05301 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05302 p->dop.dialstr[0] = '\0'; 05303 return NULL; 05304 } else { 05305 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05306 p->subs[index].f.frametype = AST_FRAME_NULL; 05307 p->subs[index].f.subclass = 0; 05308 p->dialing = 1; 05309 } 05310 p->dop.dialstr[0] = '\0'; 05311 ast_setstate(ast, AST_STATE_DIALING); 05312 } else 05313 ast_setstate(ast, AST_STATE_UP); 05314 return &p->subs[index].f; 05315 case AST_STATE_DOWN: 05316 ast_setstate(ast, AST_STATE_RING); 05317 ast->rings = 1; 05318 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05319 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05320 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 05321 return &p->subs[index].f; 05322 case AST_STATE_UP: 05323 /* Make sure it stops ringing */ 05324 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05325 /* Okay -- probably call waiting*/ 05326 if (ast_bridged_channel(p->owner)) 05327 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05328 p->subs[index].needunhold = 1; 05329 break; 05330 case AST_STATE_RESERVED: 05331 /* Start up dialtone */ 05332 if (has_voicemail(p)) 05333 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05334 else 05335 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05336 break; 05337 default: 05338 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05339 } 05340 break; 05341 case SIG_FXSLS: 05342 case SIG_FXSGS: 05343 case SIG_FXSKS: 05344 if (ast->_state == AST_STATE_RING) { 05345 p->ringt = p->ringt_base; 05346 } 05347 05348 /* Fall through */ 05349 case SIG_EM: 05350 case SIG_EM_E1: 05351 case SIG_EMWINK: 05352 case SIG_FEATD: 05353 case SIG_FEATDMF: 05354 case SIG_FEATDMF_TA: 05355 case SIG_E911: 05356 case SIG_FGC_CAMA: 05357 case SIG_FGC_CAMAMF: 05358 case SIG_FEATB: 05359 case SIG_SF: 05360 case SIG_SFWINK: 05361 case SIG_SF_FEATD: 05362 case SIG_SF_FEATDMF: 05363 case SIG_SF_FEATB: 05364 if (ast->_state == AST_STATE_PRERING) 05365 ast_setstate(ast, AST_STATE_RING); 05366 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05367 if (option_debug) 05368 ast_log(LOG_DEBUG, "Ring detected\n"); 05369 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05370 p->subs[index].f.subclass = AST_CONTROL_RING; 05371 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05372 if (option_debug) 05373 ast_log(LOG_DEBUG, "Line answered\n"); 05374 if (p->confirmanswer) { 05375 p->subs[index].f.frametype = AST_FRAME_NULL; 05376 p->subs[index].f.subclass = 0; 05377 } else { 05378 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05379 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05380 ast_setstate(ast, AST_STATE_UP); 05381 } 05382 } else if (ast->_state != AST_STATE_RING) 05383 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05384 break; 05385 default: 05386 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05387 } 05388 break; 05389 #ifdef DAHDI_EVENT_RINGBEGIN 05390 case DAHDI_EVENT_RINGBEGIN: 05391 switch (p->sig) { 05392 case SIG_FXSLS: 05393 case SIG_FXSGS: 05394 case SIG_FXSKS: 05395 if (ast->_state == AST_STATE_RING) { 05396 p->ringt = p->ringt_base; 05397 } 05398 break; 05399 } 05400 break; 05401 #endif 05402 case DAHDI_EVENT_RINGEROFF: 05403 if (p->inalarm) break; 05404 if ((p->radio || (p->oprmode < 0))) break; 05405 ast->rings++; 05406 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05407 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05408 free(p->cidspill); 05409 p->cidspill = NULL; 05410 p->callwaitcas = 0; 05411 } 05412 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05413 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05414 break; 05415 case DAHDI_EVENT_RINGERON: 05416 break; 05417 case DAHDI_EVENT_NOALARM: 05418 p->inalarm = 0; 05419 #ifdef HAVE_PRI 05420 /* Extremely unlikely but just in case */ 05421 if (p->bearer) 05422 p->bearer->inalarm = 0; 05423 #endif 05424 if (!p->unknown_alarm) { 05425 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05426 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05427 "Channel: %d\r\n", p->channel); 05428 } else { 05429 p->unknown_alarm = 0; 05430 } 05431 break; 05432 case DAHDI_EVENT_WINKFLASH: 05433 if (p->inalarm) break; 05434 if (p->radio) break; 05435 if (p->oprmode < 0) break; 05436 if (p->oprmode > 1) 05437 { 05438 struct dahdi_params par; 05439 05440 memset(&par, 0, sizeof(par)); 05441 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05442 { 05443 if (!par.rxisoffhook) 05444 { 05445 /* Make sure it stops ringing */ 05446 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05447 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05448 save_conference(p); 05449 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05450 } 05451 } 05452 break; 05453 } 05454 /* Remember last time we got a flash-hook */ 05455 gettimeofday(&p->flashtime, NULL); 05456 switch (mysig) { 05457 case SIG_FXOLS: 05458 case SIG_FXOGS: 05459 case SIG_FXOKS: 05460 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05461 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05462 p->callwaitcas = 0; 05463 05464 if (index != SUB_REAL) { 05465 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05466 goto winkflashdone; 05467 } 05468 05469 if (p->subs[SUB_CALLWAIT].owner) { 05470 /* Swap to call-wait */ 05471 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05472 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05473 p->owner = p->subs[SUB_REAL].owner; 05474 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 05475 if (p->owner->_state == AST_STATE_RINGING) { 05476 ast_setstate(p->owner, AST_STATE_UP); 05477 p->subs[SUB_REAL].needanswer = 1; 05478 } 05479 p->callwaitingrepeat = 0; 05480 p->cidcwexpire = 0; 05481 /* Start music on hold if appropriate */ 05482 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05483 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05484 S_OR(p->mohsuggest, NULL), 05485 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05486 } 05487 p->subs[SUB_CALLWAIT].needhold = 1; 05488 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05489 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05490 S_OR(p->mohsuggest, NULL), 05491 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05492 } 05493 p->subs[SUB_REAL].needunhold = 1; 05494 } else if (!p->subs[SUB_THREEWAY].owner) { 05495 if (!p->threewaycalling) { 05496 /* Just send a flash if no 3-way calling */ 05497 p->subs[SUB_REAL].needflash = 1; 05498 goto winkflashdone; 05499 } else if (!check_for_conference(p)) { 05500 char cid_num[256]; 05501 char cid_name[256]; 05502 05503 cid_num[0] = 0; 05504 cid_name[0] = 0; 05505 if (p->dahditrcallerid && p->owner) { 05506 if (p->owner->cid.cid_num) 05507 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05508 if (p->owner->cid.cid_name) 05509 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05510 } 05511 /* XXX This section needs much more error checking!!! XXX */ 05512 /* Start a 3-way call if feasible */ 05513 if (!((ast->pbx) || 05514 (ast->_state == AST_STATE_UP) || 05515 (ast->_state == AST_STATE_RING))) { 05516 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 05517 goto winkflashdone; 05518 } 05519 if (alloc_sub(p, SUB_THREEWAY)) { 05520 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05521 goto winkflashdone; 05522 } 05523 /* Make new channel */ 05524 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05525 if (p->dahditrcallerid) { 05526 if (!p->origcid_num) 05527 p->origcid_num = ast_strdup(p->cid_num); 05528 if (!p->origcid_name) 05529 p->origcid_name = ast_strdup(p->cid_name); 05530 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05531 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05532 } 05533 /* Swap things around between the three-way and real call */ 05534 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05535 /* Disable echo canceller for better dialing */ 05536 dahdi_disable_ec(p); 05537 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05538 if (res) 05539 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05540 p->owner = chan; 05541 pthread_attr_init(&attr); 05542 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05543 if (!chan) { 05544 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05545 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 05546 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05547 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05548 dahdi_enable_ec(p); 05549 ast_hangup(chan); 05550 } else { 05551 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05552 int way3bridge = 0, cdr3way = 0; 05553 05554 if (!other) { 05555 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05556 } else 05557 way3bridge = 1; 05558 05559 if (p->subs[SUB_THREEWAY].owner->cdr) 05560 cdr3way = 1; 05561 05562 if (option_verbose > 2) 05563 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 05564 /* Start music on hold if appropriate */ 05565 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05566 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05567 S_OR(p->mohsuggest, NULL), 05568 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05569 } 05570 p->subs[SUB_THREEWAY].needhold = 1; 05571 } 05572 pthread_attr_destroy(&attr); 05573 } 05574 } else { 05575 /* Already have a 3 way call */ 05576 if (p->subs[SUB_THREEWAY].inthreeway) { 05577 /* Call is already up, drop the last person */ 05578 if (option_debug) 05579 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05580 /* If the primary call isn't answered yet, use it */ 05581 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05582 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05583 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05584 p->owner = p->subs[SUB_REAL].owner; 05585 } 05586 /* Drop the last call and stop the conference */ 05587 if (option_verbose > 2) 05588 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05589 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05590 p->subs[SUB_REAL].inthreeway = 0; 05591 p->subs[SUB_THREEWAY].inthreeway = 0; 05592 } else { 05593 /* Lets see what we're up to */ 05594 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05595 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05596 int otherindex = SUB_THREEWAY; 05597 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05598 int way3bridge = 0, cdr3way = 0; 05599 05600 if (!other) { 05601 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05602 } else 05603 way3bridge = 1; 05604 05605 if (p->subs[SUB_THREEWAY].owner->cdr) 05606 cdr3way = 1; 05607 05608 if (option_verbose > 2) 05609 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); 05610 /* Put them in the threeway, and flip */ 05611 p->subs[SUB_THREEWAY].inthreeway = 1; 05612 p->subs[SUB_REAL].inthreeway = 1; 05613 if (ast->_state == AST_STATE_UP) { 05614 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05615 otherindex = SUB_REAL; 05616 } 05617 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05618 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05619 p->subs[otherindex].needunhold = 1; 05620 p->owner = p->subs[SUB_REAL].owner; 05621 if (ast->_state == AST_STATE_RINGING) { 05622 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 05623 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05624 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05625 } 05626 } else { 05627 if (option_verbose > 2) 05628 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05629 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05630 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05631 p->owner = p->subs[SUB_REAL].owner; 05632 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05633 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05634 p->subs[SUB_REAL].needunhold = 1; 05635 dahdi_enable_ec(p); 05636 } 05637 05638 } 05639 } 05640 winkflashdone: 05641 update_conf(p); 05642 break; 05643 case SIG_EM: 05644 case SIG_EM_E1: 05645 case SIG_FEATD: 05646 case SIG_SF: 05647 case SIG_SFWINK: 05648 case SIG_SF_FEATD: 05649 case SIG_FXSLS: 05650 case SIG_FXSGS: 05651 if (p->dialing) 05652 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 05653 else 05654 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05655 break; 05656 case SIG_FEATDMF_TA: 05657 switch (p->whichwink) { 05658 case 0: 05659 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05660 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05661 break; 05662 case 1: 05663 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05664 break; 05665 case 2: 05666 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05667 return NULL; 05668 } 05669 p->whichwink++; 05670 /* Fall through */ 05671 case SIG_FEATDMF: 05672 case SIG_E911: 05673 case SIG_FGC_CAMAMF: 05674 case SIG_FGC_CAMA: 05675 case SIG_FEATB: 05676 case SIG_SF_FEATDMF: 05677 case SIG_SF_FEATB: 05678 case SIG_EMWINK: 05679 /* FGD MF and EMWINK *Must* wait for wink */ 05680 if (!ast_strlen_zero(p->dop.dialstr)) { 05681 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05682 if (res < 0) { 05683 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05684 p->dop.dialstr[0] = '\0'; 05685 return NULL; 05686 } else 05687 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05688 } 05689 p->dop.dialstr[0] = '\0'; 05690 break; 05691 default: 05692 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05693 } 05694 break; 05695 case DAHDI_EVENT_HOOKCOMPLETE: 05696 if (p->inalarm) break; 05697 if ((p->radio || (p->oprmode < 0))) break; 05698 switch (mysig) { 05699 case SIG_FXSLS: /* only interesting for FXS */ 05700 case SIG_FXSGS: 05701 case SIG_FXSKS: 05702 case SIG_EM: 05703 case SIG_EM_E1: 05704 case SIG_EMWINK: 05705 case SIG_FEATD: 05706 case SIG_SF: 05707 case SIG_SFWINK: 05708 case SIG_SF_FEATD: 05709 if (!ast_strlen_zero(p->dop.dialstr)) { 05710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05711 if (res < 0) { 05712 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05713 p->dop.dialstr[0] = '\0'; 05714 return NULL; 05715 } else 05716 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05717 } 05718 p->dop.dialstr[0] = '\0'; 05719 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05720 break; 05721 case SIG_FEATDMF: 05722 case SIG_FEATDMF_TA: 05723 case SIG_E911: 05724 case SIG_FGC_CAMA: 05725 case SIG_FGC_CAMAMF: 05726 case SIG_FEATB: 05727 case SIG_SF_FEATDMF: 05728 case SIG_SF_FEATB: 05729 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05730 break; 05731 default: 05732 break; 05733 } 05734 break; 05735 case DAHDI_EVENT_POLARITY: 05736 /* 05737 * If we get a Polarity Switch event, check to see 05738 * if we should change the polarity state and 05739 * mark the channel as UP or if this is an indication 05740 * of remote end disconnect. 05741 */ 05742 if (p->polarity == POLARITY_IDLE) { 05743 p->polarity = POLARITY_REV; 05744 if (p->answeronpolarityswitch && 05745 ((ast->_state == AST_STATE_DIALING) || 05746 (ast->_state == AST_STATE_RINGING))) { 05747 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 05748 ast_setstate(p->owner, AST_STATE_UP); 05749 if (p->hanguponpolarityswitch) { 05750 gettimeofday(&p->polaritydelaytv, NULL); 05751 } 05752 } else 05753 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05754 } 05755 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05756 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05757 if (p->hanguponpolarityswitch && 05758 (p->polarityonanswerdelay > 0) && 05759 (p->polarity == POLARITY_REV) && 05760 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05761 /* Added log_debug information below to provide a better indication of what is going on */ 05762 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) ); 05763 05764 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05765 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05766 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05767 p->polarity = POLARITY_IDLE; 05768 } else { 05769 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); 05770 } 05771 } else { 05772 p->polarity = POLARITY_IDLE; 05773 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05774 } 05775 /* Added more log_debug information below to provide a better indication of what is going on */ 05776 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) ); 05777 break; 05778 default: 05779 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05780 } 05781 return &p->subs[index].f; 05782 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3583 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().
03584 { 03585 int res; 03586 int index,x, law; 03587 /*static int restore_gains(struct dahdi_pvt *p);*/ 03588 struct dahdi_pvt *p = ast->tech_pvt; 03589 struct dahdi_pvt *tmp = NULL; 03590 struct dahdi_pvt *prev = NULL; 03591 struct dahdi_params par; 03592 03593 if (option_debug) 03594 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 03595 if (!ast->tech_pvt) { 03596 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03597 return 0; 03598 } 03599 03600 ast_mutex_lock(&p->lock); 03601 03602 index = dahdi_get_index(ast, p, 1); 03603 03604 if (p->sig == SIG_PRI) { 03605 x = 1; 03606 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03607 p->cid_num[0] = '\0'; 03608 p->cid_name[0] = '\0'; 03609 } 03610 03611 x = 0; 03612 dahdi_confmute(p, 0); 03613 restore_gains(p); 03614 if (p->origcid_num) { 03615 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03616 free(p->origcid_num); 03617 p->origcid_num = NULL; 03618 } 03619 if (p->origcid_name) { 03620 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03621 free(p->origcid_name); 03622 p->origcid_name = NULL; 03623 } 03624 if (p->dsp) 03625 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 03626 p->exten[0] = '\0'; 03627 03628 if (option_debug) 03629 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03630 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03631 p->ignoredtmf = 0; 03632 03633 if (index > -1) { 03634 /* Real channel, do some fixup */ 03635 p->subs[index].owner = NULL; 03636 p->subs[index].needanswer = 0; 03637 p->subs[index].needflash = 0; 03638 p->subs[index].needringing = 0; 03639 p->subs[index].needbusy = 0; 03640 p->subs[index].needcongestion = 0; 03641 p->subs[index].linear = 0; 03642 p->subs[index].needcallerid = 0; 03643 p->polarity = POLARITY_IDLE; 03644 dahdi_setlinear(p->subs[index].dfd, 0); 03645 if (index == SUB_REAL) { 03646 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03647 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03648 if (p->subs[SUB_CALLWAIT].inthreeway) { 03649 /* We had flipped over to answer a callwait and now it's gone */ 03650 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 03651 /* Move to the call-wait, but un-own us until they flip back. */ 03652 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03653 unalloc_sub(p, SUB_CALLWAIT); 03654 p->owner = NULL; 03655 } else { 03656 /* The three way hung up, but we still have a call wait */ 03657 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03658 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03659 unalloc_sub(p, SUB_THREEWAY); 03660 if (p->subs[SUB_REAL].inthreeway) { 03661 /* This was part of a three way call. Immediately make way for 03662 another call */ 03663 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03664 p->owner = p->subs[SUB_REAL].owner; 03665 } else { 03666 /* This call hasn't been completed yet... Set owner to NULL */ 03667 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03668 p->owner = NULL; 03669 } 03670 p->subs[SUB_REAL].inthreeway = 0; 03671 } 03672 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03673 /* Move to the call-wait and switch back to them. */ 03674 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03675 unalloc_sub(p, SUB_CALLWAIT); 03676 p->owner = p->subs[SUB_REAL].owner; 03677 if (p->owner->_state != AST_STATE_UP) 03678 p->subs[SUB_REAL].needanswer = 1; 03679 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03680 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03681 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03682 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03683 unalloc_sub(p, SUB_THREEWAY); 03684 if (p->subs[SUB_REAL].inthreeway) { 03685 /* This was part of a three way call. Immediately make way for 03686 another call */ 03687 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03688 p->owner = p->subs[SUB_REAL].owner; 03689 } else { 03690 /* This call hasn't been completed yet... Set owner to NULL */ 03691 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03692 p->owner = NULL; 03693 } 03694 p->subs[SUB_REAL].inthreeway = 0; 03695 } 03696 } else if (index == SUB_CALLWAIT) { 03697 /* Ditch the holding callwait call, and immediately make it availabe */ 03698 if (p->subs[SUB_CALLWAIT].inthreeway) { 03699 /* This is actually part of a three way, placed on hold. Place the third part 03700 on music on hold now */ 03701 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03702 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03703 S_OR(p->mohsuggest, NULL), 03704 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03705 } 03706 p->subs[SUB_THREEWAY].inthreeway = 0; 03707 /* Make it the call wait now */ 03708 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03709 unalloc_sub(p, SUB_THREEWAY); 03710 } else 03711 unalloc_sub(p, SUB_CALLWAIT); 03712 } else if (index == SUB_THREEWAY) { 03713 if (p->subs[SUB_CALLWAIT].inthreeway) { 03714 /* The other party of the three way call is currently in a call-wait state. 03715 Start music on hold for them, and take the main guy out of the third call */ 03716 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03717 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03718 S_OR(p->mohsuggest, NULL), 03719 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03720 } 03721 p->subs[SUB_CALLWAIT].inthreeway = 0; 03722 } 03723 p->subs[SUB_REAL].inthreeway = 0; 03724 /* If this was part of a three way call index, let us make 03725 another three way call */ 03726 unalloc_sub(p, SUB_THREEWAY); 03727 } else { 03728 /* This wasn't any sort of call, but how are we an index? */ 03729 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03730 } 03731 } 03732 03733 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03734 p->owner = NULL; 03735 p->ringt = 0; 03736 p->distinctivering = 0; 03737 p->confirmanswer = 0; 03738 p->cidrings = 1; 03739 p->outgoing = 0; 03740 p->digital = 0; 03741 p->faxhandled = 0; 03742 p->pulsedial = 0; 03743 p->onhooktime = time(NULL); 03744 #ifdef HAVE_PRI 03745 p->proceeding = 0; 03746 p->dialing = 0; 03747 p->progress = 0; 03748 p->alerting = 0; 03749 p->setup_ack = 0; 03750 #endif 03751 if (p->dsp) { 03752 ast_dsp_free(p->dsp); 03753 p->dsp = NULL; 03754 } 03755 03756 law = DAHDI_LAW_DEFAULT; 03757 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03758 if (res < 0) 03759 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03760 /* Perform low level hangup if no owner left */ 03761 #ifdef HAVE_OPENR2 03762 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 03763 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 03764 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause); 03765 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 03766 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 03767 } else { 03768 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE"); 03769 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 03770 openr2_call_disconnect_cause_t r2cause = r2cause_user 03771 ? dahdi_ast_cause_to_r2_cause(r2cause_user) 03772 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 03773 dahdi_r2_disconnect_call(p, r2cause); 03774 } 03775 } else if (p->mfcr2call) { 03776 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 03777 p->mfcr2call = 0; 03778 } 03779 #endif 03780 #ifdef HAVE_PRI 03781 if (p->pri) { 03782 #ifdef SUPPORT_USERUSER 03783 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03784 #endif 03785 03786 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03787 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03788 if (!pri_grab(p, p->pri)) { 03789 if (p->alreadyhungup) { 03790 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03791 03792 #ifdef SUPPORT_USERUSER 03793 pri_call_set_useruser(p->call, useruser); 03794 #endif 03795 03796 pri_hangup(p->pri->pri, p->call, -1); 03797 p->call = NULL; 03798 if (p->bearer) 03799 p->bearer->call = NULL; 03800 } else { 03801 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03802 int icause = ast->hangupcause ? ast->hangupcause : -1; 03803 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03804 03805 #ifdef SUPPORT_USERUSER 03806 pri_call_set_useruser(p->call, useruser); 03807 #endif 03808 03809 p->alreadyhungup = 1; 03810 if (p->bearer) 03811 p->bearer->alreadyhungup = 1; 03812 if (cause) { 03813 if (atoi(cause)) 03814 icause = atoi(cause); 03815 } 03816 pri_hangup(p->pri->pri, p->call, icause); 03817 } 03818 if (res < 0) 03819 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03820 pri_rel(p->pri); 03821 } else { 03822 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03823 res = -1; 03824 } 03825 } else { 03826 if (p->bearer) 03827 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03828 p->call = NULL; 03829 res = 0; 03830 } 03831 } 03832 #endif 03833 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2)) 03834 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03835 if (res < 0) { 03836 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03837 } 03838 switch (p->sig) { 03839 case SIG_FXOGS: 03840 case SIG_FXOLS: 03841 case SIG_FXOKS: 03842 memset(&par, 0, sizeof(par)); 03843 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03844 if (!res) { 03845 #if 0 03846 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03847 #endif 03848 /* If they're off hook, try playing congestion */ 03849 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03850 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03851 else 03852 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03853 } 03854 break; 03855 case SIG_FXSGS: 03856 case SIG_FXSLS: 03857 case SIG_FXSKS: 03858 /* Make sure we're not made available for at least two seconds assuming 03859 we were actually used for an inbound or outbound call. */ 03860 if (ast->_state != AST_STATE_RESERVED) { 03861 time(&p->guardtime); 03862 p->guardtime += 2; 03863 } 03864 break; 03865 default: 03866 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03867 } 03868 if (p->cidspill) 03869 free(p->cidspill); 03870 if (p->sig) 03871 dahdi_disable_ec(p); 03872 x = 0; 03873 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03874 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03875 p->didtdd = 0; 03876 p->cidspill = NULL; 03877 p->callwaitcas = 0; 03878 p->callwaiting = p->permcallwaiting; 03879 p->hidecallerid = p->permhidecallerid; 03880 p->dialing = 0; 03881 p->rdnis[0] = '\0'; 03882 update_conf(p); 03883 reset_conf(p); 03884 /* Restore data mode */ 03885 if (p->sig == SIG_PRI) { 03886 x = 0; 03887 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03888 } 03889 #ifdef HAVE_PRI 03890 if (p->bearer) { 03891 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03892 /* Free up the bearer channel as well, and 03893 don't use its file descriptor anymore */ 03894 update_conf(p->bearer); 03895 reset_conf(p->bearer); 03896 p->bearer->owner = NULL; 03897 p->bearer->realcall = NULL; 03898 p->bearer = NULL; 03899 p->subs[SUB_REAL].dfd = -1; 03900 p->pri = NULL; 03901 } 03902 #endif 03903 if (num_restart_pending == 0) 03904 restart_monitor(); 03905 } 03906 03907 p->callwaitingrepeat = 0; 03908 p->cidcwexpire = 0; 03909 p->oprmode = 0; 03910 ast->tech_pvt = NULL; 03911 ast_mutex_unlock(&p->lock); 03912 ast_module_unref(ast_module_info->self); 03913 if (option_verbose > 2) 03914 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03915 03916 ast_mutex_lock(&iflock); 03917 03918 if (p->restartpending) { 03919 num_restart_pending--; 03920 } 03921 03922 tmp = iflist; 03923 prev = NULL; 03924 if (p->destroy) { 03925 while (tmp) { 03926 if (tmp == p) { 03927 destroy_channel(prev, tmp, 0); 03928 break; 03929 } else { 03930 prev = tmp; 03931 tmp = tmp->next; 03932 } 03933 } 03934 } 03935 ast_mutex_unlock(&iflock); 03936 return 0; 03937 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6328 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.
06329 { 06330 struct dahdi_pvt *p = chan->tech_pvt; 06331 int res=-1; 06332 int index; 06333 int func = DAHDI_FLASH; 06334 ast_mutex_lock(&p->lock); 06335 index = dahdi_get_index(chan, p, 0); 06336 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 06337 #ifdef HAVE_OPENR2 06338 if (p->mfcr2 && !p->mfcr2_call_accepted) { 06339 ast_mutex_unlock(&p->lock); 06340 /* if this an R2 call and the call is not yet accepted we don't want the 06341 tone indications to mess up with the MF tones */ 06342 return 0; 06343 } 06344 #endif 06345 if (index == SUB_REAL) { 06346 switch (condition) { 06347 case AST_CONTROL_BUSY: 06348 #ifdef HAVE_PRI 06349 if (p->priindication_oob && p->sig == SIG_PRI) { 06350 chan->hangupcause = AST_CAUSE_USER_BUSY; 06351 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06352 res = 0; 06353 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06354 if (p->pri->pri) { 06355 if (!pri_grab(p, p->pri)) { 06356 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06357 pri_rel(p->pri); 06358 } 06359 else 06360 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06361 } 06362 p->progress = 1; 06363 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06364 } else 06365 #endif 06366 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06367 break; 06368 case AST_CONTROL_RINGING: 06369 #ifdef HAVE_PRI 06370 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06371 if (p->pri->pri) { 06372 if (!pri_grab(p, p->pri)) { 06373 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06374 pri_rel(p->pri); 06375 } 06376 else 06377 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06378 } 06379 p->alerting = 1; 06380 } 06381 #endif 06382 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06383 if (chan->_state != AST_STATE_UP) { 06384 if ((chan->_state != AST_STATE_RING) || 06385 ((p->sig != SIG_FXSKS) && 06386 (p->sig != SIG_FXSLS) && 06387 (p->sig != SIG_FXSGS))) 06388 ast_setstate(chan, AST_STATE_RINGING); 06389 } 06390 break; 06391 case AST_CONTROL_PROCEEDING: 06392 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06393 #ifdef HAVE_PRI 06394 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06395 if (p->pri->pri) { 06396 if (!pri_grab(p, p->pri)) { 06397 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06398 pri_rel(p->pri); 06399 } 06400 else 06401 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06402 } 06403 p->proceeding = 1; 06404 p->dialing = 0; 06405 } 06406 #endif 06407 /* don't continue in ast_indicate */ 06408 res = 0; 06409 break; 06410 case AST_CONTROL_PROGRESS: 06411 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06412 #ifdef HAVE_PRI 06413 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06414 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06415 if (p->pri->pri) { 06416 if (!pri_grab(p, p->pri)) { 06417 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06418 pri_rel(p->pri); 06419 } 06420 else 06421 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06422 } 06423 p->progress = 1; 06424 } 06425 #endif 06426 /* don't continue in ast_indicate */ 06427 res = 0; 06428 break; 06429 case AST_CONTROL_CONGESTION: 06430 chan->hangupcause = AST_CAUSE_CONGESTION; 06431 #ifdef HAVE_PRI 06432 if (p->priindication_oob && p->sig == SIG_PRI) { 06433 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06434 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06435 res = 0; 06436 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06437 if (p->pri) { 06438 if (!pri_grab(p, p->pri)) { 06439 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06440 pri_rel(p->pri); 06441 } else 06442 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06443 } 06444 p->progress = 1; 06445 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06446 } else 06447 #endif 06448 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06449 break; 06450 case AST_CONTROL_HOLD: 06451 #ifdef HAVE_PRI 06452 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06453 if (!pri_grab(p, p->pri)) { 06454 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06455 pri_rel(p->pri); 06456 } else 06457 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06458 } else 06459 #endif 06460 ast_moh_start(chan, data, p->mohinterpret); 06461 break; 06462 case AST_CONTROL_UNHOLD: 06463 #ifdef HAVE_PRI 06464 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06465 if (!pri_grab(p, p->pri)) { 06466 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06467 pri_rel(p->pri); 06468 } else 06469 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06470 } else 06471 #endif 06472 ast_moh_stop(chan); 06473 break; 06474 case AST_CONTROL_RADIO_KEY: 06475 if (p->radio) 06476 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06477 res = 0; 06478 break; 06479 case AST_CONTROL_RADIO_UNKEY: 06480 if (p->radio) 06481 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06482 res = 0; 06483 break; 06484 case AST_CONTROL_FLASH: 06485 /* flash hookswitch */ 06486 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06487 /* Clear out the dial buffer */ 06488 p->dop.dialstr[0] = '\0'; 06489 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06490 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06491 chan->name, strerror(errno)); 06492 } else 06493 res = 0; 06494 } else 06495 res = 0; 06496 break; 06497 case AST_CONTROL_SRCUPDATE: 06498 res = 0; 06499 break; 06500 case -1: 06501 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06502 break; 06503 } 06504 } else 06505 res = 0; 06506 ast_mutex_unlock(&p->lock); 06507 return res; 06508 }
Definition at line 4304 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04304 { 04305 int x; 04306 if (!slave || !master) { 04307 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04308 return; 04309 } 04310 for (x = 0; x < MAX_SLAVES; x++) { 04311 if (!master->slaves[x]) { 04312 master->slaves[x] = slave; 04313 break; 04314 } 04315 } 04316 if (x >= MAX_SLAVES) { 04317 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04318 master->slaves[MAX_SLAVES - 1] = slave; 04319 } 04320 if (slave->master) 04321 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04322 slave->master = master; 04323 04324 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04325 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | index, | |||
int | law, | |||
int | transfercapability | |||
) | [static] |
Definition at line 6510 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().
06511 { 06512 struct ast_channel *tmp; 06513 int deflaw; 06514 int res; 06515 int x,y; 06516 int features; 06517 char *b2 = NULL; 06518 struct dahdi_params ps; 06519 char chanprefix[*dahdi_chan_name_len + 4]; 06520 06521 if (i->subs[index].owner) { 06522 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 06523 return NULL; 06524 } 06525 y = 1; 06526 do { 06527 if (b2) 06528 free(b2); 06529 #ifdef HAVE_PRI 06530 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06531 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06532 else 06533 #endif 06534 if (i->channel == CHAN_PSEUDO) 06535 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 06536 else 06537 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 06538 for (x = 0; x < 3; x++) { 06539 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 06540 break; 06541 } 06542 y++; 06543 } while (x < 3); 06544 strcpy(chanprefix, dahdi_chan_name); 06545 strcat(chanprefix, "/%s"); 06546 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 06547 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 06548 free(b2); 06549 if (!tmp) 06550 return NULL; 06551 tmp->tech = chan_tech; 06552 memset(&ps, 0, sizeof(ps)); 06553 ps.channo = i->channel; 06554 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06555 if (res) { 06556 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06557 ps.curlaw = DAHDI_LAW_MULAW; 06558 } 06559 if (ps.curlaw == DAHDI_LAW_ALAW) 06560 deflaw = AST_FORMAT_ALAW; 06561 else 06562 deflaw = AST_FORMAT_ULAW; 06563 if (law) { 06564 if (law == DAHDI_LAW_ALAW) 06565 deflaw = AST_FORMAT_ALAW; 06566 else 06567 deflaw = AST_FORMAT_ULAW; 06568 } 06569 tmp->fds[0] = i->subs[index].dfd; 06570 tmp->nativeformats = deflaw; 06571 /* Start out assuming ulaw since it's smaller :) */ 06572 tmp->rawreadformat = deflaw; 06573 tmp->readformat = deflaw; 06574 tmp->rawwriteformat = deflaw; 06575 tmp->writeformat = deflaw; 06576 i->subs[index].linear = 0; 06577 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 06578 features = 0; 06579 if (index == SUB_REAL) { 06580 if (i->busydetect && CANBUSYDETECT(i)) 06581 features |= DSP_FEATURE_BUSY_DETECT; 06582 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 06583 features |= DSP_FEATURE_CALL_PROGRESS; 06584 if ((!i->outgoing && (i->callprogress & 4)) || 06585 (i->outgoing && (i->callprogress & 2))) { 06586 features |= DSP_FEATURE_FAX_DETECT; 06587 } 06588 #ifdef DAHDI_TONEDETECT 06589 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06590 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 06591 #endif 06592 i->hardwaredtmf = 0; 06593 features |= DSP_FEATURE_DTMF_DETECT; 06594 #ifdef DAHDI_TONEDETECT 06595 } else if (NEED_MFDETECT(i)) { 06596 i->hardwaredtmf = 1; 06597 features |= DSP_FEATURE_DTMF_DETECT; 06598 } 06599 #endif 06600 } 06601 if (features) { 06602 if (i->dsp) { 06603 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 06604 } else { 06605 if (i->channel != CHAN_PSEUDO) 06606 i->dsp = ast_dsp_new(); 06607 else 06608 i->dsp = NULL; 06609 if (i->dsp) { 06610 i->dsp_features = features; 06611 #ifdef HAVE_PRI 06612 /* We cannot do progress detection until receives PROGRESS message */ 06613 if (i->outgoing && (i->sig == SIG_PRI)) { 06614 /* Remember requested DSP features, don't treat 06615 talking as ANSWER */ 06616 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06617 features = 0; 06618 } 06619 #endif 06620 ast_dsp_set_features(i->dsp, features); 06621 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06622 if (!ast_strlen_zero(progzone)) 06623 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06624 if (i->busydetect && CANBUSYDETECT(i)) { 06625 if(i->silencethreshold > 0) 06626 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06627 ast_dsp_set_busy_count(i->dsp, i->busycount); 06628 if(i->busytonelength > 0) 06629 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06630 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06631 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06632 } 06633 } 06634 } 06635 } 06636 06637 if (state == AST_STATE_RING) 06638 tmp->rings = 1; 06639 tmp->tech_pvt = i; 06640 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06641 /* Only FXO signalled stuff can be picked up */ 06642 tmp->callgroup = i->callgroup; 06643 tmp->pickupgroup = i->pickupgroup; 06644 } 06645 if (!ast_strlen_zero(i->language)) 06646 ast_string_field_set(tmp, language, i->language); 06647 if (!i->owner) 06648 i->owner = tmp; 06649 if (!ast_strlen_zero(i->accountcode)) 06650 ast_string_field_set(tmp, accountcode, i->accountcode); 06651 if (i->amaflags) 06652 tmp->amaflags = i->amaflags; 06653 i->subs[index].owner = tmp; 06654 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06655 ast_string_field_set(tmp, call_forward, i->call_forward); 06656 /* If we've been told "no ADSI" then enforce it */ 06657 if (!i->adsi) 06658 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06659 if (!ast_strlen_zero(i->exten)) 06660 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06661 if (!ast_strlen_zero(i->rdnis)) 06662 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06663 if (!ast_strlen_zero(i->dnid)) 06664 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06665 06666 /* Don't use ast_set_callerid() here because it will 06667 * generate a needless NewCallerID event */ 06668 #ifdef PRI_ANI 06669 if (!ast_strlen_zero(i->cid_ani)) 06670 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06671 else 06672 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06673 #else 06674 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06675 #endif 06676 tmp->cid.cid_pres = i->callingpres; 06677 tmp->cid.cid_ton = i->cid_ton; 06678 #ifdef HAVE_PRI 06679 tmp->transfercapability = transfercapability; 06680 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06681 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 06682 i->digital = 1; 06683 /* Assume calls are not idle calls unless we're told differently */ 06684 i->isidlecall = 0; 06685 i->alreadyhungup = 0; 06686 #endif 06687 /* clear the fake event in case we posted one before we had ast_channel */ 06688 i->fake_event = 0; 06689 /* Assure there is no confmute on this channel */ 06690 dahdi_confmute(i, 0); 06691 /* Configure the new channel jb */ 06692 ast_jb_configure(tmp, &global_jbconf); 06693 if (startpbx) { 06694 #ifdef HAVE_OPENR2 06695 if (i->mfcr2call) { 06696 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 06697 } 06698 #endif 06699 if (ast_pbx_start(tmp)) { 06700 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06701 ast_hangup(tmp); 06702 i->owner = NULL; 06703 return NULL; 06704 } 06705 } 06706 06707 ast_module_ref(ast_module_info->self); 06708 06709 return tmp; 06710 }
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 9840 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().
09841 { 09842 int x, y; 09843 int dchan = -1, span = -1; 09844 int dchancount = 0; 09845 09846 if (pri) { 09847 for (x = 0; x < NUM_SPANS; x++) { 09848 for (y = 0; y < NUM_DCHANS; y++) { 09849 if (pris[x].dchans[y]) 09850 dchancount++; 09851 09852 if (pris[x].dchans[y] == pri) 09853 dchan = y; 09854 } 09855 if (dchan >= 0) { 09856 span = x; 09857 break; 09858 } 09859 dchancount = 0; 09860 } 09861 if ((dchan >= 0) && (span >= 0)) { 09862 if (dchancount > 1) 09863 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 09864 else 09865 ast_log(LOG_ERROR, "%s", s); 09866 } else 09867 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09868 } else 09869 ast_log(LOG_ERROR, "%s", s); 09870 09871 ast_mutex_lock(&pridebugfdlock); 09872 09873 if (pridebugfd >= 0) { 09874 if (write(pridebugfd, s, strlen(s)) < 0) { 09875 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09876 } 09877 } 09878 09879 ast_mutex_unlock(&pridebugfdlock); 09880 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9798 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().
09799 { 09800 int x, y; 09801 int dchan = -1, span = -1; 09802 int dchancount = 0; 09803 09804 if (pri) { 09805 for (x = 0; x < NUM_SPANS; x++) { 09806 for (y = 0; y < NUM_DCHANS; y++) { 09807 if (pris[x].dchans[y]) 09808 dchancount++; 09809 09810 if (pris[x].dchans[y] == pri) 09811 dchan = y; 09812 } 09813 if (dchan >= 0) { 09814 span = x; 09815 break; 09816 } 09817 dchancount = 0; 09818 } 09819 if ((dchan >= 0) && (span >= 0)) { 09820 if (dchancount > 1) 09821 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 09822 else 09823 ast_verbose("%s", s); 09824 } else 09825 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09826 } else 09827 ast_verbose("%s", s); 09828 09829 ast_mutex_lock(&pridebugfdlock); 09830 09831 if (pridebugfd >= 0) { 09832 if (write(pridebugfd, s, strlen(s)) < 0) { 09833 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09834 } 09835 } 09836 09837 ast_mutex_unlock(&pridebugfdlock); 09838 }
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 5902 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.
05903 { 05904 struct dahdi_pvt *p = ast->tech_pvt; 05905 int res; 05906 int index; 05907 void *readbuf; 05908 struct ast_frame *f; 05909 05910 while (ast_mutex_trylock(&p->lock)) { 05911 DEADLOCK_AVOIDANCE(&ast->lock); 05912 } 05913 05914 index = dahdi_get_index(ast, p, 0); 05915 05916 /* Hang up if we don't really exist */ 05917 if (index < 0) { 05918 ast_log(LOG_WARNING, "We dont exist?\n"); 05919 ast_mutex_unlock(&p->lock); 05920 return NULL; 05921 } 05922 05923 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05924 ast_mutex_unlock(&p->lock); 05925 return NULL; 05926 } 05927 05928 p->subs[index].f.frametype = AST_FRAME_NULL; 05929 p->subs[index].f.datalen = 0; 05930 p->subs[index].f.samples = 0; 05931 p->subs[index].f.mallocd = 0; 05932 p->subs[index].f.offset = 0; 05933 p->subs[index].f.subclass = 0; 05934 p->subs[index].f.delivery = ast_tv(0,0); 05935 p->subs[index].f.src = "dahdi_read"; 05936 p->subs[index].f.data = NULL; 05937 05938 /* make sure it sends initial key state as first frame */ 05939 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05940 { 05941 struct dahdi_params ps; 05942 05943 memset(&ps, 0, sizeof(ps)); 05944 ps.channo = p->channel; 05945 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05946 ast_mutex_unlock(&p->lock); 05947 return NULL; 05948 } 05949 p->firstradio = 1; 05950 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05951 if (ps.rxisoffhook) 05952 { 05953 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05954 } 05955 else 05956 { 05957 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05958 } 05959 ast_mutex_unlock(&p->lock); 05960 return &p->subs[index].f; 05961 } 05962 if (p->ringt == 1) { 05963 ast_mutex_unlock(&p->lock); 05964 return NULL; 05965 } 05966 else if (p->ringt > 0) 05967 p->ringt--; 05968 05969 #ifdef HAVE_OPENR2 05970 if (p->mfcr2) { 05971 openr2_chan_process_event(p->r2chan); 05972 } 05973 #endif 05974 05975 if (p->subs[index].needringing) { 05976 /* Send ringing frame if requested */ 05977 p->subs[index].needringing = 0; 05978 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05979 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05980 ast_setstate(ast, AST_STATE_RINGING); 05981 ast_mutex_unlock(&p->lock); 05982 return &p->subs[index].f; 05983 } 05984 05985 if (p->subs[index].needbusy) { 05986 /* Send busy frame if requested */ 05987 p->subs[index].needbusy = 0; 05988 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05989 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05990 ast_mutex_unlock(&p->lock); 05991 return &p->subs[index].f; 05992 } 05993 05994 if (p->subs[index].needcongestion) { 05995 /* Send congestion frame if requested */ 05996 p->subs[index].needcongestion = 0; 05997 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05998 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 05999 ast_mutex_unlock(&p->lock); 06000 return &p->subs[index].f; 06001 } 06002 06003 if (p->subs[index].needcallerid) { 06004 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06005 S_OR(p->lastcid_name, NULL), 06006 S_OR(p->lastcid_num, NULL) 06007 ); 06008 p->subs[index].needcallerid = 0; 06009 } 06010 06011 if (p->subs[index].needanswer) { 06012 /* Send answer frame if requested */ 06013 p->subs[index].needanswer = 0; 06014 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06015 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 06016 ast_mutex_unlock(&p->lock); 06017 return &p->subs[index].f; 06018 } 06019 06020 #ifdef HAVE_OPENR2 06021 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06022 /* openr2 took care of reading and handling any event 06023 (needanswer, needbusy etc), if we continue we will read() 06024 twice, lets just return a null frame. This should only 06025 happen when openr2 is dialing out */ 06026 p->subs[index].f.frametype = AST_FRAME_NULL; 06027 p->subs[index].f.subclass = 0; 06028 p->subs[index].f.samples = 0; 06029 p->subs[index].f.mallocd = 0; 06030 p->subs[index].f.offset = 0; 06031 p->subs[index].f.data = NULL; 06032 p->subs[index].f.datalen= 0; 06033 ast_mutex_unlock(&p->lock); 06034 return &p->subs[index].f; 06035 } 06036 #endif 06037 06038 if (p->subs[index].needflash) { 06039 /* Send answer frame if requested */ 06040 p->subs[index].needflash = 0; 06041 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06042 p->subs[index].f.subclass = AST_CONTROL_FLASH; 06043 ast_mutex_unlock(&p->lock); 06044 return &p->subs[index].f; 06045 } 06046 06047 if (p->subs[index].needhold) { 06048 /* Send answer frame if requested */ 06049 p->subs[index].needhold = 0; 06050 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06051 p->subs[index].f.subclass = AST_CONTROL_HOLD; 06052 ast_mutex_unlock(&p->lock); 06053 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 06054 return &p->subs[index].f; 06055 } 06056 06057 if (p->subs[index].needunhold) { 06058 /* Send answer frame if requested */ 06059 p->subs[index].needunhold = 0; 06060 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06061 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 06062 ast_mutex_unlock(&p->lock); 06063 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 06064 return &p->subs[index].f; 06065 } 06066 06067 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06068 if (!p->subs[index].linear) { 06069 p->subs[index].linear = 1; 06070 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06071 if (res) 06072 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 06073 } 06074 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06075 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06076 if (p->subs[index].linear) { 06077 p->subs[index].linear = 0; 06078 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06079 if (res) 06080 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 06081 } 06082 } else { 06083 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06084 ast_mutex_unlock(&p->lock); 06085 return NULL; 06086 } 06087 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 06088 CHECK_BLOCKING(ast); 06089 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06090 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06091 /* Check for hangup */ 06092 if (res < 0) { 06093 f = NULL; 06094 if (res == -1) { 06095 if (errno == EAGAIN) { 06096 /* Return "NULL" frame if there is nobody there */ 06097 ast_mutex_unlock(&p->lock); 06098 return &p->subs[index].f; 06099 } else if (errno == ELAST) { 06100 f = __dahdi_exception(ast); 06101 } else 06102 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06103 } 06104 ast_mutex_unlock(&p->lock); 06105 return f; 06106 } 06107 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 06108 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06109 f = __dahdi_exception(ast); 06110 ast_mutex_unlock(&p->lock); 06111 return f; 06112 } 06113 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06114 int c; 06115 06116 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06117 if (c < 0) { 06118 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 06119 ast_mutex_unlock(&p->lock); 06120 return NULL; 06121 } 06122 if (c) { /* if a char to return */ 06123 p->subs[index].f.subclass = 0; 06124 p->subs[index].f.frametype = AST_FRAME_TEXT; 06125 p->subs[index].f.mallocd = 0; 06126 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06127 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 06128 p->subs[index].f.datalen = 1; 06129 *((char *) p->subs[index].f.data) = c; 06130 ast_mutex_unlock(&p->lock); 06131 return &p->subs[index].f; 06132 } 06133 } 06134 /* Ensure the CW timer decrements only on a single subchannel */ 06135 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 06136 p->callwaitingrepeat--; 06137 } 06138 if (p->cidcwexpire) 06139 p->cidcwexpire--; 06140 /* Repeat callwaiting */ 06141 if (p->callwaitingrepeat == 1) { 06142 p->callwaitrings++; 06143 dahdi_callwait(ast); 06144 } 06145 /* Expire CID/CW */ 06146 if (p->cidcwexpire == 1) { 06147 if (option_verbose > 2) 06148 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 06149 restore_conference(p); 06150 } 06151 if (p->subs[index].linear) { 06152 p->subs[index].f.datalen = READ_SIZE * 2; 06153 } else 06154 p->subs[index].f.datalen = READ_SIZE; 06155 06156 /* Handle CallerID Transmission */ 06157 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06158 send_callerid(p); 06159 } 06160 06161 p->subs[index].f.frametype = AST_FRAME_VOICE; 06162 p->subs[index].f.subclass = ast->rawreadformat; 06163 p->subs[index].f.samples = READ_SIZE; 06164 p->subs[index].f.mallocd = 0; 06165 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06166 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 06167 #if 0 06168 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 06169 #endif 06170 if (p->dialing || /* Transmitting something */ 06171 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06172 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06173 ) { 06174 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06175 don't send anything */ 06176 p->subs[index].f.frametype = AST_FRAME_NULL; 06177 p->subs[index].f.subclass = 0; 06178 p->subs[index].f.samples = 0; 06179 p->subs[index].f.mallocd = 0; 06180 p->subs[index].f.offset = 0; 06181 p->subs[index].f.data = NULL; 06182 p->subs[index].f.datalen= 0; 06183 } 06184 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 06185 /* Perform busy detection. etc on the dahdi line */ 06186 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 06187 if (f) { 06188 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 06189 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 06190 /* Treat this as a "hangup" instead of a "busy" on the assumption that 06191 a busy */ 06192 f = NULL; 06193 } 06194 } else if (f->frametype == AST_FRAME_DTMF) { 06195 #ifdef HAVE_PRI 06196 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial && 06197 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 06198 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 06199 /* Don't accept in-band DTMF when in overlap dial mode */ 06200 f->frametype = AST_FRAME_NULL; 06201 f->subclass = 0; 06202 } 06203 #endif 06204 /* DSP clears us of being pulse */ 06205 p->pulsedial = 0; 06206 } 06207 } 06208 } else 06209 f = &p->subs[index].f; 06210 06211 if (f && (f->frametype == AST_FRAME_DTMF)) 06212 dahdi_handle_dtmfup(ast, index, &f); 06213 06214 /* If we have a fake_event, trigger exception to handle it */ 06215 if (p->fake_event) 06216 ast_set_flag(ast, AST_FLAG_EXCEPTION); 06217 06218 ast_mutex_unlock(&p->lock); 06219 return f; 06220 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9269 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().
09270 { 09271 ast_group_t groupmatch = 0; 09272 int channelmatch = -1; 09273 int roundrobin = 0; 09274 int callwait = 0; 09275 int busy = 0; 09276 struct dahdi_pvt *p; 09277 struct ast_channel *tmp = NULL; 09278 char *dest=NULL; 09279 int x; 09280 char *s; 09281 char opt=0; 09282 int res=0, y=0; 09283 int backwards = 0; 09284 #ifdef HAVE_PRI 09285 int crv; 09286 int bearer = -1; 09287 int trunkgroup; 09288 struct dahdi_pri *pri=NULL; 09289 #endif 09290 struct dahdi_pvt *exit, *start, *end; 09291 ast_mutex_t *lock; 09292 int channelmatched = 0; 09293 int groupmatched = 0; 09294 09295 /* 09296 * data is ---v 09297 * Dial(DAHDI/pseudo[/extension]) 09298 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09299 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09300 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09301 * 09302 * g - channel group allocation search forward 09303 * G - channel group allocation search backward 09304 * r - channel group allocation round robin search forward 09305 * R - channel group allocation round robin search backward 09306 * 09307 * c - Wait for DTMF digit to confirm answer 09308 * r<cadance#> - Set distintive ring cadance number 09309 * d - Force bearer capability for ISDN call to digital. 09310 */ 09311 09312 /* Assume we're locking the iflock */ 09313 lock = &iflock; 09314 start = iflist; 09315 end = ifend; 09316 if (data) { 09317 dest = ast_strdupa((char *)data); 09318 } else { 09319 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09320 return NULL; 09321 } 09322 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09323 /* Retrieve the group number */ 09324 char *stringp; 09325 09326 stringp = dest + 1; 09327 s = strsep(&stringp, "/"); 09328 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09329 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09330 return NULL; 09331 } 09332 groupmatch = ((ast_group_t) 1 << x); 09333 if (toupper(dest[0]) == 'G') { 09334 if (dest[0] == 'G') { 09335 backwards = 1; 09336 p = ifend; 09337 } else 09338 p = iflist; 09339 } else { 09340 if (dest[0] == 'R') { 09341 backwards = 1; 09342 p = round_robin[x]?round_robin[x]->prev:ifend; 09343 if (!p) 09344 p = ifend; 09345 } else { 09346 p = round_robin[x]?round_robin[x]->next:iflist; 09347 if (!p) 09348 p = iflist; 09349 } 09350 roundrobin = 1; 09351 } 09352 } else { 09353 char *stringp; 09354 09355 stringp = dest; 09356 s = strsep(&stringp, "/"); 09357 p = iflist; 09358 if (!strcasecmp(s, "pseudo")) { 09359 /* Special case for pseudo */ 09360 x = CHAN_PSEUDO; 09361 channelmatch = x; 09362 } 09363 #ifdef HAVE_PRI 09364 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09365 if ((trunkgroup < 1) || (crv < 1)) { 09366 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09367 return NULL; 09368 } 09369 res--; 09370 for (x = 0; x < NUM_SPANS; x++) { 09371 if (pris[x].trunkgroup == trunkgroup) { 09372 pri = pris + x; 09373 lock = &pri->lock; 09374 start = pri->crvs; 09375 end = pri->crvend; 09376 break; 09377 } 09378 } 09379 if (!pri) { 09380 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09381 return NULL; 09382 } 09383 channelmatch = crv; 09384 p = pris[x].crvs; 09385 } 09386 #endif 09387 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09388 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09389 return NULL; 09390 } else { 09391 channelmatch = x; 09392 } 09393 } 09394 /* Search for an unowned channel */ 09395 ast_mutex_lock(lock); 09396 exit = p; 09397 while (p && !tmp) { 09398 if (roundrobin) 09399 round_robin[x] = p; 09400 #if 0 09401 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09402 #endif 09403 09404 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09405 if (option_debug) 09406 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 09407 if (p->inalarm) 09408 goto next; 09409 09410 callwait = (p->owner != NULL); 09411 #ifdef HAVE_PRI 09412 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09413 if (p->sig != SIG_FXSKS) { 09414 /* Gotta find an actual channel to use for this 09415 CRV if this isn't a callwait */ 09416 bearer = pri_find_empty_chan(pri, 0); 09417 if (bearer < 0) { 09418 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09419 p = NULL; 09420 break; 09421 } 09422 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09423 } else { 09424 if (alloc_sub(p, 0)) { 09425 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09426 p = NULL; 09427 break; 09428 } else 09429 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 09430 p->pri = pri; 09431 } 09432 } 09433 #endif 09434 #ifdef HAVE_OPENR2 09435 if (p->mfcr2) { 09436 ast_mutex_lock(&p->lock); 09437 if (p->mfcr2call) { 09438 ast_mutex_unlock(&p->lock); 09439 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 09440 goto next; 09441 } 09442 if (p->mfcr2block) { 09443 ast_mutex_unlock(&p->lock); 09444 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block); 09445 goto next; 09446 } 09447 p->mfcr2call = 1; 09448 ast_mutex_unlock(&p->lock); 09449 } 09450 #endif 09451 if (p->channel == CHAN_PSEUDO) { 09452 p = chandup(p); 09453 if (!p) { 09454 break; 09455 } 09456 } 09457 if (p->owner) { 09458 if (alloc_sub(p, SUB_CALLWAIT)) { 09459 p = NULL; 09460 break; 09461 } 09462 } 09463 p->outgoing = 1; 09464 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09465 if (!tmp) { 09466 p->outgoing = 0; 09467 } 09468 #ifdef HAVE_PRI 09469 if (p->bearer) { 09470 /* Log owner to bearer channel, too */ 09471 p->bearer->owner = tmp; 09472 } 09473 #endif 09474 /* Make special notes */ 09475 if (res > 1) { 09476 if (opt == 'c') { 09477 /* Confirm answer */ 09478 p->confirmanswer = 1; 09479 } else if (opt == 'r') { 09480 /* Distinctive ring */ 09481 if (res < 3) 09482 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09483 else 09484 p->distinctivering = y; 09485 } else if (opt == 'd') { 09486 /* If this is an ISDN call, make it digital */ 09487 p->digital = 1; 09488 if (tmp) 09489 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09490 } else { 09491 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09492 } 09493 } 09494 /* Note if the call is a call waiting call */ 09495 if (tmp && callwait) 09496 tmp->cdrflags |= AST_CDR_CALLWAIT; 09497 break; 09498 } 09499 next: 09500 if (backwards) { 09501 p = p->prev; 09502 if (!p) 09503 p = end; 09504 } else { 09505 p = p->next; 09506 if (!p) 09507 p = start; 09508 } 09509 /* stop when you roll to the one that we started from */ 09510 if (p == exit) 09511 break; 09512 } 09513 ast_mutex_unlock(lock); 09514 restart_monitor(); 09515 if (callwait) 09516 *cause = AST_CAUSE_BUSY; 09517 else if (!tmp) { 09518 if (channelmatched) { 09519 if (busy) 09520 *cause = AST_CAUSE_BUSY; 09521 } else if (groupmatched) { 09522 *cause = AST_CAUSE_CONGESTION; 09523 } 09524 } 09525 09526 return tmp; 09527 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 11901 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().
11902 { 11903 #ifdef HAVE_OPENR2 11904 int r; 11905 #endif 11906 #if defined(HAVE_PRI) 11907 int i, j; 11908 #endif 11909 int cancel_code; 11910 struct dahdi_pvt *p; 11911 11912 ast_mutex_lock(&restart_lock); 11913 11914 if (option_verbose) 11915 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 11916 dahdi_softhangup_all(); 11917 if (option_verbose > 3) 11918 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 11919 11920 #ifdef HAVE_OPENR2 11921 for (r = 0; r < NUM_SPANS; r++) { 11922 if (r2links[r].master != AST_PTHREADT_NULL) { 11923 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master); 11924 pthread_cancel(r2links[r].master); 11925 pthread_join(r2links[r].master, NULL); 11926 openr2_context_delete(r2links[r].protocol_context); 11927 } 11928 } 11929 init_mfcr2_globals(); 11930 #endif 11931 11932 #if defined(HAVE_PRI) 11933 for (i = 0; i < NUM_SPANS; i++) { 11934 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 11935 cancel_code = pthread_cancel(pris[i].master); 11936 pthread_kill(pris[i].master, SIGURG); 11937 if (option_debug > 3) 11938 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 11939 pthread_join(pris[i].master, NULL); 11940 if (option_debug > 3) 11941 ast_verbose("Joined thread of span %d\n", i); 11942 } 11943 } 11944 #endif 11945 11946 ast_mutex_lock(&monlock); 11947 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 11948 cancel_code = pthread_cancel(monitor_thread); 11949 pthread_kill(monitor_thread, SIGURG); 11950 if (option_debug > 3) 11951 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 11952 pthread_join(monitor_thread, NULL); 11953 if (option_debug > 3) 11954 ast_verbose("Joined monitor thread\n"); 11955 } 11956 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 11957 11958 ast_mutex_lock(&ss_thread_lock); 11959 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 11960 int x = DAHDI_FLASH; 11961 if (option_debug > 2) 11962 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 11963 11964 for (p = iflist; p; p = p->next) { 11965 if (p->owner) 11966 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 */ 11967 } 11968 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 11969 } 11970 11971 /* ensure any created channels before monitor threads were stopped are hungup */ 11972 dahdi_softhangup_all(); 11973 if (option_verbose > 3) 11974 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 11975 destroy_all_channels(); 11976 if (option_debug) 11977 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 11978 11979 ast_mutex_unlock(&monlock); 11980 11981 #ifdef HAVE_PRI 11982 for (i = 0; i < NUM_SPANS; i++) { 11983 for (j = 0; j < NUM_DCHANS; j++) 11984 dahdi_close_pri_fd(&(pris[i]), j); 11985 } 11986 11987 memset(pris, 0, sizeof(pris)); 11988 for (i = 0; i < NUM_SPANS; i++) { 11989 ast_mutex_init(&pris[i].lock); 11990 pris[i].offset = -1; 11991 pris[i].master = AST_PTHREADT_NULL; 11992 for (j = 0; j < NUM_DCHANS; j++) 11993 pris[i].fds[j] = -1; 11994 } 11995 pri_set_error(dahdi_pri_error); 11996 pri_set_message(dahdi_pri_message); 11997 #endif 11998 11999 if (setup_dahdi(2) != 0) { 12000 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12001 ast_mutex_unlock(&ss_thread_lock); 12002 return 1; 12003 } 12004 ast_mutex_unlock(&ss_thread_lock); 12005 ast_mutex_unlock(&restart_lock); 12006 return 0; 12007 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12009 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12010 { 12011 if (argc != 2) { 12012 return RESULT_SHOWUSAGE; 12013 } 12014 12015 if (dahdi_restart() != 0) 12016 return RESULT_FAILURE; 12017 return RESULT_SUCCESS; 12018 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4679 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04680 { 04681 int x; 04682 int res; 04683 /* Make sure our transmit state is on hook */ 04684 x = 0; 04685 x = DAHDI_ONHOOK; 04686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04687 do { 04688 x = DAHDI_RING; 04689 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04690 if (res) { 04691 switch (errno) { 04692 case EBUSY: 04693 case EINTR: 04694 /* Wait just in case */ 04695 usleep(10000); 04696 continue; 04697 case EINPROGRESS: 04698 res = 0; 04699 break; 04700 default: 04701 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04702 res = 0; 04703 } 04704 } 04705 } while (res); 04706 return res; 04707 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3333 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
03334 { 03335 return send_keypad_facility_exec(chan, data); 03336 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 13937 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.
13938 { 13939 #define END_SILENCE_LEN 400 13940 #define HEADER_MS 50 13941 #define TRAILER_MS 5 13942 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 13943 #define ASCII_BYTES_PER_CHAR 80 13944 13945 unsigned char *buf,*mybuf; 13946 struct dahdi_pvt *p = c->tech_pvt; 13947 struct pollfd fds[1]; 13948 int size,res,fd,len,x; 13949 int bytes=0; 13950 /* Initial carrier (imaginary) */ 13951 float cr = 1.0; 13952 float ci = 0.0; 13953 float scont = 0.0; 13954 int index; 13955 13956 index = dahdi_get_index(c, p, 0); 13957 if (index < 0) { 13958 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 13959 return -1; 13960 } 13961 if (!text[0]) return(0); /* if nothing to send, dont */ 13962 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 13963 if (p->mate) 13964 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 13965 else 13966 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 13967 if (!buf) 13968 return -1; 13969 mybuf = buf; 13970 if (p->mate) { 13971 int codec = AST_LAW(p); 13972 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 13973 PUT_CLID_MARKMS; 13974 } 13975 /* Put actual message */ 13976 for (x = 0; text[x]; x++) { 13977 PUT_CLID(text[x]); 13978 } 13979 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 13980 PUT_CLID_MARKMS; 13981 } 13982 len = bytes; 13983 buf = mybuf; 13984 } else { 13985 len = tdd_generate(p->tdd, buf, text); 13986 if (len < 1) { 13987 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 13988 free(mybuf); 13989 return -1; 13990 } 13991 } 13992 memset(buf + len, 0x7f, END_SILENCE_LEN); 13993 len += END_SILENCE_LEN; 13994 fd = p->subs[index].dfd; 13995 while (len) { 13996 if (ast_check_hangup(c)) { 13997 free(mybuf); 13998 return -1; 13999 } 14000 size = len; 14001 if (size > READ_SIZE) 14002 size = READ_SIZE; 14003 fds[0].fd = fd; 14004 fds[0].events = POLLOUT | POLLPRI; 14005 fds[0].revents = 0; 14006 res = poll(fds, 1, -1); 14007 if (!res) { 14008 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 14009 continue; 14010 } 14011 /* if got exception */ 14012 if (fds[0].revents & POLLPRI) { 14013 ast_free(mybuf); 14014 return -1; 14015 } 14016 if (!(fds[0].revents & POLLOUT)) { 14017 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 14018 continue; 14019 } 14020 res = write(fd, buf, size); 14021 if (res != size) { 14022 if (res == -1) { 14023 free(mybuf); 14024 return -1; 14025 } 14026 if (option_debug) 14027 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 14028 break; 14029 } 14030 len -= size; 14031 buf += size; 14032 } 14033 free(mybuf); 14034 return(0); 14035 }
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 9972 of file chan_dahdi.c.
09973 { 09974 int res; 09975 res = ioctl(dfd, DAHDI_SETLAW, &law); 09976 if (res) 09977 return res; 09978 return 0; 09979 }
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 4043 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.
04044 { 04045 char *cp; 04046 signed char *scp; 04047 int x; 04048 int index; 04049 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04050 struct oprmode *oprmode; 04051 04052 04053 /* all supported options require data */ 04054 if (!data || (datalen < 1)) { 04055 errno = EINVAL; 04056 return -1; 04057 } 04058 04059 switch (option) { 04060 case AST_OPTION_TXGAIN: 04061 scp = (signed char *) data; 04062 index = dahdi_get_index(chan, p, 0); 04063 if (index < 0) { 04064 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04065 return -1; 04066 } 04067 if (option_debug) 04068 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04069 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 04070 case AST_OPTION_RXGAIN: 04071 scp = (signed char *) data; 04072 index = dahdi_get_index(chan, p, 0); 04073 if (index < 0) { 04074 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04075 return -1; 04076 } 04077 if (option_debug) 04078 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04079 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 04080 case AST_OPTION_TONE_VERIFY: 04081 if (!p->dsp) 04082 break; 04083 cp = (char *) data; 04084 switch (*cp) { 04085 case 1: 04086 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04087 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04088 break; 04089 case 2: 04090 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04091 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04092 break; 04093 default: 04094 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04095 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04096 break; 04097 } 04098 break; 04099 case AST_OPTION_TDD: 04100 /* turn on or off TDD */ 04101 cp = (char *) data; 04102 p->mate = 0; 04103 if (!*cp) { /* turn it off */ 04104 if (option_debug) 04105 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04106 if (p->tdd) 04107 tdd_free(p->tdd); 04108 p->tdd = 0; 04109 break; 04110 } 04111 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 04112 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04113 dahdi_disable_ec(p); 04114 /* otherwise, turn it on */ 04115 if (!p->didtdd) { /* if havent done it yet */ 04116 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04117 unsigned char *buf; 04118 int size, res, fd, len; 04119 struct pollfd fds[1]; 04120 04121 buf = mybuf; 04122 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04123 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04124 len = 40000; 04125 index = dahdi_get_index(chan, p, 0); 04126 if (index < 0) { 04127 ast_log(LOG_WARNING, "No index in TDD?\n"); 04128 return -1; 04129 } 04130 fd = p->subs[index].dfd; 04131 while (len) { 04132 if (ast_check_hangup(chan)) 04133 return -1; 04134 size = len; 04135 if (size > READ_SIZE) 04136 size = READ_SIZE; 04137 fds[0].fd = fd; 04138 fds[0].events = POLLPRI | POLLOUT; 04139 fds[0].revents = 0; 04140 res = poll(fds, 1, -1); 04141 if (!res) { 04142 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 04143 continue; 04144 } 04145 /* if got exception */ 04146 if (fds[0].revents & POLLPRI) 04147 return -1; 04148 if (!(fds[0].revents & POLLOUT)) { 04149 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 04150 continue; 04151 } 04152 res = write(fd, buf, size); 04153 if (res != size) { 04154 if (res == -1) return -1; 04155 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04156 break; 04157 } 04158 len -= size; 04159 buf += size; 04160 } 04161 p->didtdd = 1; /* set to have done it now */ 04162 } 04163 if (*cp == 2) { /* Mate mode */ 04164 if (p->tdd) 04165 tdd_free(p->tdd); 04166 p->tdd = 0; 04167 p->mate = 1; 04168 break; 04169 } 04170 if (!p->tdd) { /* if we dont have one yet */ 04171 p->tdd = tdd_new(); /* allocate one */ 04172 } 04173 break; 04174 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04175 if (!p->dsp) 04176 break; 04177 cp = (char *) data; 04178 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04179 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04180 p->dtmfrelax = 0; 04181 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 04182 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04183 break; 04184 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04185 cp = (char *) data; 04186 if (!*cp) { 04187 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04188 x = 0; 04189 dahdi_disable_ec(p); 04190 } else { 04191 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04192 x = 1; 04193 } 04194 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04195 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04196 break; 04197 case AST_OPTION_OPRMODE: /* Operator services mode */ 04198 oprmode = (struct oprmode *) data; 04199 pp = oprmode->peer->tech_pvt; 04200 p->oprmode = pp->oprmode = 0; 04201 /* setup peers */ 04202 p->oprpeer = pp; 04203 pp->oprpeer = p; 04204 /* setup modes, if any */ 04205 if (oprmode->mode) 04206 { 04207 pp->oprmode = oprmode->mode; 04208 p->oprmode = -oprmode->mode; 04209 } 04210 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 04211 oprmode->mode, chan->name,oprmode->peer->name);; 04212 break; 04213 case AST_OPTION_ECHOCAN: 04214 cp = (char *) data; 04215 if (*cp) { 04216 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 04217 dahdi_enable_ec(p); 04218 } else { 04219 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 04220 dahdi_disable_ec(p); 04221 } 04222 break; 04223 } 04224 errno = 0; 04225 04226 return 0; 04227 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12081 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.
12082 { 12083 int channel; 12084 struct dahdi_pvt *tmp = NULL; 12085 struct dahdi_confinfo ci; 12086 struct dahdi_params ps; 12087 int x; 12088 ast_mutex_t *lock; 12089 struct dahdi_pvt *start; 12090 #ifdef HAVE_PRI 12091 char *c; 12092 int trunkgroup; 12093 struct dahdi_pri *pri=NULL; 12094 #endif 12095 12096 lock = &iflock; 12097 start = iflist; 12098 12099 if (argc != 4) 12100 return RESULT_SHOWUSAGE; 12101 #ifdef HAVE_PRI 12102 if ((c = strchr(argv[3], ':'))) { 12103 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12104 return RESULT_SHOWUSAGE; 12105 if ((trunkgroup < 1) || (channel < 1)) 12106 return RESULT_SHOWUSAGE; 12107 for (x = 0; x < NUM_SPANS; x++) { 12108 if (pris[x].trunkgroup == trunkgroup) { 12109 pri = pris + x; 12110 break; 12111 } 12112 } 12113 if (pri) { 12114 start = pri->crvs; 12115 lock = &pri->lock; 12116 } else { 12117 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12118 return RESULT_FAILURE; 12119 } 12120 } else 12121 #endif 12122 channel = atoi(argv[3]); 12123 12124 ast_mutex_lock(lock); 12125 tmp = start; 12126 while (tmp) { 12127 if (tmp->channel == channel) { 12128 #ifdef HAVE_PRI 12129 if (pri) 12130 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12131 else 12132 #endif 12133 ast_cli(fd, "Channel: %d\n", tmp->channel); 12134 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12135 ast_cli(fd, "Span: %d\n", tmp->span); 12136 ast_cli(fd, "Extension: %s\n", tmp->exten); 12137 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12138 ast_cli(fd, "Context: %s\n", tmp->context); 12139 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 12140 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 12141 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 12142 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 12143 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 12144 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12145 ast_cli(fd, "Radio: %d\n", tmp->radio); 12146 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12147 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)" : ""); 12148 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)" : ""); 12149 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)" : ""); 12150 ast_cli(fd, "Confno: %d\n", tmp->confno); 12151 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 12152 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 12153 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12154 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12155 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12156 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12157 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12158 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12159 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 12160 if (tmp->master) 12161 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 12162 for (x = 0; x < MAX_SLAVES; x++) { 12163 if (tmp->slaves[x]) 12164 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12165 } 12166 #ifdef HAVE_OPENR2 12167 if (tmp->mfcr2) { 12168 char calldir[OR2_MAX_PATH]; 12169 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 12170 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 12171 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No"); 12172 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No"); 12173 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 12174 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 12175 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 12176 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 12177 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 12178 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 12179 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 12180 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 12181 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 12182 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No"); 12183 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No"); 12184 #endif 12185 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 12186 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 12187 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 12188 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 12189 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 12190 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 12191 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 12192 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 12193 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 12194 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 12195 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 12196 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 12197 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 12198 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 12199 } 12200 #endif 12201 #ifdef HAVE_PRI 12202 if (tmp->pri) { 12203 ast_cli(fd, "PRI Flags: "); 12204 if (tmp->resetting) 12205 ast_cli(fd, "Resetting "); 12206 if (tmp->call) 12207 ast_cli(fd, "Call "); 12208 if (tmp->bearer) 12209 ast_cli(fd, "Bearer "); 12210 ast_cli(fd, "\n"); 12211 if (tmp->logicalspan) 12212 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12213 else 12214 ast_cli(fd, "PRI Logical Span: Implicit\n"); 12215 } 12216 12217 #endif 12218 memset(&ci, 0, sizeof(ci)); 12219 ps.channo = tmp->channel; 12220 if (tmp->subs[SUB_REAL].dfd > -1) { 12221 memset(&ci, 0, sizeof(ci)); 12222 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12223 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12224 } 12225 #ifdef DAHDI_GETCONFMUTE 12226 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12227 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12228 } 12229 #endif 12230 memset(&ps, 0, sizeof(ps)); 12231 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12232 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12233 } else { 12234 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12235 } 12236 } 12237 if (ISTRUNK(tmp)) { 12238 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12239 if (!ast_strlen_zero(progzone)) 12240 ast_cli(fd, "Progress Zone: %s\n", progzone); 12241 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12242 if(tmp->busydetect) { 12243 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 12244 if(tmp->busytonelength > 0) { 12245 ast_cli(fd, "Busy Pattern:\n"); 12246 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12247 if (tmp->busyquietlength > 0) 12248 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12249 else 12250 ast_cli(fd, " -- Detect Tone Only\n"); 12251 if(tmp->busyfuzziness > 0) 12252 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12253 } 12254 } 12255 } 12256 ast_mutex_unlock(lock); 12257 return RESULT_SUCCESS; 12258 } 12259 tmp = tmp->next; 12260 } 12261 12262 ast_cli(fd, "Unable to find given channel %d\n", channel); 12263 ast_mutex_unlock(lock); 12264 return RESULT_FAILURE; 12265 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12020 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.
12021 { 12022 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12023 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12024 struct dahdi_pvt *tmp = NULL; 12025 char tmps[20] = ""; 12026 ast_mutex_t *lock; 12027 struct dahdi_pvt *start; 12028 #ifdef HAVE_PRI 12029 int trunkgroup; 12030 struct dahdi_pri *pri = NULL; 12031 int x; 12032 #endif 12033 12034 lock = &iflock; 12035 start = iflist; 12036 12037 #ifdef HAVE_PRI 12038 if (argc == 4) { 12039 if ((trunkgroup = atoi(argv[3])) < 1) 12040 return RESULT_SHOWUSAGE; 12041 for (x = 0; x < NUM_SPANS; x++) { 12042 if (pris[x].trunkgroup == trunkgroup) { 12043 pri = pris + x; 12044 break; 12045 } 12046 } 12047 if (pri) { 12048 start = pri->crvs; 12049 lock = &pri->lock; 12050 } else { 12051 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12052 return RESULT_FAILURE; 12053 } 12054 } else 12055 #endif 12056 if (argc != 3) 12057 return RESULT_SHOWUSAGE; 12058 12059 ast_mutex_lock(lock); 12060 #ifdef HAVE_PRI 12061 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12062 #else 12063 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12064 #endif 12065 12066 tmp = start; 12067 while (tmp) { 12068 if (tmp->channel > 0) { 12069 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12070 } else 12071 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12072 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 12073 tmp = tmp->next; 12074 } 12075 ast_mutex_unlock(lock); 12076 return RESULT_SUCCESS; 12077 #undef FORMAT 12078 #undef FORMAT2 12079 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12298 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
12298 { 12299 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 12300 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 12301 12302 int span; 12303 int res; 12304 char alarms[50]; 12305 12306 int ctl; 12307 struct dahdi_spaninfo s; 12308 12309 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 12310 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 12311 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 12312 return RESULT_FAILURE; 12313 } 12314 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 12315 12316 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 12317 s.spanno = span; 12318 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 12319 if (res) { 12320 continue; 12321 } 12322 alarms[0] = '\0'; 12323 if (s.alarms > 0) { 12324 if (s.alarms & DAHDI_ALARM_BLUE) 12325 strcat(alarms, "BLU/"); 12326 if (s.alarms & DAHDI_ALARM_YELLOW) 12327 strcat(alarms, "YEL/"); 12328 if (s.alarms & DAHDI_ALARM_RED) 12329 strcat(alarms, "RED/"); 12330 if (s.alarms & DAHDI_ALARM_LOOPBACK) 12331 strcat(alarms, "LB/"); 12332 if (s.alarms & DAHDI_ALARM_RECOVER) 12333 strcat(alarms, "REC/"); 12334 if (s.alarms & DAHDI_ALARM_NOTOPEN) 12335 strcat(alarms, "NOP/"); 12336 if (!strlen(alarms)) 12337 strcat(alarms, "UUU/"); 12338 if (strlen(alarms)) { 12339 /* Strip trailing / */ 12340 alarms[strlen(alarms) - 1] = '\0'; 12341 } 12342 } else { 12343 if (s.numchans) 12344 strcpy(alarms, "OK"); 12345 else 12346 strcpy(alarms, "UNCONFIGURED"); 12347 } 12348 12349 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 12350 } 12351 close(ctl); 12352 12353 return RESULT_SUCCESS; 12354 #undef FORMAT 12355 #undef FORMAT2 12356 }
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 11872 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().
11873 { 11874 struct dahdi_pvt *p; 11875 retry: 11876 ast_mutex_lock(&iflock); 11877 for (p = iflist; p; p = p->next) { 11878 ast_mutex_lock(&p->lock); 11879 if (p->owner && !p->restartpending) { 11880 if (ast_channel_trylock(p->owner)) { 11881 if (option_debug > 2) 11882 ast_verbose("Avoiding deadlock\n"); 11883 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 11884 ast_mutex_unlock(&p->lock); 11885 ast_mutex_unlock(&iflock); 11886 goto retry; 11887 } 11888 if (option_debug > 2) 11889 ast_verbose("Softhanging up on %s\n", p->owner->name); 11890 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 11891 p->restartpending = 1; 11892 num_restart_pending++; 11893 ast_channel_unlock(p->owner); 11894 } 11895 ast_mutex_unlock(&p->lock); 11896 } 11897 ast_mutex_unlock(&iflock); 11898 }
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 4248 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().
04249 { 04250 /* Unlink a specific slave or all slaves/masters from a given master */ 04251 int x; 04252 int hasslaves; 04253 if (!master) 04254 return; 04255 if (needlock) { 04256 ast_mutex_lock(&master->lock); 04257 if (slave) { 04258 while (ast_mutex_trylock(&slave->lock)) { 04259 DEADLOCK_AVOIDANCE(&master->lock); 04260 } 04261 } 04262 } 04263 hasslaves = 0; 04264 for (x = 0; x < MAX_SLAVES; x++) { 04265 if (master->slaves[x]) { 04266 if (!slave || (master->slaves[x] == slave)) { 04267 /* Take slave out of the conference */ 04268 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04269 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04270 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04271 master->slaves[x]->master = NULL; 04272 master->slaves[x] = NULL; 04273 } else 04274 hasslaves = 1; 04275 } 04276 if (!hasslaves) 04277 master->inconference = 0; 04278 } 04279 if (!slave) { 04280 if (master->master) { 04281 /* Take master out of the conference */ 04282 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04283 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04284 hasslaves = 0; 04285 for (x = 0; x < MAX_SLAVES; x++) { 04286 if (master->master->slaves[x] == master) 04287 master->master->slaves[x] = NULL; 04288 else if (master->master->slaves[x]) 04289 hasslaves = 1; 04290 } 04291 if (!hasslaves) 04292 master->master->inconference = 0; 04293 } 04294 master->master = NULL; 04295 } 04296 update_conf(master); 04297 if (needlock) { 04298 if (slave) 04299 ast_mutex_unlock(&slave->lock); 04300 ast_mutex_unlock(&master->lock); 04301 } 04302 }
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 6732 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06733 { 06734 int j; 06735 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 06736 for (;;) 06737 { 06738 /* set bits of interest */ 06739 j = DAHDI_IOMUX_SIGEVENT; 06740 /* wait for some happening */ 06741 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06742 /* exit loop if we have it */ 06743 if (j & DAHDI_IOMUX_SIGEVENT) break; 06744 } 06745 /* get the event info */ 06746 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06747 return 0; 06748 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6245 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.
06246 { 06247 struct dahdi_pvt *p = ast->tech_pvt; 06248 int res; 06249 int index; 06250 index = dahdi_get_index(ast, p, 0); 06251 if (index < 0) { 06252 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06253 return -1; 06254 } 06255 06256 #if 0 06257 #ifdef HAVE_PRI 06258 ast_mutex_lock(&p->lock); 06259 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06260 if (p->pri->pri) { 06261 if (!pri_grab(p, p->pri)) { 06262 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06263 pri_rel(p->pri); 06264 } else 06265 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06266 } 06267 p->proceeding=1; 06268 } 06269 ast_mutex_unlock(&p->lock); 06270 #endif 06271 #endif 06272 /* Write a frame of (presumably voice) data */ 06273 if (frame->frametype != AST_FRAME_VOICE) { 06274 if (frame->frametype != AST_FRAME_IMAGE) 06275 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06276 return 0; 06277 } 06278 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06279 (frame->subclass != AST_FORMAT_ULAW) && 06280 (frame->subclass != AST_FORMAT_ALAW)) { 06281 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06282 return -1; 06283 } 06284 if (p->dialing) { 06285 if (option_debug) 06286 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06287 return 0; 06288 } 06289 if (!p->owner) { 06290 if (option_debug) 06291 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 06292 return 0; 06293 } 06294 if (p->cidspill) { 06295 if (option_debug) 06296 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 06297 return 0; 06298 } 06299 /* Return if it's not valid data */ 06300 if (!frame->data || !frame->datalen) 06301 return 0; 06302 06303 if (frame->subclass == AST_FORMAT_SLINEAR) { 06304 if (!p->subs[index].linear) { 06305 p->subs[index].linear = 1; 06306 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06307 if (res) 06308 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06309 } 06310 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06311 } else { 06312 /* x-law already */ 06313 if (p->subs[index].linear) { 06314 p->subs[index].linear = 0; 06315 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06316 if (res) 06317 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06318 } 06319 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06320 } 06321 if (res < 0) { 06322 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06323 return -1; 06324 } 06325 return 0; 06326 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3249 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().
03250 { 03251 int x; 03252 struct dahdi_pvt *p, *pl; 03253 03254 while (num_restart_pending) { 03255 usleep(1); 03256 } 03257 03258 ast_mutex_lock(&iflock); 03259 /* Destroy all the interfaces and free their memory */ 03260 p = iflist; 03261 while (p) { 03262 /* Free any callerid */ 03263 if (p->cidspill) 03264 ast_free(p->cidspill); 03265 pl = p; 03266 p = p->next; 03267 x = pl->channel; 03268 /* Free associated memory */ 03269 if (pl) 03270 destroy_dahdi_pvt(&pl); 03271 if (option_verbose > 2) 03272 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03273 } 03274 iflist = NULL; 03275 ifcount = 0; 03276 ast_mutex_unlock(&iflock); 03277 }
Definition at line 3199 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().
03200 { 03201 int owned = 0; 03202 int i = 0; 03203 03204 if (!now) { 03205 if (cur->owner) { 03206 owned = 1; 03207 } 03208 03209 for (i = 0; i < 3; i++) { 03210 if (cur->subs[i].owner) { 03211 owned = 1; 03212 } 03213 } 03214 if (!owned) { 03215 if (prev) { 03216 prev->next = cur->next; 03217 if (prev->next) 03218 prev->next->prev = prev; 03219 else 03220 ifend = prev; 03221 } else { 03222 iflist = cur->next; 03223 if (iflist) 03224 iflist->prev = NULL; 03225 else 03226 ifend = NULL; 03227 } 03228 destroy_dahdi_pvt(&cur); 03229 } 03230 } else { 03231 if (prev) { 03232 prev->next = cur->next; 03233 if (prev->next) 03234 prev->next->prev = prev; 03235 else 03236 ifend = prev; 03237 } else { 03238 iflist = cur->next; 03239 if (iflist) 03240 iflist->prev = NULL; 03241 else 03242 ifend = NULL; 03243 } 03244 destroy_dahdi_pvt(&cur); 03245 } 03246 return 0; 03247 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3181 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().
03182 { 03183 struct dahdi_pvt *p = *pvt; 03184 /* Remove channel from the list */ 03185 if (p->prev) 03186 p->prev->next = p->next; 03187 if (p->next) 03188 p->next->prev = p->prev; 03189 if (p->use_smdi) 03190 ast_smdi_interface_unref(p->smdi_iface); 03191 ast_mutex_destroy(&p->lock); 03192 dahdi_close_sub(p, SUB_REAL); 03193 if (p->owner) 03194 p->owner->tech_pvt = NULL; 03195 free(p); 03196 *pvt = NULL; 03197 }
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 4327 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().
04328 { 04329 #ifdef DAHDI_TONEDETECT 04330 int val; 04331 #endif 04332 04333 p->ignoredtmf = 1; 04334 04335 #ifdef DAHDI_TONEDETECT 04336 val = 0; 04337 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04338 #endif 04339 if (!p->hardwaredtmf && p->dsp) { 04340 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04341 ast_dsp_set_features(p->dsp, p->dsp_features); 04342 } 04343 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 9743 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().
09744 { 09745 struct ast_channel *chan = vchan; 09746 struct dahdi_pvt *pvt = chan->tech_pvt; 09747 struct ast_frame *f; 09748 char ex[80]; 09749 /* Wait up to 30 seconds for an answer */ 09750 int newms, ms = 30000; 09751 if (option_verbose > 2) 09752 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 09753 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 09754 if (ast_call(chan, ex, 0)) { 09755 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 09756 ast_hangup(chan); 09757 return NULL; 09758 } 09759 while ((newms = ast_waitfor(chan, ms)) > 0) { 09760 f = ast_read(chan); 09761 if (!f) { 09762 /* Got hangup */ 09763 break; 09764 } 09765 if (f->frametype == AST_FRAME_CONTROL) { 09766 switch (f->subclass) { 09767 case AST_CONTROL_ANSWER: 09768 /* Launch the PBX */ 09769 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 09770 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 09771 chan->priority = 1; 09772 if (option_verbose > 3) 09773 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 09774 ast_pbx_run(chan); 09775 /* It's already hungup, return immediately */ 09776 return NULL; 09777 case AST_CONTROL_BUSY: 09778 if (option_verbose > 3) 09779 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 09780 break; 09781 case AST_CONTROL_CONGESTION: 09782 if (option_verbose > 3) 09783 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 09784 break; 09785 }; 09786 } 09787 ast_frfree(f); 09788 ms = newms; 09789 } 09790 /* Hangup the channel since nothing happend */ 09791 ast_hangup(chan); 09792 return NULL; 09793 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8143 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().
08144 { 08145 int count, res, res2, spoint, pollres=0; 08146 struct dahdi_pvt *i; 08147 struct dahdi_pvt *last = NULL; 08148 struct dahdi_pvt *doomed; 08149 time_t thispass = 0, lastpass = 0; 08150 int found; 08151 char buf[1024]; 08152 struct pollfd *pfds=NULL; 08153 int lastalloc = -1; 08154 /* This thread monitors all the frame relay interfaces which are not yet in use 08155 (and thus do not have a separate thread) indefinitely */ 08156 /* From here on out, we die whenever asked */ 08157 #if 0 08158 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08159 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08160 return NULL; 08161 } 08162 ast_log(LOG_DEBUG, "Monitor starting...\n"); 08163 #endif 08164 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08165 08166 for (;;) { 08167 /* Lock the interface list */ 08168 ast_mutex_lock(&iflock); 08169 if (!pfds || (lastalloc != ifcount)) { 08170 if (pfds) { 08171 free(pfds); 08172 pfds = NULL; 08173 } 08174 if (ifcount) { 08175 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08176 ast_mutex_unlock(&iflock); 08177 return NULL; 08178 } 08179 } 08180 lastalloc = ifcount; 08181 } 08182 /* Build the stuff we're going to poll on, that is the socket of every 08183 dahdi_pvt that does not have an associated owner channel */ 08184 count = 0; 08185 i = iflist; 08186 while (i) { 08187 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 08188 if (!i->owner && !i->subs[SUB_REAL].owner) { 08189 /* This needs to be watched, as it lacks an owner */ 08190 pfds[count].fd = i->subs[SUB_REAL].dfd; 08191 pfds[count].events = POLLPRI; 08192 pfds[count].revents = 0; 08193 /* Message waiting or r2 channels also get watched for reading */ 08194 if (i->cidspill) 08195 pfds[count].events |= POLLIN; 08196 count++; 08197 } 08198 } 08199 i = i->next; 08200 } 08201 /* Okay, now that we know what to do, release the interface lock */ 08202 ast_mutex_unlock(&iflock); 08203 08204 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08205 pthread_testcancel(); 08206 /* Wait at least a second for something to happen */ 08207 res = poll(pfds, count, 1000); 08208 pthread_testcancel(); 08209 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08210 08211 /* Okay, poll has finished. Let's see what happened. */ 08212 if (res < 0) { 08213 if ((errno != EAGAIN) && (errno != EINTR)) 08214 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08215 continue; 08216 } 08217 /* Alright, lock the interface list again, and let's look and see what has 08218 happened */ 08219 ast_mutex_lock(&iflock); 08220 found = 0; 08221 spoint = 0; 08222 lastpass = thispass; 08223 thispass = time(NULL); 08224 doomed = NULL; 08225 for (i = iflist;; i = i->next) { 08226 if (doomed) { 08227 int res; 08228 res = dahdi_destroy_channel_bynum(doomed->channel); 08229 if (!res) { 08230 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08231 } 08232 doomed = NULL; 08233 } 08234 if (!i) { 08235 break; 08236 } 08237 if (thispass != lastpass) { 08238 if (!found && ((i == last) || ((i == iflist) && !last))) { 08239 last = i; 08240 if (last) { 08241 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 08242 (last->sig & __DAHDI_SIG_FXO)) { 08243 res = ast_app_has_voicemail(last->mailbox, NULL); 08244 if (last->msgstate != res) { 08245 int x; 08246 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08247 x = DAHDI_FLUSH_BOTH; 08248 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08249 if (res2) 08250 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 08251 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08252 /* Turn on on hook transfer for 4 seconds */ 08253 x = 4000; 08254 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08255 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08256 last->cidpos = 0; 08257 last->msgstate = res; 08258 last->onhooktime = thispass; 08259 } 08260 found ++; 08261 } 08262 } 08263 last = last->next; 08264 } 08265 } 08266 } 08267 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08268 if (i->radio && !i->owner) 08269 { 08270 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08271 if (res) 08272 { 08273 if (option_debug) 08274 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08275 /* Don't hold iflock while handling init events */ 08276 ast_mutex_unlock(&iflock); 08277 doomed = handle_init_event(i, res); 08278 ast_mutex_lock(&iflock); 08279 } 08280 continue; 08281 } 08282 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08283 if (pollres & POLLIN) { 08284 if (i->owner || i->subs[SUB_REAL].owner) { 08285 #ifdef HAVE_PRI 08286 if (!i->pri) 08287 #endif 08288 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08289 continue; 08290 } 08291 if (!i->cidspill) { 08292 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08293 continue; 08294 } 08295 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08296 if (res > 0) { 08297 /* We read some number of bytes. Write an equal amount of data */ 08298 if (res > i->cidlen - i->cidpos) 08299 res = i->cidlen - i->cidpos; 08300 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 08301 if (res2 > 0) { 08302 i->cidpos += res2; 08303 if (i->cidpos >= i->cidlen) { 08304 free(i->cidspill); 08305 i->cidspill = 0; 08306 i->cidpos = 0; 08307 i->cidlen = 0; 08308 } 08309 } else { 08310 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 08311 i->msgstate = -1; 08312 } 08313 } else { 08314 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08315 } 08316 } 08317 if (pollres & POLLPRI) { 08318 if (i->owner || i->subs[SUB_REAL].owner) { 08319 #ifdef HAVE_PRI 08320 if (!i->pri) 08321 #endif 08322 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08323 continue; 08324 } 08325 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08326 if (option_debug) 08327 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08328 /* Don't hold iflock while handling init events */ 08329 ast_mutex_unlock(&iflock); 08330 doomed = handle_init_event(i, res); 08331 ast_mutex_lock(&iflock); 08332 } 08333 } 08334 } 08335 ast_mutex_unlock(&iflock); 08336 } 08337 /* Never reached */ 08338 return NULL; 08339 08340 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4345 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().
04346 { 04347 #ifdef DAHDI_TONEDETECT 04348 int val; 04349 #endif 04350 04351 if (p->channel == CHAN_PSEUDO) 04352 return; 04353 04354 p->ignoredtmf = 0; 04355 04356 #ifdef DAHDI_TONEDETECT 04357 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04358 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04359 #endif 04360 if (!p->hardwaredtmf && p->dsp) { 04361 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04362 ast_dsp_set_features(p->dsp, p->dsp_features); 04363 } 04364 }
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 12456 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().
12457 { 12458 struct dahdi_pvt *p = iflist; 12459 while (p) { 12460 if (p->channel == channel) { 12461 break; 12462 } 12463 p = p->next; 12464 } 12465 return p; 12466 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4785 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().
04786 { 04787 int res; 04788 struct dahdi_spaninfo zi; 04789 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04790 /* 04791 * The conditional compilation is needed only in asterisk-1.4 for 04792 * backward compatibility with old zaptel drivers that don't have 04793 * a DAHDI_PARAMS.chan_alarms field. 04794 */ 04795 struct dahdi_params params; 04796 #endif 04797 04798 memset(&zi, 0, sizeof(zi)); 04799 zi.spanno = p->span; 04800 04801 /* First check for span alarms */ 04802 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 04803 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04804 return 0; 04805 } 04806 if (zi.alarms != DAHDI_ALARM_NONE) 04807 return zi.alarms; 04808 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04809 /* No alarms on the span. Check for channel alarms. */ 04810 memset(¶ms, 0, sizeof(params)); 04811 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04812 return params.chan_alarms; 04813 /* ioctl failed */ 04814 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04815 #endif 04816 return DAHDI_ALARM_NONE; 04817 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4901 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().
04902 { 04903 const char *alarm_str = alarm2str(alarms); 04904 04905 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04906 * doesn't know what to do with it. Don't confuse users with log messages. */ 04907 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04908 p->unknown_alarm = 1; 04909 return; 04910 } else { 04911 p->unknown_alarm = 0; 04912 } 04913 04914 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04915 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04916 "Alarm: %s\r\n" 04917 "Channel: %d\r\n", 04918 alarm_str, p->channel); 04919 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12271 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
12272 { 12273 int i, j; 12274 for (i = 0; i < num_cadence; i++) { 12275 char output[1024]; 12276 char tmp[16], tmp2[64]; 12277 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12278 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12279 12280 for (j = 0; j < 16; j++) { 12281 if (cadences[i].ringcadence[j] == 0) 12282 break; 12283 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12284 if (cidrings[i] * 2 - 1 == j) 12285 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12286 else 12287 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12288 if (j != 0) 12289 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12290 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12291 } 12292 ast_cli(fd,"%s\n",output); 12293 } 12294 return 0; 12295 }
Definition at line 7933 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.
07934 { 07935 int res; 07936 pthread_t threadid; 07937 pthread_attr_t attr; 07938 struct ast_channel *chan; 07939 pthread_attr_init(&attr); 07940 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07941 /* Handle an event on a given channel for the monitor thread. */ 07942 switch (event) { 07943 case DAHDI_EVENT_NONE: 07944 case DAHDI_EVENT_BITSCHANGED: 07945 break; 07946 case DAHDI_EVENT_WINKFLASH: 07947 case DAHDI_EVENT_RINGOFFHOOK: 07948 if (i->inalarm) break; 07949 if (i->radio) break; 07950 /* Got a ring/answer. What kind of channel are we? */ 07951 switch (i->sig) { 07952 case SIG_FXOLS: 07953 case SIG_FXOGS: 07954 case SIG_FXOKS: 07955 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07956 if (res && (errno == EBUSY)) 07957 break; 07958 if (i->cidspill) { 07959 /* Cancel VMWI spill */ 07960 free(i->cidspill); 07961 i->cidspill = NULL; 07962 } 07963 if (i->immediate) { 07964 dahdi_enable_ec(i); 07965 /* The channel is immediately up. Start right away */ 07966 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 07967 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 07968 if (!chan) { 07969 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 07970 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07971 if (res < 0) 07972 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07973 } 07974 } else { 07975 /* Check for callerid, digits, etc */ 07976 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 07977 if (chan) { 07978 if (has_voicemail(i)) 07979 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 07980 else 07981 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 07982 if (res < 0) 07983 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 07984 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 07985 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 07986 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07987 if (res < 0) 07988 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 07989 ast_hangup(chan); 07990 } 07991 } else 07992 ast_log(LOG_WARNING, "Unable to create channel\n"); 07993 } 07994 break; 07995 case SIG_FXSLS: 07996 case SIG_FXSGS: 07997 case SIG_FXSKS: 07998 i->ringt = i->ringt_base; 07999 /* Fall through */ 08000 case SIG_EMWINK: 08001 case SIG_FEATD: 08002 case SIG_FEATDMF: 08003 case SIG_FEATDMF_TA: 08004 case SIG_E911: 08005 case SIG_FGC_CAMA: 08006 case SIG_FGC_CAMAMF: 08007 case SIG_FEATB: 08008 case SIG_EM: 08009 case SIG_EM_E1: 08010 case SIG_SFWINK: 08011 case SIG_SF_FEATD: 08012 case SIG_SF_FEATDMF: 08013 case SIG_SF_FEATB: 08014 case SIG_SF: 08015 /* Check for callerid, digits, etc */ 08016 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08017 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08018 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08019 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08020 if (res < 0) 08021 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08022 ast_hangup(chan); 08023 } else if (!chan) { 08024 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08025 } 08026 break; 08027 default: 08028 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08029 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08030 if (res < 0) 08031 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08032 pthread_attr_destroy(&attr); 08033 return NULL; 08034 } 08035 break; 08036 case DAHDI_EVENT_NOALARM: 08037 i->inalarm = 0; 08038 if (!i->unknown_alarm) { 08039 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08040 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08041 "Channel: %d\r\n", i->channel); 08042 } else { 08043 i->unknown_alarm = 0; 08044 } 08045 break; 08046 case DAHDI_EVENT_ALARM: 08047 i->inalarm = 1; 08048 res = get_alarms(i); 08049 handle_alarms(i, res); 08050 /* fall thru intentionally */ 08051 case DAHDI_EVENT_ONHOOK: 08052 if (i->radio) 08053 break; 08054 /* Back on hook. Hang up. */ 08055 switch (i->sig) { 08056 case SIG_FXOLS: 08057 case SIG_FXOGS: 08058 case SIG_FEATD: 08059 case SIG_FEATDMF: 08060 case SIG_FEATDMF_TA: 08061 case SIG_E911: 08062 case SIG_FGC_CAMA: 08063 case SIG_FGC_CAMAMF: 08064 case SIG_FEATB: 08065 case SIG_EM: 08066 case SIG_EM_E1: 08067 case SIG_EMWINK: 08068 case SIG_SF_FEATD: 08069 case SIG_SF_FEATDMF: 08070 case SIG_SF_FEATB: 08071 case SIG_SF: 08072 case SIG_SFWINK: 08073 case SIG_FXSLS: 08074 case SIG_FXSGS: 08075 case SIG_FXSKS: 08076 case SIG_GR303FXSKS: 08077 dahdi_disable_ec(i); 08078 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08079 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08080 break; 08081 case SIG_GR303FXOKS: 08082 case SIG_FXOKS: 08083 dahdi_disable_ec(i); 08084 /* Diddle the battery for the zhone */ 08085 #ifdef ZHONE_HACK 08086 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08087 usleep(1); 08088 #endif 08089 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08090 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08091 break; 08092 case SIG_PRI: 08093 dahdi_disable_ec(i); 08094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08095 break; 08096 default: 08097 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08098 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08099 pthread_attr_destroy(&attr); 08100 return NULL; 08101 } 08102 break; 08103 case DAHDI_EVENT_POLARITY: 08104 switch (i->sig) { 08105 case SIG_FXSLS: 08106 case SIG_FXSKS: 08107 case SIG_FXSGS: 08108 /* We have already got a PR before the channel was 08109 created, but it wasn't handled. We need polarity 08110 to be REV for remote hangup detection to work. 08111 At least in Spain */ 08112 if (i->hanguponpolarityswitch) 08113 i->polarity = POLARITY_REV; 08114 08115 if (i->cid_start == CID_START_POLARITY) { 08116 i->polarity = POLARITY_REV; 08117 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 08118 "CID detection on channel %d\n", 08119 i->channel); 08120 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08121 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08122 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08123 } 08124 } 08125 break; 08126 default: 08127 ast_log(LOG_WARNING, "handle_init_event detected " 08128 "polarity reversal on non-FXO (SIG_FXS) " 08129 "interface %d\n", i->channel); 08130 } 08131 break; 08132 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08133 ast_log(LOG_NOTICE, 08134 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08135 i->channel); 08136 pthread_attr_destroy(&attr); 08137 return i; 08138 } 08139 pthread_attr_destroy(&attr); 08140 return NULL; 08141 }
static int handle_mfcr2_call_files | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11679 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.
11680 { 11681 struct dahdi_pvt *p = NULL; 11682 int channo = 0; 11683 if (argc < 4) { 11684 return RESULT_SHOWUSAGE; 11685 } 11686 channo = (argc == 5) ? atoi(argv[4]) : -1; 11687 ast_mutex_lock(&iflock); 11688 p = iflist; 11689 while (p) { 11690 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11691 p = p->next; 11692 continue; 11693 } 11694 if ((channo != -1) && (p->channel != channo )) { 11695 p = p->next; 11696 continue; 11697 } 11698 if (ast_true(argv[3])) { 11699 openr2_chan_enable_call_files(p->r2chan); 11700 } else { 11701 openr2_chan_disable_call_files(p->r2chan); 11702 } 11703 if (channo != -1) { 11704 if (ast_true(argv[3])) { 11705 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 11706 } else { 11707 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 11708 } 11709 break; 11710 } else { 11711 p = p->next; 11712 } 11713 } 11714 if ((channo != -1) && !p) { 11715 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11716 } 11717 if (channo == -1) { 11718 if (ast_true(argv[3])) { 11719 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n"); 11720 } else { 11721 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n"); 11722 } 11723 } 11724 ast_mutex_unlock(&iflock); 11725 return RESULT_SUCCESS; 11726 }
static int handle_mfcr2_set_blocked | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11763 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.
11764 { 11765 struct dahdi_pvt *p = NULL; 11766 int channo = 0; 11767 channo = (argc == 4) ? atoi(argv[3]) : -1; 11768 ast_mutex_lock(&iflock); 11769 p = iflist; 11770 while (p) { 11771 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11772 p = p->next; 11773 continue; 11774 } 11775 if ((channo != -1) && (p->channel != channo )) { 11776 p = p->next; 11777 continue; 11778 } 11779 if (!openr2_chan_set_blocked(p->r2chan)) { 11780 ast_mutex_lock(&p->lock); 11781 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK; 11782 ast_mutex_unlock(&p->lock); 11783 } else { 11784 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel); 11785 } 11786 if (channo != -1) { 11787 break; 11788 } else { 11789 p = p->next; 11790 } 11791 } 11792 if ((channo != -1) && !p) { 11793 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11794 } 11795 ast_mutex_unlock(&iflock); 11796 return RESULT_SUCCESS; 11797 }
static int handle_mfcr2_set_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11620 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.
11621 { 11622 struct dahdi_pvt *p = NULL; 11623 int channo = 0; 11624 char *toklevel = NULL; 11625 char *saveptr = NULL; 11626 char *logval = NULL; 11627 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 11628 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 11629 if (argc < 4) { 11630 return RESULT_SHOWUSAGE; 11631 } 11632 channo = (argc == 5) ? atoi(argv[4]) : -1; 11633 logval = ast_strdupa(argv[3]); 11634 toklevel = strtok_r(logval, ",", &saveptr); 11635 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11636 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]); 11637 return RESULT_FAILURE; 11638 } else if (OR2_LOG_NOTHING == tmplevel) { 11639 loglevel = tmplevel; 11640 } else { 11641 loglevel |= tmplevel; 11642 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 11643 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11644 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 11645 continue; 11646 } 11647 loglevel |= tmplevel; 11648 } 11649 } 11650 ast_mutex_lock(&iflock); 11651 p = iflist; 11652 while (p) { 11653 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11654 p = p->next; 11655 continue; 11656 } 11657 if ((channo != -1) && (p->channel != channo )) { 11658 p = p->next; 11659 continue; 11660 } 11661 openr2_chan_set_log_level(p->r2chan, loglevel); 11662 if (channo != -1) { 11663 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel); 11664 break; 11665 } else { 11666 p = p->next; 11667 } 11668 } 11669 if ((channo != -1) && !p) { 11670 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11671 } 11672 if (channo == -1) { 11673 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]); 11674 } 11675 ast_mutex_unlock(&iflock); 11676 return RESULT_SUCCESS; 11677 }
static int handle_mfcr2_set_idle | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11728 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.
11729 { 11730 struct dahdi_pvt *p = NULL; 11731 int channo = 0; 11732 channo = (argc == 4) ? atoi(argv[3]) : -1; 11733 ast_mutex_lock(&iflock); 11734 p = iflist; 11735 while (p) { 11736 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11737 p = p->next; 11738 continue; 11739 } 11740 if ((channo != -1) && (p->channel != channo )) { 11741 p = p->next; 11742 continue; 11743 } 11744 if (!openr2_chan_set_idle(p->r2chan)) { 11745 ast_mutex_lock(&p->lock); 11746 p->mfcr2call = 0; 11747 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 11748 ast_mutex_unlock(&p->lock); 11749 } 11750 if (channo != -1) { 11751 break; 11752 } else { 11753 p = p->next; 11754 } 11755 } 11756 if ((channo != -1) && !p) { 11757 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11758 } 11759 ast_mutex_unlock(&iflock); 11760 return RESULT_SUCCESS; 11761 }
static int handle_mfcr2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11551 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.
11552 { 11553 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 11554 int filtertype = 0; 11555 int targetnum = 0; 11556 char channo[5]; 11557 char anino[5]; 11558 char dnisno[5]; 11559 struct dahdi_pvt *p; 11560 openr2_context_t *r2context; 11561 openr2_variant_t r2variant; 11562 if (!((argc == 3) || (argc == 5))) { 11563 return RESULT_SHOWUSAGE; 11564 } 11565 if (argc == 5) { 11566 if (!strcasecmp(argv[3], "group")) { 11567 targetnum = atoi(argv[4]); 11568 if ((targetnum < 0) || (targetnum > 63)) 11569 return RESULT_SHOWUSAGE; 11570 targetnum = 1 << targetnum; 11571 filtertype = 1; 11572 } else if (!strcasecmp(argv[3], "context")) { 11573 filtertype = 2; 11574 } else { 11575 return RESULT_SHOWUSAGE; 11576 } 11577 } 11578 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 11579 ast_mutex_lock(&iflock); 11580 p = iflist; 11581 while (p) { 11582 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11583 p = p->next; 11584 continue; 11585 } 11586 if (filtertype) { 11587 switch(filtertype) { 11588 case 1: /* mfcr2 show channels group <group> */ 11589 if (p->group != targetnum) { 11590 p = p->next; 11591 continue; 11592 } 11593 break; 11594 case 2: /* mfcr2 show channels context <context> */ 11595 if (strcasecmp(p->context, argv[4])) { 11596 p= p->next; 11597 continue; 11598 } 11599 break; 11600 default: 11601 ; 11602 } 11603 } 11604 r2context = openr2_chan_get_context(p->r2chan); 11605 r2variant = openr2_context_get_variant(r2context); 11606 snprintf(channo, sizeof(channo), "%d", p->channel); 11607 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 11608 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 11609 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 11610 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 11611 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 11612 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 11613 p = p->next; 11614 } 11615 ast_mutex_unlock(&iflock); 11616 return RESULT_SUCCESS; 11617 #undef FORMAT 11618 }
static int handle_mfcr2_show_variants | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11533 of file chan_dahdi.c.
References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.
11534 { 11535 #define FORMAT "%4s %40s\n" 11536 int numvariants = 0; 11537 int i; 11538 const openr2_variant_entry_t *variants; 11539 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 11540 ast_cli(fd, "Failed to get list of variants.\n"); 11541 return RESULT_FAILURE; 11542 } 11543 ast_cli(fd, FORMAT, "Variant Code", "Country"); 11544 for (i = 0; i < numvariants; i++) { 11545 ast_cli(fd, FORMAT, variants[i].name, variants[i].country); 11546 } 11547 return RESULT_SUCCESS; 11548 #undef FORMAT 11549 }
static int handle_mfcr2_version | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11527 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11528 { 11529 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 11530 return RESULT_SUCCESS; 11531 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11280 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11281 { 11282 int span; 11283 int x; 11284 if (argc < 4) { 11285 return RESULT_SHOWUSAGE; 11286 } 11287 span = atoi(argv[3]); 11288 if ((span < 1) || (span > NUM_SPANS)) { 11289 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 11290 return RESULT_SUCCESS; 11291 } 11292 if (!pris[span-1].pri) { 11293 ast_cli(fd, "No PRI running on span %d\n", span); 11294 return RESULT_SUCCESS; 11295 } 11296 for (x = 0; x < NUM_DCHANS; x++) { 11297 if (pris[span-1].dchans[x]) 11298 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11299 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11300 PRI_DEBUG_Q921_STATE); 11301 } 11302 ast_cli(fd, "Enabled debugging on span %d\n", span); 11303 return RESULT_SUCCESS; 11304 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11308 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11309 { 11310 int span; 11311 int x; 11312 if (argc < 5) 11313 return RESULT_SHOWUSAGE; 11314 span = atoi(argv[4]); 11315 if ((span < 1) || (span > NUM_SPANS)) { 11316 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11317 return RESULT_SUCCESS; 11318 } 11319 if (!pris[span-1].pri) { 11320 ast_cli(fd, "No PRI running on span %d\n", span); 11321 return RESULT_SUCCESS; 11322 } 11323 for (x = 0; x < NUM_DCHANS; x++) { 11324 if (pris[span-1].dchans[x]) 11325 pri_set_debug(pris[span-1].dchans[x], 0); 11326 } 11327 ast_cli(fd, "Disabled debugging on span %d\n", span); 11328 return RESULT_SUCCESS; 11329 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11331 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11332 { 11333 int span; 11334 int x; 11335 if (argc < 5) 11336 return RESULT_SHOWUSAGE; 11337 span = atoi(argv[4]); 11338 if ((span < 1) || (span > NUM_SPANS)) { 11339 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11340 return RESULT_SUCCESS; 11341 } 11342 if (!pris[span-1].pri) { 11343 ast_cli(fd, "No PRI running on span %d\n", span); 11344 return RESULT_SUCCESS; 11345 } 11346 for (x = 0; x < NUM_DCHANS; x++) { 11347 if (pris[span-1].dchans[x]) 11348 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11349 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11350 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 11351 } 11352 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 11353 return RESULT_SUCCESS; 11354 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11233 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.
11234 { 11235 int myfd; 11236 11237 if (!strncasecmp(argv[1], "set", 3)) { 11238 if (argc < 5) 11239 return RESULT_SHOWUSAGE; 11240 11241 if (ast_strlen_zero(argv[4])) 11242 return RESULT_SHOWUSAGE; 11243 11244 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 11245 if (myfd < 0) { 11246 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 11247 return RESULT_SUCCESS; 11248 } 11249 11250 ast_mutex_lock(&pridebugfdlock); 11251 11252 if (pridebugfd >= 0) 11253 close(pridebugfd); 11254 11255 pridebugfd = myfd; 11256 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 11257 11258 ast_mutex_unlock(&pridebugfdlock); 11259 11260 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 11261 } else { 11262 /* Assume it is unset */ 11263 ast_mutex_lock(&pridebugfdlock); 11264 close(pridebugfd); 11265 pridebugfd = -1; 11266 ast_cli(fd, "PRI debug output to file disabled\n"); 11267 ast_mutex_unlock(&pridebugfdlock); 11268 } 11269 11270 return RESULT_SUCCESS; 11271 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11437 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock, ast_mutex_unlock, debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
11438 { 11439 int x; 11440 int span; 11441 int count=0; 11442 int debug=0; 11443 11444 for (span = 0; span < NUM_SPANS; span++) { 11445 if (pris[span].pri) { 11446 for (x = 0; x < NUM_DCHANS; x++) { 11447 debug = 0; 11448 if (pris[span].dchans[x]) { 11449 debug = pri_get_debug(pris[span].dchans[x]); 11450 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" ); 11451 count++; 11452 } 11453 } 11454 } 11455 11456 } 11457 ast_mutex_lock(&pridebugfdlock); 11458 if (pridebugfd >= 0) 11459 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 11460 ast_mutex_unlock(&pridebugfdlock); 11461 11462 if (!count) 11463 ast_cli(fd, "No debug set or no PRI running\n"); 11464 return RESULT_SUCCESS; 11465 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11398 of file chan_dahdi.c.
References ast_cli(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11399 { 11400 int span; 11401 int x; 11402 char status[256]; 11403 if (argc < 4) 11404 return RESULT_SHOWUSAGE; 11405 span = atoi(argv[3]); 11406 if ((span < 1) || (span > NUM_SPANS)) { 11407 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 11408 return RESULT_SUCCESS; 11409 } 11410 if (!pris[span-1].pri) { 11411 ast_cli(fd, "No PRI running on span %d\n", span); 11412 return RESULT_SUCCESS; 11413 } 11414 for (x = 0; x < NUM_DCHANS; x++) { 11415 if (pris[span-1].dchannels[x]) { 11416 #ifdef PRI_DUMP_INFO_STR 11417 char *info_str = NULL; 11418 #endif 11419 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 11420 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 11421 ast_cli(fd, "Status: %s\n", status); 11422 #ifdef PRI_DUMP_INFO_STR 11423 info_str = pri_dump_info_str(pris[span-1].pri); 11424 if (info_str) { 11425 ast_cli(fd, "%s", info_str); 11426 free(info_str); 11427 } 11428 #else 11429 pri_dump_info(pris[span-1].pri); 11430 #endif 11431 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 11432 } 11433 } 11434 return RESULT_SUCCESS; 11435 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11377 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11378 { 11379 int span; 11380 int x; 11381 char status[256]; 11382 if (argc != 3) 11383 return RESULT_SHOWUSAGE; 11384 11385 for (span = 0; span < NUM_SPANS; span++) { 11386 if (pris[span].pri) { 11387 for (x = 0; x < NUM_DCHANS; x++) { 11388 if (pris[span].dchannels[x]) { 11389 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 11390 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 11391 } 11392 } 11393 } 11394 } 11395 return RESULT_SUCCESS; 11396 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11274 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11274 { 11275 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 11276 return RESULT_SUCCESS; 11277 }
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 13868 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.
13869 { 13870 int res; 13871 13872 #ifdef HAVE_PRI 13873 int y,i; 13874 memset(pris, 0, sizeof(pris)); 13875 for (y = 0; y < NUM_SPANS; y++) { 13876 ast_mutex_init(&pris[y].lock); 13877 pris[y].offset = -1; 13878 pris[y].master = AST_PTHREADT_NULL; 13879 for (i = 0; i < NUM_DCHANS; i++) 13880 pris[y].fds[i] = -1; 13881 } 13882 pri_set_error(dahdi_pri_error); 13883 pri_set_message(dahdi_pri_message); 13884 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13885 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 13886 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 13887 } 13888 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 13889 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 13890 #endif 13891 #ifdef HAVE_OPENR2 13892 init_mfcr2_globals(); 13893 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13894 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec, 13895 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip); 13896 } 13897 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec, 13898 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip); 13899 #endif 13900 if ((res = setup_dahdi(0))) { 13901 return AST_MODULE_LOAD_DECLINE; 13902 } 13903 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13904 chan_tech = &dahdi_tech; 13905 } else { 13906 chan_tech = &zap_tech; 13907 } 13908 if (ast_channel_register(chan_tech)) { 13909 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 13910 __unload_module(); 13911 return -1; 13912 } 13913 #ifdef HAVE_PRI 13914 ast_string_field_init(&inuse, 16); 13915 ast_string_field_set(&inuse, name, "GR-303InUse"); 13916 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 13917 #endif 13918 #ifdef HAVE_OPENR2 13919 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 13920 #endif 13921 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 13922 13923 memset(round_robin, 0, sizeof(round_robin)); 13924 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 13925 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 13926 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 13927 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 13928 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 13929 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 13930 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 13931 13932 ast_cond_init(&ss_thread_complete, NULL); 13933 13934 return res; 13935 }
static struct dahdi_mfcr2* mfcr2_get_context | ( | int | id | ) | [static] |
Definition at line 8374 of file chan_dahdi.c.
References ast_log(), LOG_ERROR, and r2links.
Referenced by mkintf().
08375 { 08376 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) { 08377 ast_log(LOG_ERROR, "No more R2 links available!.\n"); 08378 return NULL; 08379 } 08380 return &r2links[id]; 08381 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 9530 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().
09531 { 09532 struct dahdi_pvt *p; 09533 struct dahdi_mfcr2 *mfcr2 = data; 09534 /* we should be using pthread_key_create 09535 and allocate pollers dynamically. 09536 I think do_monitor() could be leaking, since it 09537 could be cancelled at any time and is not 09538 using thread keys, why?, */ 09539 struct pollfd pollers[sizeof(mfcr2->pvts)]; 09540 int maxsleep = 20; 09541 int res = 0; 09542 int i = 0; 09543 int pollsize = 0; 09544 int oldstate = 0; 09545 int was_idle = 0; 09546 int quit_loop = 0; 09547 /* now that we're ready to get calls, unblock our side and 09548 get current line state */ 09549 for (i = 0; i < mfcr2->numchans; i++) { 09550 p = mfcr2->pvts[i]; 09551 if (openr2_chan_set_idle(p->r2chan)) { 09552 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel); 09553 } else { 09554 ast_mutex_lock(&p->lock); 09555 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 09556 mfcr2->pvts[i]->mfcr2call = 0; 09557 ast_mutex_unlock(&p->lock); 09558 } 09559 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 09560 } 09561 while(1) { 09562 /* we trust here that the mfcr2 channel list will not ever change once 09563 the module is loaded */ 09564 pollsize = 0; 09565 for (i = 0; i < mfcr2->numchans; i++) { 09566 pollers[i].revents = 0; 09567 pollers[i].events = 0; 09568 if (mfcr2->pvts[i]->owner) { 09569 continue; 09570 } 09571 if (!mfcr2->pvts[i]->r2chan) { 09572 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 09573 quit_loop = 1; 09574 break; 09575 } 09576 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 09577 pollers[i].events = POLLIN | POLLPRI; 09578 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 09579 pollsize++; 09580 } 09581 if (quit_loop) { 09582 break; 09583 } 09584 09585 if (pollsize == 0) { 09586 if (!was_idle) { 09587 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n"); 09588 was_idle = 1; 09589 } 09590 poll(NULL, 0, maxsleep); 09591 continue; 09592 } 09593 was_idle = 0; 09594 09595 /* probably poll() is a valid cancel point, lets just be on the safe side 09596 by calling pthread_testcancel */ 09597 pthread_testcancel(); 09598 res = poll(pollers, pollsize, maxsleep); 09599 pthread_testcancel(); 09600 if ((res < 0) && (errno != EINTR)) { 09601 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 09602 break; 09603 } 09604 /* do we want to allow to cancel while processing events? */ 09605 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 09606 for (i = 0; i < mfcr2->numchans; i++) { 09607 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) { 09608 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 09609 } 09610 } 09611 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 09612 } 09613 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 09614 return 0; 09615 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8507 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().
08508 { 08509 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08510 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08511 char fn[80]; 08512 #if 1 08513 struct dahdi_bufferinfo bi; 08514 #endif 08515 int res; 08516 int span=0; 08517 int here = 0; 08518 int x; 08519 struct dahdi_pvt **wlist; 08520 struct dahdi_pvt **wend; 08521 struct dahdi_params p; 08522 08523 wlist = &iflist; 08524 wend = &ifend; 08525 08526 #ifdef HAVE_PRI 08527 if (pri) { 08528 wlist = &pri->crvs; 08529 wend = &pri->crvend; 08530 } 08531 #endif 08532 08533 tmp2 = *wlist; 08534 prev = NULL; 08535 08536 while (tmp2) { 08537 if (!tmp2->destroy) { 08538 if (tmp2->channel == channel) { 08539 tmp = tmp2; 08540 here = 1; 08541 break; 08542 } 08543 if (tmp2->channel > channel) { 08544 break; 08545 } 08546 } 08547 prev = tmp2; 08548 tmp2 = tmp2->next; 08549 } 08550 08551 if (!here && reloading != 1) { 08552 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08553 if (tmp) 08554 free(tmp); 08555 return NULL; 08556 } 08557 ast_mutex_init(&tmp->lock); 08558 ifcount++; 08559 for (x = 0; x < 3; x++) 08560 tmp->subs[x].dfd = -1; 08561 tmp->channel = channel; 08562 tmp->priindication_oob = conf->chan.priindication_oob; 08563 } 08564 08565 if (tmp) { 08566 int chan_sig = conf->chan.sig; 08567 if (!here) { 08568 if ((channel != CHAN_PSEUDO) && !pri) { 08569 int count = 0; 08570 snprintf(fn, sizeof(fn), "%d", channel); 08571 /* Open non-blocking */ 08572 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08573 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 */ 08574 usleep(1); 08575 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08576 count++; 08577 } 08578 /* Allocate a DAHDI structure */ 08579 if (tmp->subs[SUB_REAL].dfd < 0) { 08580 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); 08581 destroy_dahdi_pvt(&tmp); 08582 return NULL; 08583 } 08584 memset(&p, 0, sizeof(p)); 08585 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08586 if (res < 0) { 08587 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08588 destroy_dahdi_pvt(&tmp); 08589 return NULL; 08590 } 08591 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 08592 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)); 08593 destroy_dahdi_pvt(&tmp); 08594 return NULL; 08595 } 08596 tmp->law = p.curlaw; 08597 tmp->span = p.spanno; 08598 span = p.spanno - 1; 08599 } else { 08600 if (channel == CHAN_PSEUDO) 08601 chan_sig = 0; 08602 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08603 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08604 return NULL; 08605 } 08606 } 08607 #ifdef HAVE_PRI 08608 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08609 int offset; 08610 int myswitchtype; 08611 int matchesdchan; 08612 int x,y; 08613 offset = 0; 08614 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08615 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08616 destroy_dahdi_pvt(&tmp); 08617 return NULL; 08618 } 08619 if (span >= NUM_SPANS) { 08620 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08621 destroy_dahdi_pvt(&tmp); 08622 return NULL; 08623 } else { 08624 struct dahdi_spaninfo si; 08625 si.spanno = 0; 08626 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08627 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08628 destroy_dahdi_pvt(&tmp); 08629 return NULL; 08630 } 08631 /* Store the logical span first based upon the real span */ 08632 tmp->logicalspan = pris[span].prilogicalspan; 08633 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08634 if (span < 0) { 08635 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08636 destroy_dahdi_pvt(&tmp); 08637 return NULL; 08638 } 08639 if (chan_sig == SIG_PRI) 08640 myswitchtype = conf->pri.switchtype; 08641 else 08642 myswitchtype = PRI_SWITCH_GR303_TMC; 08643 /* Make sure this isn't a d-channel */ 08644 matchesdchan=0; 08645 for (x = 0; x < NUM_SPANS; x++) { 08646 for (y = 0; y < NUM_DCHANS; y++) { 08647 if (pris[x].dchannels[y] == tmp->channel) { 08648 matchesdchan = 1; 08649 break; 08650 } 08651 } 08652 } 08653 offset = p.chanpos; 08654 if (!matchesdchan) { 08655 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08656 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08657 destroy_dahdi_pvt(&tmp); 08658 return NULL; 08659 } 08660 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08661 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08662 destroy_dahdi_pvt(&tmp); 08663 return NULL; 08664 } 08665 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08666 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08667 destroy_dahdi_pvt(&tmp); 08668 return NULL; 08669 } 08670 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08671 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08672 destroy_dahdi_pvt(&tmp); 08673 return NULL; 08674 } 08675 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08676 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08677 destroy_dahdi_pvt(&tmp); 08678 return NULL; 08679 } 08680 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08681 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08682 destroy_dahdi_pvt(&tmp); 08683 return NULL; 08684 } 08685 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08686 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08687 destroy_dahdi_pvt(&tmp); 08688 return NULL; 08689 } 08690 if (pris[span].numchans >= MAX_CHANNELS) { 08691 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08692 pris[span].trunkgroup); 08693 destroy_dahdi_pvt(&tmp); 08694 return NULL; 08695 } 08696 pris[span].nodetype = conf->pri.nodetype; 08697 pris[span].switchtype = myswitchtype; 08698 pris[span].nsf = conf->pri.nsf; 08699 pris[span].dialplan = conf->pri.dialplan; 08700 pris[span].localdialplan = conf->pri.localdialplan; 08701 pris[span].pvts[pris[span].numchans++] = tmp; 08702 pris[span].minunused = conf->pri.minunused; 08703 pris[span].minidle = conf->pri.minidle; 08704 pris[span].overlapdial = conf->pri.overlapdial; 08705 #ifdef HAVE_PRI_INBANDDISCONNECT 08706 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08707 #endif 08708 pris[span].facilityenable = conf->pri.facilityenable; 08709 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08710 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08711 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08712 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08713 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08714 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08715 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08716 pris[span].resetinterval = conf->pri.resetinterval; 08717 08718 tmp->pri = &pris[span]; 08719 tmp->prioffset = offset; 08720 tmp->call = NULL; 08721 } else { 08722 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08723 destroy_dahdi_pvt(&tmp); 08724 return NULL; 08725 } 08726 } 08727 } else { 08728 tmp->prioffset = 0; 08729 } 08730 #endif 08731 #ifdef HAVE_OPENR2 08732 if (chan_sig == SIG_MFCR2 && reloading != 1) { 08733 char logdir[OR2_MAX_PATH]; 08734 struct dahdi_mfcr2 *dahdi_r2; 08735 int threshold = 0; 08736 int snres = 0; 08737 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index); 08738 if (!dahdi_r2) { 08739 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 08740 } else if (!dahdi_r2->protocol_context){ 08741 char tmplogdir[] = "/tmp"; 08742 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 08743 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis); 08744 if (!dahdi_r2->protocol_context) { 08745 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 08746 destroy_dahdi_pvt(&tmp); 08747 return NULL; 08748 } 08749 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel); 08750 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first); 08751 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category); 08752 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold); 08753 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout); 08754 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout); 08755 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer); 08756 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept); 08757 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 08758 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off); 08759 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection); 08760 #endif 08761 if (ast_strlen_zero(mfcr2_cur_logdir)) { 08762 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) { 08763 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08764 } 08765 } else { 08766 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir); 08767 if (snres >= sizeof(logdir)) { 08768 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 08769 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08770 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08771 } 08772 } else { 08773 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08774 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 08775 } 08776 } 08777 } 08778 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) { 08779 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) { 08780 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file); 08781 } 08782 } 08783 } 08784 if (dahdi_r2) { 08785 /* TODO: should we check numchans overflow, or is it already done by DAHDI? */ 08786 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp; 08787 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context, 08788 tmp->subs[SUB_REAL].dfd, NULL, NULL); 08789 if (!tmp->r2chan) { 08790 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context); 08791 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 08792 destroy_dahdi_pvt(&tmp); 08793 return NULL; 08794 } 08795 openr2_chan_set_client_data(tmp->r2chan, tmp); 08796 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 08797 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 08798 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel); 08799 if (mfcr2_cur_call_files) { 08800 openr2_chan_enable_call_files(tmp->r2chan); 08801 } 08802 tmp->mfcr2_category = mfcr2_cur_category; 08803 tmp->mfcr2 = dahdi_r2; 08804 tmp->mfcr2call = 0; 08805 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK; 08806 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer; 08807 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls; 08808 tmp->mfcr2_ani_index = 0; 08809 tmp->mfcr2_dnis_index = 0; 08810 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls; 08811 tmp->mfcr2_forced_release = mfcr2_cur_forced_release; 08812 } 08813 } 08814 #endif 08815 } else { 08816 chan_sig = tmp->sig; 08817 if (tmp->subs[SUB_REAL].dfd > -1) { 08818 memset(&p, 0, sizeof(p)); 08819 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08820 } 08821 } 08822 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08823 switch (chan_sig) { 08824 case SIG_FXSKS: 08825 case SIG_FXSLS: 08826 case SIG_EM: 08827 case SIG_EM_E1: 08828 case SIG_EMWINK: 08829 case SIG_FEATD: 08830 case SIG_FEATDMF: 08831 case SIG_FEATDMF_TA: 08832 case SIG_FEATB: 08833 case SIG_E911: 08834 case SIG_SF: 08835 case SIG_SFWINK: 08836 case SIG_FGC_CAMA: 08837 case SIG_FGC_CAMAMF: 08838 case SIG_SF_FEATD: 08839 case SIG_SF_FEATDMF: 08840 case SIG_SF_FEATB: 08841 p.starttime = 250; 08842 break; 08843 } 08844 08845 if (tmp->radio) { 08846 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08847 p.channo = channel; 08848 p.rxwinktime = 1; 08849 p.rxflashtime = 1; 08850 p.starttime = 1; 08851 p.debouncetime = 5; 08852 } 08853 if (!tmp->radio) { 08854 p.channo = channel; 08855 /* Override timing settings based on config file */ 08856 if (conf->timing.prewinktime >= 0) 08857 p.prewinktime = conf->timing.prewinktime; 08858 if (conf->timing.preflashtime >= 0) 08859 p.preflashtime = conf->timing.preflashtime; 08860 if (conf->timing.winktime >= 0) 08861 p.winktime = conf->timing.winktime; 08862 if (conf->timing.flashtime >= 0) 08863 p.flashtime = conf->timing.flashtime; 08864 if (conf->timing.starttime >= 0) 08865 p.starttime = conf->timing.starttime; 08866 if (conf->timing.rxwinktime >= 0) 08867 p.rxwinktime = conf->timing.rxwinktime; 08868 if (conf->timing.rxflashtime >= 0) 08869 p.rxflashtime = conf->timing.rxflashtime; 08870 if (conf->timing.debouncetime >= 0) 08871 p.debouncetime = conf->timing.debouncetime; 08872 } 08873 08874 /* dont set parms on a pseudo-channel (or CRV) */ 08875 if (tmp->subs[SUB_REAL].dfd >= 0) 08876 { 08877 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 08878 if (res < 0) { 08879 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 08880 destroy_dahdi_pvt(&tmp); 08881 return NULL; 08882 } 08883 } 08884 #if 1 08885 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 08886 memset(&bi, 0, sizeof(bi)); 08887 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08888 if (!res) { 08889 bi.txbufpolicy = conf->chan.buf_policy; 08890 bi.rxbufpolicy = conf->chan.buf_policy; 08891 bi.numbufs = conf->chan.buf_no; 08892 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08893 if (res < 0) { 08894 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 08895 } 08896 } else 08897 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 08898 } 08899 #endif 08900 tmp->immediate = conf->chan.immediate; 08901 tmp->transfertobusy = conf->chan.transfertobusy; 08902 tmp->sig = chan_sig; 08903 tmp->outsigmod = conf->chan.outsigmod; 08904 tmp->ringt_base = ringt_base; 08905 tmp->firstradio = 0; 08906 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 08907 tmp->permcallwaiting = conf->chan.callwaiting; 08908 else 08909 tmp->permcallwaiting = 0; 08910 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 08911 tmp->destroy = 0; 08912 tmp->drings = drings; 08913 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 08914 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 08915 tmp->threewaycalling = conf->chan.threewaycalling; 08916 tmp->adsi = conf->chan.adsi; 08917 tmp->use_smdi = conf->chan.use_smdi; 08918 tmp->permhidecallerid = conf->chan.hidecallerid; 08919 tmp->callreturn = conf->chan.callreturn; 08920 tmp->echocancel = conf->chan.echocancel; 08921 tmp->echotraining = conf->chan.echotraining; 08922 tmp->pulse = conf->chan.pulse; 08923 if (tmp->echocancel) 08924 tmp->echocanbridged = conf->chan.echocanbridged; 08925 else { 08926 if (conf->chan.echocanbridged) 08927 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 08928 tmp->echocanbridged = 0; 08929 } 08930 tmp->busydetect = conf->chan.busydetect; 08931 tmp->busycount = conf->chan.busycount; 08932 tmp->busycompare = conf->chan.busycompare; 08933 tmp->busytonelength = conf->chan.busytonelength; 08934 tmp->busyquietlength = conf->chan.busyquietlength; 08935 tmp->busyfuzziness = conf->chan.busyfuzziness; 08936 tmp->silencethreshold = conf->chan.silencethreshold; 08937 tmp->callprogress = conf->chan.callprogress; 08938 tmp->cancallforward = conf->chan.cancallforward; 08939 tmp->dtmfrelax = conf->chan.dtmfrelax; 08940 tmp->callwaiting = tmp->permcallwaiting; 08941 tmp->hidecallerid = tmp->permhidecallerid; 08942 tmp->channel = channel; 08943 tmp->stripmsd = conf->chan.stripmsd; 08944 tmp->use_callerid = conf->chan.use_callerid; 08945 tmp->cid_signalling = conf->chan.cid_signalling; 08946 tmp->cid_start = conf->chan.cid_start; 08947 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 08948 tmp->restrictcid = conf->chan.restrictcid; 08949 tmp->use_callingpres = conf->chan.use_callingpres; 08950 tmp->priexclusive = conf->chan.priexclusive; 08951 if (tmp->usedistinctiveringdetection) { 08952 if (!tmp->use_callerid) { 08953 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 08954 tmp->use_callerid = 1; 08955 } 08956 } 08957 08958 if (tmp->cid_signalling == CID_SIG_SMDI) { 08959 if (!tmp->use_smdi) { 08960 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 08961 tmp->use_smdi = 1; 08962 } 08963 } 08964 if (tmp->use_smdi) { 08965 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 08966 if (!(tmp->smdi_iface)) { 08967 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 08968 tmp->use_smdi = 0; 08969 } 08970 } 08971 08972 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 08973 tmp->amaflags = conf->chan.amaflags; 08974 if (!here) { 08975 tmp->confno = -1; 08976 tmp->propconfno = -1; 08977 } 08978 tmp->canpark = conf->chan.canpark; 08979 tmp->transfer = conf->chan.transfer; 08980 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 08981 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 08982 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 08983 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 08984 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 08985 tmp->cid_ton = 0; 08986 if (chan_sig != SIG_PRI) { 08987 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 08988 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 08989 } else { 08990 tmp->cid_num[0] = '\0'; 08991 tmp->cid_name[0] = '\0'; 08992 } 08993 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 08994 tmp->msgstate = -1; 08995 tmp->group = conf->chan.group; 08996 tmp->callgroup = conf->chan.callgroup; 08997 tmp->pickupgroup= conf->chan.pickupgroup; 08998 tmp->rxgain = conf->chan.rxgain; 08999 tmp->txgain = conf->chan.txgain; 09000 tmp->tonezone = conf->chan.tonezone; 09001 tmp->onhooktime = time(NULL); 09002 if (tmp->subs[SUB_REAL].dfd > -1) { 09003 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09004 if (tmp->dsp) 09005 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09006 update_conf(tmp); 09007 if (!here) { 09008 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2)) 09009 /* Hang it up to be sure it's good */ 09010 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09011 } 09012 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09013 #ifdef HAVE_PRI 09014 /* the dchannel is down so put the channel in alarm */ 09015 if (tmp->pri && !pri_is_up(tmp->pri)) { 09016 tmp->inalarm = 1; 09017 } 09018 #endif 09019 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09020 tmp->inalarm = 1; 09021 handle_alarms(tmp, res); 09022 } else { 09023 /* yes, this looks strange... the unknown_alarm flag is only used to 09024 control whether an 'alarm cleared' message gets generated when we 09025 get an indication that the channel is no longer in alarm status. 09026 however, the channel *could* be in an alarm status that we aren't 09027 aware of (since get_alarms() only reports span alarms, not channel 09028 alarms). setting this flag will cause any potential 'alarm cleared' 09029 message to be suppressed, but if a real alarm occurs before that 09030 happens, this flag will get cleared by it and the situation will 09031 be normal. 09032 */ 09033 tmp->unknown_alarm = 1; 09034 } 09035 } 09036 09037 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09038 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09039 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09040 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09041 09042 } 09043 if (tmp && !here) { 09044 /* nothing on the iflist */ 09045 if (!*wlist) { 09046 *wlist = tmp; 09047 tmp->prev = NULL; 09048 tmp->next = NULL; 09049 *wend = tmp; 09050 } else { 09051 /* at least one member on the iflist */ 09052 struct dahdi_pvt *working = *wlist; 09053 09054 /* check if we maybe have to put it on the begining */ 09055 if (working->channel > tmp->channel) { 09056 tmp->next = *wlist; 09057 tmp->prev = NULL; 09058 (*wlist)->prev = tmp; 09059 *wlist = tmp; 09060 } else { 09061 /* go through all the members and put the member in the right place */ 09062 while (working) { 09063 /* in the middle */ 09064 if (working->next) { 09065 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09066 tmp->next = working->next; 09067 tmp->prev = working; 09068 working->next->prev = tmp; 09069 working->next = tmp; 09070 break; 09071 } 09072 } else { 09073 /* the last */ 09074 if (working->channel < tmp->channel) { 09075 working->next = tmp; 09076 tmp->next = NULL; 09077 tmp->prev = working; 09078 *wend = tmp; 09079 break; 09080 } 09081 } 09082 working = working->next; 09083 } 09084 } 09085 } 09086 } 09087 return tmp; 09088 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 6222 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().
06223 { 06224 int sent=0; 06225 int size; 06226 int res; 06227 int fd; 06228 fd = p->subs[index].dfd; 06229 while (len) { 06230 size = len; 06231 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06232 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06233 res = write(fd, buf, size); 06234 if (res != size) { 06235 if (option_debug) 06236 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06237 return sent; 06238 } 06239 len -= size; 06240 buf += size; 06241 } 06242 return sent; 06243 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6713 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06714 { 06715 char c; 06716 06717 *str = 0; /* start with empty output buffer */ 06718 for (;;) 06719 { 06720 /* Wait for the first digit (up to specified ms). */ 06721 c = ast_waitfordigit(chan, ms); 06722 /* if timeout, hangup or error, return as such */ 06723 if (c < 1) 06724 return c; 06725 *str++ = c; 06726 *str = 0; 06727 if (strchr(term, c)) 06728 return 1; 06729 } 06730 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3384 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().
03385 { 03386 int x = -1; 03387 03388 for (x = 0; x < NUM_DCHANS; x++) { 03389 if ((pri->dchans[x] == pri->pri)) 03390 break; 03391 } 03392 03393 return pri->fds[x]; 03394 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3354 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().
03355 { 03356 bearer->owner = &inuse; 03357 bearer->realcall = crv; 03358 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03359 if (crv->subs[SUB_REAL].owner) 03360 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 03361 crv->bearer = bearer; 03362 crv->call = bearer->call; 03363 crv->pri = pri; 03364 return 0; 03365 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9882 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().
09883 { 09884 do { 09885 pri->resetpos++; 09886 } while ((pri->resetpos < pri->numchans) && 09887 (!pri->pvts[pri->resetpos] || 09888 pri->pvts[pri->resetpos]->call || 09889 pri->pvts[pri->resetpos]->resetting)); 09890 if (pri->resetpos < pri->numchans) { 09891 /* Mark the channel as resetting and restart it */ 09892 pri->pvts[pri->resetpos]->resetting = 1; 09893 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 09894 } else { 09895 pri->resetting = 0; 09896 time(&pri->lastreset); 09897 } 09898 return 0; 09899 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8494 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08495 { 08496 if (pris[span].mastertrunkgroup) { 08497 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); 08498 return -1; 08499 } 08500 pris[span].mastertrunkgroup = trunkgroup; 08501 pris[span].prilogicalspan = logicalspan; 08502 return 0; 08503 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8431 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().
08432 { 08433 struct dahdi_spaninfo si; 08434 struct dahdi_params p; 08435 int fd; 08436 int span; 08437 int ospan=0; 08438 int x,y; 08439 for (x = 0; x < NUM_SPANS; x++) { 08440 if (pris[x].trunkgroup == trunkgroup) { 08441 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08442 return -1; 08443 } 08444 } 08445 for (y = 0; y < NUM_DCHANS; y++) { 08446 if (!channels[y]) 08447 break; 08448 memset(&si, 0, sizeof(si)); 08449 memset(&p, 0, sizeof(p)); 08450 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 08451 if (fd < 0) { 08452 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08453 return -1; 08454 } 08455 x = channels[y]; 08456 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08457 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08458 close(fd); 08459 return -1; 08460 } 08461 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08462 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08463 return -1; 08464 } 08465 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08466 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08467 close(fd); 08468 return -1; 08469 } 08470 span = p.spanno - 1; 08471 if (pris[span].trunkgroup) { 08472 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08473 close(fd); 08474 return -1; 08475 } 08476 if (pris[span].pvts[0]) { 08477 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08478 close(fd); 08479 return -1; 08480 } 08481 if (!y) { 08482 pris[span].trunkgroup = trunkgroup; 08483 pris[span].offset = channels[y] - p.chanpos; 08484 ospan = span; 08485 } 08486 pris[ospan].dchannels[y] = channels[y]; 08487 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08488 pris[span].span = span + 1; 08489 close(fd); 08490 } 08491 return 0; 08492 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 9981 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.
09982 { 09983 struct dahdi_pri *pri = vpri; 09984 pri_event *e; 09985 struct pollfd fds[NUM_DCHANS]; 09986 int res; 09987 int chanpos = 0; 09988 int x; 09989 int haveidles; 09990 int activeidles; 09991 int nextidle = -1; 09992 struct ast_channel *c; 09993 struct timeval tv, lowest, *next; 09994 struct timeval lastidle = { 0, 0 }; 09995 int doidling=0; 09996 char *cc; 09997 char idlen[80]; 09998 struct ast_channel *idle; 09999 pthread_t p; 10000 time_t t; 10001 int i, which=-1; 10002 int numdchans; 10003 int cause=0; 10004 struct dahdi_pvt *crv; 10005 pthread_t threadid; 10006 pthread_attr_t attr; 10007 char ani2str[6]; 10008 char plancallingnum[256]; 10009 char plancallingani[256]; 10010 char calledtonstr[10]; 10011 10012 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10013 10014 gettimeofday(&lastidle, NULL); 10015 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10016 /* Need to do idle dialing, check to be sure though */ 10017 cc = strchr(pri->idleext, '@'); 10018 if (cc) { 10019 *cc = '\0'; 10020 cc++; 10021 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10022 #if 0 10023 /* Extensions may not be loaded yet */ 10024 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10025 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10026 else 10027 #endif 10028 doidling = 1; 10029 } else 10030 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10031 } 10032 for (;;) { 10033 for (i = 0; i < NUM_DCHANS; i++) { 10034 if (!pri->dchannels[i]) 10035 break; 10036 fds[i].fd = pri->fds[i]; 10037 fds[i].events = POLLIN | POLLPRI; 10038 fds[i].revents = 0; 10039 } 10040 numdchans = i; 10041 time(&t); 10042 ast_mutex_lock(&pri->lock); 10043 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10044 if (pri->resetting && pri_is_up(pri)) { 10045 if (pri->resetpos < 0) 10046 pri_check_restart(pri); 10047 } else { 10048 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10049 pri->resetting = 1; 10050 pri->resetpos = -1; 10051 } 10052 } 10053 } 10054 /* Look for any idle channels if appropriate */ 10055 if (doidling && pri_is_up(pri)) { 10056 nextidle = -1; 10057 haveidles = 0; 10058 activeidles = 0; 10059 for (x = pri->numchans; x >= 0; x--) { 10060 if (pri->pvts[x] && !pri->pvts[x]->owner && 10061 !pri->pvts[x]->call) { 10062 if (haveidles < pri->minunused) { 10063 haveidles++; 10064 } else if (!pri->pvts[x]->resetting) { 10065 nextidle = x; 10066 break; 10067 } 10068 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10069 activeidles++; 10070 } 10071 if (nextidle > -1) { 10072 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10073 /* Don't create a new idle call more than once per second */ 10074 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10075 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 10076 if (idle) { 10077 pri->pvts[nextidle]->isidlecall = 1; 10078 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10079 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10080 dahdi_hangup(idle); 10081 } 10082 } else 10083 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10084 gettimeofday(&lastidle, NULL); 10085 } 10086 } else if ((haveidles < pri->minunused) && 10087 (activeidles > pri->minidle)) { 10088 /* Mark something for hangup if there is something 10089 that can be hungup */ 10090 for (x = pri->numchans; x >= 0; x--) { 10091 /* find a candidate channel */ 10092 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10093 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10094 haveidles++; 10095 /* Stop if we have enough idle channels or 10096 can't spare any more active idle ones */ 10097 if ((haveidles >= pri->minunused) || 10098 (activeidles <= pri->minidle)) 10099 break; 10100 } 10101 } 10102 } 10103 } 10104 /* Start with reasonable max */ 10105 lowest = ast_tv(60, 0); 10106 for (i = 0; i < NUM_DCHANS; i++) { 10107 /* Find lowest available d-channel */ 10108 if (!pri->dchannels[i]) 10109 break; 10110 if ((next = pri_schedule_next(pri->dchans[i]))) { 10111 /* We need relative time here */ 10112 tv = ast_tvsub(*next, ast_tvnow()); 10113 if (tv.tv_sec < 0) { 10114 tv = ast_tv(0,0); 10115 } 10116 if (doidling || pri->resetting) { 10117 if (tv.tv_sec > 1) { 10118 tv = ast_tv(1, 0); 10119 } 10120 } else { 10121 if (tv.tv_sec > 60) { 10122 tv = ast_tv(60, 0); 10123 } 10124 } 10125 } else if (doidling || pri->resetting) { 10126 /* Make sure we stop at least once per second if we're 10127 monitoring idle channels */ 10128 tv = ast_tv(1,0); 10129 } else { 10130 /* Don't poll for more than 60 seconds */ 10131 tv = ast_tv(60, 0); 10132 } 10133 if (!i || ast_tvcmp(tv, lowest) < 0) { 10134 lowest = tv; 10135 } 10136 } 10137 ast_mutex_unlock(&pri->lock); 10138 10139 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 10140 pthread_testcancel(); 10141 e = NULL; 10142 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 10143 pthread_testcancel(); 10144 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10145 10146 ast_mutex_lock(&pri->lock); 10147 if (!res) { 10148 for (which = 0; which < NUM_DCHANS; which++) { 10149 if (!pri->dchans[which]) 10150 break; 10151 /* Just a timeout, run the scheduler */ 10152 e = pri_schedule_run(pri->dchans[which]); 10153 if (e) 10154 break; 10155 } 10156 } else if (res > -1) { 10157 for (which = 0; which < NUM_DCHANS; which++) { 10158 if (!pri->dchans[which]) 10159 break; 10160 if (fds[which].revents & POLLPRI) { 10161 /* Check for an event */ 10162 x = 0; 10163 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 10164 if (x) 10165 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); 10166 /* Keep track of alarm state */ 10167 if (x == DAHDI_EVENT_ALARM) { 10168 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 10169 pri_find_dchan(pri); 10170 } else if (x == DAHDI_EVENT_NOALARM) { 10171 pri->dchanavail[which] |= DCHAN_NOTINALARM; 10172 pri_restart(pri->dchans[which]); 10173 } 10174 10175 if (option_debug) 10176 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 10177 } else if (fds[which].revents & POLLIN) { 10178 e = pri_check_event(pri->dchans[which]); 10179 } 10180 if (e) 10181 break; 10182 } 10183 } else if (errno != EINTR) 10184 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 10185 10186 if (e) { 10187 if (pri->debug) 10188 pri_dump_event(pri->dchans[which], e); 10189 10190 if (e->e != PRI_EVENT_DCHAN_DOWN) { 10191 if (!(pri->dchanavail[which] & DCHAN_UP)) { 10192 if (option_verbose > 1) 10193 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 10194 } 10195 pri->dchanavail[which] |= DCHAN_UP; 10196 } else { 10197 if (pri->dchanavail[which] & DCHAN_UP) { 10198 if (option_verbose > 1) 10199 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 10200 } 10201 pri->dchanavail[which] &= ~DCHAN_UP; 10202 } 10203 10204 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 10205 /* Must be an NFAS group that has the secondary dchan active */ 10206 pri->pri = pri->dchans[which]; 10207 10208 switch (e->e) { 10209 case PRI_EVENT_DCHAN_UP: 10210 if (!pri->pri) pri_find_dchan(pri); 10211 10212 /* Note presense of D-channel */ 10213 time(&pri->lastreset); 10214 10215 /* Restart in 5 seconds */ 10216 if (pri->resetinterval > -1) { 10217 pri->lastreset -= pri->resetinterval; 10218 pri->lastreset += 5; 10219 } 10220 pri->resetting = 0; 10221 /* Take the channels from inalarm condition */ 10222 for (i = 0; i < pri->numchans; i++) 10223 if (pri->pvts[i]) { 10224 pri->pvts[i]->inalarm = 0; 10225 } 10226 break; 10227 case PRI_EVENT_DCHAN_DOWN: 10228 pri_find_dchan(pri); 10229 if (!pri_is_up(pri)) { 10230 pri->resetting = 0; 10231 /* Hangup active channels and put them in alarm mode */ 10232 for (i = 0; i < pri->numchans; i++) { 10233 struct dahdi_pvt *p = pri->pvts[i]; 10234 if (p) { 10235 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 10236 /* T309 is not enabled : hangup calls when alarm occurs */ 10237 if (p->call) { 10238 if (p->pri && p->pri->pri) { 10239 pri_hangup(p->pri->pri, p->call, -1); 10240 pri_destroycall(p->pri->pri, p->call); 10241 p->call = NULL; 10242 } else 10243 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 10244 } 10245 if (p->realcall) { 10246 pri_hangup_all(p->realcall, pri); 10247 } else if (p->owner) 10248 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10249 } 10250 p->inalarm = 1; 10251 } 10252 } 10253 } 10254 break; 10255 case PRI_EVENT_RESTART: 10256 if (e->restart.channel > -1) { 10257 chanpos = pri_find_principle(pri, e->restart.channel); 10258 if (chanpos < 0) 10259 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 10260 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10261 else { 10262 if (option_verbose > 2) 10263 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 10264 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10265 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10266 if (pri->pvts[chanpos]->call) { 10267 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 10268 pri->pvts[chanpos]->call = NULL; 10269 } 10270 /* Force soft hangup if appropriate */ 10271 if (pri->pvts[chanpos]->realcall) 10272 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10273 else if (pri->pvts[chanpos]->owner) 10274 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10275 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10276 } 10277 } else { 10278 if (option_verbose > 2) 10279 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 10280 for (x = 0; x < pri->numchans; x++) 10281 if (pri->pvts[x]) { 10282 ast_mutex_lock(&pri->pvts[x]->lock); 10283 if (pri->pvts[x]->call) { 10284 pri_destroycall(pri->pri, pri->pvts[x]->call); 10285 pri->pvts[x]->call = NULL; 10286 } 10287 if (pri->pvts[x]->realcall) 10288 pri_hangup_all(pri->pvts[x]->realcall, pri); 10289 else if (pri->pvts[x]->owner) 10290 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10291 ast_mutex_unlock(&pri->pvts[x]->lock); 10292 } 10293 } 10294 break; 10295 case PRI_EVENT_KEYPAD_DIGIT: 10296 chanpos = pri_find_principle(pri, e->digit.channel); 10297 if (chanpos < 0) { 10298 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 10299 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 10300 } else { 10301 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 10302 if (chanpos > -1) { 10303 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10304 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 10305 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 10306 /* how to do that */ 10307 int digitlen = strlen(e->digit.digits); 10308 char digit; 10309 int i; 10310 for (i = 0; i < digitlen; i++) { 10311 digit = e->digit.digits[i]; 10312 { 10313 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10314 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10315 } 10316 } 10317 } 10318 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10319 } 10320 } 10321 break; 10322 10323 case PRI_EVENT_INFO_RECEIVED: 10324 chanpos = pri_find_principle(pri, e->ring.channel); 10325 if (chanpos < 0) { 10326 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 10327 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10328 } else { 10329 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 10330 if (chanpos > -1) { 10331 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10332 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 10333 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 10334 /* how to do that */ 10335 int digitlen = strlen(e->ring.callednum); 10336 char digit; 10337 int i; 10338 for (i = 0; i < digitlen; i++) { 10339 digit = e->ring.callednum[i]; 10340 { 10341 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10342 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10343 } 10344 } 10345 } 10346 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10347 } 10348 } 10349 break; 10350 case PRI_EVENT_RING: 10351 crv = NULL; 10352 if (e->ring.channel == -1) 10353 chanpos = pri_find_empty_chan(pri, 1); 10354 else 10355 chanpos = pri_find_principle(pri, e->ring.channel); 10356 /* if no channel specified find one empty */ 10357 if (chanpos < 0) { 10358 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 10359 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10360 } else { 10361 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10362 if (pri->pvts[chanpos]->owner) { 10363 if (pri->pvts[chanpos]->call == e->ring.call) { 10364 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 10365 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10366 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10367 break; 10368 } else { 10369 /* This is where we handle initial glare */ 10370 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 10371 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10372 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10373 chanpos = -1; 10374 } 10375 } 10376 if (chanpos > -1) 10377 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10378 } 10379 if ((chanpos < 0) && (e->ring.flexible)) 10380 chanpos = pri_find_empty_chan(pri, 1); 10381 if (chanpos > -1) { 10382 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10383 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 10384 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 10385 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 10386 if (crv) 10387 ast_mutex_lock(&crv->lock); 10388 if (!crv || crv->owner) { 10389 pri->pvts[chanpos]->call = NULL; 10390 if (crv) { 10391 if (crv->owner) 10392 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10393 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); 10394 } else 10395 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); 10396 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 10397 if (crv) 10398 ast_mutex_unlock(&crv->lock); 10399 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10400 break; 10401 } 10402 } 10403 pri->pvts[chanpos]->call = e->ring.call; 10404 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 10405 if (pri->pvts[chanpos]->use_callerid) { 10406 ast_shrink_phone_number(plancallingnum); 10407 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 10408 #ifdef PRI_ANI 10409 if (!ast_strlen_zero(e->ring.callingani)) { 10410 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 10411 ast_shrink_phone_number(plancallingani); 10412 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 10413 } else { 10414 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10415 } 10416 #endif 10417 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 10418 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 10419 } else { 10420 pri->pvts[chanpos]->cid_num[0] = '\0'; 10421 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10422 pri->pvts[chanpos]->cid_name[0] = '\0'; 10423 pri->pvts[chanpos]->cid_ton = 0; 10424 } 10425 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 10426 e->ring.redirectingnum, e->ring.callingplanrdnis); 10427 /* If immediate=yes go to s|1 */ 10428 if (pri->pvts[chanpos]->immediate) { 10429 if (option_verbose > 2) 10430 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 10431 pri->pvts[chanpos]->exten[0] = 's'; 10432 pri->pvts[chanpos]->exten[1] = '\0'; 10433 } 10434 /* Get called number */ 10435 else if (!ast_strlen_zero(e->ring.callednum)) { 10436 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 10437 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10438 } else if (pri->overlapdial) 10439 pri->pvts[chanpos]->exten[0] = '\0'; 10440 else { 10441 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 10442 pri->pvts[chanpos]->exten[0] = 's'; 10443 pri->pvts[chanpos]->exten[1] = '\0'; 10444 } 10445 /* Set DNID on all incoming calls -- even immediate */ 10446 if (!ast_strlen_zero(e->ring.callednum)) 10447 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10448 /* No number yet, but received "sending complete"? */ 10449 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 10450 if (option_verbose > 2) 10451 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 10452 pri->pvts[chanpos]->exten[0] = 's'; 10453 pri->pvts[chanpos]->exten[1] = '\0'; 10454 } 10455 10456 /* Make sure extension exists (or in overlap dial mode, can exist) */ 10457 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 10458 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10459 /* Setup law */ 10460 int law; 10461 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 10462 /* Set to audio mode at this point */ 10463 law = 1; 10464 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 10465 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 10466 } 10467 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 10468 law = DAHDI_LAW_ALAW; 10469 else 10470 law = DAHDI_LAW_MULAW; 10471 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 10472 if (res < 0) 10473 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 10474 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 10475 if (res < 0) 10476 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 10477 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 10478 /* Just announce proceeding */ 10479 pri->pvts[chanpos]->proceeding = 1; 10480 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 10481 } else { 10482 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 10483 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10484 else 10485 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10486 } 10487 /* Get the use_callingpres state */ 10488 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 10489 10490 /* Start PBX */ 10491 if (!e->ring.complete 10492 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 10493 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10494 /* 10495 * Release the PRI lock while we create the channel 10496 * so other threads can send D channel messages. 10497 */ 10498 ast_mutex_unlock(&pri->lock); 10499 if (crv) { 10500 /* Set bearer and such */ 10501 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 10502 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10503 pri->pvts[chanpos]->owner = &inuse; 10504 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 10505 } else { 10506 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10507 } 10508 ast_mutex_lock(&pri->lock); 10509 if (c) { 10510 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10511 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10512 } 10513 if (e->ring.ani2 >= 0) { 10514 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10515 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10516 } 10517 10518 #ifdef SUPPORT_USERUSER 10519 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10520 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10521 } 10522 #endif 10523 10524 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10525 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10526 if (e->ring.redirectingreason >= 0) 10527 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10528 } 10529 10530 pthread_attr_init(&attr); 10531 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 10532 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 10533 if (option_verbose > 2) 10534 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 10535 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 10536 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10537 } else { 10538 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10539 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10540 if (c) 10541 ast_hangup(c); 10542 else { 10543 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10544 pri->pvts[chanpos]->call = NULL; 10545 } 10546 } 10547 pthread_attr_destroy(&attr); 10548 } else { 10549 /* 10550 * Release the PRI lock while we create the channel 10551 * so other threads can send D channel messages. 10552 */ 10553 ast_mutex_unlock(&pri->lock); 10554 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 10555 ast_mutex_lock(&pri->lock); 10556 if (c) { 10557 /* 10558 * It is reasonably safe to set the following 10559 * channel variables while the PRI and DAHDI private 10560 * structures are locked. The PBX has not been 10561 * started yet and it is unlikely that any other task 10562 * will do anything with the channel we have just 10563 * created. 10564 */ 10565 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10566 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10567 } 10568 if (e->ring.ani2 >= 0) { 10569 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10570 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10571 } 10572 10573 #ifdef SUPPORT_USERUSER 10574 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10575 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10576 } 10577 #endif 10578 10579 if (e->ring.redirectingreason >= 0) 10580 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10581 10582 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10583 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10584 } 10585 if (c && !ast_pbx_start(c)) { 10586 if (option_verbose > 2) 10587 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 10588 plancallingnum, pri->pvts[chanpos]->exten, 10589 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10590 10591 dahdi_enable_ec(pri->pvts[chanpos]); 10592 } else { 10593 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10594 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10595 if (c) { 10596 ast_hangup(c); 10597 } else { 10598 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10599 pri->pvts[chanpos]->call = NULL; 10600 } 10601 } 10602 } 10603 } else { 10604 if (option_verbose > 2) 10605 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 10606 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 10607 pri->pvts[chanpos]->prioffset, pri->span); 10608 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 10609 pri->pvts[chanpos]->call = NULL; 10610 pri->pvts[chanpos]->exten[0] = '\0'; 10611 } 10612 if (crv) 10613 ast_mutex_unlock(&crv->lock); 10614 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10615 } else { 10616 if (e->ring.flexible) 10617 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 10618 else 10619 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 10620 } 10621 break; 10622 case PRI_EVENT_RINGING: 10623 chanpos = pri_find_principle(pri, e->ringing.channel); 10624 if (chanpos < 0) { 10625 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 10626 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10627 } else { 10628 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 10629 if (chanpos < 0) { 10630 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 10631 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10632 } else { 10633 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10634 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10635 dahdi_enable_ec(pri->pvts[chanpos]); 10636 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 10637 pri->pvts[chanpos]->alerting = 1; 10638 } else 10639 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 10640 #ifdef PRI_PROGRESS_MASK 10641 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10642 #else 10643 if (e->ringing.progress == 8) { 10644 #endif 10645 /* Now we can do call progress detection */ 10646 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10647 /* RINGING detection isn't required because we got ALERTING signal */ 10648 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 10649 pri->pvts[chanpos]->dsp_features = 0; 10650 } 10651 } 10652 10653 #ifdef SUPPORT_USERUSER 10654 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 10655 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10656 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10657 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 10658 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10659 } 10660 #endif 10661 10662 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10663 } 10664 } 10665 break; 10666 case PRI_EVENT_PROGRESS: 10667 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 10668 chanpos = pri_find_principle(pri, e->proceeding.channel); 10669 if (chanpos > -1) { 10670 #ifdef PRI_PROGRESS_MASK 10671 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 10672 #else 10673 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 10674 #endif 10675 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10676 10677 if (e->proceeding.cause > -1) { 10678 if (option_verbose > 2) 10679 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 10680 10681 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 10682 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 10683 if (pri->pvts[chanpos]->owner) { 10684 if (option_verbose > 2) 10685 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 10686 10687 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 10688 f.subclass = AST_CONTROL_BUSY; 10689 } 10690 } 10691 } 10692 10693 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10694 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 10695 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10696 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10697 #ifdef PRI_PROGRESS_MASK 10698 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10699 #else 10700 if (e->proceeding.progress == 8) { 10701 #endif 10702 /* Now we can do call progress detection */ 10703 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10704 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10705 pri->pvts[chanpos]->dsp_features = 0; 10706 } 10707 /* Bring voice path up */ 10708 f.subclass = AST_CONTROL_PROGRESS; 10709 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10710 } 10711 pri->pvts[chanpos]->progress = 1; 10712 pri->pvts[chanpos]->dialing = 0; 10713 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10714 } 10715 } 10716 break; 10717 case PRI_EVENT_PROCEEDING: 10718 chanpos = pri_find_principle(pri, e->proceeding.channel); 10719 if (chanpos > -1) { 10720 if (!pri->pvts[chanpos]->proceeding) { 10721 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10722 10723 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10724 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 10725 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10726 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10727 #ifdef PRI_PROGRESS_MASK 10728 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10729 #else 10730 if (e->proceeding.progress == 8) { 10731 #endif 10732 /* Now we can do call progress detection */ 10733 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10734 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10735 pri->pvts[chanpos]->dsp_features = 0; 10736 } 10737 /* Bring voice path up */ 10738 f.subclass = AST_CONTROL_PROGRESS; 10739 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10740 } 10741 pri->pvts[chanpos]->proceeding = 1; 10742 pri->pvts[chanpos]->dialing = 0; 10743 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10744 } 10745 } 10746 break; 10747 case PRI_EVENT_FACNAME: 10748 chanpos = pri_find_principle(pri, e->facname.channel); 10749 if (chanpos < 0) { 10750 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 10751 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10752 } else { 10753 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 10754 if (chanpos < 0) { 10755 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 10756 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10757 } else { 10758 /* Re-use *69 field for PRI */ 10759 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10760 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 10761 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 10762 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 10763 dahdi_enable_ec(pri->pvts[chanpos]); 10764 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10765 } 10766 } 10767 break; 10768 case PRI_EVENT_ANSWER: 10769 chanpos = pri_find_principle(pri, e->answer.channel); 10770 if (chanpos < 0) { 10771 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 10772 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10773 } else { 10774 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 10775 if (chanpos < 0) { 10776 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 10777 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10778 } else { 10779 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10780 /* Now we can do call progress detection */ 10781 10782 /* We changed this so it turns on the DSP no matter what... progress or no progress. 10783 * By this time, we need DTMF detection and other features that were previously disabled 10784 * -- Matt F */ 10785 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10786 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10787 pri->pvts[chanpos]->dsp_features = 0; 10788 } 10789 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 10790 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 10791 x = DAHDI_START; 10792 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 10793 if (res < 0) { 10794 if (errno != EINPROGRESS) { 10795 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 10796 } 10797 } 10798 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10799 pri->pvts[chanpos]->dialing = 1; 10800 /* Send any "w" waited stuff */ 10801 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 10802 if (res < 0) { 10803 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 10804 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10805 } else 10806 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 10807 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10808 } else if (pri->pvts[chanpos]->confirmanswer) { 10809 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 10810 } else { 10811 pri->pvts[chanpos]->dialing = 0; 10812 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 10813 /* Enable echo cancellation if it's not on already */ 10814 dahdi_enable_ec(pri->pvts[chanpos]); 10815 } 10816 10817 #ifdef SUPPORT_USERUSER 10818 if (!ast_strlen_zero(e->answer.useruserinfo)) { 10819 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10820 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10821 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 10822 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10823 } 10824 #endif 10825 10826 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10827 } 10828 } 10829 break; 10830 case PRI_EVENT_HANGUP: 10831 chanpos = pri_find_principle(pri, e->hangup.channel); 10832 if (chanpos < 0) { 10833 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 10834 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10835 } else { 10836 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10837 if (chanpos > -1) { 10838 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10839 if (!pri->pvts[chanpos]->alreadyhungup) { 10840 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 10841 pri->pvts[chanpos]->alreadyhungup = 1; 10842 if (pri->pvts[chanpos]->realcall) 10843 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10844 else if (pri->pvts[chanpos]->owner) { 10845 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 10846 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10847 switch (pri->pvts[chanpos]->owner->_state) { 10848 case AST_STATE_BUSY: 10849 case AST_STATE_UP: 10850 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10851 break; 10852 default: 10853 switch (e->hangup.cause) { 10854 case PRI_CAUSE_USER_BUSY: 10855 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10856 break; 10857 case PRI_CAUSE_CALL_REJECTED: 10858 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10859 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10860 case PRI_CAUSE_SWITCH_CONGESTION: 10861 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10862 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10863 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10864 break; 10865 default: 10866 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10867 } 10868 break; 10869 } 10870 } 10871 if (option_verbose > 2) 10872 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 10873 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 10874 } else { 10875 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10876 pri->pvts[chanpos]->call = NULL; 10877 } 10878 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10879 if (option_verbose > 2) 10880 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 10881 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10882 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10883 pri->pvts[chanpos]->resetting = 1; 10884 } 10885 if (e->hangup.aoc_units > -1) 10886 if (option_verbose > 2) 10887 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10888 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10889 10890 #ifdef SUPPORT_USERUSER 10891 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 10892 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10893 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10894 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10895 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10896 } 10897 #endif 10898 10899 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10900 } else { 10901 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 10902 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10903 } 10904 } 10905 break; 10906 #ifndef PRI_EVENT_HANGUP_REQ 10907 #error please update libpri 10908 #endif 10909 case PRI_EVENT_HANGUP_REQ: 10910 chanpos = pri_find_principle(pri, e->hangup.channel); 10911 if (chanpos < 0) { 10912 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 10913 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10914 } else { 10915 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10916 if (chanpos > -1) { 10917 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10918 if (pri->pvts[chanpos]->realcall) 10919 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10920 else if (pri->pvts[chanpos]->owner) { 10921 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10922 switch (pri->pvts[chanpos]->owner->_state) { 10923 case AST_STATE_BUSY: 10924 case AST_STATE_UP: 10925 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10926 break; 10927 default: 10928 switch (e->hangup.cause) { 10929 case PRI_CAUSE_USER_BUSY: 10930 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10931 break; 10932 case PRI_CAUSE_CALL_REJECTED: 10933 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10934 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10935 case PRI_CAUSE_SWITCH_CONGESTION: 10936 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10937 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10938 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10939 break; 10940 default: 10941 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10942 } 10943 break; 10944 } 10945 if (option_verbose > 2) 10946 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); 10947 if (e->hangup.aoc_units > -1) 10948 if (option_verbose > 2) 10949 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10950 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10951 } else { 10952 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10953 pri->pvts[chanpos]->call = NULL; 10954 } 10955 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10956 if (option_verbose > 2) 10957 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 10958 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10959 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10960 pri->pvts[chanpos]->resetting = 1; 10961 } 10962 10963 #ifdef SUPPORT_USERUSER 10964 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 10965 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10966 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10967 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10968 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10969 } 10970 #endif 10971 10972 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10973 } else { 10974 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); 10975 } 10976 } 10977 break; 10978 case PRI_EVENT_HANGUP_ACK: 10979 chanpos = pri_find_principle(pri, e->hangup.channel); 10980 if (chanpos < 0) { 10981 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 10982 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10983 } else { 10984 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10985 if (chanpos > -1) { 10986 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10987 pri->pvts[chanpos]->call = NULL; 10988 pri->pvts[chanpos]->resetting = 0; 10989 if (pri->pvts[chanpos]->owner) { 10990 if (option_verbose > 2) 10991 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); 10992 } 10993 10994 #ifdef SUPPORT_USERUSER 10995 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 10996 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10997 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10998 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 10999 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11000 } 11001 #endif 11002 11003 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11004 } 11005 } 11006 break; 11007 case PRI_EVENT_CONFIG_ERR: 11008 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11009 break; 11010 case PRI_EVENT_RESTART_ACK: 11011 chanpos = pri_find_principle(pri, e->restartack.channel); 11012 if (chanpos < 0) { 11013 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11014 channel number, so we have to figure it out... This must be why 11015 everybody resets exactly a channel at a time. */ 11016 for (x = 0; x < pri->numchans; x++) { 11017 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11018 chanpos = x; 11019 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11020 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11021 pri->pvts[chanpos]->prioffset, pri->span); 11022 if (pri->pvts[chanpos]->realcall) 11023 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11024 else if (pri->pvts[chanpos]->owner) { 11025 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11026 pri->pvts[chanpos]->prioffset, pri->span); 11027 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11028 } 11029 pri->pvts[chanpos]->resetting = 0; 11030 if (option_verbose > 2) 11031 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11032 pri->pvts[chanpos]->prioffset, pri->span); 11033 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11034 if (pri->resetting) 11035 pri_check_restart(pri); 11036 break; 11037 } 11038 } 11039 if (chanpos < 0) { 11040 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11041 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11042 } 11043 } else { 11044 if (pri->pvts[chanpos]) { 11045 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11046 if (pri->pvts[chanpos]->realcall) 11047 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11048 else if (pri->pvts[chanpos]->owner) { 11049 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11050 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11051 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11052 } 11053 pri->pvts[chanpos]->resetting = 0; 11054 if (option_verbose > 2) 11055 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11056 pri->pvts[chanpos]->prioffset, pri->span); 11057 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11058 if (pri->resetting) 11059 pri_check_restart(pri); 11060 } 11061 } 11062 break; 11063 case PRI_EVENT_SETUP_ACK: 11064 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11065 if (chanpos < 0) { 11066 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11067 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11068 } else { 11069 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11070 if (chanpos > -1) { 11071 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11072 pri->pvts[chanpos]->setup_ack = 1; 11073 /* Send any queued digits */ 11074 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11075 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11076 pri_information(pri->pri, pri->pvts[chanpos]->call, 11077 pri->pvts[chanpos]->dialdest[x]); 11078 } 11079 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11080 } else 11081 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11082 } 11083 break; 11084 case PRI_EVENT_NOTIFY: 11085 chanpos = pri_find_principle(pri, e->notify.channel); 11086 if (chanpos < 0) { 11087 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11088 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11089 } else { 11090 struct ast_frame f = { AST_FRAME_CONTROL, }; 11091 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11092 switch (e->notify.info) { 11093 case PRI_NOTIFY_REMOTE_HOLD: 11094 f.subclass = AST_CONTROL_HOLD; 11095 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11096 break; 11097 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11098 f.subclass = AST_CONTROL_UNHOLD; 11099 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11100 break; 11101 } 11102 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11103 } 11104 break; 11105 default: 11106 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 11107 } 11108 } 11109 ast_mutex_unlock(&pri->lock); 11110 } 11111 /* Never reached */ 11112 return NULL; 11113 }
Definition at line 9620 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
09621 { 09622 struct dahdi_pvt *p; 09623 p = pri->crvs; 09624 while (p) { 09625 if (p->channel == crv) 09626 return p; 09627 p = p->next; 09628 } 09629 return NULL; 09630 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3396 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03397 { 03398 int oldslot = -1; 03399 struct pri *old; 03400 int newslot = -1; 03401 int x; 03402 old = pri->pri; 03403 for (x = 0; x < NUM_DCHANS; x++) { 03404 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03405 newslot = x; 03406 if (pri->dchans[x] == old) { 03407 oldslot = x; 03408 } 03409 } 03410 if (newslot < 0) { 03411 newslot = 0; 03412 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03413 pri->dchannels[newslot]); 03414 } 03415 if (old && (oldslot != newslot)) 03416 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03417 pri->dchannels[oldslot], pri->dchannels[newslot]); 03418 pri->pri = pri->dchans[newslot]; 03419 return 0; 03420 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9243 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().
09244 { 09245 int x; 09246 if (backwards) 09247 x = pri->numchans; 09248 else 09249 x = 0; 09250 for (;;) { 09251 if (backwards && (x < 0)) 09252 break; 09253 if (!backwards && (x >= pri->numchans)) 09254 break; 09255 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09256 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 09257 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09258 return x; 09259 } 09260 if (backwards) 09261 x--; 09262 else 09263 x++; 09264 } 09265 return -1; 09266 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 9633 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.
09634 { 09635 int x; 09636 int span = PRI_SPAN(channel); 09637 int spanfd; 09638 struct dahdi_params param; 09639 int principle = -1; 09640 int explicit = PRI_EXPLICIT(channel); 09641 channel = PRI_CHANNEL(channel); 09642 09643 if (!explicit) { 09644 spanfd = pri_active_dchan_fd(pri); 09645 memset(¶m, 0, sizeof(param)); 09646 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 09647 return -1; 09648 span = pris[param.spanno - 1].prilogicalspan; 09649 } 09650 09651 for (x = 0; x < pri->numchans; x++) { 09652 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 09653 principle = x; 09654 break; 09655 } 09656 } 09657 09658 return principle; 09659 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 9661 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.
09662 { 09663 int x; 09664 struct dahdi_pvt *crv; 09665 if (!c) { 09666 if (principle < 0) 09667 return -1; 09668 return principle; 09669 } 09670 if ((principle > -1) && 09671 (principle < pri->numchans) && 09672 (pri->pvts[principle]) && 09673 (pri->pvts[principle]->call == c)) 09674 return principle; 09675 /* First, check for other bearers */ 09676 for (x = 0; x < pri->numchans; x++) { 09677 if (!pri->pvts[x]) 09678 continue; 09679 if (pri->pvts[x]->call == c) { 09680 /* Found our call */ 09681 if (principle != x) { 09682 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 09683 09684 if (option_verbose > 2) 09685 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 09686 old->channel, new->channel); 09687 if (new->owner) { 09688 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 09689 old->channel, new->channel, new->channel); 09690 return -1; 09691 } 09692 /* Fix it all up now */ 09693 new->owner = old->owner; 09694 old->owner = NULL; 09695 if (new->owner) { 09696 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 09697 new->owner->tech_pvt = new; 09698 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 09699 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 09700 old->subs[SUB_REAL].owner = NULL; 09701 } else 09702 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); 09703 new->call = old->call; 09704 old->call = NULL; 09705 09706 /* Copy any DSP that may be present */ 09707 new->dsp = old->dsp; 09708 new->dsp_features = old->dsp_features; 09709 old->dsp = NULL; 09710 old->dsp_features = 0; 09711 } 09712 return principle; 09713 } 09714 } 09715 /* Now check for a CRV with no bearer */ 09716 crv = pri->crvs; 09717 while (crv) { 09718 if (crv->call == c) { 09719 /* This is our match... Perform some basic checks */ 09720 if (crv->bearer) 09721 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 09722 else if (pri->pvts[principle]->owner) 09723 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 09724 else { 09725 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 09726 wakeup the potential sleeper */ 09727 dahdi_close_sub(crv, SUB_REAL); 09728 pri->pvts[principle]->call = crv->call; 09729 pri_assign_bearer(crv, pri, pri->pvts[principle]); 09730 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 09731 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 09732 pri->trunkgroup, crv->channel); 09733 wakeup_sub(crv, SUB_REAL, pri); 09734 } 09735 return principle; 09736 } 09737 crv = crv->next; 09738 } 09739 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 09740 return -1; 09741 }
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 9901 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.
09902 { 09903 int x; 09904 int redo; 09905 ast_mutex_unlock(&pri->lock); 09906 ast_mutex_lock(&p->lock); 09907 do { 09908 redo = 0; 09909 for (x = 0; x < 3; x++) { 09910 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 09911 redo++; 09912 DEADLOCK_AVOIDANCE(&p->lock); 09913 } 09914 if (p->subs[x].owner) { 09915 ast_queue_hangup(p->subs[x].owner); 09916 ast_mutex_unlock(&p->subs[x].owner->lock); 09917 } 09918 } 09919 } while (redo); 09920 ast_mutex_unlock(&p->lock); 09921 ast_mutex_lock(&pri->lock); 09922 return 0; 09923 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3344 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03345 { 03346 int x; 03347 for (x = 0; x < NUM_DCHANS; x++) { 03348 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03349 return 1; 03350 } 03351 return 0; 03352 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3367 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03368 { 03369 switch (level) { 03370 case 0: 03371 return "Primary"; 03372 case 1: 03373 return "Secondary"; 03374 case 2: 03375 return "Tertiary"; 03376 case 3: 03377 return "Quaternary"; 03378 default: 03379 return "<Unknown>"; 03380 } 03381 }
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 8385 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().
08386 { 08387 int x; 08388 int trunkgroup; 08389 /* Get appropriate trunk group if there is one */ 08390 trunkgroup = pris[*span].mastertrunkgroup; 08391 if (trunkgroup) { 08392 /* Select a specific trunk group */ 08393 for (x = 0; x < NUM_SPANS; x++) { 08394 if (pris[x].trunkgroup == trunkgroup) { 08395 *span = x; 08396 return 0; 08397 } 08398 } 08399 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08400 *span = -1; 08401 } else { 08402 if (pris[*span].trunkgroup) { 08403 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08404 *span = -1; 08405 } else if (pris[*span].mastertrunkgroup) { 08406 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08407 *span = -1; 08408 } else { 08409 if (si->totalchans == 31) { 08410 /* E1 */ 08411 pris[*span].dchannels[0] = 16 + offset; 08412 } else if (si->totalchans == 24) { 08413 /* T1 or J1 */ 08414 pris[*span].dchannels[0] = 24 + offset; 08415 } else if (si->totalchans == 3) { 08416 /* BRI */ 08417 pris[*span].dchannels[0] = 3 + offset; 08418 } else { 08419 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); 08420 *span = -1; 08421 return 0; 08422 } 08423 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08424 pris[*span].offset = offset; 08425 pris[*span].span = *span + 1; 08426 } 08427 } 08428 return 0; 08429 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 12884 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().
12885 { 12886 struct dahdi_pvt *tmp; 12887 int y; 12888 int found_pseudo = 0; 12889 char dahdichan[MAX_CHANLIST_LEN] = {}; 12890 12891 for (; v; v = v->next) { 12892 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 12893 continue; 12894 12895 /* Create the interface list */ 12896 if (!strcasecmp(v->name, "channel") 12897 #ifdef HAVE_PRI 12898 || !strcasecmp(v->name, "crv") 12899 #endif 12900 ) { 12901 int iscrv; 12902 if (skipchannels) 12903 continue; 12904 iscrv = !strcasecmp(v->name, "crv"); 12905 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 12906 return -1; 12907 } else if (!strcasecmp(v->name, "buffers")) { 12908 int res; 12909 char policy[21] = ""; 12910 12911 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 12912 if (res != 2) { 12913 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 12914 confp->chan.buf_no = numbufs; 12915 continue; 12916 } 12917 if (confp->chan.buf_no < 0) 12918 confp->chan.buf_no = numbufs; 12919 if (!strcasecmp(policy, "full")) { 12920 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 12921 } else if (!strcasecmp(policy, "immediate")) { 12922 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 12923 } else { 12924 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 12925 } 12926 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 12927 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 12928 if (v->name[0] == 'z' || v->name[0] == 'Z') { 12929 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 12930 } 12931 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 12932 if (ast_true(v->value)) 12933 confp->chan.usedistinctiveringdetection = 1; 12934 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 12935 if (ast_true(v->value)) 12936 distinctiveringaftercid = 1; 12937 } else if (!strcasecmp(v->name, "dring1context")) { 12938 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 12939 } else if (!strcasecmp(v->name, "dring2context")) { 12940 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 12941 } else if (!strcasecmp(v->name, "dring3context")) { 12942 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 12943 } else if (!strcasecmp(v->name, "dring1")) { 12944 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 12945 } else if (!strcasecmp(v->name, "dring2")) { 12946 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 12947 } else if (!strcasecmp(v->name, "dring3")) { 12948 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 12949 } else if (!strcasecmp(v->name, "usecallerid")) { 12950 confp->chan.use_callerid = ast_true(v->value); 12951 } else if (!strcasecmp(v->name, "cidsignalling")) { 12952 if (!strcasecmp(v->value, "bell")) 12953 confp->chan.cid_signalling = CID_SIG_BELL; 12954 else if (!strcasecmp(v->value, "v23")) 12955 confp->chan.cid_signalling = CID_SIG_V23; 12956 else if (!strcasecmp(v->value, "dtmf")) 12957 confp->chan.cid_signalling = CID_SIG_DTMF; 12958 else if (!strcasecmp(v->value, "smdi")) 12959 confp->chan.cid_signalling = CID_SIG_SMDI; 12960 else if (!strcasecmp(v->value, "v23_jp")) 12961 confp->chan.cid_signalling = CID_SIG_V23_JP; 12962 else if (ast_true(v->value)) 12963 confp->chan.cid_signalling = CID_SIG_BELL; 12964 } else if (!strcasecmp(v->name, "cidstart")) { 12965 if (!strcasecmp(v->value, "ring")) 12966 confp->chan.cid_start = CID_START_RING; 12967 else if (!strcasecmp(v->value, "polarity")) 12968 confp->chan.cid_start = CID_START_POLARITY; 12969 else if (ast_true(v->value)) 12970 confp->chan.cid_start = CID_START_RING; 12971 } else if (!strcasecmp(v->name, "threewaycalling")) { 12972 confp->chan.threewaycalling = ast_true(v->value); 12973 } else if (!strcasecmp(v->name, "cancallforward")) { 12974 confp->chan.cancallforward = ast_true(v->value); 12975 } else if (!strcasecmp(v->name, "relaxdtmf")) { 12976 if (ast_true(v->value)) 12977 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 12978 else 12979 confp->chan.dtmfrelax = 0; 12980 } else if (!strcasecmp(v->name, "mailbox")) { 12981 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 12982 } else if (!strcasecmp(v->name, "hasvoicemail")) { 12983 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 12984 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 12985 } 12986 } else if (!strcasecmp(v->name, "adsi")) { 12987 confp->chan.adsi = ast_true(v->value); 12988 } else if (!strcasecmp(v->name, "usesmdi")) { 12989 confp->chan.use_smdi = ast_true(v->value); 12990 } else if (!strcasecmp(v->name, "smdiport")) { 12991 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 12992 } else if (!strcasecmp(v->name, "transfer")) { 12993 confp->chan.transfer = ast_true(v->value); 12994 } else if (!strcasecmp(v->name, "canpark")) { 12995 confp->chan.canpark = ast_true(v->value); 12996 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 12997 confp->chan.echocanbridged = ast_true(v->value); 12998 } else if (!strcasecmp(v->name, "busydetect")) { 12999 confp->chan.busydetect = ast_true(v->value); 13000 } else if (!strcasecmp(v->name, "busycount")) { 13001 confp->chan.busycount = atoi(v->value); 13002 } else if (!strcasecmp(v->name, "silencethreshold")) { 13003 confp->chan.silencethreshold = atoi(v->value); 13004 } else if (!strcasecmp(v->name, "busycompare")) { 13005 confp->chan.busycompare = ast_true(v->value); 13006 } else if (!strcasecmp(v->name, "busypattern")) { 13007 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 13008 if (count == 1) 13009 confp->chan.busyquietlength = 0; 13010 else if (count < 1) 13011 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 13012 } else if (!strcasecmp(v->name, "busyfuzziness")) { 13013 confp->chan.busyfuzziness = atoi(v->value); 13014 } else if (!strcasecmp(v->name, "callprogress")) { 13015 if (ast_true(v->value)) 13016 confp->chan.callprogress |= 1; 13017 else 13018 confp->chan.callprogress &= ~1; 13019 } else if (!strcasecmp(v->name, "faxdetect")) { 13020 if (!strcasecmp(v->value, "incoming")) { 13021 confp->chan.callprogress |= 4; 13022 confp->chan.callprogress &= ~2; 13023 } else if (!strcasecmp(v->value, "outgoing")) { 13024 confp->chan.callprogress &= ~4; 13025 confp->chan.callprogress |= 2; 13026 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 13027 confp->chan.callprogress |= 6; 13028 else 13029 confp->chan.callprogress &= ~6; 13030 } else if (!strcasecmp(v->name, "echocancel")) { 13031 if (!ast_strlen_zero(v->value)) { 13032 y = atoi(v->value); 13033 } else 13034 y = 0; 13035 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 13036 confp->chan.echocancel = y; 13037 else { 13038 confp->chan.echocancel = ast_true(v->value); 13039 if (confp->chan.echocancel) 13040 confp->chan.echocancel=128; 13041 } 13042 } else if (!strcasecmp(v->name, "echotraining")) { 13043 if (sscanf(v->value, "%30d", &y) == 1) { 13044 if ((y < 10) || (y > 4000)) { 13045 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 13046 } else { 13047 confp->chan.echotraining = y; 13048 } 13049 } else if (ast_true(v->value)) { 13050 confp->chan.echotraining = 400; 13051 } else 13052 confp->chan.echotraining = 0; 13053 } else if (!strcasecmp(v->name, "hidecallerid")) { 13054 confp->chan.hidecallerid = ast_true(v->value); 13055 } else if (!strcasecmp(v->name, "hidecalleridname")) { 13056 confp->chan.hidecalleridname = ast_true(v->value); 13057 } else if (!strcasecmp(v->name, "pulsedial")) { 13058 confp->chan.pulse = ast_true(v->value); 13059 } else if (!strcasecmp(v->name, "callreturn")) { 13060 confp->chan.callreturn = ast_true(v->value); 13061 } else if (!strcasecmp(v->name, "callwaiting")) { 13062 confp->chan.callwaiting = ast_true(v->value); 13063 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 13064 confp->chan.callwaitingcallerid = ast_true(v->value); 13065 } else if (!strcasecmp(v->name, "context")) { 13066 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 13067 } else if (!strcasecmp(v->name, "language")) { 13068 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 13069 } else if (!strcasecmp(v->name, "progzone")) { 13070 ast_copy_string(progzone, v->value, sizeof(progzone)); 13071 } else if (!strcasecmp(v->name, "mohinterpret") 13072 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 13073 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 13074 } else if (!strcasecmp(v->name, "mohsuggest")) { 13075 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 13076 } else if (!strcasecmp(v->name, "stripmsd")) { 13077 confp->chan.stripmsd = atoi(v->value); 13078 } else if (!strcasecmp(v->name, "jitterbuffers")) { 13079 numbufs = atoi(v->value); 13080 } else if (!strcasecmp(v->name, "group")) { 13081 confp->chan.group = ast_get_group(v->value); 13082 } else if (!strcasecmp(v->name, "callgroup")) { 13083 confp->chan.callgroup = ast_get_group(v->value); 13084 } else if (!strcasecmp(v->name, "pickupgroup")) { 13085 confp->chan.pickupgroup = ast_get_group(v->value); 13086 } else if (!strcasecmp(v->name, "immediate")) { 13087 confp->chan.immediate = ast_true(v->value); 13088 } else if (!strcasecmp(v->name, "transfertobusy")) { 13089 confp->chan.transfertobusy = ast_true(v->value); 13090 } else if (!strcasecmp(v->name, "rxgain")) { 13091 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 13092 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 13093 } 13094 } else if (!strcasecmp(v->name, "txgain")) { 13095 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 13096 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 13097 } 13098 } else if (!strcasecmp(v->name, "tonezone")) { 13099 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 13100 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 13101 } 13102 } else if (!strcasecmp(v->name, "callerid")) { 13103 if (!strcasecmp(v->value, "asreceived")) { 13104 confp->chan.cid_num[0] = '\0'; 13105 confp->chan.cid_name[0] = '\0'; 13106 } else { 13107 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 13108 } 13109 } else if (!strcasecmp(v->name, "fullname")) { 13110 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 13111 } else if (!strcasecmp(v->name, "cid_number")) { 13112 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 13113 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 13114 confp->chan.dahditrcallerid = ast_true(v->value); 13115 if (strstr(v->name, "zap")) { 13116 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 13117 } 13118 } else if (!strcasecmp(v->name, "restrictcid")) { 13119 confp->chan.restrictcid = ast_true(v->value); 13120 } else if (!strcasecmp(v->name, "usecallingpres")) { 13121 confp->chan.use_callingpres = ast_true(v->value); 13122 } else if (!strcasecmp(v->name, "accountcode")) { 13123 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 13124 } else if (!strcasecmp(v->name, "amaflags")) { 13125 y = ast_cdr_amaflags2int(v->value); 13126 if (y < 0) 13127 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 13128 else 13129 confp->chan.amaflags = y; 13130 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 13131 confp->chan.polarityonanswerdelay = atoi(v->value); 13132 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 13133 confp->chan.answeronpolarityswitch = ast_true(v->value); 13134 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 13135 confp->chan.hanguponpolarityswitch = ast_true(v->value); 13136 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 13137 confp->chan.sendcalleridafter = atoi(v->value); 13138 } else if (reload != 1) { 13139 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 13140 confp->chan.outsigmod = -1; 13141 if (!strcasecmp(v->value, "em")) { 13142 confp->chan.sig = SIG_EM; 13143 } else if (!strcasecmp(v->value, "em_e1")) { 13144 confp->chan.sig = SIG_EM_E1; 13145 } else if (!strcasecmp(v->value, "em_w")) { 13146 confp->chan.sig = SIG_EMWINK; 13147 confp->chan.radio = 0; 13148 } else if (!strcasecmp(v->value, "fxs_ls")) { 13149 confp->chan.sig = SIG_FXSLS; 13150 confp->chan.radio = 0; 13151 } else if (!strcasecmp(v->value, "fxs_gs")) { 13152 confp->chan.sig = SIG_FXSGS; 13153 confp->chan.radio = 0; 13154 } else if (!strcasecmp(v->value, "fxs_ks")) { 13155 confp->chan.sig = SIG_FXSKS; 13156 confp->chan.radio = 0; 13157 } else if (!strcasecmp(v->value, "fxo_ls")) { 13158 confp->chan.sig = SIG_FXOLS; 13159 confp->chan.radio = 0; 13160 } else if (!strcasecmp(v->value, "fxo_gs")) { 13161 confp->chan.sig = SIG_FXOGS; 13162 confp->chan.radio = 0; 13163 } else if (!strcasecmp(v->value, "fxo_ks")) { 13164 confp->chan.sig = SIG_FXOKS; 13165 confp->chan.radio = 0; 13166 } else if (!strcasecmp(v->value, "fxs_rx")) { 13167 confp->chan.sig = SIG_FXSKS; 13168 confp->chan.radio = 1; 13169 } else if (!strcasecmp(v->value, "fxo_rx")) { 13170 confp->chan.sig = SIG_FXOLS; 13171 confp->chan.radio = 1; 13172 } else if (!strcasecmp(v->value, "fxs_tx")) { 13173 confp->chan.sig = SIG_FXSLS; 13174 confp->chan.radio = 1; 13175 } else if (!strcasecmp(v->value, "fxo_tx")) { 13176 confp->chan.sig = SIG_FXOGS; 13177 confp->chan.radio = 1; 13178 } else if (!strcasecmp(v->value, "em_rx")) { 13179 confp->chan.sig = SIG_EM; 13180 confp->chan.radio = 1; 13181 } else if (!strcasecmp(v->value, "em_tx")) { 13182 confp->chan.sig = SIG_EM; 13183 confp->chan.radio = 1; 13184 } else if (!strcasecmp(v->value, "em_rxtx")) { 13185 confp->chan.sig = SIG_EM; 13186 confp->chan.radio = 2; 13187 } else if (!strcasecmp(v->value, "em_txrx")) { 13188 confp->chan.sig = SIG_EM; 13189 confp->chan.radio = 2; 13190 } else if (!strcasecmp(v->value, "sf")) { 13191 confp->chan.sig = SIG_SF; 13192 confp->chan.radio = 0; 13193 } else if (!strcasecmp(v->value, "sf_w")) { 13194 confp->chan.sig = SIG_SFWINK; 13195 confp->chan.radio = 0; 13196 } else if (!strcasecmp(v->value, "sf_featd")) { 13197 confp->chan.sig = SIG_FEATD; 13198 confp->chan.radio = 0; 13199 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13200 confp->chan.sig = SIG_FEATDMF; 13201 confp->chan.radio = 0; 13202 } else if (!strcasecmp(v->value, "sf_featb")) { 13203 confp->chan.sig = SIG_SF_FEATB; 13204 confp->chan.radio = 0; 13205 } else if (!strcasecmp(v->value, "sf")) { 13206 confp->chan.sig = SIG_SF; 13207 confp->chan.radio = 0; 13208 } else if (!strcasecmp(v->value, "sf_rx")) { 13209 confp->chan.sig = SIG_SF; 13210 confp->chan.radio = 1; 13211 } else if (!strcasecmp(v->value, "sf_tx")) { 13212 confp->chan.sig = SIG_SF; 13213 confp->chan.radio = 1; 13214 } else if (!strcasecmp(v->value, "sf_rxtx")) { 13215 confp->chan.sig = SIG_SF; 13216 confp->chan.radio = 2; 13217 } else if (!strcasecmp(v->value, "sf_txrx")) { 13218 confp->chan.sig = SIG_SF; 13219 confp->chan.radio = 2; 13220 } else if (!strcasecmp(v->value, "featd")) { 13221 confp->chan.sig = SIG_FEATD; 13222 confp->chan.radio = 0; 13223 } else if (!strcasecmp(v->value, "featdmf")) { 13224 confp->chan.sig = SIG_FEATDMF; 13225 confp->chan.radio = 0; 13226 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13227 confp->chan.sig = SIG_FEATDMF_TA; 13228 confp->chan.radio = 0; 13229 } else if (!strcasecmp(v->value, "e911")) { 13230 confp->chan.sig = SIG_E911; 13231 confp->chan.radio = 0; 13232 } else if (!strcasecmp(v->value, "fgccama")) { 13233 confp->chan.sig = SIG_FGC_CAMA; 13234 confp->chan.radio = 0; 13235 } else if (!strcasecmp(v->value, "fgccamamf")) { 13236 confp->chan.sig = SIG_FGC_CAMAMF; 13237 confp->chan.radio = 0; 13238 } else if (!strcasecmp(v->value, "featb")) { 13239 confp->chan.sig = SIG_FEATB; 13240 confp->chan.radio = 0; 13241 #ifdef HAVE_OPENR2 13242 } else if (!strcasecmp(v->value, "mfcr2")) { 13243 confp->chan.sig = SIG_MFCR2; 13244 #endif 13245 #ifdef HAVE_PRI 13246 } else if (!strcasecmp(v->value, "pri_net")) { 13247 confp->chan.radio = 0; 13248 confp->chan.sig = SIG_PRI; 13249 confp->pri.nodetype = PRI_NETWORK; 13250 } else if (!strcasecmp(v->value, "pri_cpe")) { 13251 confp->chan.sig = SIG_PRI; 13252 confp->chan.radio = 0; 13253 confp->pri.nodetype = PRI_CPE; 13254 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 13255 confp->chan.sig = SIG_GR303FXOKS; 13256 confp->chan.radio = 0; 13257 confp->pri.nodetype = PRI_NETWORK; 13258 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 13259 confp->chan.sig = SIG_GR303FXSKS; 13260 confp->chan.radio = 0; 13261 confp->pri.nodetype = PRI_CPE; 13262 #endif 13263 } else { 13264 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13265 } 13266 } else if (!strcasecmp(v->name, "outsignalling")) { 13267 if (!strcasecmp(v->value, "em")) { 13268 confp->chan.outsigmod = SIG_EM; 13269 } else if (!strcasecmp(v->value, "em_e1")) { 13270 confp->chan.outsigmod = SIG_EM_E1; 13271 } else if (!strcasecmp(v->value, "em_w")) { 13272 confp->chan.outsigmod = SIG_EMWINK; 13273 } else if (!strcasecmp(v->value, "sf")) { 13274 confp->chan.outsigmod = SIG_SF; 13275 } else if (!strcasecmp(v->value, "sf_w")) { 13276 confp->chan.outsigmod = SIG_SFWINK; 13277 } else if (!strcasecmp(v->value, "sf_featd")) { 13278 confp->chan.outsigmod = SIG_FEATD; 13279 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13280 confp->chan.outsigmod = SIG_FEATDMF; 13281 } else if (!strcasecmp(v->value, "sf_featb")) { 13282 confp->chan.outsigmod = SIG_SF_FEATB; 13283 } else if (!strcasecmp(v->value, "sf")) { 13284 confp->chan.outsigmod = SIG_SF; 13285 } else if (!strcasecmp(v->value, "featd")) { 13286 confp->chan.outsigmod = SIG_FEATD; 13287 } else if (!strcasecmp(v->value, "featdmf")) { 13288 confp->chan.outsigmod = SIG_FEATDMF; 13289 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13290 confp->chan.outsigmod = SIG_FEATDMF_TA; 13291 } else if (!strcasecmp(v->value, "e911")) { 13292 confp->chan.outsigmod = SIG_E911; 13293 } else if (!strcasecmp(v->value, "fgccama")) { 13294 confp->chan.outsigmod = SIG_FGC_CAMA; 13295 } else if (!strcasecmp(v->value, "fgccamamf")) { 13296 confp->chan.outsigmod = SIG_FGC_CAMAMF; 13297 } else if (!strcasecmp(v->value, "featb")) { 13298 confp->chan.outsigmod = SIG_FEATB; 13299 } else { 13300 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13301 } 13302 #ifdef HAVE_PRI 13303 } else if (!strcasecmp(v->name, "pridialplan")) { 13304 if (!strcasecmp(v->value, "national")) { 13305 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 13306 } else if (!strcasecmp(v->value, "unknown")) { 13307 confp->pri.dialplan = PRI_UNKNOWN + 1; 13308 } else if (!strcasecmp(v->value, "private")) { 13309 confp->pri.dialplan = PRI_PRIVATE + 1; 13310 } else if (!strcasecmp(v->value, "international")) { 13311 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 13312 } else if (!strcasecmp(v->value, "local")) { 13313 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 13314 } else if (!strcasecmp(v->value, "dynamic")) { 13315 confp->pri.dialplan = -1; 13316 } else { 13317 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13318 } 13319 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 13320 if (!strcasecmp(v->value, "national")) { 13321 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 13322 } else if (!strcasecmp(v->value, "unknown")) { 13323 confp->pri.localdialplan = PRI_UNKNOWN + 1; 13324 } else if (!strcasecmp(v->value, "private")) { 13325 confp->pri.localdialplan = PRI_PRIVATE + 1; 13326 } else if (!strcasecmp(v->value, "international")) { 13327 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 13328 } else if (!strcasecmp(v->value, "local")) { 13329 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 13330 } else if (!strcasecmp(v->value, "dynamic")) { 13331 confp->pri.localdialplan = -1; 13332 } else { 13333 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13334 } 13335 } else if (!strcasecmp(v->name, "switchtype")) { 13336 if (!strcasecmp(v->value, "national")) 13337 confp->pri.switchtype = PRI_SWITCH_NI2; 13338 else if (!strcasecmp(v->value, "ni1")) 13339 confp->pri.switchtype = PRI_SWITCH_NI1; 13340 else if (!strcasecmp(v->value, "dms100")) 13341 confp->pri.switchtype = PRI_SWITCH_DMS100; 13342 else if (!strcasecmp(v->value, "4ess")) 13343 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 13344 else if (!strcasecmp(v->value, "5ess")) 13345 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 13346 else if (!strcasecmp(v->value, "euroisdn")) 13347 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 13348 else if (!strcasecmp(v->value, "qsig")) 13349 confp->pri.switchtype = PRI_SWITCH_QSIG; 13350 else { 13351 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 13352 return -1; 13353 } 13354 } else if (!strcasecmp(v->name, "nsf")) { 13355 if (!strcasecmp(v->value, "sdn")) 13356 confp->pri.nsf = PRI_NSF_SDN; 13357 else if (!strcasecmp(v->value, "megacom")) 13358 confp->pri.nsf = PRI_NSF_MEGACOM; 13359 else if (!strcasecmp(v->value, "tollfreemegacom")) 13360 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 13361 else if (!strcasecmp(v->value, "accunet")) 13362 confp->pri.nsf = PRI_NSF_ACCUNET; 13363 else if (!strcasecmp(v->value, "none")) 13364 confp->pri.nsf = PRI_NSF_NONE; 13365 else { 13366 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 13367 confp->pri.nsf = PRI_NSF_NONE; 13368 } 13369 } else if (!strcasecmp(v->name, "priindication")) { 13370 if (!strcasecmp(v->value, "outofband")) 13371 confp->chan.priindication_oob = 1; 13372 else if (!strcasecmp(v->value, "inband")) 13373 confp->chan.priindication_oob = 0; 13374 else 13375 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 13376 v->value, v->lineno); 13377 } else if (!strcasecmp(v->name, "priexclusive")) { 13378 confp->chan.priexclusive = ast_true(v->value); 13379 } else if (!strcasecmp(v->name, "internationalprefix")) { 13380 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 13381 } else if (!strcasecmp(v->name, "nationalprefix")) { 13382 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 13383 } else if (!strcasecmp(v->name, "localprefix")) { 13384 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 13385 } else if (!strcasecmp(v->name, "privateprefix")) { 13386 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 13387 } else if (!strcasecmp(v->name, "unknownprefix")) { 13388 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 13389 } else if (!strcasecmp(v->name, "resetinterval")) { 13390 if (!strcasecmp(v->value, "never")) 13391 confp->pri.resetinterval = -1; 13392 else if (atoi(v->value) >= 60) 13393 confp->pri.resetinterval = atoi(v->value); 13394 else 13395 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 13396 v->value, v->lineno); 13397 } else if (!strcasecmp(v->name, "minunused")) { 13398 confp->pri.minunused = atoi(v->value); 13399 } else if (!strcasecmp(v->name, "minidle")) { 13400 confp->pri.minidle = atoi(v->value); 13401 } else if (!strcasecmp(v->name, "idleext")) { 13402 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 13403 } else if (!strcasecmp(v->name, "idledial")) { 13404 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 13405 } else if (!strcasecmp(v->name, "overlapdial")) { 13406 if (ast_true(v->value)) { 13407 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13408 } else if (!strcasecmp(v->value, "incoming")) { 13409 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 13410 } else if (!strcasecmp(v->value, "outgoing")) { 13411 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 13412 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 13413 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13414 } else { 13415 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 13416 } 13417 #ifdef HAVE_PRI_INBANDDISCONNECT 13418 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 13419 confp->pri.inbanddisconnect = ast_true(v->value); 13420 #endif 13421 } else if (!strcasecmp(v->name, "pritimer")) { 13422 #ifdef PRI_GETSET_TIMERS 13423 char tmp[20]; 13424 char *timerc; 13425 char *c; 13426 int timer; 13427 int timeridx; 13428 13429 ast_copy_string(tmp, v->value, sizeof(tmp)); 13430 c = tmp; 13431 timerc = strsep(&c, ","); 13432 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 13433 timeridx = pri_timer2idx(timerc); 13434 timer = atoi(c); 13435 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 13436 ast_log(LOG_WARNING, 13437 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 13438 v->lineno); 13439 } else if (!timer) { 13440 ast_log(LOG_WARNING, 13441 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 13442 c, timerc, v->lineno); 13443 } else { 13444 pritimers[timeridx] = timer; 13445 } 13446 } else { 13447 ast_log(LOG_WARNING, 13448 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 13449 v->value, v->lineno); 13450 } 13451 #endif /* PRI_GETSET_TIMERS */ 13452 } else if (!strcasecmp(v->name, "facilityenable")) { 13453 confp->pri.facilityenable = ast_true(v->value); 13454 #endif /* HAVE_PRI */ 13455 #ifdef HAVE_OPENR2 13456 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 13457 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file)); 13458 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); 13459 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 13460 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir)); 13461 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 13462 mfcr2_cur_variant = openr2_proto_get_variant(v->value); 13463 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) { 13464 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno); 13465 } 13466 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 13467 mfcr2_cur_mfback_timeout = atoi(v->value); 13468 if (!mfcr2_cur_mfback_timeout) { 13469 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 13470 mfcr2_cur_mfback_timeout = -1; 13471 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) { 13472 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 13473 } 13474 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 13475 mfcr2_cur_metering_pulse_timeout = atoi(v->value); 13476 if (mfcr2_cur_metering_pulse_timeout > 500) { 13477 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n"); 13478 } 13479 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 13480 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) { 13481 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0; 13482 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) { 13483 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0; 13484 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) { 13485 mfcr2_cur_dtmf_time_on = atoi(v->value); 13486 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) { 13487 mfcr2_cur_dtmf_time_off = atoi(v->value); 13488 #endif 13489 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 13490 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0; 13491 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 13492 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0; 13493 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 13494 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0; 13495 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 13496 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0; 13497 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 13498 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0; 13499 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 13500 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0; 13501 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 13502 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0; 13503 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 13504 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0; 13505 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 13506 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0; 13507 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 13508 mfcr2_cur_max_ani = atoi(v->value); 13509 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) { 13510 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1; 13511 } 13512 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 13513 mfcr2_cur_max_dnis = atoi(v->value); 13514 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) { 13515 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1; 13516 } 13517 } else if (!strcasecmp(v->name, "mfcr2_category")) { 13518 mfcr2_cur_category = openr2_proto_get_category(v->value); 13519 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) { 13520 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 13521 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 13522 v->value, v->lineno); 13523 } 13524 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 13525 openr2_log_level_t tmplevel; 13526 char *toklevel = NULL; 13527 char *saveptr = NULL; 13528 char *logval = ast_strdupa(v->value); 13529 toklevel = strtok_r(logval, ",", &saveptr); 13530 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13531 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno); 13532 } else if (OR2_LOG_NOTHING == tmplevel) { 13533 mfcr2_cur_loglevel = tmplevel; 13534 } else { 13535 mfcr2_cur_loglevel |= tmplevel; 13536 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 13537 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13538 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno); 13539 continue; 13540 } 13541 mfcr2_cur_loglevel |= tmplevel; 13542 } 13543 } 13544 #endif /* HAVE_OPENR2 */ 13545 13546 } else if (!strcasecmp(v->name, "cadence")) { 13547 /* setup to scan our argument */ 13548 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 13549 int i; 13550 struct dahdi_ring_cadence new_cadence; 13551 int cid_location = -1; 13552 int firstcadencepos = 0; 13553 char original_args[80]; 13554 int cadence_is_ok = 1; 13555 13556 ast_copy_string(original_args, v->value, sizeof(original_args)); 13557 /* 16 cadences allowed (8 pairs) */ 13558 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]); 13559 13560 /* Cadence must be even (on/off) */ 13561 if (element_count % 2 == 1) { 13562 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 13563 cadence_is_ok = 0; 13564 } 13565 13566 /* Ring cadences cannot be negative */ 13567 for (i = 0; i < element_count; i++) { 13568 if (c[i] == 0) { 13569 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 13570 cadence_is_ok = 0; 13571 break; 13572 } else if (c[i] < 0) { 13573 if (i % 2 == 1) { 13574 /* Silence duration, negative possibly okay */ 13575 if (cid_location == -1) { 13576 cid_location = i; 13577 c[i] *= -1; 13578 } else { 13579 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 13580 cadence_is_ok = 0; 13581 break; 13582 } 13583 } else { 13584 if (firstcadencepos == 0) { 13585 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 13586 /* duration will be passed negative to the DAHDI driver */ 13587 } else { 13588 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 13589 cadence_is_ok = 0; 13590 break; 13591 } 13592 } 13593 } 13594 } 13595 13596 /* Substitute our scanned cadence */ 13597 for (i = 0; i < 16; i++) { 13598 new_cadence.ringcadence[i] = c[i]; 13599 } 13600 13601 if (cadence_is_ok) { 13602 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 13603 if (element_count < 2) { 13604 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 13605 } else { 13606 if (cid_location == -1) { 13607 /* user didn't say; default to first pause */ 13608 cid_location = 1; 13609 } else { 13610 /* convert element_index to cidrings value */ 13611 cid_location = (cid_location + 1) / 2; 13612 } 13613 /* ---we like their cadence; try to install it--- */ 13614 if (!user_has_defined_cadences++) 13615 /* this is the first user-defined cadence; clear the default user cadences */ 13616 num_cadence = 0; 13617 if ((num_cadence+1) >= NUM_CADENCE_MAX) 13618 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 13619 else { 13620 cadences[num_cadence] = new_cadence; 13621 cidrings[num_cadence++] = cid_location; 13622 if (option_verbose > 2) 13623 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 13624 } 13625 } 13626 } 13627 } else if (!strcasecmp(v->name, "ringtimeout")) { 13628 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 13629 } else if (!strcasecmp(v->name, "prewink")) { 13630 confp->timing.prewinktime = atoi(v->value); 13631 } else if (!strcasecmp(v->name, "preflash")) { 13632 confp->timing.preflashtime = atoi(v->value); 13633 } else if (!strcasecmp(v->name, "wink")) { 13634 confp->timing.winktime = atoi(v->value); 13635 } else if (!strcasecmp(v->name, "flash")) { 13636 confp->timing.flashtime = atoi(v->value); 13637 } else if (!strcasecmp(v->name, "start")) { 13638 confp->timing.starttime = atoi(v->value); 13639 } else if (!strcasecmp(v->name, "rxwink")) { 13640 confp->timing.rxwinktime = atoi(v->value); 13641 } else if (!strcasecmp(v->name, "rxflash")) { 13642 confp->timing.rxflashtime = atoi(v->value); 13643 } else if (!strcasecmp(v->name, "debounce")) { 13644 confp->timing.debouncetime = atoi(v->value); 13645 } else if (!strcasecmp(v->name, "toneduration")) { 13646 int toneduration; 13647 int ctlfd; 13648 int res; 13649 struct dahdi_dialparams dps; 13650 13651 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 13652 13653 if (ctlfd == -1) { 13654 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 13655 return -1; 13656 } 13657 13658 toneduration = atoi(v->value); 13659 if (toneduration > -1) { 13660 memset(&dps, 0, sizeof(dps)); 13661 13662 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 13663 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 13664 if (res < 0) { 13665 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 13666 return -1; 13667 } 13668 } 13669 close(ctlfd); 13670 } else if (!strcasecmp(v->name, "defaultcic")) { 13671 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 13672 } else if (!strcasecmp(v->name, "defaultozz")) { 13673 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 13674 } 13675 } else if (!skipchannels) 13676 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 13677 } 13678 if (dahdichan[0]) { 13679 /* The user has set 'dahdichan' */ 13680 /*< \todo pass proper line number instead of 0 */ 13681 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 13682 return -1; 13683 } 13684 } 13685 /*< \todo why check for the pseudo in the per-channel section. 13686 * Any actual use for manual setup of the pseudo channel? */ 13687 if (!found_pseudo && reload != 1) { 13688 /* use the default configuration for a channel, so 13689 that any settings from real configured channels 13690 don't "leak" into the pseudo channel config 13691 */ 13692 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13693 13694 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 13695 13696 if (tmp) { 13697 if (option_verbose > 2) 13698 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 13699 } else { 13700 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 13701 } 13702 } 13703 return 0; 13704 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 9925 of file chan_dahdi.c.
Referenced by __oh323_new().
09926 { 09927 switch (redirectingreason) { 09928 case 0: 09929 return "UNKNOWN"; 09930 case 1: 09931 return "BUSY"; 09932 case 2: 09933 return "NO_REPLY"; 09934 case 0xF: 09935 return "UNCONDITIONAL"; 09936 default: 09937 return "NOREDIRECT"; 09938 } 09939 }
static int reload | ( | void | ) | [static] |
Definition at line 14038 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
14039 { 14040 int res = 0; 14041 14042 res = setup_dahdi(1); 14043 if (res) { 14044 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 14045 return -1; 14046 } 14047 return 0; 14048 }
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 8342 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().
08343 { 08344 pthread_attr_t attr; 08345 pthread_attr_init(&attr); 08346 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08347 /* If we're supposed to be stopped -- stay stopped */ 08348 if (monitor_thread == AST_PTHREADT_STOP) 08349 return 0; 08350 ast_mutex_lock(&monlock); 08351 if (monitor_thread == pthread_self()) { 08352 ast_mutex_unlock(&monlock); 08353 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08354 return -1; 08355 } 08356 if (monitor_thread != AST_PTHREADT_NULL) { 08357 /* Wake up the thread */ 08358 pthread_kill(monitor_thread, SIGURG); 08359 } else { 08360 /* Start a new monitor */ 08361 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 08362 ast_mutex_unlock(&monlock); 08363 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08364 pthread_attr_destroy(&attr); 08365 return -1; 08366 } 08367 } 08368 ast_mutex_unlock(&monlock); 08369 pthread_attr_destroy(&attr); 08370 return 0; 08371 }
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 3293 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().
03294 { 03295 /* Data will be our digit string */ 03296 struct dahdi_pvt *p; 03297 char *digits = (char *) data; 03298 03299 if (ast_strlen_zero(digits)) { 03300 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 03301 return -1; 03302 } 03303 03304 p = (struct dahdi_pvt *)chan->tech_pvt; 03305 03306 if (!p) { 03307 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 03308 return -1; 03309 } 03310 03311 ast_mutex_lock(&p->lock); 03312 03313 if (!p->pri || !p->call) { 03314 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 03315 ast_mutex_unlock(&p->lock); 03316 return -1; 03317 } 03318 03319 if (!pri_grab(p, p->pri)) { 03320 pri_keypad_facility(p->pri->pri, p->call, digits); 03321 pri_rel(p->pri); 03322 } else { 03323 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 03324 ast_mutex_unlock(&p->lock); 03325 return -1; 03326 } 03327 03328 ast_mutex_unlock(&p->lock); 03329 03330 return 0; 03331 }
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 13706 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().
13707 { 13708 struct ast_config *cfg; 13709 struct ast_variable *v; 13710 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13711 int res; 13712 13713 #ifdef HAVE_PRI 13714 char *c; 13715 int spanno; 13716 int i, x; 13717 int logicalspan; 13718 int trunkgroup; 13719 int dchannels[NUM_DCHANS]; 13720 #endif 13721 13722 #ifdef HAVE_ZAPTEL 13723 int load_from_zapata_conf = 1; 13724 #else 13725 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 13726 #endif 13727 13728 if (load_from_zapata_conf) { 13729 if (!(cfg = ast_config_load("zapata.conf"))) { 13730 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 13731 return 0; 13732 } 13733 } else { 13734 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 13735 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 13736 return 0; 13737 } 13738 } 13739 13740 /* It's a little silly to lock it, but we mind as well just to be sure */ 13741 ast_mutex_lock(&iflock); 13742 #ifdef HAVE_PRI 13743 if (reload != 1) { 13744 /* Process trunkgroups first */ 13745 v = ast_variable_browse(cfg, "trunkgroups"); 13746 while (v) { 13747 if (!strcasecmp(v->name, "trunkgroup")) { 13748 trunkgroup = atoi(v->value); 13749 if (trunkgroup > 0) { 13750 if ((c = strchr(v->value, ','))) { 13751 i = 0; 13752 memset(dchannels, 0, sizeof(dchannels)); 13753 while (c && (i < NUM_DCHANS)) { 13754 dchannels[i] = atoi(c + 1); 13755 if (dchannels[i] < 0) { 13756 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); 13757 } else 13758 i++; 13759 c = strchr(c + 1, ','); 13760 } 13761 if (i) { 13762 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 13763 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); 13764 } else if (option_verbose > 1) 13765 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"); 13766 } else 13767 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13768 } else 13769 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13770 } else 13771 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 13772 } else if (!strcasecmp(v->name, "spanmap")) { 13773 spanno = atoi(v->value); 13774 if (spanno > 0) { 13775 if ((c = strchr(v->value, ','))) { 13776 trunkgroup = atoi(c + 1); 13777 if (trunkgroup > 0) { 13778 if ((c = strchr(c + 1, ','))) 13779 logicalspan = atoi(c + 1); 13780 else 13781 logicalspan = 0; 13782 if (logicalspan >= 0) { 13783 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 13784 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13785 } else if (option_verbose > 1) 13786 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13787 } else 13788 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); 13789 } else 13790 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 13791 } else 13792 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 13793 } else 13794 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 13795 } else { 13796 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 13797 } 13798 v = v->next; 13799 } 13800 } 13801 #endif 13802 13803 /* Copy the default jb config over global_jbconf */ 13804 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 13805 13806 v = ast_variable_browse(cfg, "channels"); 13807 res = process_dahdi(&conf, "", v, reload, 0); 13808 ast_mutex_unlock(&iflock); 13809 ast_config_destroy(cfg); 13810 if (res) 13811 return res; 13812 cfg = ast_config_load("users.conf"); 13813 if (cfg) { 13814 char *cat; 13815 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 13816 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 13817 if (!strcasecmp(cat, "general")) 13818 continue; 13819 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 13820 struct dahdi_chan_conf sect_conf; 13821 memcpy(§_conf, &conf, sizeof(sect_conf)); 13822 13823 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 13824 } 13825 } 13826 ast_config_destroy(cfg); 13827 } 13828 #ifdef HAVE_PRI 13829 if (reload != 1) { 13830 for (x = 0; x < NUM_SPANS; x++) { 13831 if (pris[x].pvts[0]) { 13832 if (start_pri(pris + x)) { 13833 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 13834 return -1; 13835 } else if (option_verbose > 1) 13836 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 13837 } 13838 } 13839 } 13840 #endif 13841 #ifdef HAVE_OPENR2 13842 if (reload != 1) { 13843 int x; 13844 for (x = 0; x < NUM_SPANS; x++) { 13845 if (r2links[x].protocol_context) { 13846 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) { 13847 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1); 13848 return -1; 13849 } else { 13850 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1); 13851 } 13852 } 13853 } 13854 } 13855 #endif 13856 /* And start the monitor for the first time */ 13857 restart_monitor(); 13858 return 0; 13859 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6750 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().
06751 { 06752 struct ast_channel *chan = data; 06753 struct dahdi_pvt *p = chan->tech_pvt; 06754 char exten[AST_MAX_EXTENSION] = ""; 06755 char exten2[AST_MAX_EXTENSION] = ""; 06756 unsigned char buf[256]; 06757 char dtmfcid[300]; 06758 char dtmfbuf[300]; 06759 struct callerid_state *cs = NULL; 06760 char *name = NULL, *number = NULL; 06761 int distMatches; 06762 int curRingData[3]; 06763 int receivedRingT; 06764 int counter1; 06765 int counter; 06766 int samples = 0; 06767 struct ast_smdi_md_message *smdi_msg = NULL; 06768 int flags = 0; 06769 int i; 06770 int timeout; 06771 int getforward = 0; 06772 char *s1, *s2; 06773 int len = 0; 06774 int res; 06775 int index; 06776 06777 ast_mutex_lock(&ss_thread_lock); 06778 ss_thread_count++; 06779 ast_mutex_unlock(&ss_thread_lock); 06780 /* in the bizarre case where the channel has become a zombie before we 06781 even get started here, abort safely 06782 */ 06783 if (!p) { 06784 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06785 ast_hangup(chan); 06786 goto quit; 06787 } 06788 if (option_verbose > 2) 06789 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 06790 index = dahdi_get_index(chan, p, 1); 06791 if (index < 0) { 06792 ast_log(LOG_WARNING, "Huh?\n"); 06793 ast_hangup(chan); 06794 goto quit; 06795 } 06796 if (p->dsp) 06797 ast_dsp_digitreset(p->dsp); 06798 switch (p->sig) { 06799 #ifdef HAVE_PRI 06800 case SIG_PRI: 06801 /* Now loop looking for an extension */ 06802 ast_copy_string(exten, p->exten, sizeof(exten)); 06803 len = strlen(exten); 06804 res = 0; 06805 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06806 if (len && !ast_ignore_pattern(chan->context, exten)) 06807 tone_zone_play_tone(p->subs[index].dfd, -1); 06808 else 06809 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06810 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06811 timeout = matchdigittimeout; 06812 else 06813 timeout = gendigittimeout; 06814 res = ast_waitfordigit(chan, timeout); 06815 if (res < 0) { 06816 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06817 ast_hangup(chan); 06818 goto quit; 06819 } else if (res) { 06820 exten[len++] = res; 06821 exten[len] = '\0'; 06822 } else 06823 break; 06824 } 06825 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06826 if (ast_strlen_zero(exten)) { 06827 if (option_verbose > 2) 06828 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 06829 exten[0] = 's'; 06830 exten[1] = '\0'; 06831 } 06832 tone_zone_play_tone(p->subs[index].dfd, -1); 06833 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06834 /* Start the real PBX */ 06835 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06836 if (p->dsp) ast_dsp_digitreset(p->dsp); 06837 dahdi_enable_ec(p); 06838 ast_setstate(chan, AST_STATE_RING); 06839 res = ast_pbx_run(chan); 06840 if (res) { 06841 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06842 } 06843 } else { 06844 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06845 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06846 ast_hangup(chan); 06847 p->exten[0] = '\0'; 06848 /* Since we send release complete here, we won't get one */ 06849 p->call = NULL; 06850 } 06851 goto quit; 06852 break; 06853 #endif 06854 case SIG_FEATD: 06855 case SIG_FEATDMF: 06856 case SIG_FEATDMF_TA: 06857 case SIG_E911: 06858 case SIG_FGC_CAMAMF: 06859 case SIG_FEATB: 06860 case SIG_EMWINK: 06861 case SIG_SF_FEATD: 06862 case SIG_SF_FEATDMF: 06863 case SIG_SF_FEATB: 06864 case SIG_SFWINK: 06865 if (dahdi_wink(p, index)) 06866 goto quit; 06867 /* Fall through */ 06868 case SIG_EM: 06869 case SIG_EM_E1: 06870 case SIG_SF: 06871 case SIG_FGC_CAMA: 06872 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06873 if (p->dsp) 06874 ast_dsp_digitreset(p->dsp); 06875 /* set digit mode appropriately */ 06876 if (p->dsp) { 06877 if (NEED_MFDETECT(p)) 06878 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06879 else 06880 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06881 } 06882 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06883 /* Wait for the first digit only if immediate=no */ 06884 if (!p->immediate) 06885 /* Wait for the first digit (up to 5 seconds). */ 06886 res = ast_waitfordigit(chan, 5000); 06887 else 06888 res = 0; 06889 if (res > 0) { 06890 /* save first char */ 06891 dtmfbuf[0] = res; 06892 switch (p->sig) { 06893 case SIG_FEATD: 06894 case SIG_SF_FEATD: 06895 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06896 if (res > 0) 06897 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06898 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06899 break; 06900 case SIG_FEATDMF_TA: 06901 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06902 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06903 if (dahdi_wink(p, index)) goto quit; 06904 dtmfbuf[0] = 0; 06905 /* Wait for the first digit (up to 5 seconds). */ 06906 res = ast_waitfordigit(chan, 5000); 06907 if (res <= 0) break; 06908 dtmfbuf[0] = res; 06909 /* fall through intentionally */ 06910 case SIG_FEATDMF: 06911 case SIG_E911: 06912 case SIG_FGC_CAMAMF: 06913 case SIG_SF_FEATDMF: 06914 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06915 /* if international caca, do it again to get real ANO */ 06916 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06917 { 06918 if (dahdi_wink(p, index)) goto quit; 06919 dtmfbuf[0] = 0; 06920 /* Wait for the first digit (up to 5 seconds). */ 06921 res = ast_waitfordigit(chan, 5000); 06922 if (res <= 0) break; 06923 dtmfbuf[0] = res; 06924 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06925 } 06926 if (res > 0) { 06927 /* if E911, take off hook */ 06928 if (p->sig == SIG_E911) 06929 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06930 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06931 } 06932 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06933 break; 06934 case SIG_FEATB: 06935 case SIG_SF_FEATB: 06936 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06937 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06938 break; 06939 case SIG_EMWINK: 06940 /* if we received a '*', we are actually receiving Feature Group D 06941 dial syntax, so use that mode; otherwise, fall through to normal 06942 mode 06943 */ 06944 if (res == '*') { 06945 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06946 if (res > 0) 06947 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06948 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06949 break; 06950 } 06951 default: 06952 /* If we got the first digit, get the rest */ 06953 len = 1; 06954 dtmfbuf[len] = '\0'; 06955 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06956 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06957 timeout = matchdigittimeout; 06958 } else { 06959 timeout = gendigittimeout; 06960 } 06961 res = ast_waitfordigit(chan, timeout); 06962 if (res < 0) { 06963 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06964 ast_hangup(chan); 06965 goto quit; 06966 } else if (res) { 06967 dtmfbuf[len++] = res; 06968 dtmfbuf[len] = '\0'; 06969 } else { 06970 break; 06971 } 06972 } 06973 break; 06974 } 06975 } 06976 if (res == -1) { 06977 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06978 ast_hangup(chan); 06979 goto quit; 06980 } else if (res < 0) { 06981 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 06982 ast_hangup(chan); 06983 goto quit; 06984 } 06985 06986 if (p->sig == SIG_FGC_CAMA) { 06987 char anibuf[100]; 06988 06989 if (ast_safe_sleep(chan,1000) == -1) { 06990 ast_hangup(chan); 06991 goto quit; 06992 } 06993 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06994 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06995 res = my_getsigstr(chan, anibuf, "#", 10000); 06996 if ((res > 0) && (strlen(anibuf) > 2)) { 06997 if (anibuf[strlen(anibuf) - 1] == '#') 06998 anibuf[strlen(anibuf) - 1] = 0; 06999 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07000 } 07001 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07002 } 07003 07004 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07005 if (ast_strlen_zero(exten)) 07006 ast_copy_string(exten, "s", sizeof(exten)); 07007 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07008 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07009 if (exten[0] == '*') { 07010 char *stringp=NULL; 07011 ast_copy_string(exten2, exten, sizeof(exten2)); 07012 /* Parse out extension and callerid */ 07013 stringp=exten2 +1; 07014 s1 = strsep(&stringp, "*"); 07015 s2 = strsep(&stringp, "*"); 07016 if (s2) { 07017 if (!ast_strlen_zero(p->cid_num)) 07018 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07019 else 07020 ast_set_callerid(chan, s1, NULL, s1); 07021 ast_copy_string(exten, s2, sizeof(exten)); 07022 } else 07023 ast_copy_string(exten, s1, sizeof(exten)); 07024 } else if (p->sig == SIG_FEATD) 07025 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07026 } 07027 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07028 if (exten[0] == '*') { 07029 char *stringp=NULL; 07030 ast_copy_string(exten2, exten, sizeof(exten2)); 07031 /* Parse out extension and callerid */ 07032 stringp=exten2 +1; 07033 s1 = strsep(&stringp, "#"); 07034 s2 = strsep(&stringp, "#"); 07035 if (s2) { 07036 if (!ast_strlen_zero(p->cid_num)) 07037 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07038 else 07039 if (*(s1 + 2)) 07040 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07041 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07042 } else 07043 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07044 } else 07045 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07046 } 07047 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07048 if (exten[0] == '*') { 07049 char *stringp=NULL; 07050 ast_copy_string(exten2, exten, sizeof(exten2)); 07051 /* Parse out extension and callerid */ 07052 stringp=exten2 +1; 07053 s1 = strsep(&stringp, "#"); 07054 s2 = strsep(&stringp, "#"); 07055 if (s2 && (*(s2 + 1) == '0')) { 07056 if (*(s2 + 2)) 07057 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07058 } 07059 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07060 else ast_copy_string(exten, "911", sizeof(exten)); 07061 } else 07062 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 07063 } 07064 if (p->sig == SIG_FEATB) { 07065 if (exten[0] == '*') { 07066 char *stringp=NULL; 07067 ast_copy_string(exten2, exten, sizeof(exten2)); 07068 /* Parse out extension and callerid */ 07069 stringp=exten2 +1; 07070 s1 = strsep(&stringp, "#"); 07071 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 07072 } else 07073 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 07074 } 07075 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07076 dahdi_wink(p, index); 07077 /* some switches require a minimum guard time between 07078 the last FGD wink and something that answers 07079 immediately. This ensures it */ 07080 if (ast_safe_sleep(chan,100)) goto quit; 07081 } 07082 dahdi_enable_ec(p); 07083 if (NEED_MFDETECT(p)) { 07084 if (p->dsp) { 07085 if (!p->hardwaredtmf) 07086 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07087 else { 07088 ast_dsp_free(p->dsp); 07089 p->dsp = NULL; 07090 } 07091 } 07092 } 07093 07094 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 07095 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07096 if (p->dsp) ast_dsp_digitreset(p->dsp); 07097 res = ast_pbx_run(chan); 07098 if (res) { 07099 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07100 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07101 } 07102 goto quit; 07103 } else { 07104 if (option_verbose > 2) 07105 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 07106 sleep(2); 07107 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 07108 if (res < 0) 07109 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 07110 else 07111 sleep(1); 07112 res = ast_streamfile(chan, "ss-noservice", chan->language); 07113 if (res >= 0) 07114 ast_waitstream(chan, ""); 07115 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07116 ast_hangup(chan); 07117 goto quit; 07118 } 07119 break; 07120 case SIG_FXOLS: 07121 case SIG_FXOGS: 07122 case SIG_FXOKS: 07123 /* Read the first digit */ 07124 timeout = firstdigittimeout; 07125 /* If starting a threeway call, never timeout on the first digit so someone 07126 can use flash-hook as a "hold" feature */ 07127 if (p->subs[SUB_THREEWAY].owner) 07128 timeout = 999999; 07129 while (len < AST_MAX_EXTENSION-1) { 07130 /* Read digit unless it's supposed to be immediate, in which case the 07131 only answer is 's' */ 07132 if (p->immediate) 07133 res = 's'; 07134 else 07135 res = ast_waitfordigit(chan, timeout); 07136 timeout = 0; 07137 if (res < 0) { 07138 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07139 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07140 ast_hangup(chan); 07141 goto quit; 07142 } else if (res) { 07143 exten[len++]=res; 07144 exten[len] = '\0'; 07145 } 07146 if (!ast_ignore_pattern(chan->context, exten)) 07147 tone_zone_play_tone(p->subs[index].dfd, -1); 07148 else 07149 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07150 if (!strcmp(exten,ast_pickup_ext())) { 07151 /* Scan all channels and see if there are any 07152 * ringing channels that have call groups 07153 * that equal this channels pickup group 07154 */ 07155 if (index == SUB_REAL) { 07156 /* Switch us from Third call to Call Wait */ 07157 if (p->subs[SUB_THREEWAY].owner) { 07158 /* If you make a threeway call and the *8# a call, it should actually 07159 look like a callwait */ 07160 alloc_sub(p, SUB_CALLWAIT); 07161 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07162 unalloc_sub(p, SUB_THREEWAY); 07163 } 07164 dahdi_enable_ec(p); 07165 if (ast_pickup_call(chan)) { 07166 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 07167 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07168 dahdi_wait_event(p->subs[index].dfd); 07169 } 07170 ast_hangup(chan); 07171 goto quit; 07172 } else { 07173 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07174 ast_hangup(chan); 07175 goto quit; 07176 } 07177 07178 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 07179 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07180 if (getforward) { 07181 /* Record this as the forwarding extension */ 07182 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 07183 if (option_verbose > 2) 07184 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 07185 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07186 if (res) 07187 break; 07188 usleep(500000); 07189 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07190 sleep(1); 07191 memset(exten, 0, sizeof(exten)); 07192 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07193 len = 0; 07194 getforward = 0; 07195 } else { 07196 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07197 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07198 if (!ast_strlen_zero(p->cid_num)) { 07199 if (!p->hidecallerid) 07200 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07201 else 07202 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07203 } 07204 if (!ast_strlen_zero(p->cid_name)) { 07205 if (!p->hidecallerid) 07206 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07207 } 07208 ast_setstate(chan, AST_STATE_RING); 07209 dahdi_enable_ec(p); 07210 res = ast_pbx_run(chan); 07211 if (res) { 07212 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07213 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07214 } 07215 goto quit; 07216 } 07217 } else { 07218 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07219 so just set the timeout to matchdigittimeout and wait some more */ 07220 timeout = matchdigittimeout; 07221 } 07222 } else if (res == 0) { 07223 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 07224 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07225 dahdi_wait_event(p->subs[index].dfd); 07226 ast_hangup(chan); 07227 goto quit; 07228 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07229 if (option_verbose > 2) 07230 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 07231 /* Disable call waiting if enabled */ 07232 p->callwaiting = 0; 07233 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07234 if (res) { 07235 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07236 chan->name, strerror(errno)); 07237 } 07238 len = 0; 07239 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 07240 memset(exten, 0, sizeof(exten)); 07241 timeout = firstdigittimeout; 07242 07243 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07244 if (option_verbose > 2) 07245 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 07246 /* Disable Caller*ID if enabled */ 07247 p->hidecallerid = 1; 07248 if (chan->cid.cid_num) 07249 free(chan->cid.cid_num); 07250 chan->cid.cid_num = NULL; 07251 if (chan->cid.cid_name) 07252 free(chan->cid.cid_name); 07253 chan->cid.cid_name = NULL; 07254 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07255 if (res) { 07256 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07257 chan->name, strerror(errno)); 07258 } 07259 len = 0; 07260 memset(exten, 0, sizeof(exten)); 07261 timeout = firstdigittimeout; 07262 } else if (p->callreturn && !strcmp(exten, "*69")) { 07263 res = 0; 07264 if (!ast_strlen_zero(p->lastcid_num)) { 07265 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07266 } 07267 if (!res) 07268 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07269 break; 07270 } else if (!strcmp(exten, "*78")) { 07271 /* Do not disturb */ 07272 if (option_verbose > 2) 07273 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 07274 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07275 "Channel: %s/%d\r\n" 07276 "Status: enabled\r\n", dahdi_chan_name, p->channel); 07277 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07278 p->dnd = 1; 07279 getforward = 0; 07280 memset(exten, 0, sizeof(exten)); 07281 len = 0; 07282 } else if (!strcmp(exten, "*79")) { 07283 /* Do not disturb */ 07284 if (option_verbose > 2) 07285 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 07286 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07287 "Channel: %s/%d\r\n" 07288 "Status: disabled\r\n", dahdi_chan_name, p->channel); 07289 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07290 p->dnd = 0; 07291 getforward = 0; 07292 memset(exten, 0, sizeof(exten)); 07293 len = 0; 07294 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07295 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07296 getforward = 1; 07297 memset(exten, 0, sizeof(exten)); 07298 len = 0; 07299 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07300 if (option_verbose > 2) 07301 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 07302 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07303 memset(p->call_forward, 0, sizeof(p->call_forward)); 07304 getforward = 0; 07305 memset(exten, 0, sizeof(exten)); 07306 len = 0; 07307 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07308 p->subs[SUB_THREEWAY].owner && 07309 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07310 /* This is a three way call, the main call being a real channel, 07311 and we're parking the first call. */ 07312 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07313 if (option_verbose > 2) 07314 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 07315 break; 07316 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07317 if (option_verbose > 2) 07318 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 07319 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07320 if (!res) { 07321 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07322 memset(exten, 0, sizeof(exten)); 07323 len = 0; 07324 } 07325 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07326 if (option_verbose > 2) 07327 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 07328 /* Enable Caller*ID if enabled */ 07329 p->hidecallerid = 0; 07330 if (chan->cid.cid_num) 07331 free(chan->cid.cid_num); 07332 chan->cid.cid_num = NULL; 07333 if (chan->cid.cid_name) 07334 free(chan->cid.cid_name); 07335 chan->cid.cid_name = NULL; 07336 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07337 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07338 if (res) { 07339 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07340 chan->name, strerror(errno)); 07341 } 07342 len = 0; 07343 memset(exten, 0, sizeof(exten)); 07344 timeout = firstdigittimeout; 07345 } else if (!strcmp(exten, "*0")) { 07346 struct ast_channel *nbridge = 07347 p->subs[SUB_THREEWAY].owner; 07348 struct dahdi_pvt *pbridge = NULL; 07349 /* set up the private struct of the bridged one, if any */ 07350 if (nbridge && ast_bridged_channel(nbridge)) 07351 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07352 if (nbridge && pbridge && 07353 (nbridge->tech == chan_tech) && 07354 (ast_bridged_channel(nbridge)->tech == chan_tech) && 07355 ISTRUNK(pbridge)) { 07356 int func = DAHDI_FLASH; 07357 /* Clear out the dial buffer */ 07358 p->dop.dialstr[0] = '\0'; 07359 /* flash hookswitch */ 07360 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07361 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07362 nbridge->name, strerror(errno)); 07363 } 07364 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07365 unalloc_sub(p, SUB_THREEWAY); 07366 p->owner = p->subs[SUB_REAL].owner; 07367 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07368 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07369 ast_hangup(chan); 07370 goto quit; 07371 } else { 07372 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07373 dahdi_wait_event(p->subs[index].dfd); 07374 tone_zone_play_tone(p->subs[index].dfd, -1); 07375 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07376 unalloc_sub(p, SUB_THREEWAY); 07377 p->owner = p->subs[SUB_REAL].owner; 07378 ast_hangup(chan); 07379 goto quit; 07380 } 07381 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07382 ((exten[0] != '*') || (strlen(exten) > 2))) { 07383 if (option_debug) 07384 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); 07385 break; 07386 } 07387 if (!timeout) 07388 timeout = gendigittimeout; 07389 if (len && !ast_ignore_pattern(chan->context, exten)) 07390 tone_zone_play_tone(p->subs[index].dfd, -1); 07391 } 07392 break; 07393 case SIG_FXSLS: 07394 case SIG_FXSGS: 07395 case SIG_FXSKS: 07396 #ifdef HAVE_PRI 07397 if (p->pri) { 07398 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07399 struct ast_frame *f; 07400 int res; 07401 time_t start; 07402 07403 time(&start); 07404 ast_setstate(chan, AST_STATE_RING); 07405 while (time(NULL) < start + 3) { 07406 res = ast_waitfor(chan, 1000); 07407 if (res) { 07408 f = ast_read(chan); 07409 if (!f) { 07410 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07411 ast_hangup(chan); 07412 goto quit; 07413 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07414 res = 1; 07415 } else 07416 res = 0; 07417 ast_frfree(f); 07418 if (res) { 07419 ast_log(LOG_DEBUG, "Got ring!\n"); 07420 res = 0; 07421 break; 07422 } 07423 } 07424 } 07425 } 07426 #endif 07427 /* check for SMDI messages */ 07428 if (p->use_smdi && p->smdi_iface) { 07429 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07430 07431 if (smdi_msg != NULL) { 07432 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07433 07434 if (smdi_msg->type == 'B') 07435 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07436 else if (smdi_msg->type == 'N') 07437 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07438 07439 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 07440 } else { 07441 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07442 } 07443 } 07444 07445 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07446 number = smdi_msg->calling_st; 07447 07448 /* If we want caller id, we're in a prering state due to a polarity reversal 07449 * and we're set to use a polarity reversal to trigger the start of caller id, 07450 * grab the caller id and wait for ringing to start... */ 07451 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 07452 /* If set to use DTMF CID signalling, listen for DTMF */ 07453 if (p->cid_signalling == CID_SIG_DTMF) { 07454 int i = 0; 07455 cs = NULL; 07456 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 07457 "channel %s\n", chan->name); 07458 dahdi_setlinear(p->subs[index].dfd, 0); 07459 res = 2000; 07460 for (;;) { 07461 struct ast_frame *f; 07462 res = ast_waitfor(chan, res); 07463 if (res <= 0) { 07464 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07465 "Exiting simple switch\n"); 07466 ast_hangup(chan); 07467 goto quit; 07468 } 07469 f = ast_read(chan); 07470 if (!f) 07471 break; 07472 if (f->frametype == AST_FRAME_DTMF) { 07473 dtmfbuf[i++] = f->subclass; 07474 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07475 res = 2000; 07476 } 07477 ast_frfree(f); 07478 if (chan->_state == AST_STATE_RING || 07479 chan->_state == AST_STATE_RINGING) 07480 break; /* Got ring */ 07481 } 07482 dtmfbuf[i] = '\0'; 07483 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07484 /* Got cid and ring. */ 07485 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 07486 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07487 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07488 dtmfcid, flags); 07489 /* If first byte is NULL, we have no cid */ 07490 if (!ast_strlen_zero(dtmfcid)) 07491 number = dtmfcid; 07492 else 07493 number = NULL; 07494 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07495 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07496 cs = callerid_new(p->cid_signalling); 07497 if (cs) { 07498 samples = 0; 07499 #if 1 07500 bump_gains(p); 07501 #endif 07502 /* Take out of linear mode for Caller*ID processing */ 07503 dahdi_setlinear(p->subs[index].dfd, 0); 07504 07505 /* First we wait and listen for the Caller*ID */ 07506 for (;;) { 07507 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07508 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07509 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07510 callerid_free(cs); 07511 ast_hangup(chan); 07512 goto quit; 07513 } 07514 if (i & DAHDI_IOMUX_SIGEVENT) { 07515 res = dahdi_get_event(p->subs[index].dfd); 07516 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07517 07518 if (p->cid_signalling == CID_SIG_V23_JP) { 07519 #ifdef DAHDI_EVENT_RINGBEGIN 07520 if (res == DAHDI_EVENT_RINGBEGIN) { 07521 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07522 usleep(1); 07523 } 07524 #endif 07525 } else { 07526 res = 0; 07527 break; 07528 } 07529 } else if (i & DAHDI_IOMUX_READ) { 07530 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07531 if (res < 0) { 07532 if (errno != ELAST) { 07533 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07534 callerid_free(cs); 07535 ast_hangup(chan); 07536 goto quit; 07537 } 07538 break; 07539 } 07540 samples += res; 07541 07542 if (p->cid_signalling == CID_SIG_V23_JP) { 07543 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07544 } else { 07545 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07546 } 07547 07548 if (res < 0) { 07549 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07550 break; 07551 } else if (res) 07552 break; 07553 else if (samples > (8000 * 10)) 07554 break; 07555 } 07556 } 07557 if (res == 1) { 07558 callerid_get(cs, &name, &number, &flags); 07559 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07560 } 07561 07562 if (p->cid_signalling == CID_SIG_V23_JP) { 07563 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07564 usleep(1); 07565 res = 4000; 07566 } else { 07567 07568 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07569 res = 2000; 07570 } 07571 07572 for (;;) { 07573 struct ast_frame *f; 07574 res = ast_waitfor(chan, res); 07575 if (res <= 0) { 07576 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07577 "Exiting simple switch\n"); 07578 ast_hangup(chan); 07579 goto quit; 07580 } 07581 if (!(f = ast_read(chan))) { 07582 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07583 ast_hangup(chan); 07584 goto quit; 07585 } 07586 ast_frfree(f); 07587 if (chan->_state == AST_STATE_RING || 07588 chan->_state == AST_STATE_RINGING) 07589 break; /* Got ring */ 07590 } 07591 07592 /* We must have a ring by now, so, if configured, lets try to listen for 07593 * distinctive ringing */ 07594 if (p->usedistinctiveringdetection) { 07595 len = 0; 07596 distMatches = 0; 07597 /* Clear the current ring data array so we dont have old data in it. */ 07598 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07599 curRingData[receivedRingT] = 0; 07600 receivedRingT = 0; 07601 counter = 0; 07602 counter1 = 0; 07603 /* Check to see if context is what it should be, if not set to be. */ 07604 if (strcmp(p->context,p->defcontext) != 0) { 07605 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07606 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07607 } 07608 07609 for (;;) { 07610 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07611 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07612 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07613 callerid_free(cs); 07614 ast_hangup(chan); 07615 goto quit; 07616 } 07617 if (i & DAHDI_IOMUX_SIGEVENT) { 07618 res = dahdi_get_event(p->subs[index].dfd); 07619 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07620 res = 0; 07621 /* Let us detect distinctive ring */ 07622 07623 curRingData[receivedRingT] = p->ringt; 07624 07625 if (p->ringt < p->ringt_base/2) 07626 break; 07627 /* Increment the ringT counter so we can match it against 07628 values in chan_dahdi.conf for distinctive ring */ 07629 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07630 break; 07631 } else if (i & DAHDI_IOMUX_READ) { 07632 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07633 if (res < 0) { 07634 if (errno != ELAST) { 07635 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07636 callerid_free(cs); 07637 ast_hangup(chan); 07638 goto quit; 07639 } 07640 break; 07641 } 07642 if (p->ringt) 07643 p->ringt--; 07644 if (p->ringt == 1) { 07645 res = -1; 07646 break; 07647 } 07648 } 07649 } 07650 if (option_verbose > 2) 07651 /* this only shows up if you have n of the dring patterns filled in */ 07652 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07653 07654 for (counter = 0; counter < 3; counter++) { 07655 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07656 channel */ 07657 distMatches = 0; 07658 for (counter1 = 0; counter1 < 3; counter1++) { 07659 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07660 (p->drings.ringnum[counter].ring[counter1]-10)) { 07661 distMatches++; 07662 } 07663 } 07664 if (distMatches == 3) { 07665 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07666 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07667 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07668 if (option_verbose > 2) 07669 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07670 break; 07671 } 07672 } 07673 } 07674 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07675 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07676 #if 1 07677 restore_gains(p); 07678 #endif 07679 } else 07680 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07681 } else { 07682 ast_log(LOG_WARNING, "Channel %s in prering " 07683 "state, but I have nothing to do. " 07684 "Terminating simple switch, should be " 07685 "restarted by the actual ring.\n", 07686 chan->name); 07687 ast_hangup(chan); 07688 goto quit; 07689 } 07690 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07691 /* FSK Bell202 callerID */ 07692 cs = callerid_new(p->cid_signalling); 07693 if (cs) { 07694 #if 1 07695 bump_gains(p); 07696 #endif 07697 samples = 0; 07698 len = 0; 07699 distMatches = 0; 07700 /* Clear the current ring data array so we dont have old data in it. */ 07701 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07702 curRingData[receivedRingT] = 0; 07703 receivedRingT = 0; 07704 counter = 0; 07705 counter1 = 0; 07706 /* Check to see if context is what it should be, if not set to be. */ 07707 if (strcmp(p->context,p->defcontext) != 0) { 07708 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07709 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07710 } 07711 07712 /* Take out of linear mode for Caller*ID processing */ 07713 dahdi_setlinear(p->subs[index].dfd, 0); 07714 for (;;) { 07715 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07716 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07717 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07718 callerid_free(cs); 07719 ast_hangup(chan); 07720 goto quit; 07721 } 07722 if (i & DAHDI_IOMUX_SIGEVENT) { 07723 res = dahdi_get_event(p->subs[index].dfd); 07724 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07725 /* If we get a PR event, they hung up while processing calerid */ 07726 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07727 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07728 p->polarity = POLARITY_IDLE; 07729 callerid_free(cs); 07730 ast_hangup(chan); 07731 goto quit; 07732 } 07733 res = 0; 07734 /* Let us detect callerid when the telco uses distinctive ring */ 07735 07736 curRingData[receivedRingT] = p->ringt; 07737 07738 if (p->ringt < p->ringt_base/2) 07739 break; 07740 /* Increment the ringT counter so we can match it against 07741 values in chan_dahdi.conf for distinctive ring */ 07742 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07743 break; 07744 } else if (i & DAHDI_IOMUX_READ) { 07745 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07746 if (res < 0) { 07747 if (errno != ELAST) { 07748 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07749 callerid_free(cs); 07750 ast_hangup(chan); 07751 goto quit; 07752 } 07753 break; 07754 } 07755 if (p->ringt) 07756 p->ringt--; 07757 if (p->ringt == 1) { 07758 res = -1; 07759 break; 07760 } 07761 samples += res; 07762 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07763 if (res < 0) { 07764 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07765 break; 07766 } else if (res) 07767 break; 07768 else if (samples > (8000 * 10)) 07769 break; 07770 } 07771 } 07772 if (res == 1) { 07773 callerid_get(cs, &name, &number, &flags); 07774 if (option_debug) 07775 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07776 } 07777 if (distinctiveringaftercid == 1) { 07778 /* Clear the current ring data array so we dont have old data in it. */ 07779 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07780 curRingData[receivedRingT] = 0; 07781 } 07782 receivedRingT = 0; 07783 if (option_verbose > 2) 07784 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 07785 for (;;) { 07786 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07787 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07788 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07789 callerid_free(cs); 07790 ast_hangup(chan); 07791 goto quit; 07792 } 07793 if (i & DAHDI_IOMUX_SIGEVENT) { 07794 res = dahdi_get_event(p->subs[index].dfd); 07795 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07796 res = 0; 07797 /* Let us detect callerid when the telco uses distinctive ring */ 07798 07799 curRingData[receivedRingT] = p->ringt; 07800 07801 if (p->ringt < p->ringt_base/2) 07802 break; 07803 /* Increment the ringT counter so we can match it against 07804 values in chan_dahdi.conf for distinctive ring */ 07805 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07806 break; 07807 } else if (i & DAHDI_IOMUX_READ) { 07808 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07809 if (res < 0) { 07810 if (errno != ELAST) { 07811 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07812 callerid_free(cs); 07813 ast_hangup(chan); 07814 goto quit; 07815 } 07816 break; 07817 } 07818 if (p->ringt) 07819 p->ringt--; 07820 if (p->ringt == 1) { 07821 res = -1; 07822 break; 07823 } 07824 } 07825 } 07826 } 07827 if (p->usedistinctiveringdetection) { 07828 if (option_verbose > 2) 07829 /* this only shows up if you have n of the dring patterns filled in */ 07830 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07831 07832 for (counter = 0; counter < 3; counter++) { 07833 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07834 channel */ 07835 if (option_verbose > 2) 07836 /* this only shows up if you have n of the dring patterns filled in */ 07837 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 07838 p->drings.ringnum[counter].ring[0], 07839 p->drings.ringnum[counter].ring[1], 07840 p->drings.ringnum[counter].ring[2]); 07841 distMatches = 0; 07842 for (counter1 = 0; counter1 < 3; counter1++) { 07843 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07844 (p->drings.ringnum[counter].ring[counter1]-10)) { 07845 distMatches++; 07846 } 07847 } 07848 if (distMatches == 3) { 07849 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07850 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07851 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07852 if (option_verbose > 2) 07853 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07854 break; 07855 } 07856 } 07857 } 07858 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07859 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07860 #if 1 07861 restore_gains(p); 07862 #endif 07863 if (res < 0) { 07864 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07865 } 07866 } else 07867 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07868 } 07869 else 07870 cs = NULL; 07871 07872 if (number) 07873 ast_shrink_phone_number(number); 07874 ast_set_callerid(chan, number, name, number); 07875 07876 if (smdi_msg) 07877 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07878 07879 if (cs) 07880 callerid_free(cs); 07881 07882 ast_setstate(chan, AST_STATE_RING); 07883 chan->rings = 1; 07884 p->ringt = p->ringt_base; 07885 res = ast_pbx_run(chan); 07886 if (res) { 07887 ast_hangup(chan); 07888 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07889 } 07890 goto quit; 07891 default: 07892 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07893 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07894 if (res < 0) 07895 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07896 } 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 ast_hangup(chan); 07901 quit: 07902 ast_mutex_lock(&ss_thread_lock); 07903 ss_thread_count--; 07904 ast_cond_signal(&ss_thread_complete); 07905 ast_mutex_unlock(&ss_thread_lock); 07906 return NULL; 07907 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11115 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().
11116 { 11117 int res, x; 11118 struct dahdi_params p; 11119 struct dahdi_bufferinfo bi; 11120 struct dahdi_spaninfo si; 11121 int i; 11122 11123 for (i = 0; i < NUM_DCHANS; i++) { 11124 if (!pri->dchannels[i]) 11125 break; 11126 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 11127 x = pri->dchannels[i]; 11128 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11129 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11130 return -1; 11131 } 11132 memset(&p, 0, sizeof(p)); 11133 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11134 if (res) { 11135 dahdi_close_pri_fd(pri, i); 11136 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11137 return -1; 11138 } 11139 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11140 dahdi_close_pri_fd(pri, i); 11141 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 11142 return -1; 11143 } 11144 memset(&si, 0, sizeof(si)); 11145 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11146 if (res) { 11147 dahdi_close_pri_fd(pri, i); 11148 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11149 } 11150 if (!si.alarms) 11151 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11152 else 11153 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11154 memset(&bi, 0, sizeof(bi)); 11155 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 11156 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 11157 bi.numbufs = 32; 11158 bi.bufsize = 1024; 11159 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 11160 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 11161 dahdi_close_pri_fd(pri, i); 11162 return -1; 11163 } 11164 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 11165 /* Force overlap dial if we're doing GR-303! */ 11166 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 11167 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 11168 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 11169 #ifdef HAVE_PRI_INBANDDISCONNECT 11170 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 11171 #endif 11172 /* Enslave to master if appropriate */ 11173 if (i) 11174 pri_enslave(pri->dchans[0], pri->dchans[i]); 11175 if (!pri->dchans[i]) { 11176 dahdi_close_pri_fd(pri, i); 11177 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 11178 return -1; 11179 } 11180 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 11181 pri_set_nsf(pri->dchans[i], pri->nsf); 11182 #ifdef PRI_GETSET_TIMERS 11183 for (x = 0; x < PRI_MAX_TIMERS; x++) { 11184 if (pritimers[x] != 0) 11185 pri_set_timer(pri->dchans[i], x, pritimers[x]); 11186 } 11187 #endif 11188 } 11189 /* Assume primary is the one we use */ 11190 pri->pri = pri->dchans[0]; 11191 pri->resetpos = -1; 11192 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 11193 for (i = 0; i < NUM_DCHANS; i++) { 11194 if (!pri->dchannels[i]) 11195 break; 11196 dahdi_close_pri_fd(pri, i); 11197 } 11198 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 11199 return -1; 11200 } 11201 return 0; 11202 }
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 12776 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy, lock, NUM_SPANS, and pris.
12777 { 12778 #ifdef HAVE_PRI 12779 int y; 12780 for (y = 0; y < NUM_SPANS; y++) 12781 ast_mutex_destroy(&pris[y].lock); 12782 #endif 12783 return __unload_module(); 12784 }
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 3539 of file chan_dahdi.c.
References dahdi_accept_r2_call_exec().
Referenced by load_module().
03540 { 03541 return dahdi_accept_r2_call_exec(chan, data); 03542 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12600 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12601 { 12602 return __action_dialoffhook(s, m, 1); 12603 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12500 of file chan_dahdi.c.
References __action_dnd(), and s.
12501 { 12502 return __action_dnd(s, m, 1, 0); 12503 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12490 of file chan_dahdi.c.
References __action_dnd(), and s.
12491 { 12492 return __action_dnd(s, m, 1, 1); 12493 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12679 of file chan_dahdi.c.
References __action_restart(), and s.
12680 { 12681 return __action_restart(s, m, 1); 12682 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12655 of file chan_dahdi.c.
References __action_showchannels(), and s.
12656 { 12657 return __action_showchannels(s, m, 1); 12658 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12529 of file chan_dahdi.c.
References __action_transfer(), and s.
12530 { 12531 return __action_transfer(s, m, 1); 12532 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12557 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12558 { 12559 return __action_transferhangup(s, m, 1); 12560 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3338 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
03339 { 03340 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); 03341 return send_keypad_facility_exec(chan, data); 03342 }
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 = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 14064 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 14064 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 12396 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 12401 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 12381 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 12391 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 12386 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 12406 of file chan_dahdi.c.
char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 3424 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 3430 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 3427 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 11812 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 11821 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 11808 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 11816 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 11805 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 11802 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 11799 of file chan_dahdi.c.
char dahdi_restart_usage[] [static] |
Definition at line 12374 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3280 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 3286 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3283 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 12267 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 12366 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 12370 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 11467 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 11471 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 11475 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 11479 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 11483 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 228 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 12362 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 12358 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 3425 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 3434 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 3428 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 3281 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 3289 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3284 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |