#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <libpri.h>
#include <openr2.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
#include "asterisk/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"
Go to the source code of this file.
Data Structures | |
struct | dahdi_chan_conf |
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More... | |
struct | dahdi_distRings |
struct | dahdi_mfcr2 |
struct | dahdi_pri |
struct | dahdi_pvt |
struct | dahdi_subchannel |
struct | distRingData |
struct | ringContextData |
Defines | |
#define | ASCII_BYTES_PER_CHAR 80 |
#define | AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
#define | CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
#define | CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
#define | CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define | CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define | CHAN_PSEUDO -2 |
#define | CHANNEL_PSEUDO -12 |
#define | CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define | CONF_USER_REAL (1 << 0) |
#define | CONF_USER_THIRDCALL (1 << 1) |
#define | DAHDI_EVENT_DTMFDOWN 0 |
#define | DAHDI_EVENT_DTMFUP 0 |
#define | DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define | DAHDI_OVERLAPDIAL_INCOMING 2 |
#define | DAHDI_OVERLAPDIAL_NONE 0 |
#define | DAHDI_OVERLAPDIAL_OUTGOING 1 |
#define | DAHDI_R2_LOCAL_BLOCK (1 << 1) |
#define | DAHDI_R2_REMOTE_BLOCK (1 << 0) |
#define | DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define | DCHAN_NOTINALARM (1 << 1) |
#define | DCHAN_PROVISIONED (1 << 0) |
#define | DCHAN_UP (1 << 2) |
#define | DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID. | |
#define | DEFAULT_PRI_DEBUG 0 |
#define | DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
#define | END_SILENCE_LEN 400 |
#define | FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define | FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" |
#define | FORMAT "%4s %40s\n" |
#define | FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define | GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel) |
#define | HANGUP 1 |
#define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
#define | HEADER_MS 50 |
#define | ISTRUNK(p) |
#define | local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
#define | local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr) |
#define | local_astman_register(a, b, c, d) |
#define | local_astman_unregister(a) |
#define | MASK_AVAIL (1 << 0) |
#define | MASK_INUSE (1 << 1) |
#define | MAX_CHANLIST_LEN 80 |
#define | MAX_CHANNELS 672 |
#define | MAX_SLAVES 4 |
#define | MIN_MS_SINCE_FLASH ( (2000) ) |
#define | NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro. | |
#define | NUM_CADENCE_MAX 25 |
#define | NUM_DCHANS 4 |
#define | NUM_SPANS 32 |
#define | POLARITY_IDLE 0 |
#define | POLARITY_REV 1 |
#define | PRI_CHANNEL(p) ((p) & 0xff) |
#define | PRI_EXPLICIT(p) (((p) >> 16) & 0x01) |
#define | PRI_SPAN(p) (((p) >> 8) & 0xff) |
#define | PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
#define | READ_SIZE 160 |
#define | sig2str dahdi_sig2str |
#define | SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
#define | SIG_EM DAHDI_SIG_EM |
#define | SIG_EM_E1 DAHDI_SIG_EM_E1 |
#define | SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
#define | SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
#define | SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
#define | SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
#define | SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
#define | SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
#define | SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
#define | SIG_FXOGS DAHDI_SIG_FXOGS |
#define | SIG_FXOKS DAHDI_SIG_FXOKS |
#define | SIG_FXOLS DAHDI_SIG_FXOLS |
#define | SIG_FXSGS DAHDI_SIG_FXSGS |
#define | SIG_FXSKS DAHDI_SIG_FXSKS |
#define | SIG_FXSLS DAHDI_SIG_FXSLS |
#define | SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
#define | SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
#define | SIG_MFCR2 DAHDI_SIG_CAS |
#define | SIG_PRI DAHDI_SIG_CLEAR |
#define | SIG_SF DAHDI_SIG_SF |
#define | SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
#define | SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
#define | SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
#define | SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
#define | SMDI_MD_WAIT_TIMEOUT 1500 |
#define | SUB_CALLWAIT 1 |
#define | SUB_REAL 0 |
#define | SUB_THREEWAY 2 |
#define | tdesc "DAHDI Telephony w/PRI" |
#define | TRAILER_MS 5 |
#define | TRANSFER 0 |
Functions | |
static int | __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd) |
static int | __action_restart (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_showchannels (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transfer (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode) |
static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
static void | __reg_module (void) |
static int | __unload_module (void) |
static void | __unreg_module (void) |
static char * | alarm2str (int alarm) |
static int | alloc_sub (struct dahdi_pvt *p, int x) |
static void | apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan) |
static int | attempt_transfer (struct dahdi_pvt *p) |
static int | available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched) |
static int | build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo) |
static void | build_status (char *s, size_t len, int status, int active) |
static int | bump_gains (struct dahdi_pvt *p) |
static int | calc_energy (const unsigned char *buf, int len, int law) |
static struct dahdi_pvt * | chandup (struct dahdi_pvt *src) |
static int | check_for_conference (struct dahdi_pvt *p) |
static char * | complete_span_4 (const char *line, const char *word, int pos, int state) |
static char * | complete_span_5 (const char *line, const char *word, int pos, int state) |
static char * | complete_span_helper (const char *line, const char *word, int pos, int state, int rpos) |
static int | conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel) |
static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index) |
static int | dahdi_accept_r2_call_exec (struct ast_channel *chan, void *data) |
static int | dahdi_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndoff (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndon (struct mansession *s, const struct message *m) |
static int | dahdi_action_restart (struct mansession *s, const struct message *m) |
static int | dahdi_action_showchannels (struct mansession *s, const struct message *m) |
static int | dahdi_action_transfer (struct mansession *s, const struct message *m) |
static int | dahdi_action_transferhangup (struct mansession *s, const struct message *m) |
static int | dahdi_answer (struct ast_channel *ast) |
static openr2_call_disconnect_cause_t | dahdi_ast_cause_to_r2_cause (int cause) |
static enum ast_bridge_result | dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | dahdi_call (struct ast_channel *ast, char *rdest, int timeout) |
static int | dahdi_callwait (struct ast_channel *ast) |
static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
static void | dahdi_close (int fd) |
static void | dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num) |
static void | dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num) |
static int | dahdi_confmute (struct dahdi_pvt *p, int muted) |
static int | dahdi_destroy_channel (int fd, int argc, char **argv) |
static int | dahdi_destroy_channel_bynum (int channel) |
static int | dahdi_digit_begin (struct ast_channel *ast, char digit) |
static int | dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
static void | dahdi_disable_ec (struct dahdi_pvt *p) |
static void | dahdi_enable_ec (struct dahdi_pvt *p) |
static struct ast_frame * | dahdi_exception (struct ast_channel *ast) |
static int | dahdi_fake_event (struct dahdi_pvt *p, int mode) |
static int | dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | dahdi_func_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len) |
static int | dahdi_get_event (int fd) |
Avoid the silly dahdi_getevent which ignores a bunch of events. | |
static int | dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok) |
static void | dahdi_handle_dtmfup (struct ast_channel *ast, int index, struct ast_frame **dest) |
static struct ast_frame * | dahdi_handle_event (struct ast_channel *ast) |
static int | dahdi_hangup (struct ast_channel *ast) |
static int | dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen) |
static void | dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master) |
static struct ast_channel * | dahdi_new (struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability) |
static int | dahdi_open (char *fn) |
static void | dahdi_pri_error (struct pri *pri, char *s) |
static void | dahdi_pri_message (struct pri *pri, char *s) |
static void | dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri) |
static int16_t | dahdi_r2_alaw_to_linear (uint8_t sample) |
static int | dahdi_r2_answer (struct dahdi_pvt *p) |
static void | dahdi_r2_disconnect_call (struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause) |
static openr2_calling_party_category_t | dahdi_r2_get_channel_category (struct ast_channel *c) |
static uint8_t | dahdi_r2_linear_to_alaw (int sample) |
static void | dahdi_r2_on_ani_digit_received (openr2_chan_t *r2chan, char digit) |
static void | dahdi_r2_on_billing_pulse_received (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_accepted (openr2_chan_t *r2chan, openr2_call_mode_t mode) |
static void | dahdi_r2_on_call_answered (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_disconnect (openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause) |
static void | dahdi_r2_on_call_end (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_init (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_call_offered (openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category) |
static void | dahdi_r2_on_call_read (openr2_chan_t *r2chan, const unsigned char *buf, int buflen) |
static void | dahdi_r2_on_chan_log (openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap) |
static void | dahdi_r2_on_context_log (openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap) |
static int | dahdi_r2_on_dnis_digit_received (openr2_chan_t *r2chan, char digit) |
static void | dahdi_r2_on_hardware_alarm (openr2_chan_t *r2chan, int alarm) |
static void | dahdi_r2_on_line_blocked (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_line_idle (openr2_chan_t *r2chan) |
static void | dahdi_r2_on_os_error (openr2_chan_t *r2chan, int errorcode) |
static void | dahdi_r2_on_protocol_error (openr2_chan_t *r2chan, openr2_protocol_error_t reason) |
static void | dahdi_r2_write_log (openr2_log_level_t level, char *logmessage) |
static struct ast_frame * | dahdi_read (struct ast_channel *ast) |
static struct ast_channel * | dahdi_request (const char *type, int format, void *data, int *cause) |
static int | dahdi_restart (void) |
static int | dahdi_restart_cmd (int fd, int argc, char **argv) |
static int | dahdi_ring_phone (struct dahdi_pvt *p) |
static int | dahdi_send_keypad_facility_exec (struct ast_channel *chan, void *data) |
static int | dahdi_sendtext (struct ast_channel *c, const char *text) |
static int | dahdi_set_hook (int fd, int hs) |
static int | dahdi_setlaw (int dfd, int law) |
static int | dahdi_setlinear (int dfd, int linear) |
static int | dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen) |
static int | dahdi_show_channel (int fd, int argc, char **argv) |
static int | dahdi_show_channels (int fd, int argc, char **argv) |
static int | dahdi_show_status (int fd, int argc, char *argv[]) |
static char * | dahdi_sig2str (int sig) |
static void | dahdi_softhangup_all (void) |
static void | dahdi_train_ec (struct dahdi_pvt *p) |
static void | dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock) |
static int | dahdi_wait_event (int fd) |
Avoid the silly dahdi_waitevent which ignores a bunch of events. | |
static int | dahdi_wink (struct dahdi_pvt *p, int index) |
static int | dahdi_write (struct ast_channel *ast, struct ast_frame *frame) |
static void | destroy_all_channels (void) |
static int | destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now) |
static void | destroy_dahdi_pvt (struct dahdi_pvt **pvt) |
static char * | dialplan2str (int dialplan) |
static int | digit_to_dtmfindex (char digit) |
static void | disable_dtmf_detect (struct dahdi_pvt *p) |
static void * | do_idle_thread (void *vchan) |
static void * | do_monitor (void *data) |
static void | enable_dtmf_detect (struct dahdi_pvt *p) |
static char * | event2str (int event) |
static void | fill_rxgain (struct dahdi_gains *g, float gain, int law) |
static void | fill_txgain (struct dahdi_gains *g, float gain, int law) |
static struct dahdi_pvt * | find_channel (int channel) |
static int | get_alarms (struct dahdi_pvt *p) |
static void | handle_alarms (struct dahdi_pvt *p, int alarms) |
static int | handle_dahdi_show_cadences (int fd, int argc, char *argv[]) |
static struct dahdi_pvt * | handle_init_event (struct dahdi_pvt *i, int event) |
static int | handle_mfcr2_call_files (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_blocked (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_debug (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_set_idle (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_show_channels (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_show_variants (int fd, int argc, char *argv[]) |
static int | handle_mfcr2_version (int fd, int argc, char *argv[]) |
static int | handle_pri_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_no_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_really_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_set_debug_file (int fd, int argc, char **argv) |
static int | handle_pri_show_debug (int fd, int argc, char *argv[]) |
static int | handle_pri_show_span (int fd, int argc, char *argv[]) |
static int | handle_pri_show_spans (int fd, int argc, char *argv[]) |
static int | handle_pri_version (int fd, int agc, char *argv[]) |
static int | has_voicemail (struct dahdi_pvt *p) |
static void | init_mfcr2_globals (void) |
static int | isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c) |
static int | isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out) |
static int | load_module (void) |
static struct dahdi_mfcr2 * | mfcr2_get_context (int id) |
static void * | mfcr2_monitor (void *data) |
static struct dahdi_pvt * | mkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading) |
static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear) |
static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
static int | pri_active_dchan_fd (struct dahdi_pri *pri) |
static int | pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer) |
static int | pri_check_restart (struct dahdi_pri *pri) |
static int | pri_create_spanmap (int span, int trunkgroup, int logicalspan) |
static int | pri_create_trunkgroup (int trunkgroup, int *channels) |
static void * | pri_dchannel (void *vpri) |
static struct dahdi_pvt * | pri_find_crv (struct dahdi_pri *pri, int crv) |
static int | pri_find_dchan (struct dahdi_pri *pri) |
static int | pri_find_empty_chan (struct dahdi_pri *pri, int backwards) |
static int | pri_find_principle (struct dahdi_pri *pri, int channel) |
static int | pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c) |
static int | pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri) |
static int | pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri) |
static int | pri_is_up (struct dahdi_pri *pri) |
static char * | pri_order (int level) |
static void | pri_rel (struct dahdi_pri *pri) |
static int | pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si) |
static int | process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels) |
static char * | redirectingreason2str (int redirectingreason) |
static int | reload (void) |
static int | reset_conf (struct dahdi_pvt *p) |
static int | restart_monitor (void) |
static int | restore_conference (struct dahdi_pvt *p) |
static int | restore_gains (struct dahdi_pvt *p) |
static int | save_conference (struct dahdi_pvt *p) |
static int | send_callerid (struct dahdi_pvt *p) |
static int | send_cwcidspill (struct dahdi_pvt *p) |
static int | send_keypad_facility_exec (struct ast_channel *chan, void *data) |
static int | set_actual_gain (int fd, int chan, float rxgain, float txgain, int law) |
static int | set_actual_rxgain (int fd, int chan, float gain, int law) |
static int | set_actual_txgain (int fd, int chan, float gain, int law) |
static int | setup_dahdi (int reload) |
static void * | ss_thread (void *data) |
static int | start_pri (struct dahdi_pri *pri) |
static void | swap_subs (struct dahdi_pvt *p, int a, int b) |
static int | unalloc_sub (struct dahdi_pvt *p, int x) |
static int | unload_module (void) |
static int | update_conf (struct dahdi_pvt *p) |
static void | wakeup_sub (struct dahdi_pvt *p, int a, struct dahdi_pri *pri) |
static int | zap_accept_r2_call_exec (struct ast_channel *chan, void *data) |
static int | zap_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | zap_action_dndoff (struct mansession *s, const struct message *m) |
static int | zap_action_dndon (struct mansession *s, const struct message *m) |
static int | zap_action_restart (struct mansession *s, const struct message *m) |
static int | zap_action_showchannels (struct mansession *s, const struct message *m) |
static int | zap_action_transfer (struct mansession *s, const struct message *m) |
static int | zap_action_transferhangup (struct mansession *s, const struct message *m) |
static int | zap_send_keypad_facility_exec (struct ast_channel *chan, void *data) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
static struct ast_channel_tech * | chan_tech |
static int | cidrings [NUM_CADENCE_MAX] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
static struct ast_cli_entry | cli_zap_destroy_channel_deprecated |
static struct ast_cli_entry | cli_zap_restart_deprecated |
static struct ast_cli_entry | cli_zap_show_cadences_deprecated |
static struct ast_cli_entry | cli_zap_show_channel_deprecated |
static struct ast_cli_entry | cli_zap_show_channels_deprecated |
static struct ast_cli_entry | cli_zap_show_status_deprecated |
static char * | dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" |
static char * | dahdi_accept_r2_call_descrip |
static char * | dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" |
static struct ast_cli_entry | dahdi_cli [] |
static struct ast_cli_entry | dahdi_mfcr2_cli [] |
static struct ast_cli_entry | dahdi_pri_cli [] |
static const char | dahdi_r2_callfiles_help [] |
static openr2_event_interface_t | dahdi_r2_event_iface |
static const char | dahdi_r2_setblocked_help [] |
static const char | dahdi_r2_setdebug_help [] |
static const char | dahdi_r2_setidle_help [] |
static const char | dahdi_r2_showchannels_help [] |
static openr2_transcoder_interface_t | dahdi_r2_transcode_iface |
static const char | dahdi_r2_variants_help [] |
static const char | dahdi_r2_version_help [] |
static char | dahdi_restart_usage [] |
static char * | dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" |
static char * | dahdi_send_keypad_facility_descrip |
static char * | dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" |
static char | dahdi_show_cadences_usage [] |
static char | dahdi_show_status_usage [] |
static struct ast_channel_tech | dahdi_tech |
static struct ast_jb_conf | default_jbconf |
static char | defaultcic [64] = "" |
static char | defaultozz [64] = "" |
static char | destroy_channel_usage [] |
static int | distinctiveringaftercid = 0 |
static struct dahdi_distRings | drings |
static int | dtmfcid_level = 256 |
static char * | events [] |
static int | firstdigittimeout = 16000 |
Wait up to 16 seconds for first digit (FXO logic). | |
static int | gendigittimeout = 8000 |
How long to wait for following digits (FXO logic). | |
static struct ast_jb_conf | global_jbconf |
static int | ifcount = 0 |
static struct dahdi_pvt * | ifend |
static struct dahdi_pvt * | iflist |
static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
Protect the interface list (of dahdi_pvt's). | |
static struct ast_channel | inuse |
static int | matchdigittimeout = 3000 |
How long to wait for an extra digit, if there is an ambiguous match. | |
static int | mfcr2_cur_accept_on_offer = 1 |
static int | mfcr2_cur_allow_collect_calls = 0 |
static int | mfcr2_cur_call_files = 0 |
static openr2_calling_party_category_t | mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER |
static int | mfcr2_cur_charge_calls = 1 |
static int | mfcr2_cur_context_index = 0 |
static int | mfcr2_cur_double_answer = 0 |
static int | mfcr2_cur_forced_release = 0 |
static int | mfcr2_cur_get_ani_first = -1 |
static int | mfcr2_cur_immediate_accept = -1 |
static char | mfcr2_cur_logdir [OR2_MAX_PATH] |
static openr2_log_level_t | mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING |
static int | mfcr2_cur_max_ani = 10 |
static int | mfcr2_cur_max_dnis = 4 |
static int | mfcr2_cur_metering_pulse_timeout = -1 |
static int | mfcr2_cur_mfback_timeout = -1 |
static char | mfcr2_cur_r2proto_file [OR2_MAX_PATH] |
static int | mfcr2_cur_skip_category = -1 |
static openr2_variant_t | mfcr2_cur_variant = OR2_VAR_UNKNOWN |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
static int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static const char | pri_debug_help [] |
static const char | pri_no_debug_help [] |
static const char | pri_really_debug_help [] |
static const char | pri_show_span_help [] |
static const char | pri_show_spans_help [] |
static int | pridebugfd = -1 |
static ast_mutex_t | pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static char | pridebugfilename [1024] = "" |
static struct dahdi_pri | pris [NUM_SPANS] |
static char | progzone [10] = "" |
static struct dahdi_mfcr2 | r2links [NUM_SPANS] |
static ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static int | ringt_base = DEFAULT_RINGT |
Configured ring timeout base. | |
dahdi_pvt * | round_robin [32] |
static char | show_channel_usage [] |
static char | show_channels_usage [] |
static ast_cond_t | ss_thread_complete |
static int | ss_thread_count = 0 |
static ast_mutex_t | ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static char * | subnames [] |
static const char | tdesc [] |
static int | user_has_defined_cadences = 0 |
static char * | zap_accept_r2_call_app = "ZapAcceptR2Call" |
static char * | zap_accept_r2_call_descrip |
static char * | zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" |
static char * | zap_send_keypad_facility_app = "ZapSendKeypadFacility" |
static char * | zap_send_keypad_facility_descrip |
static char * | zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" |
static struct ast_channel_tech | zap_tech |
You need to install libraries before you attempt to compile and install the DAHDI channel.
Definition in file chan_dahdi.c.
#define ASCII_BYTES_PER_CHAR 80 |
Referenced by dahdi_sendtext().
#define AST_LAW | ( | p | ) | (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
Definition at line 156 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().
#define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
#define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 298 of file chan_dahdi.c.
#define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
#define CHAN_PSEUDO -2 |
Definition at line 200 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().
#define CHANNEL_PSEUDO -12 |
Definition at line 154 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 473 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 474 of file chan_dahdi.c.
#define DAHDI_EVENT_DTMFDOWN 0 |
#define DAHDI_EVENT_DTMFUP 0 |
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
#define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 211 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), handle_pri_show_span(), and process_dahdi().
#define DAHDI_OVERLAPDIAL_NONE 0 |
#define DAHDI_OVERLAPDIAL_OUTGOING 1 |
#define DAHDI_R2_LOCAL_BLOCK (1 << 1) |
Definition at line 1646 of file chan_dahdi.c.
Referenced by handle_mfcr2_set_blocked(), handle_mfcr2_set_idle(), mfcr2_monitor(), and mkintf().
#define DAHDI_R2_REMOTE_BLOCK (1 << 0) |
Definition at line 1645 of file chan_dahdi.c.
Referenced by dahdi_r2_on_line_blocked(), dahdi_r2_on_line_idle(), and mkintf().
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
#define DCHAN_NOTINALARM (1 << 1) |
#define DCHAN_PROVISIONED (1 << 0) |
Definition at line 202 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
#define DCHAN_UP (1 << 2) |
Definition at line 204 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 152 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_PRI_DEBUG 0 |
#define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 302 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" |
#define FORMAT "%4s %40s\n" |
#define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1137 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 12542 of file chan_dahdi.c.
Referenced by __action_transferhangup(), and dahdi_fake_event().
#define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().
#define HEADER_MS 50 |
Referenced by dahdi_sendtext().
#define ISTRUNK | ( | p | ) |
Value:
Definition at line 1184 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().
#define local_astman_ack | ( | s, | |||
m, | |||||
msg, | |||||
zap | ) | do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
Definition at line 12572 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 12573 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
#define local_astman_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) |
#define local_astman_unregister | ( | a | ) |
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 295 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 296 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 12987 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 198 of file chan_dahdi.c.
Referenced by mkintf().
#define MAX_SLAVES 4 |
#define MIN_MS_SINCE_FLASH ( (2000) ) |
#define NEED_MFDETECT | ( | p | ) | (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro.
Definition at line 159 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 1162 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 197 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().
#define NUM_SPANS 32 |
Definition at line 196 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), init_mfcr2_globals(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().
#define POLARITY_IDLE 0 |
Definition at line 431 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 432 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and handle_init_event().
#define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
#define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
#define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
#define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 353 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), and pri_check_restart().
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 293 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_setoption(), and send_cwcidspill().
#define sig2str dahdi_sig2str |
Definition at line 2166 of file chan_dahdi.c.
Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 175 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 192 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 171 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 174 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 173 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 176 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 183 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 184 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 182 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 180 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), do_monitor(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 181 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), do_monitor(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 179 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), do_monitor(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 193 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 186 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), mkintf(), and process_dahdi().
#define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 185 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_SF DAHDI_SIG_SF |
Definition at line 187 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 191 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 190 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 427 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define SUB_REAL 0 |
Active call
Definition at line 426 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_answered(), dahdi_r2_on_call_disconnect(), dahdi_r2_on_call_offered(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mfcr2_monitor(), mkintf(), pri_assign_bearer(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().
#define SUB_THREEWAY 2 |
Three-way call
Definition at line 428 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define tdesc "DAHDI Telephony w/PRI" |
Definition at line 14163 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 12541 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 12671 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().
12672 { 12673 struct dahdi_pvt *p = NULL; 12674 const char *channel = local_astman_header(m, "Channel", zap_mode); 12675 const char *number = astman_get_header(m, "Number"); 12676 int i; 12677 12678 if (ast_strlen_zero(channel)) { 12679 astman_send_error(s, m, "No channel specified"); 12680 return 0; 12681 } 12682 if (ast_strlen_zero(number)) { 12683 astman_send_error(s, m, "No number specified"); 12684 return 0; 12685 } 12686 if (!(p = find_channel(atoi(channel)))) { 12687 astman_send_error(s, m, "No such channel"); 12688 return 0; 12689 } 12690 if (!p->owner) { 12691 astman_send_error(s, m, "Channel does not have an owner"); 12692 return 0; 12693 } 12694 for (i = 0; i < strlen(number); i++) { 12695 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 12696 12697 dahdi_queue_frame(p, &f, NULL); 12698 } 12699 local_astman_ack(s, m, "DialOffHook", zap_mode); 12700 12701 return 0; 12702 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 12575 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().
12576 { 12577 struct dahdi_pvt *p = NULL; 12578 const char *channel = local_astman_header(m, "Channel", zap_mode); 12579 12580 if (ast_strlen_zero(channel)) { 12581 astman_send_error(s, m, "No channel specified"); 12582 return 0; 12583 } 12584 if (!(p = find_channel(atoi(channel)))) { 12585 astman_send_error(s, m, "No such channel"); 12586 return 0; 12587 } 12588 p->dnd = dnd; 12589 local_astman_ack(s, m, "DND", zap_mode); 12590 12591 return 0; 12592 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12769 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().
12770 { 12771 if (dahdi_restart() != 0) { 12772 if (zap_mode) { 12773 astman_send_error(s, m, "Failed to restart Zap"); 12774 } else { 12775 astman_send_error(s, m, "Failed to restart DAHDI"); 12776 } 12777 return 1; 12778 } 12779 local_astman_ack(s, m, "Restart: Success", zap_mode); 12780 return 0; 12781 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12714 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().
12715 { 12716 struct dahdi_pvt *tmp = NULL; 12717 const char *id = astman_get_header(m, "ActionID"); 12718 char idText[256] = ""; 12719 12720 local_astman_ack(s, m, " channel status will follow", zap_mode); 12721 if (!ast_strlen_zero(id)) 12722 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 12723 12724 ast_mutex_lock(&iflock); 12725 12726 tmp = iflist; 12727 while (tmp) { 12728 if (tmp->channel > 0) { 12729 int alarm = get_alarms(tmp); 12730 astman_append(s, 12731 "Event: %sShowChannels\r\n" 12732 "Channel: %d\r\n" 12733 "Signalling: %s\r\n" 12734 "Context: %s\r\n" 12735 "DND: %s\r\n" 12736 "Alarm: %s\r\n" 12737 "%s" 12738 "\r\n", 12739 dahdi_chan_name, 12740 tmp->channel, sig2str(tmp->sig), tmp->context, 12741 tmp->dnd ? "Enabled" : "Disabled", 12742 alarm2str(alarm), idText); 12743 } 12744 12745 tmp = tmp->next; 12746 } 12747 12748 ast_mutex_unlock(&iflock); 12749 12750 astman_append(s, 12751 "Event: %sShowChannelsComplete\r\n" 12752 "%s" 12753 "\r\n", 12754 dahdi_chan_name, 12755 idText); 12756 return 0; 12757 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12614 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().
12615 { 12616 struct dahdi_pvt *p = NULL; 12617 const char *channel = local_astman_header(m, "Channel", zap_mode); 12618 12619 if (ast_strlen_zero(channel)) { 12620 astman_send_error(s, m, "No channel specified"); 12621 return 0; 12622 } 12623 if (!(p = find_channel(atoi(channel)))) { 12624 astman_send_error(s, m, "No such channel"); 12625 return 0; 12626 } 12627 dahdi_fake_event(p,TRANSFER); 12628 local_astman_ack(s, m, "Transfer", zap_mode); 12629 12630 return 0; 12631 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 12643 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().
12644 { 12645 struct dahdi_pvt *p = NULL; 12646 const char *channel = local_astman_header(m, "Channel", zap_mode); 12647 12648 if (ast_strlen_zero(channel)) { 12649 astman_send_error(s, m, "No channel specified"); 12650 return 0; 12651 } 12652 if (!(p = find_channel(atoi(channel)))) { 12653 astman_send_error(s, m, "No such channel"); 12654 return 0; 12655 } 12656 dahdi_fake_event(p, HANGUP); 12657 local_astman_ack(s, m, "Hangup", zap_mode); 12658 return 0; 12659 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5791 of file chan_dahdi.c.
References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.
Referenced by dahdi_exception().
05792 { 05793 struct dahdi_pvt *p = ast->tech_pvt; 05794 int res; 05795 int usedindex=-1; 05796 int index; 05797 struct ast_frame *f; 05798 05799 05800 index = dahdi_get_index(ast, p, 1); 05801 05802 p->subs[index].f.frametype = AST_FRAME_NULL; 05803 p->subs[index].f.datalen = 0; 05804 p->subs[index].f.samples = 0; 05805 p->subs[index].f.mallocd = 0; 05806 p->subs[index].f.offset = 0; 05807 p->subs[index].f.subclass = 0; 05808 p->subs[index].f.delivery = ast_tv(0,0); 05809 p->subs[index].f.src = "dahdi_exception"; 05810 p->subs[index].f.data = NULL; 05811 05812 05813 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05814 /* If nobody owns us, absorb the event appropriately, otherwise 05815 we loop indefinitely. This occurs when, during call waiting, the 05816 other end hangs up our channel so that it no longer exists, but we 05817 have neither FLASH'd nor ONHOOK'd to signify our desire to 05818 change to the other channel. */ 05819 if (p->fake_event) { 05820 res = p->fake_event; 05821 p->fake_event = 0; 05822 } else 05823 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05824 /* Switch to real if there is one and this isn't something really silly... */ 05825 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05826 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05827 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 05828 p->owner = p->subs[SUB_REAL].owner; 05829 if (p->owner && ast_bridged_channel(p->owner)) 05830 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05831 p->subs[SUB_REAL].needunhold = 1; 05832 } 05833 switch (res) { 05834 case DAHDI_EVENT_ONHOOK: 05835 dahdi_disable_ec(p); 05836 if (p->owner) { 05837 if (option_verbose > 2) 05838 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 05839 dahdi_ring_phone(p); 05840 p->callwaitingrepeat = 0; 05841 p->cidcwexpire = 0; 05842 } else 05843 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05844 update_conf(p); 05845 break; 05846 case DAHDI_EVENT_RINGOFFHOOK: 05847 dahdi_enable_ec(p); 05848 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05849 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05850 p->subs[SUB_REAL].needanswer = 1; 05851 p->dialing = 0; 05852 } 05853 break; 05854 case DAHDI_EVENT_HOOKCOMPLETE: 05855 case DAHDI_EVENT_RINGERON: 05856 case DAHDI_EVENT_RINGEROFF: 05857 /* Do nothing */ 05858 break; 05859 case DAHDI_EVENT_WINKFLASH: 05860 gettimeofday(&p->flashtime, NULL); 05861 if (p->owner) { 05862 if (option_verbose > 2) 05863 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05864 if (p->owner->_state != AST_STATE_UP) { 05865 /* Answer if necessary */ 05866 usedindex = dahdi_get_index(p->owner, p, 0); 05867 if (usedindex > -1) { 05868 p->subs[usedindex].needanswer = 1; 05869 } 05870 ast_setstate(p->owner, AST_STATE_UP); 05871 } 05872 p->callwaitingrepeat = 0; 05873 p->cidcwexpire = 0; 05874 if (ast_bridged_channel(p->owner)) 05875 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05876 p->subs[SUB_REAL].needunhold = 1; 05877 } else 05878 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05879 update_conf(p); 05880 break; 05881 default: 05882 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05883 } 05884 f = &p->subs[index].f; 05885 return f; 05886 } 05887 if (!(p->radio || (p->oprmode < 0)) && option_debug) 05888 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05889 /* If it's not us, return NULL immediately */ 05890 if (ast != p->owner) { 05891 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05892 f = &p->subs[index].f; 05893 return f; 05894 } 05895 f = dahdi_handle_event(ast); 05896 return f; 05897 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 14172 of file chan_dahdi.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 12800 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().
12801 { 12802 struct dahdi_pvt *p; 12803 #ifdef HAVE_OPENR2 12804 int r; 12805 #endif 12806 #ifdef HAVE_PRI 12807 int i, j; 12808 for (i = 0; i < NUM_SPANS; i++) { 12809 if (pris[i].master != AST_PTHREADT_NULL) 12810 pthread_cancel(pris[i].master); 12811 } 12812 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 12813 12814 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12815 ast_unregister_application(dahdi_send_keypad_facility_app); 12816 } 12817 ast_unregister_application(zap_send_keypad_facility_app); 12818 #endif 12819 #ifdef HAVE_OPENR2 12820 for (r = 0; r < NUM_SPANS; r++) { 12821 if (r2links[r].master != AST_PTHREADT_NULL) { 12822 pthread_cancel(r2links[r].master); 12823 pthread_join(r2links[r].master, NULL); 12824 } 12825 } 12826 ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0])); 12827 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 12828 ast_unregister_application(dahdi_accept_r2_call_app); 12829 } 12830 ast_unregister_application(zap_accept_r2_call_app); 12831 #endif 12832 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 12833 local_astman_unregister("DialOffHook"); 12834 local_astman_unregister("Hangup"); 12835 local_astman_unregister("Transfer"); 12836 local_astman_unregister("DNDoff"); 12837 local_astman_unregister("DNDon"); 12838 local_astman_unregister("ShowChannels"); 12839 local_astman_unregister("Restart"); 12840 ast_channel_unregister(chan_tech); 12841 ast_mutex_lock(&iflock); 12842 /* Hangup all interfaces if they have an owner */ 12843 p = iflist; 12844 while (p) { 12845 if (p->owner) 12846 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 12847 p = p->next; 12848 } 12849 ast_mutex_unlock(&iflock); 12850 ast_mutex_lock(&monlock); 12851 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12852 pthread_cancel(monitor_thread); 12853 pthread_kill(monitor_thread, SIGURG); 12854 pthread_join(monitor_thread, NULL); 12855 } 12856 monitor_thread = AST_PTHREADT_STOP; 12857 ast_mutex_unlock(&monlock); 12858 12859 destroy_all_channels(); 12860 #ifdef HAVE_PRI 12861 for (i = 0; i < NUM_SPANS; i++) { 12862 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 12863 pthread_join(pris[i].master, NULL); 12864 for (j = 0; j < NUM_DCHANS; j++) { 12865 dahdi_close_pri_fd(&(pris[i]), j); 12866 } 12867 } 12868 #endif 12869 #ifdef HAVE_OPENR2 12870 for (r = 0; r < NUM_SPANS; r++) { 12871 if (r2links[r].protocol_context) { 12872 openr2_context_delete(r2links[r].protocol_context); 12873 } 12874 } 12875 #endif 12876 ast_cond_destroy(&ss_thread_complete); 12877 return 0; 12878 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 14172 of file chan_dahdi.c.
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 2075 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
02076 { 02077 int x; 02078 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 02079 if (alarms[x].alarm & alarm) 02080 return alarms[x].name; 02081 } 02082 return alarm ? "Unknown Alarm" : "No Alarm"; 02083 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1877 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), DAHDI_FILE_PSEUDO, dahdi_open(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
01878 { 01879 struct dahdi_bufferinfo bi; 01880 int res; 01881 if (p->subs[x].dfd < 0) { 01882 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 01883 if (p->subs[x].dfd > -1) { 01884 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01885 if (!res) { 01886 bi.txbufpolicy = p->buf_policy; 01887 bi.rxbufpolicy = p->buf_policy; 01888 bi.numbufs = p->buf_no; 01889 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01890 if (res < 0) { 01891 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01892 } 01893 } else 01894 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01895 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01896 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01897 dahdi_close_sub(p, x); 01898 return -1; 01899 } 01900 if (option_debug) 01901 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01902 return 0; 01903 } else 01904 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01905 return -1; 01906 } 01907 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01908 return -1; 01909 }
static void apply_plan_to_number | ( | char * | buf, | |
size_t | size, | |||
const struct dahdi_pri * | pri, | |||
const char * | number, | |||
const int | plan | |||
) | [static] |
Definition at line 10045 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.
10046 { 10047 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10048 if (size) { 10049 *buf = '\0'; 10050 } 10051 return; 10052 } 10053 10054 switch (plan) { 10055 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10056 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10057 break; 10058 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10059 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10060 break; 10061 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10062 snprintf(buf, size, "%s%s", pri->localprefix, number); 10063 break; 10064 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10065 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10066 break; 10067 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10068 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10069 break; 10070 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10071 snprintf(buf, size, "%s", number); 10072 break; 10073 } 10074 }
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4718 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().
04719 { 04720 /* In order to transfer, we need at least one of the channels to 04721 actually be in a call bridge. We can't conference two applications 04722 together (but then, why would we want to?) */ 04723 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04724 /* The three-way person we're about to transfer to could still be in MOH, so 04725 stop if now if appropriate */ 04726 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04727 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04728 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04729 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04730 } 04731 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04732 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04733 } 04734 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04735 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04736 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04737 return -1; 04738 } 04739 /* Orphan the channel after releasing the lock */ 04740 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04741 unalloc_sub(p, SUB_THREEWAY); 04742 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04743 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04744 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04745 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04746 } 04747 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04748 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04749 } 04750 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04751 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04752 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04753 return -1; 04754 } 04755 /* Three-way is now the REAL */ 04756 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04757 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 04758 unalloc_sub(p, SUB_THREEWAY); 04759 /* Tell the caller not to hangup */ 04760 return 1; 04761 } else { 04762 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04763 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04764 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04765 return -1; 04766 } 04767 return 0; 04768 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 9194 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().
09195 { 09196 int res; 09197 struct dahdi_params par; 09198 09199 /* First, check group matching */ 09200 if (groupmatch) { 09201 if ((p->group & groupmatch) != groupmatch) 09202 return 0; 09203 *groupmatched = 1; 09204 } 09205 /* Check to see if we have a channel match */ 09206 if (channelmatch != -1) { 09207 if (p->channel != channelmatch) 09208 return 0; 09209 *channelmatched = 1; 09210 } 09211 /* We're at least busy at this point */ 09212 if (busy) { 09213 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09214 *busy = 1; 09215 } 09216 /* If do not disturb, definitely not */ 09217 if (p->dnd) 09218 return 0; 09219 /* If guard time, definitely not */ 09220 if (p->guardtime && (time(NULL) < p->guardtime)) 09221 return 0; 09222 09223 /* If no owner definitely available */ 09224 if (!p->owner) { 09225 #ifdef HAVE_PRI 09226 /* Trust PRI */ 09227 if (p->pri) { 09228 if (p->resetting || p->call) 09229 return 0; 09230 else 09231 return 1; 09232 } 09233 #endif 09234 #ifdef HAVE_OPENR2 09235 /* Trust MFC/R2 */ 09236 if (p->mfcr2) { 09237 if (p->mfcr2call || p->mfcr2block) 09238 return 0; 09239 else 09240 return 1; 09241 } 09242 #endif 09243 if (!(p->radio || (p->oprmode < 0))) 09244 { 09245 if (!p->sig || (p->sig == SIG_FXSLS)) 09246 return 1; 09247 /* Check hook state */ 09248 if (p->subs[SUB_REAL].dfd > -1) { 09249 memset(&par, 0, sizeof(par)); 09250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09251 } else { 09252 /* Assume not off hook on CVRS */ 09253 res = 0; 09254 par.rxisoffhook = 0; 09255 } 09256 if (res) { 09257 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09258 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09259 /* When "onhook" that means no battery on the line, and thus 09260 it is out of service..., if it's on a TDM card... If it's a channel 09261 bank, there is no telling... */ 09262 if (par.rxbits > -1) 09263 return 1; 09264 if (par.rxisoffhook) 09265 return 1; 09266 else 09267 #ifdef DAHDI_CHECK_HOOKSTATE 09268 return 0; 09269 #else 09270 return 1; 09271 #endif 09272 } else if (par.rxisoffhook) { 09273 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 09274 /* Not available when the other end is off hook */ 09275 return 0; 09276 } 09277 } 09278 return 1; 09279 } 09280 09281 /* If it's not an FXO, forget about call wait */ 09282 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09283 return 0; 09284 09285 if (!p->callwaiting) { 09286 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09287 return 0; 09288 } 09289 09290 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09291 /* If there is already a call waiting call, then we can't take a second one */ 09292 return 0; 09293 } 09294 09295 if ((p->owner->_state != AST_STATE_UP) && 09296 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09297 /* If the current call is not up, then don't allow the call */ 09298 return 0; 09299 } 09300 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09301 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09302 return 0; 09303 } 09304 /* We're cool */ 09305 return 1; 09306 }
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 12890 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().
12891 { 12892 char *c, *chan; 12893 int x, start, finish; 12894 struct dahdi_pvt *tmp; 12895 #ifdef HAVE_PRI 12896 struct dahdi_pri *pri; 12897 int trunkgroup, y; 12898 #endif 12899 12900 if ((reload == 0) && (conf->chan.sig < 0)) { 12901 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 12902 return -1; 12903 } 12904 12905 c = ast_strdupa(value); 12906 12907 #ifdef HAVE_PRI 12908 pri = NULL; 12909 if (iscrv) { 12910 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 12911 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 12912 return -1; 12913 } 12914 if (trunkgroup < 1) { 12915 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 12916 return -1; 12917 } 12918 c += y; 12919 for (y = 0; y < NUM_SPANS; y++) { 12920 if (pris[y].trunkgroup == trunkgroup) { 12921 pri = pris + y; 12922 break; 12923 } 12924 } 12925 if (!pri) { 12926 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 12927 return -1; 12928 } 12929 } 12930 #endif 12931 12932 while ((chan = strsep(&c, ","))) { 12933 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 12934 /* Range */ 12935 } else if (sscanf(chan, "%30d", &start)) { 12936 /* Just one */ 12937 finish = start; 12938 } else if (!strcasecmp(chan, "pseudo")) { 12939 finish = start = CHAN_PSEUDO; 12940 if (found_pseudo) 12941 *found_pseudo = 1; 12942 } else { 12943 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 12944 return -1; 12945 } 12946 if (finish < start) { 12947 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 12948 x = finish; 12949 finish = start; 12950 start = x; 12951 } 12952 12953 for (x = start; x <= finish; x++) { 12954 #ifdef HAVE_PRI 12955 tmp = mkintf(x, conf, pri, reload); 12956 #else 12957 tmp = mkintf(x, conf, NULL, reload); 12958 #endif 12959 12960 if (tmp) { 12961 if (option_verbose > 2) { 12962 #ifdef HAVE_PRI 12963 if (pri) 12964 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 12965 else 12966 #endif 12967 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 12968 } 12969 } else { 12970 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 12971 (reload == 1) ? "reconfigure" : "register", value); 12972 return -1; 12973 } 12974 } 12975 #ifdef HAVE_OPENR2 12976 if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) { 12977 mfcr2_cur_context_index++; 12978 } 12979 #endif 12980 } 12981 12982 return 0; 12983 }
static void build_status | ( | char * | s, | |
size_t | len, | |||
int | status, | |||
int | active | |||
) | [static] |
Definition at line 11460 of file chan_dahdi.c.
References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
11461 { 11462 if (!s || len < 1) { 11463 return; 11464 } 11465 s[0] = '\0'; 11466 if (status & DCHAN_PROVISIONED) 11467 strncat(s, "Provisioned, ", len - strlen(s) - 1); 11468 if (!(status & DCHAN_NOTINALARM)) 11469 strncat(s, "In Alarm, ", len - strlen(s) - 1); 11470 if (status & DCHAN_UP) 11471 strncat(s, "Up", len - strlen(s) - 1); 11472 else 11473 strncat(s, "Down", len - strlen(s) - 1); 11474 if (active) 11475 strncat(s, ", Active", len - strlen(s) - 1); 11476 else 11477 strncat(s, ", Standby", len - strlen(s) - 1); 11478 s[len - 1] = '\0'; 11479 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2526 of file chan_dahdi.c.
References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by ss_thread().
02527 { 02528 int res; 02529 02530 /* Bump receive gain by 5.0db */ 02531 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 02532 if (res) { 02533 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02534 return -1; 02535 } 02536 02537 return 0; 02538 }
static int calc_energy | ( | const unsigned char * | buf, | |
int | len, | |||
int | law | |||
) | [static] |
Definition at line 7947 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, ast_log(), AST_MULAW, and option_verbose.
07948 { 07949 int x; 07950 int sum = 0; 07951 int ssum = 0, mean = 0; 07952 07953 if (!len) 07954 return 0; 07955 07956 /* First calc mean signal (DC offset) */ 07957 for (x = 0; x < len; x++) 07958 ssum += (law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])); 07959 07960 mean = ssum / len; 07961 07962 for (x = 0; x < len; x++) { 07963 sum += abs((law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x])) - mean); 07964 if (option_verbose > 7) 07965 ast_log(LOG_WARNING, "x %i, bufx: %i sum %i, ssum %i\n", x, buf[x], sum, ssum); 07966 } 07967 07968 if (option_verbose > 5) 07969 ast_log(LOG_WARNING, "mean %i, energy %i\n", mean, sum/len); 07970 07971 return sum / len; 07972 }
Definition at line 9308 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().
09309 { 09310 struct dahdi_pvt *p; 09311 struct dahdi_bufferinfo bi; 09312 int res; 09313 09314 if ((p = ast_malloc(sizeof(*p)))) { 09315 memcpy(p, src, sizeof(struct dahdi_pvt)); 09316 ast_mutex_init(&p->lock); 09317 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO); 09318 /* Allocate a DAHDI structure */ 09319 if (p->subs[SUB_REAL].dfd < 0) { 09320 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09321 destroy_dahdi_pvt(&p); 09322 return NULL; 09323 } 09324 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09325 if (!res) { 09326 bi.txbufpolicy = p->buf_policy; 09327 bi.rxbufpolicy = p->buf_policy; 09328 bi.numbufs = p->buf_no; 09329 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09330 if (res < 0) { 09331 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09332 } 09333 } else 09334 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09335 } 09336 p->destroy = 1; 09337 p->next = iflist; 09338 p->prev = NULL; 09339 iflist = p; 09340 if (iflist->next) 09341 iflist->next->prev = p; 09342 return p; 09343 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4770 of file chan_dahdi.c.
References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event().
04771 { 04772 struct dahdi_confinfo ci; 04773 /* Fine if we already have a master, etc */ 04774 if (p->master || (p->confno > -1)) 04775 return 0; 04776 memset(&ci, 0, sizeof(ci)); 04777 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04778 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04779 return 0; 04780 } 04781 /* If we have no master and don't have a confno, then 04782 if we're in a conference, it's probably a MeetMe room or 04783 some such, so don't let us 3-way out! */ 04784 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04785 if (option_verbose > 2) 04786 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 04787 return 1; 04788 } 04789 return 0; 04790 }
static char* complete_span_4 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11327 of file chan_dahdi.c.
References complete_span_helper().
11328 { 11329 return complete_span_helper(line,word,pos,state,3); 11330 }
static char* complete_span_5 | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 11332 of file chan_dahdi.c.
References complete_span_helper().
11333 { 11334 return complete_span_helper(line,word,pos,state,4); 11335 }
static char* complete_span_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos | |||
) | [static] |
Definition at line 11308 of file chan_dahdi.c.
References asprintf, ast_log(), errno, NUM_SPANS, and pris.
Referenced by complete_span_4(), and complete_span_5().
11309 { 11310 int which, span; 11311 char *ret = NULL; 11312 11313 if (pos != rpos) 11314 return ret; 11315 11316 for (which = span = 0; span < NUM_SPANS; span++) { 11317 if (pris[span].pri && ++which > state) { 11318 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 11319 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 11320 } 11321 break; 11322 } 11323 } 11324 return ret; 11325 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 2168 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_DEBUG, and LOG_WARNING.
Referenced by update_conf().
02169 { 02170 /* If the conference already exists, and we're already in it 02171 don't bother doing anything */ 02172 struct dahdi_confinfo zi; 02173 02174 memset(&zi, 0, sizeof(zi)); 02175 zi.chan = 0; 02176 02177 if (slavechannel > 0) { 02178 /* If we have only one slave, do a digital mon */ 02179 zi.confmode = DAHDI_CONF_DIGITALMON; 02180 zi.confno = slavechannel; 02181 } else { 02182 if (!index) { 02183 /* Real-side and pseudo-side both participate in conference */ 02184 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 02185 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02186 } else 02187 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02188 zi.confno = p->confno; 02189 } 02190 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 02191 return 0; 02192 if (c->dfd < 0) 02193 return 0; 02194 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02195 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 02196 return -1; 02197 } 02198 if (slavechannel < 1) { 02199 p->confno = zi.confno; 02200 } 02201 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02202 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02203 return 0; 02204 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 2217 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), LOG_DEBUG, and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
02218 { 02219 struct dahdi_confinfo zi; 02220 if (/* Can't delete if there's no dfd */ 02221 (c->dfd < 0) || 02222 /* Don't delete from the conference if it's not our conference */ 02223 !isourconf(p, c) 02224 /* Don't delete if we don't think it's conferenced at all (implied) */ 02225 ) return 0; 02226 memset(&zi, 0, sizeof(zi)); 02227 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02228 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 02229 return -1; 02230 } 02231 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02232 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02233 return 0; 02234 }
static int dahdi_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3445 of file chan_dahdi.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_strlen_zero(), dahdi_tech, f, LOG_DEBUG, parse(), and ast_channel::tech.
Referenced by load_module(), and zap_accept_r2_call_exec().
03446 { 03447 /* data is whether to accept with charge or no charge */ 03448 openr2_call_mode_t accept_mode; 03449 int res, timeout, maxloops; 03450 struct ast_frame *f; 03451 struct dahdi_pvt *p; 03452 char *parse; 03453 AST_DECLARE_APP_ARGS(args, 03454 AST_APP_ARG(charge); 03455 ); 03456 03457 if (ast_strlen_zero(data)) { 03458 ast_log(LOG_DEBUG, "No data sent to application!\n"); 03459 return -1; 03460 } 03461 03462 if (chan->tech != &dahdi_tech) { 03463 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n"); 03464 return -1; 03465 } 03466 03467 p = (struct dahdi_pvt *)chan->tech_pvt; 03468 if (!p) { 03469 ast_log(LOG_DEBUG, "Unable to find technology private!\n"); 03470 return -1; 03471 } 03472 03473 parse = ast_strdupa(data); 03474 AST_STANDARD_APP_ARGS(args, parse); 03475 03476 if (ast_strlen_zero(args.charge)) { 03477 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n"); 03478 return -1; 03479 } 03480 03481 ast_mutex_lock(&p->lock); 03482 if (!p->mfcr2 || !p->mfcr2call) { 03483 ast_mutex_unlock(&p->lock); 03484 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name); 03485 return -1; 03486 } 03487 03488 if (p->mfcr2_call_accepted) { 03489 ast_mutex_unlock(&p->lock); 03490 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name); 03491 return 0; 03492 } 03493 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE; 03494 if (openr2_chan_accept_call(p->r2chan, accept_mode)) { 03495 ast_mutex_unlock(&p->lock); 03496 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03497 return -1; 03498 } 03499 ast_mutex_unlock(&p->lock); 03500 03501 res = 0; 03502 timeout = 100; 03503 maxloops = 50; /* wait up to 5 seconds */ 03504 /* we need to read() until the call is accepted */ 03505 while (maxloops > 0) { 03506 maxloops--; 03507 if (ast_check_hangup(chan)) { 03508 break; 03509 } 03510 res = ast_waitfor(chan, timeout); 03511 if (res < 0) { 03512 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name); 03513 res = -1; 03514 break; 03515 } 03516 if (res == 0) { 03517 continue; 03518 } 03519 f = ast_read(chan); 03520 if (!f) { 03521 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name); 03522 res = -1; 03523 break; 03524 } 03525 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 03526 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name); 03527 ast_frfree(f); 03528 res = -1; 03529 break; 03530 } 03531 ast_frfree(f); 03532 ast_mutex_lock(&p->lock); 03533 if (p->mfcr2_call_accepted) { 03534 ast_mutex_unlock(&p->lock); 03535 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n"); 03536 break; 03537 } 03538 ast_mutex_unlock(&p->lock); 03539 } 03540 if (res == -1) { 03541 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n"); 03542 } 03543 return res; 03544 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12709 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12710 { 12711 return __action_dialoffhook(s, m, 0); 12712 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12609 of file chan_dahdi.c.
References __action_dnd(), and s.
12610 { 12611 return __action_dnd(s, m, 0, 0); 12612 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12599 of file chan_dahdi.c.
References __action_dnd(), and s.
12600 { 12601 return __action_dnd(s, m, 0, 1); 12602 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12788 of file chan_dahdi.c.
References __action_restart(), and s.
12789 { 12790 return __action_restart(s, m, 0); 12791 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12764 of file chan_dahdi.c.
References __action_showchannels(), and s.
12765 { 12766 return __action_showchannels(s, m, 0); 12767 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12638 of file chan_dahdi.c.
References __action_transfer(), and s.
12639 { 12640 return __action_transfer(s, m, 0); 12641 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12666 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12667 { 12668 return __action_transferhangup(s, m, 0); 12669 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3946 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_get_index(), dahdi_r2_answer(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_charge_calls, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
03947 { 03948 struct dahdi_pvt *p = ast->tech_pvt; 03949 int res = 0; 03950 int index; 03951 int oldstate = ast->_state; 03952 ast_setstate(ast, AST_STATE_UP); 03953 ast_mutex_lock(&p->lock); 03954 index = dahdi_get_index(ast, p, 0); 03955 if (index < 0) 03956 index = SUB_REAL; 03957 /* nothing to do if a radio channel */ 03958 if ((p->radio || (p->oprmode < 0))) { 03959 ast_mutex_unlock(&p->lock); 03960 return 0; 03961 } 03962 switch (p->sig) { 03963 case SIG_FXSLS: 03964 case SIG_FXSGS: 03965 case SIG_FXSKS: 03966 p->ringt = 0; 03967 /* Fall through */ 03968 case SIG_EM: 03969 case SIG_EM_E1: 03970 case SIG_EMWINK: 03971 case SIG_FEATD: 03972 case SIG_FEATDMF: 03973 case SIG_FEATDMF_TA: 03974 case SIG_E911: 03975 case SIG_FGC_CAMA: 03976 case SIG_FGC_CAMAMF: 03977 case SIG_FEATB: 03978 case SIG_SF: 03979 case SIG_SFWINK: 03980 case SIG_SF_FEATD: 03981 case SIG_SF_FEATDMF: 03982 case SIG_SF_FEATB: 03983 case SIG_FXOLS: 03984 case SIG_FXOGS: 03985 case SIG_FXOKS: 03986 /* Pick up the line */ 03987 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 03988 if (p->hanguponpolarityswitch) { 03989 gettimeofday(&p->polaritydelaytv, NULL); 03990 } 03991 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03992 tone_zone_play_tone(p->subs[index].dfd, -1); 03993 p->dialing = 0; 03994 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03995 if (oldstate == AST_STATE_RINGING) { 03996 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 03997 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03998 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03999 p->owner = p->subs[SUB_REAL].owner; 04000 } 04001 } 04002 if (p->sig & __DAHDI_SIG_FXS) { 04003 dahdi_enable_ec(p); 04004 dahdi_train_ec(p); 04005 } 04006 break; 04007 #ifdef HAVE_PRI 04008 case SIG_PRI: 04009 /* Send a pri acknowledge */ 04010 if (!pri_grab(p, p->pri)) { 04011 p->proceeding = 1; 04012 p->dialing = 0; 04013 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04014 pri_rel(p->pri); 04015 } else { 04016 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04017 res = -1; 04018 } 04019 break; 04020 #endif 04021 #ifdef HAVE_OPENR2 04022 case SIG_MFCR2: 04023 if (!p->mfcr2_accept_on_offer) { 04024 /* the call was not accepted on offer, so it must be accepted now before answering, 04025 the answer will be executed when the callback on_call_accepted is executed */ 04026 if (p->mfcr2_charge_calls) { 04027 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel); 04028 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04029 } else { 04030 ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel); 04031 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04032 } 04033 } else { 04034 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04035 res = dahdi_r2_answer(p); 04036 } 04037 break; 04038 #endif 04039 case 0: 04040 ast_mutex_unlock(&p->lock); 04041 return 0; 04042 default: 04043 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04044 res = -1; 04045 } 04046 ast_mutex_unlock(&p->lock); 04047 return res; 04048 }
static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause | ( | int | cause | ) | [static] |
Definition at line 3551 of file chan_dahdi.c.
References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INTERWORKING, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), and LOG_DEBUG.
Referenced by dahdi_hangup().
03552 { 03553 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING; 03554 switch (cause) { 03555 case AST_CAUSE_USER_BUSY: 03556 case AST_CAUSE_CALL_REJECTED: 03557 case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */ 03558 r2cause = OR2_CAUSE_BUSY_NUMBER; 03559 break; 03560 03561 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION: 03562 case AST_CAUSE_SWITCH_CONGESTION: 03563 r2cause = OR2_CAUSE_NETWORK_CONGESTION; 03564 break; 03565 03566 case AST_CAUSE_UNALLOCATED: 03567 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER; 03568 break; 03569 03570 case AST_CAUSE_NETWORK_OUT_OF_ORDER: 03571 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 03572 r2cause = OR2_CAUSE_OUT_OF_ORDER; 03573 break; 03574 03575 case AST_CAUSE_NO_ANSWER: 03576 case AST_CAUSE_NO_USER_RESPONSE: 03577 r2cause = OR2_CAUSE_NO_ANSWER; 03578 break; 03579 03580 default: 03581 r2cause = OR2_CAUSE_NORMAL_CLEARING; 03582 break; 03583 } 03584 ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 03585 r2cause, openr2_proto_get_disconnect_string(r2cause), cause); 03586 return r2cause; 03587 }
static enum ast_bridge_result dahdi_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) | [static] |
Definition at line 4373 of file chan_dahdi.c.
References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, ast_channel::name, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.
04374 { 04375 struct ast_channel *who; 04376 struct dahdi_pvt *p0, *p1, *op0, *op1; 04377 struct dahdi_pvt *master = NULL, *slave = NULL; 04378 struct ast_frame *f; 04379 int inconf = 0; 04380 int nothingok = 1; 04381 int ofd0, ofd1; 04382 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04383 int os0 = -1, os1 = -1; 04384 int priority = 0; 04385 struct ast_channel *oc0, *oc1; 04386 enum ast_bridge_result res; 04387 04388 #ifdef PRI_2BCT 04389 int triedtopribridge = 0; 04390 q931_call *q931c0 = NULL, *q931c1 = NULL; 04391 #endif 04392 04393 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04394 There is code below to handle it properly until DTMF is actually seen, 04395 but due to currently unresolved issues it's ignored... 04396 */ 04397 04398 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04399 return AST_BRIDGE_FAILED_NOWARN; 04400 04401 ast_mutex_lock(&c0->lock); 04402 while (ast_mutex_trylock(&c1->lock)) { 04403 DEADLOCK_AVOIDANCE(&c0->lock); 04404 } 04405 04406 p0 = c0->tech_pvt; 04407 p1 = c1->tech_pvt; 04408 /* cant do pseudo-channels here */ 04409 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04410 ast_mutex_unlock(&c0->lock); 04411 ast_mutex_unlock(&c1->lock); 04412 return AST_BRIDGE_FAILED_NOWARN; 04413 } 04414 04415 oi0 = dahdi_get_index(c0, p0, 0); 04416 oi1 = dahdi_get_index(c1, p1, 0); 04417 if ((oi0 < 0) || (oi1 < 0)) { 04418 ast_mutex_unlock(&c0->lock); 04419 ast_mutex_unlock(&c1->lock); 04420 return AST_BRIDGE_FAILED; 04421 } 04422 04423 op0 = p0 = c0->tech_pvt; 04424 op1 = p1 = c1->tech_pvt; 04425 ofd0 = c0->fds[0]; 04426 ofd1 = c1->fds[0]; 04427 oc0 = p0->owner; 04428 oc1 = p1->owner; 04429 04430 if (ast_mutex_trylock(&p0->lock)) { 04431 /* Don't block, due to potential for deadlock */ 04432 ast_mutex_unlock(&c0->lock); 04433 ast_mutex_unlock(&c1->lock); 04434 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04435 return AST_BRIDGE_RETRY; 04436 } 04437 if (ast_mutex_trylock(&p1->lock)) { 04438 /* Don't block, due to potential for deadlock */ 04439 ast_mutex_unlock(&p0->lock); 04440 ast_mutex_unlock(&c0->lock); 04441 ast_mutex_unlock(&c1->lock); 04442 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04443 return AST_BRIDGE_RETRY; 04444 } 04445 04446 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04447 if (p0->owner && p1->owner) { 04448 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04449 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04450 master = p0; 04451 slave = p1; 04452 inconf = 1; 04453 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04454 master = p1; 04455 slave = p0; 04456 inconf = 1; 04457 } else { 04458 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04459 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04460 p0->channel, 04461 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04462 p0->subs[SUB_REAL].inthreeway, p0->channel, 04463 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04464 p1->subs[SUB_REAL].inthreeway); 04465 } 04466 nothingok = 0; 04467 } 04468 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04469 if (p1->subs[SUB_THREEWAY].inthreeway) { 04470 master = p1; 04471 slave = p0; 04472 nothingok = 0; 04473 } 04474 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04475 if (p0->subs[SUB_THREEWAY].inthreeway) { 04476 master = p0; 04477 slave = p1; 04478 nothingok = 0; 04479 } 04480 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04481 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04482 don't put us in anything */ 04483 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04484 master = p1; 04485 slave = p0; 04486 nothingok = 0; 04487 } 04488 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04489 /* Same as previous */ 04490 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04491 master = p0; 04492 slave = p1; 04493 nothingok = 0; 04494 } 04495 } 04496 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 04497 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04498 if (master && slave) { 04499 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04500 in an active threeway call with a channel that is ringing, we should 04501 indicate ringing. */ 04502 if ((oi1 == SUB_THREEWAY) && 04503 p1->subs[SUB_THREEWAY].inthreeway && 04504 p1->subs[SUB_REAL].owner && 04505 p1->subs[SUB_REAL].inthreeway && 04506 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04507 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04508 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04509 os1 = p1->subs[SUB_REAL].owner->_state; 04510 } else { 04511 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04512 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04513 } 04514 if ((oi0 == SUB_THREEWAY) && 04515 p0->subs[SUB_THREEWAY].inthreeway && 04516 p0->subs[SUB_REAL].owner && 04517 p0->subs[SUB_REAL].inthreeway && 04518 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04519 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04520 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04521 os0 = p0->subs[SUB_REAL].owner->_state; 04522 } else { 04523 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04524 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04525 } 04526 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04527 if (!p0->echocanbridged || !p1->echocanbridged) { 04528 /* Disable echo cancellation if appropriate */ 04529 dahdi_disable_ec(p0); 04530 dahdi_disable_ec(p1); 04531 } 04532 } 04533 dahdi_link(slave, master); 04534 master->inconference = inconf; 04535 } else if (!nothingok) 04536 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04537 04538 update_conf(p0); 04539 update_conf(p1); 04540 t0 = p0->subs[SUB_REAL].inthreeway; 04541 t1 = p1->subs[SUB_REAL].inthreeway; 04542 04543 ast_mutex_unlock(&p0->lock); 04544 ast_mutex_unlock(&p1->lock); 04545 04546 ast_mutex_unlock(&c0->lock); 04547 ast_mutex_unlock(&c1->lock); 04548 04549 /* Native bridge failed */ 04550 if ((!master || !slave) && !nothingok) { 04551 dahdi_enable_ec(p0); 04552 dahdi_enable_ec(p1); 04553 return AST_BRIDGE_FAILED; 04554 } 04555 04556 if (option_verbose > 2) 04557 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 04558 04559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04560 disable_dtmf_detect(op0); 04561 04562 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04563 disable_dtmf_detect(op1); 04564 04565 for (;;) { 04566 struct ast_channel *c0_priority[2] = {c0, c1}; 04567 struct ast_channel *c1_priority[2] = {c1, c0}; 04568 04569 /* Here's our main loop... Start by locking things, looking for private parts, 04570 and then balking if anything is wrong */ 04571 ast_mutex_lock(&c0->lock); 04572 while (ast_mutex_trylock(&c1->lock)) { 04573 DEADLOCK_AVOIDANCE(&c0->lock); 04574 } 04575 04576 p0 = c0->tech_pvt; 04577 p1 = c1->tech_pvt; 04578 04579 if (op0 == p0) 04580 i0 = dahdi_get_index(c0, p0, 1); 04581 if (op1 == p1) 04582 i1 = dahdi_get_index(c1, p1, 1); 04583 ast_mutex_unlock(&c0->lock); 04584 ast_mutex_unlock(&c1->lock); 04585 04586 if (!timeoutms || 04587 (op0 != p0) || 04588 (op1 != p1) || 04589 (ofd0 != c0->fds[0]) || 04590 (ofd1 != c1->fds[0]) || 04591 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04592 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04593 (oc0 != p0->owner) || 04594 (oc1 != p1->owner) || 04595 (t0 != p0->subs[SUB_REAL].inthreeway) || 04596 (t1 != p1->subs[SUB_REAL].inthreeway) || 04597 (oi0 != i0) || 04598 (oi1 != i1)) { 04599 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04600 op0->channel, oi0, op1->channel, oi1); 04601 res = AST_BRIDGE_RETRY; 04602 goto return_from_bridge; 04603 } 04604 04605 #ifdef PRI_2BCT 04606 q931c0 = p0->call; 04607 q931c1 = p1->call; 04608 if (p0->transfer && p1->transfer 04609 && q931c0 && q931c1 04610 && !triedtopribridge) { 04611 pri_channel_bridge(q931c0, q931c1); 04612 triedtopribridge = 1; 04613 } 04614 #endif 04615 04616 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04617 if (!who) { 04618 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 04619 continue; 04620 } 04621 f = ast_read(who); 04622 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04623 *fo = f; 04624 *rc = who; 04625 res = AST_BRIDGE_COMPLETE; 04626 goto return_from_bridge; 04627 } 04628 if (f->frametype == AST_FRAME_DTMF) { 04629 if ((who == c0) && p0->pulsedial) { 04630 ast_write(c1, f); 04631 } else if ((who == c1) && p1->pulsedial) { 04632 ast_write(c0, f); 04633 } else { 04634 *fo = f; 04635 *rc = who; 04636 res = AST_BRIDGE_COMPLETE; 04637 goto return_from_bridge; 04638 } 04639 } 04640 ast_frfree(f); 04641 04642 /* Swap who gets priority */ 04643 priority = !priority; 04644 } 04645 04646 return_from_bridge: 04647 if (op0 == p0) 04648 dahdi_enable_ec(p0); 04649 04650 if (op1 == p1) 04651 dahdi_enable_ec(p1); 04652 04653 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04654 enable_dtmf_detect(op0); 04655 04656 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04657 enable_dtmf_detect(op1); 04658 04659 dahdi_unlink(slave, master, 1); 04660 04661 return res; 04662 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 2714 of file chan_dahdi.c.
References ast_channel::_state, ast_callerid_generate(), ast_copy_string(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_r2_get_channel_category(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, dahdi_pvt::mfcr2, ast_channel::name, dahdi_pri::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
02715 { 02716 struct dahdi_pvt *p = ast->tech_pvt; 02717 int x, res, index,mysig; 02718 char *c, *n, *l; 02719 #ifdef HAVE_PRI 02720 char *s = NULL; 02721 #endif 02722 char dest[256]; /* must be same length as p->dialdest */ 02723 ast_mutex_lock(&p->lock); 02724 ast_copy_string(dest, rdest, sizeof(dest)); 02725 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02726 if ((ast->_state == AST_STATE_BUSY)) { 02727 p->subs[SUB_REAL].needbusy = 1; 02728 ast_mutex_unlock(&p->lock); 02729 return 0; 02730 } 02731 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02732 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02733 ast_mutex_unlock(&p->lock); 02734 return -1; 02735 } 02736 p->dialednone = 0; 02737 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02738 { 02739 /* Special pseudo -- automatically up */ 02740 ast_setstate(ast, AST_STATE_UP); 02741 ast_mutex_unlock(&p->lock); 02742 return 0; 02743 } 02744 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02745 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02746 if (res) 02747 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02748 p->outgoing = 1; 02749 02750 if (IS_DIGITAL(ast->transfercapability)) { 02751 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02752 } else { 02753 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02754 } 02755 02756 mysig = p->sig; 02757 if (p->outsigmod > -1) 02758 mysig = p->outsigmod; 02759 02760 switch (mysig) { 02761 case SIG_FXOLS: 02762 case SIG_FXOGS: 02763 case SIG_FXOKS: 02764 if (p->owner == ast) { 02765 /* Normal ring, on hook */ 02766 02767 /* Don't send audio while on hook, until the call is answered */ 02768 p->dialing = 1; 02769 if (p->use_callerid) { 02770 /* Generate the Caller-ID spill if desired */ 02771 if (p->cidspill) { 02772 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02773 free(p->cidspill); 02774 } 02775 p->callwaitcas = 0; 02776 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02777 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02778 p->cidpos = 0; 02779 send_callerid(p); 02780 } 02781 } 02782 /* Choose proper cadence */ 02783 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02784 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02785 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02786 p->cidrings = cidrings[p->distinctivering - 1]; 02787 } else { 02788 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02789 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02790 p->cidrings = p->sendcalleridafter; 02791 } 02792 02793 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02794 c = strchr(dest, '/'); 02795 if (c) 02796 c++; 02797 if (c && (strlen(c) < p->stripmsd)) { 02798 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02799 c = NULL; 02800 } 02801 if (c) { 02802 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02803 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02804 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 02805 } else { 02806 p->dop.dialstr[0] = '\0'; 02807 } 02808 x = DAHDI_RING; 02809 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02810 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02811 ast_mutex_unlock(&p->lock); 02812 return -1; 02813 } 02814 p->dialing = 1; 02815 } else { 02816 /* Call waiting call */ 02817 p->callwaitrings = 0; 02818 if (ast->cid.cid_num) 02819 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02820 else 02821 p->callwait_num[0] = '\0'; 02822 if (ast->cid.cid_name) 02823 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02824 else 02825 p->callwait_name[0] = '\0'; 02826 /* Call waiting tone instead */ 02827 if (dahdi_callwait(ast)) { 02828 ast_mutex_unlock(&p->lock); 02829 return -1; 02830 } 02831 /* Make ring-back */ 02832 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02833 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02834 02835 } 02836 n = ast->cid.cid_name; 02837 l = ast->cid.cid_num; 02838 if (l) 02839 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02840 else 02841 p->lastcid_num[0] = '\0'; 02842 if (n) 02843 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02844 else 02845 p->lastcid_name[0] = '\0'; 02846 ast_setstate(ast, AST_STATE_RINGING); 02847 index = dahdi_get_index(ast, p, 0); 02848 if (index > -1) { 02849 p->subs[index].needringing = 1; 02850 } 02851 break; 02852 case SIG_FXSLS: 02853 case SIG_FXSGS: 02854 case SIG_FXSKS: 02855 case SIG_EMWINK: 02856 case SIG_EM: 02857 case SIG_EM_E1: 02858 case SIG_FEATD: 02859 case SIG_FEATDMF: 02860 case SIG_E911: 02861 case SIG_FGC_CAMA: 02862 case SIG_FGC_CAMAMF: 02863 case SIG_FEATB: 02864 case SIG_SFWINK: 02865 case SIG_SF: 02866 case SIG_SF_FEATD: 02867 case SIG_SF_FEATDMF: 02868 case SIG_FEATDMF_TA: 02869 case SIG_SF_FEATB: 02870 c = strchr(dest, '/'); 02871 if (c) 02872 c++; 02873 else 02874 c = ""; 02875 if (strlen(c) < p->stripmsd) { 02876 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02877 ast_mutex_unlock(&p->lock); 02878 return -1; 02879 } 02880 #ifdef HAVE_PRI 02881 /* Start the trunk, if not GR-303 */ 02882 if (!p->pri) { 02883 #endif 02884 x = DAHDI_START; 02885 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02886 if (res < 0) { 02887 if (errno != EINPROGRESS) { 02888 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02889 ast_mutex_unlock(&p->lock); 02890 return -1; 02891 } 02892 } 02893 #ifdef HAVE_PRI 02894 } 02895 #endif 02896 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02897 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02898 02899 c += p->stripmsd; 02900 02901 switch (mysig) { 02902 case SIG_FEATD: 02903 l = ast->cid.cid_num; 02904 if (l) 02905 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02906 else 02907 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02908 break; 02909 case SIG_FEATDMF: 02910 l = ast->cid.cid_num; 02911 if (l) 02912 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02913 else 02914 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02915 break; 02916 case SIG_FEATDMF_TA: 02917 { 02918 const char *cic, *ozz; 02919 02920 /* If you have to go through a Tandem Access point you need to use this */ 02921 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02922 if (!ozz) 02923 ozz = defaultozz; 02924 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02925 if (!cic) 02926 cic = defaultcic; 02927 if (!ozz || !cic) { 02928 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02929 ast_mutex_unlock(&p->lock); 02930 return -1; 02931 } 02932 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02933 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02934 p->whichwink = 0; 02935 } 02936 break; 02937 case SIG_E911: 02938 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02939 break; 02940 case SIG_FGC_CAMA: 02941 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02942 break; 02943 case SIG_FGC_CAMAMF: 02944 case SIG_FEATB: 02945 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02946 break; 02947 default: 02948 if (p->pulse) 02949 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02950 else 02951 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02952 break; 02953 } 02954 02955 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02956 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02957 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02958 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02959 p->echobreak = 1; 02960 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02961 } else 02962 p->echobreak = 0; 02963 if (!res) { 02964 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02965 int saveerr = errno; 02966 02967 x = DAHDI_ONHOOK; 02968 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02969 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02970 ast_mutex_unlock(&p->lock); 02971 return -1; 02972 } 02973 } else 02974 ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res); 02975 p->dialing = 1; 02976 if (ast_strlen_zero(c)) 02977 p->dialednone = 1; 02978 ast_setstate(ast, AST_STATE_DIALING); 02979 break; 02980 case 0: 02981 /* Special pseudo -- automatically up*/ 02982 ast_setstate(ast, AST_STATE_UP); 02983 break; 02984 case SIG_PRI: 02985 case SIG_MFCR2: 02986 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02987 p->dialdest[0] = '\0'; 02988 p->dialing = 1; 02989 break; 02990 default: 02991 ast_log(LOG_DEBUG, "not yet implemented\n"); 02992 ast_mutex_unlock(&p->lock); 02993 return -1; 02994 } 02995 #ifdef HAVE_OPENR2 02996 if (p->mfcr2) { 02997 int strip = p->stripmsd; 02998 int callres = 0; 02999 c = strchr(dest, '/'); 03000 if (c) { 03001 c++; 03002 } else { 03003 c = dest; 03004 } 03005 if (!p->hidecallerid) { 03006 l = ast->cid.cid_num; 03007 } else { 03008 l = NULL; 03009 } 03010 if (strlen(c) < strip) { 03011 ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip); 03012 strip = 0; 03013 } 03014 p->dialing = 1; 03015 callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast)); 03016 if (-1 == callres) { 03017 ast_mutex_unlock(&p->lock); 03018 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03019 return -1; 03020 } 03021 ast_setstate(ast, AST_STATE_DIALING); 03022 } 03023 #endif /* HAVE_OPENR2 */ 03024 #ifdef HAVE_PRI 03025 if (p->pri) { 03026 struct pri_sr *sr; 03027 #ifdef SUPPORT_USERUSER 03028 const char *useruser; 03029 #endif 03030 int pridialplan; 03031 int dp_strip; 03032 int prilocaldialplan; 03033 int ldp_strip; 03034 int exclusive; 03035 const char *rr_str; 03036 int redirect_reason; 03037 03038 c = strchr(dest, '/'); 03039 if (c) { 03040 c++; 03041 } else { 03042 c = ""; 03043 } 03044 03045 l = NULL; 03046 n = NULL; 03047 if (!p->hidecallerid) { 03048 l = ast->cid.cid_num; 03049 if (!p->hidecalleridname) { 03050 n = ast->cid.cid_name; 03051 } 03052 } 03053 03054 03055 if (strlen(c) < p->stripmsd) { 03056 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03057 ast_mutex_unlock(&p->lock); 03058 return -1; 03059 } 03060 if (mysig != SIG_FXSKS) { 03061 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03062 s = strchr(c + p->stripmsd, 'w'); 03063 if (s) { 03064 if (strlen(s) > 1) 03065 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03066 else 03067 p->dop.dialstr[0] = '\0'; 03068 *s = '\0'; 03069 } else { 03070 p->dop.dialstr[0] = '\0'; 03071 } 03072 } 03073 if (pri_grab(p, p->pri)) { 03074 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03075 ast_mutex_unlock(&p->lock); 03076 return -1; 03077 } 03078 if (!(p->call = pri_new_call(p->pri->pri))) { 03079 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03080 pri_rel(p->pri); 03081 ast_mutex_unlock(&p->lock); 03082 return -1; 03083 } 03084 if (!(sr = pri_sr_new())) { 03085 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03086 pri_destroycall(p->pri->pri, p->call); 03087 p->call = NULL; 03088 pri_rel(p->pri); 03089 ast_mutex_unlock(&p->lock); 03090 return -1; 03091 } 03092 if (p->bearer || (mysig == SIG_FXSKS)) { 03093 if (p->bearer) { 03094 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 03095 p->bearer->call = p->call; 03096 } else 03097 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 03098 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03099 } 03100 p->digital = IS_DIGITAL(ast->transfercapability); 03101 03102 /* Should the picked channel be used exclusively? */ 03103 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03104 exclusive = 1; 03105 } else { 03106 exclusive = 0; 03107 } 03108 03109 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03110 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03111 (p->digital ? -1 : 03112 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03113 if (p->pri->facilityenable) 03114 pri_facility_enable(p->pri->pri); 03115 03116 if (option_verbose > 2) 03117 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03118 dp_strip = 0; 03119 pridialplan = p->pri->dialplan - 1; 03120 if (pridialplan == -2) { /* compute dynamically */ 03121 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03122 dp_strip = strlen(p->pri->internationalprefix); 03123 pridialplan = PRI_INTERNATIONAL_ISDN; 03124 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03125 dp_strip = strlen(p->pri->nationalprefix); 03126 pridialplan = PRI_NATIONAL_ISDN; 03127 } else { 03128 pridialplan = PRI_LOCAL_ISDN; 03129 } 03130 } 03131 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03132 03133 ldp_strip = 0; 03134 prilocaldialplan = p->pri->localdialplan - 1; 03135 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 03136 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03137 ldp_strip = strlen(p->pri->internationalprefix); 03138 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03139 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03140 ldp_strip = strlen(p->pri->nationalprefix); 03141 prilocaldialplan = PRI_NATIONAL_ISDN; 03142 } else { 03143 prilocaldialplan = PRI_LOCAL_ISDN; 03144 } 03145 } 03146 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03147 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03148 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03149 if (!strcasecmp(rr_str, "UNKNOWN")) 03150 redirect_reason = 0; 03151 else if (!strcasecmp(rr_str, "BUSY")) 03152 redirect_reason = 1; 03153 else if (!strcasecmp(rr_str, "NO_REPLY")) 03154 redirect_reason = 2; 03155 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03156 redirect_reason = 15; 03157 else 03158 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03159 } else 03160 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03161 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03162 03163 #ifdef SUPPORT_USERUSER 03164 /* User-user info */ 03165 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03166 03167 if (useruser) 03168 pri_sr_set_useruser(sr, useruser); 03169 #endif 03170 03171 if (pri_setup(p->pri->pri, p->call, sr)) { 03172 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03173 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03174 pri_rel(p->pri); 03175 ast_mutex_unlock(&p->lock); 03176 pri_sr_free(sr); 03177 return -1; 03178 } 03179 pri_sr_free(sr); 03180 ast_setstate(ast, AST_STATE_DIALING); 03181 pri_rel(p->pri); 03182 } 03183 #endif 03184 ast_mutex_unlock(&p->lock); 03185 return 0; 03186 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2686 of file chan_dahdi.c.
References ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call().
02687 { 02688 struct dahdi_pvt *p = ast->tech_pvt; 02689 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02690 if (p->cidspill) { 02691 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02692 free(p->cidspill); 02693 } 02694 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02695 return -1; 02696 save_conference(p); 02697 /* Silence */ 02698 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02699 if (!p->callwaitrings && p->callwaitingcallerid) { 02700 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02701 p->callwaitcas = 1; 02702 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02703 } else { 02704 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02705 p->callwaitcas = 0; 02706 p->cidlen = 2400 + READ_SIZE * 4; 02707 } 02708 p->cidpos = 0; 02709 send_callerid(p); 02710 02711 return 0; 02712 }
static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 997 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by setup_dahdi().
00997 { 00998 /* recall that if a field is not included here it is initialized 00999 * to 0 or equivalent 01000 */ 01001 struct dahdi_chan_conf conf = { 01002 #ifdef HAVE_PRI 01003 .pri = { 01004 .nsf = PRI_NSF_NONE, 01005 .switchtype = PRI_SWITCH_NI2, 01006 .dialplan = PRI_NATIONAL_ISDN + 1, 01007 .localdialplan = PRI_NATIONAL_ISDN + 1, 01008 .nodetype = PRI_CPE, 01009 01010 .minunused = 2, 01011 .idleext = "", 01012 .idledial = "", 01013 .internationalprefix = "", 01014 .nationalprefix = "", 01015 .localprefix = "", 01016 .privateprefix = "", 01017 .unknownprefix = "", 01018 01019 .resetinterval = 3600 01020 }, 01021 #endif 01022 .chan = { 01023 .context = "default", 01024 .cid_num = "", 01025 .cid_name = "", 01026 .mohinterpret = "default", 01027 .mohsuggest = "", 01028 .transfertobusy = 1, 01029 01030 .cid_signalling = CID_SIG_BELL, 01031 .cid_start = CID_START_RING, 01032 .dahditrcallerid = 0, 01033 .use_callerid = 1, 01034 .sig = -1, 01035 .outsigmod = -1, 01036 01037 .tonezone = -1, 01038 01039 .echocancel = 1, 01040 01041 .busycount = 3, 01042 .busycompare = 0, 01043 .busytonelength = 0, 01044 .busyquietlength = 0, 01045 .busyfuzziness = 0, 01046 .silencethreshold = 0, 01047 01048 .accountcode = "", 01049 01050 .mailbox = "", 01051 01052 01053 .polarityonanswerdelay = 600, 01054 01055 .sendcalleridafter = DEFAULT_CIDRINGS, 01056 01057 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01058 .buf_no = numbufs 01059 }, 01060 .timing = { 01061 .prewinktime = -1, 01062 .preflashtime = -1, 01063 .winktime = -1, 01064 .flashtime = -1, 01065 .starttime = -1, 01066 .rxwinktime = -1, 01067 .rxflashtime = -1, 01068 .debouncetime = -1 01069 }, 01070 .smdi_port = "/dev/ttyS0", 01071 }; 01072 01073 return conf; 01074 }
static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1847 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().
static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
int | fd_num | |||
) | [static] |
Definition at line 1860 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01861 { 01862 dahdi_close(pri->fds[fd_num]); 01863 pri->fds[fd_num] = -1; 01864 }
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 1853 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().
01854 { 01855 dahdi_close(chan_pvt->subs[sub_num].dfd); 01856 chan_pvt->subs[sub_num].dfd = -1; 01857 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 2570 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().
02571 { 02572 int x, y, res; 02573 x = muted; 02574 if (p->sig == SIG_PRI) { 02575 y = 1; 02576 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02577 if (res) 02578 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02579 } 02580 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02581 if (res < 0) 02582 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02583 return res; 02584 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11964 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
11965 { 11966 int channel; 11967 11968 if (argc != 4) 11969 return RESULT_SHOWUSAGE; 11970 11971 channel = atoi(argv[3]); 11972 11973 return dahdi_destroy_channel_bynum(channel); 11974 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 7975 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().
07976 { 07977 struct dahdi_pvt *tmp = NULL; 07978 struct dahdi_pvt *prev = NULL; 07979 07980 ast_mutex_lock(&iflock); 07981 tmp = iflist; 07982 while (tmp) { 07983 if (tmp->channel == channel) { 07984 int x = DAHDI_FLASH; 07985 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 */ 07986 destroy_channel(prev, tmp, 1); 07987 ast_mutex_unlock(&iflock); 07988 ast_module_unref(ast_module_info->self); 07989 return RESULT_SUCCESS; 07990 } 07991 prev = tmp; 07992 tmp = tmp->next; 07993 } 07994 ast_mutex_unlock(&iflock); 07995 return RESULT_FAILURE; 07996 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1944 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulse, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01945 { 01946 struct dahdi_pvt *pvt; 01947 int index; 01948 int dtmf = -1; 01949 01950 pvt = chan->tech_pvt; 01951 01952 ast_mutex_lock(&pvt->lock); 01953 01954 index = dahdi_get_index(chan, pvt, 0); 01955 01956 if ((index != SUB_REAL) || !pvt->owner) 01957 goto out; 01958 01959 #ifdef HAVE_PRI 01960 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01961 if (pvt->setup_ack) { 01962 if (!pri_grab(pvt, pvt->pri)) { 01963 pri_information(pvt->pri->pri, pvt->call, digit); 01964 pri_rel(pvt->pri); 01965 } else 01966 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01967 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01968 int res; 01969 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01970 res = strlen(pvt->dialdest); 01971 pvt->dialdest[res++] = digit; 01972 pvt->dialdest[res] = '\0'; 01973 } 01974 goto out; 01975 } 01976 #endif 01977 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01978 goto out; 01979 01980 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01981 int res; 01982 struct dahdi_dialoperation zo = { 01983 .op = DAHDI_DIAL_OP_APPEND, 01984 .dialstr[0] = 'T', 01985 .dialstr[1] = digit, 01986 .dialstr[2] = 0, 01987 }; 01988 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01989 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01990 else 01991 pvt->dialing = 1; 01992 } else { 01993 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01994 pvt->dialing = 1; 01995 pvt->begindigit = digit; 01996 } 01997 01998 out: 01999 ast_mutex_unlock(&pvt->lock); 02000 02001 return 0; 02002 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2004 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
02005 { 02006 struct dahdi_pvt *pvt; 02007 int res = 0; 02008 int index; 02009 int x; 02010 02011 pvt = chan->tech_pvt; 02012 02013 ast_mutex_lock(&pvt->lock); 02014 02015 index = dahdi_get_index(chan, pvt, 0); 02016 02017 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 02018 goto out; 02019 02020 #ifdef HAVE_PRI 02021 /* This means that the digit was already sent via PRI signalling */ 02022 if (pvt->sig == SIG_PRI && !pvt->begindigit) 02023 goto out; 02024 #endif 02025 02026 if (pvt->begindigit) { 02027 x = -1; 02028 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 02029 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 02030 pvt->dialing = 0; 02031 pvt->begindigit = 0; 02032 } 02033 02034 out: 02035 ast_mutex_unlock(&pvt->lock); 02036 02037 return res; 02038 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2401 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().
02402 { 02403 int x; 02404 int res; 02405 if (p->echocancel) { 02406 x = 0; 02407 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02408 if (res) 02409 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02410 else if (option_debug) 02411 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 02412 } 02413 p->echocanon = 0; 02414 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2351 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_r2_on_call_accepted(), dahdi_setoption(), handle_init_event(), and ss_thread().
02352 { 02353 int x; 02354 int res; 02355 if (!p) 02356 return; 02357 if (p->echocanon) { 02358 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 02359 return; 02360 } 02361 if (p->digital) { 02362 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 02363 return; 02364 } 02365 if (p->echocancel) { 02366 if (p->sig == SIG_PRI) { 02367 x = 1; 02368 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02369 if (res) 02370 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02371 } 02372 x = p->echocancel; 02373 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 02374 if (res) 02375 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02376 else { 02377 p->echocanon = 1; 02378 if (option_debug) 02379 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 02380 } 02381 } else if (option_debug) 02382 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 02383 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5899 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05900 { 05901 struct dahdi_pvt *p = ast->tech_pvt; 05902 struct ast_frame *f; 05903 ast_mutex_lock(&p->lock); 05904 f = __dahdi_exception(ast); 05905 ast_mutex_unlock(&p->lock); 05906 return f; 05907 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 12544 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().
12545 { 12546 if (p) { 12547 switch (mode) { 12548 case TRANSFER: 12549 p->fake_event = DAHDI_EVENT_WINKFLASH; 12550 break; 12551 case HANGUP: 12552 p->fake_event = DAHDI_EVENT_ONHOOK; 12553 break; 12554 default: 12555 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 12556 } 12557 } 12558 return 0; 12559 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 4664 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.
04665 { 04666 struct dahdi_pvt *p = newchan->tech_pvt; 04667 int x; 04668 ast_mutex_lock(&p->lock); 04669 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 04670 if (p->owner == oldchan) { 04671 p->owner = newchan; 04672 } 04673 for (x = 0; x < 3; x++) 04674 if (p->subs[x].owner == oldchan) { 04675 if (!x) 04676 dahdi_unlink(NULL, p, 0); 04677 p->subs[x].owner = newchan; 04678 } 04679 if (newchan->_state == AST_STATE_RINGING) 04680 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04681 update_conf(p); 04682 ast_mutex_unlock(&p->lock); 04683 return 0; 04684 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 4236 of file chan_dahdi.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.
04237 { 04238 struct dahdi_pvt *p = chan->tech_pvt; 04239 04240 if (!strcasecmp(data, "rxgain")) { 04241 ast_mutex_lock(&p->lock); 04242 snprintf(buf, len, "%f", p->rxgain); 04243 ast_mutex_unlock(&p->lock); 04244 } else if (!strcasecmp(data, "txgain")) { 04245 ast_mutex_lock(&p->lock); 04246 snprintf(buf, len, "%f", p->txgain); 04247 ast_mutex_unlock(&p->lock); 04248 } else { 04249 ast_copy_string(buf, "", len); 04250 } 04251 return 0; 04252 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 272 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00273 { 00274 int j; 00275 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00276 return -1; 00277 return j; 00278 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 1190 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), dahdi_write(), and ss_thread().
01191 { 01192 int res; 01193 if (p->subs[SUB_REAL].owner == ast) 01194 res = 0; 01195 else if (p->subs[SUB_CALLWAIT].owner == ast) 01196 res = 1; 01197 else if (p->subs[SUB_THREEWAY].owner == ast) 01198 res = 2; 01199 else { 01200 res = -1; 01201 if (!nullok) 01202 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01203 } 01204 return res; 01205 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 4826 of file chan_dahdi.c.
References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, free, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event().
04827 { 04828 struct dahdi_pvt *p = ast->tech_pvt; 04829 struct ast_frame *f = *dest; 04830 04831 if (option_debug) 04832 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04833 04834 if (p->confirmanswer) { 04835 if (option_debug) 04836 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 04837 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04838 of a DTMF digit */ 04839 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04840 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04841 *dest = &p->subs[index].f; 04842 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04843 p->confirmanswer = 0; 04844 } else if (p->callwaitcas) { 04845 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04846 if (option_debug) 04847 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 04848 if (p->cidspill) 04849 free(p->cidspill); 04850 send_cwcidspill(p); 04851 } 04852 if ((f->subclass != 'm') && (f->subclass != 'u')) 04853 p->callwaitcas = 0; 04854 p->subs[index].f.frametype = AST_FRAME_NULL; 04855 p->subs[index].f.subclass = 0; 04856 *dest = &p->subs[index].f; 04857 } else if (f->subclass == 'f') { 04858 /* Fax tone -- Handle and return NULL */ 04859 if ((p->callprogress & 0x6) && !p->faxhandled) { 04860 p->faxhandled = 1; 04861 if (strcmp(ast->exten, "fax")) { 04862 const char *target_context = S_OR(ast->macrocontext, ast->context); 04863 04864 /* We need to unlock 'ast' here because ast_exists_extension has the 04865 * potential to start autoservice on the channel. Such action is prone 04866 * to deadlock. 04867 */ 04868 ast_mutex_unlock(&p->lock); 04869 ast_channel_unlock(ast); 04870 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04871 ast_channel_lock(ast); 04872 ast_mutex_lock(&p->lock); 04873 if (option_verbose > 2) 04874 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 04875 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04876 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04877 if (ast_async_goto(ast, target_context, "fax", 1)) 04878 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04879 } else { 04880 ast_channel_lock(ast); 04881 ast_mutex_lock(&p->lock); 04882 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04883 } 04884 } else if (option_debug) 04885 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 04886 } else if (option_debug) 04887 ast_log(LOG_DEBUG, "Fax already handled\n"); 04888 dahdi_confmute(p, 0); 04889 p->subs[index].f.frametype = AST_FRAME_NULL; 04890 p->subs[index].f.subclass = 0; 04891 *dest = &p->subs[index].f; 04892 } else if (f->subclass == 'm') { 04893 /* Confmute request */ 04894 dahdi_confmute(p, 1); 04895 p->subs[index].f.frametype = AST_FRAME_NULL; 04896 p->subs[index].f.subclass = 0; 04897 *dest = &p->subs[index].f; 04898 } else if (f->subclass == 'u') { 04899 /* Unmute */ 04900 dahdi_confmute(p, 0); 04901 p->subs[index].f.frametype = AST_FRAME_NULL; 04902 p->subs[index].f.subclass = 0; 04903 *dest = &p->subs[index].f; 04904 } else 04905 dahdi_confmute(p, 0); 04906 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4928 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verbose(), attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
04929 { 04930 int res, x; 04931 int index, mysig; 04932 char *c; 04933 struct dahdi_pvt *p = ast->tech_pvt; 04934 pthread_t threadid; 04935 pthread_attr_t attr; 04936 struct ast_channel *chan; 04937 struct ast_frame *f; 04938 04939 index = dahdi_get_index(ast, p, 0); 04940 mysig = p->sig; 04941 if (p->outsigmod > -1) 04942 mysig = p->outsigmod; 04943 p->subs[index].f.frametype = AST_FRAME_NULL; 04944 p->subs[index].f.subclass = 0; 04945 p->subs[index].f.datalen = 0; 04946 p->subs[index].f.samples = 0; 04947 p->subs[index].f.mallocd = 0; 04948 p->subs[index].f.offset = 0; 04949 p->subs[index].f.src = "dahdi_handle_event"; 04950 p->subs[index].f.data = NULL; 04951 f = &p->subs[index].f; 04952 04953 if (index < 0) 04954 return &p->subs[index].f; 04955 if (p->fake_event) { 04956 res = p->fake_event; 04957 p->fake_event = 0; 04958 } else 04959 res = dahdi_get_event(p->subs[index].dfd); 04960 04961 if (option_debug) 04962 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 04963 04964 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04965 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04966 04967 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04968 #ifdef HAVE_PRI 04969 if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04970 /* absorb event */ 04971 } else { 04972 #endif 04973 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 04974 p->subs[index].f.subclass = res & 0xff; 04975 #ifdef HAVE_PRI 04976 } 04977 #endif 04978 dahdi_handle_dtmfup(ast, index, &f); 04979 return f; 04980 } 04981 04982 if (res & DAHDI_EVENT_DTMFDOWN) { 04983 if (option_debug) 04984 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 04985 /* Mute conference */ 04986 dahdi_confmute(p, 1); 04987 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 04988 p->subs[index].f.subclass = res & 0xff; 04989 return &p->subs[index].f; 04990 } 04991 04992 switch (res) { 04993 #ifdef DAHDI_EVENT_EC_DISABLED 04994 case DAHDI_EVENT_EC_DISABLED: 04995 if (option_verbose > 2) 04996 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04997 p->echocanon = 0; 04998 break; 04999 #endif 05000 case DAHDI_EVENT_BITSCHANGED: 05001 #ifdef HAVE_OPENR2 05002 if (p->sig != SIG_MFCR2) { 05003 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05004 } else { 05005 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 05006 openr2_chan_handle_cas(p->r2chan); 05007 } 05008 #else 05009 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 05010 #endif 05011 case DAHDI_EVENT_PULSE_START: 05012 /* Stop tone if there's a pulse start and the PBX isn't started */ 05013 if (!ast->pbx) 05014 tone_zone_play_tone(p->subs[index].dfd, -1); 05015 break; 05016 case DAHDI_EVENT_DIALCOMPLETE: 05017 #ifdef HAVE_OPENR2 05018 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05019 /* we don't need to do anything for this event for R2 signaling 05020 if the call is being setup */ 05021 break; 05022 } 05023 #endif 05024 if (p->inalarm) break; 05025 if ((p->radio || (p->oprmode < 0))) break; 05026 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 05027 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05028 return NULL; 05029 } 05030 if (!x) { /* if not still dialing in driver */ 05031 dahdi_enable_ec(p); 05032 if (p->echobreak) { 05033 dahdi_train_ec(p); 05034 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05035 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05037 p->echobreak = 0; 05038 } else { 05039 p->dialing = 0; 05040 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05041 /* if thru with dialing after offhook */ 05042 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05043 ast_setstate(ast, AST_STATE_UP); 05044 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05045 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05046 break; 05047 } else { /* if to state wait for offhook to dial rest */ 05048 /* we now wait for off hook */ 05049 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05050 } 05051 } 05052 if (ast->_state == AST_STATE_DIALING) { 05053 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05054 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 05055 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) { 05056 ast_setstate(ast, AST_STATE_RINGING); 05057 } else if (!p->answeronpolarityswitch) { 05058 ast_setstate(ast, AST_STATE_UP); 05059 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05060 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05061 /* If aops=0 and hops=1, this is necessary */ 05062 p->polarity = POLARITY_REV; 05063 } else { 05064 /* Start clean, so we can catch the change to REV polarity when party answers */ 05065 p->polarity = POLARITY_IDLE; 05066 } 05067 } 05068 } 05069 } 05070 break; 05071 case DAHDI_EVENT_ALARM: 05072 #ifdef HAVE_PRI 05073 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05074 /* T309 is not enabled : hangup calls when alarm occurs */ 05075 if (p->call) { 05076 if (p->pri && p->pri->pri) { 05077 if (!pri_grab(p, p->pri)) { 05078 pri_hangup(p->pri->pri, p->call, -1); 05079 pri_destroycall(p->pri->pri, p->call); 05080 p->call = NULL; 05081 pri_rel(p->pri); 05082 } else 05083 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 05084 } else 05085 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05086 } 05087 if (p->owner) 05088 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05089 } 05090 if (p->bearer) 05091 p->bearer->inalarm = 1; 05092 else 05093 #endif 05094 p->inalarm = 1; 05095 res = get_alarms(p); 05096 handle_alarms(p, res); 05097 #ifdef HAVE_PRI 05098 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05099 /* fall through intentionally */ 05100 } else { 05101 break; 05102 } 05103 #endif 05104 #ifdef HAVE_OPENR2 05105 if (p->sig == SIG_MFCR2) 05106 break; 05107 #endif 05108 case DAHDI_EVENT_ONHOOK: 05109 if (p->radio) { 05110 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05111 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05112 break; 05113 } 05114 if (p->oprmode < 0) 05115 { 05116 if (p->oprmode != -1) break; 05117 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05118 { 05119 /* Make sure it starts ringing */ 05120 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05121 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05122 save_conference(p->oprpeer); 05123 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05124 } 05125 break; 05126 } 05127 switch (p->sig) { 05128 case SIG_FXOLS: 05129 case SIG_FXOGS: 05130 case SIG_FXOKS: 05131 p->onhooktime = time(NULL); 05132 p->msgstate = -1; 05133 /* Check for some special conditions regarding call waiting */ 05134 if (index == SUB_REAL) { 05135 /* The normal line was hung up */ 05136 if (p->subs[SUB_CALLWAIT].owner) { 05137 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05138 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05139 if (option_verbose > 2) 05140 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05141 unalloc_sub(p, SUB_CALLWAIT); 05142 #if 0 05143 p->subs[index].needanswer = 0; 05144 p->subs[index].needringing = 0; 05145 #endif 05146 p->callwaitingrepeat = 0; 05147 p->cidcwexpire = 0; 05148 p->owner = NULL; 05149 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05150 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05151 p->dialing = 1; 05152 dahdi_ring_phone(p); 05153 } else if (p->subs[SUB_THREEWAY].owner) { 05154 unsigned int mssinceflash; 05155 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 05156 the private structure -- not especially easy or clean */ 05157 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 05158 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 05159 ast_mutex_unlock(&p->lock); 05160 DEADLOCK_AVOIDANCE(&ast->lock); 05161 /* We can grab ast and p in that order, without worry. We should make sure 05162 nothing seriously bad has happened though like some sort of bizarre double 05163 masquerade! */ 05164 ast_mutex_lock(&p->lock); 05165 if (p->owner != ast) { 05166 ast_log(LOG_WARNING, "This isn't good...\n"); 05167 return NULL; 05168 } 05169 } 05170 if (!p->subs[SUB_THREEWAY].owner) { 05171 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05172 return NULL; 05173 } 05174 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05175 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 05176 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05177 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05178 hanging up. Hangup both channels now */ 05179 if (p->subs[SUB_THREEWAY].owner) 05180 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 05181 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05182 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05183 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05184 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05185 if (p->transfer) { 05186 /* In any case this isn't a threeway call anymore */ 05187 p->subs[SUB_REAL].inthreeway = 0; 05188 p->subs[SUB_THREEWAY].inthreeway = 0; 05189 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05190 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05191 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05192 /* Swap subs and dis-own channel */ 05193 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05194 p->owner = NULL; 05195 /* Ring the phone */ 05196 dahdi_ring_phone(p); 05197 } else { 05198 if ((res = attempt_transfer(p)) < 0) { 05199 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05200 if (p->subs[SUB_THREEWAY].owner) 05201 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05202 } else if (res) { 05203 /* Don't actually hang up at this point */ 05204 if (p->subs[SUB_THREEWAY].owner) 05205 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05206 break; 05207 } 05208 } 05209 } else { 05210 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05211 if (p->subs[SUB_THREEWAY].owner) 05212 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05213 } 05214 } else { 05215 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 05216 /* Swap subs and dis-own channel */ 05217 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05218 p->owner = NULL; 05219 /* Ring the phone */ 05220 dahdi_ring_phone(p); 05221 } 05222 } 05223 } else { 05224 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 05225 } 05226 /* Fall through */ 05227 default: 05228 dahdi_disable_ec(p); 05229 return NULL; 05230 } 05231 break; 05232 case DAHDI_EVENT_RINGOFFHOOK: 05233 if (p->inalarm) break; 05234 if (p->oprmode < 0) 05235 { 05236 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05237 { 05238 /* Make sure it stops ringing */ 05239 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05240 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 05241 restore_conference(p->oprpeer); 05242 } 05243 break; 05244 } 05245 if (p->radio) 05246 { 05247 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05248 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05249 break; 05250 } 05251 /* for E911, its supposed to wait for offhook then dial 05252 the second half of the dial string */ 05253 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 05254 c = strchr(p->dialdest, '/'); 05255 if (c) 05256 c++; 05257 else 05258 c = p->dialdest; 05259 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 05260 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 05261 if (strlen(p->dop.dialstr) > 4) { 05262 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 05263 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 05264 p->echorest[sizeof(p->echorest) - 1] = '\0'; 05265 p->echobreak = 1; 05266 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05267 } else 05268 p->echobreak = 0; 05269 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05270 int saveerr = errno; 05271 05272 x = DAHDI_ONHOOK; 05273 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05274 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05275 return NULL; 05276 } 05277 p->dialing = 1; 05278 return &p->subs[index].f; 05279 } 05280 switch (p->sig) { 05281 case SIG_FXOLS: 05282 case SIG_FXOGS: 05283 case SIG_FXOKS: 05284 switch (ast->_state) { 05285 case AST_STATE_RINGING: 05286 dahdi_enable_ec(p); 05287 dahdi_train_ec(p); 05288 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05289 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05290 /* Make sure it stops ringing */ 05291 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05292 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 05293 if (p->cidspill) { 05294 /* Cancel any running CallerID spill */ 05295 free(p->cidspill); 05296 p->cidspill = NULL; 05297 } 05298 p->dialing = 0; 05299 p->callwaitcas = 0; 05300 if (p->confirmanswer) { 05301 /* Ignore answer if "confirm answer" is enabled */ 05302 p->subs[index].f.frametype = AST_FRAME_NULL; 05303 p->subs[index].f.subclass = 0; 05304 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05305 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05306 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05307 if (res < 0) { 05308 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05309 p->dop.dialstr[0] = '\0'; 05310 return NULL; 05311 } else { 05312 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05313 p->subs[index].f.frametype = AST_FRAME_NULL; 05314 p->subs[index].f.subclass = 0; 05315 p->dialing = 1; 05316 } 05317 p->dop.dialstr[0] = '\0'; 05318 ast_setstate(ast, AST_STATE_DIALING); 05319 } else 05320 ast_setstate(ast, AST_STATE_UP); 05321 return &p->subs[index].f; 05322 case AST_STATE_DOWN: 05323 ast_setstate(ast, AST_STATE_RING); 05324 ast->rings = 1; 05325 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05326 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 05327 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 05328 return &p->subs[index].f; 05329 case AST_STATE_UP: 05330 /* Make sure it stops ringing */ 05331 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05332 /* Okay -- probably call waiting*/ 05333 if (ast_bridged_channel(p->owner)) 05334 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05335 p->subs[index].needunhold = 1; 05336 break; 05337 case AST_STATE_RESERVED: 05338 /* Start up dialtone */ 05339 if (has_voicemail(p)) 05340 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05341 else 05342 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05343 break; 05344 default: 05345 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05346 } 05347 break; 05348 case SIG_FXSLS: 05349 case SIG_FXSGS: 05350 case SIG_FXSKS: 05351 if (ast->_state == AST_STATE_RING) { 05352 p->ringt = p->ringt_base; 05353 } 05354 05355 /* Fall through */ 05356 case SIG_EM: 05357 case SIG_EM_E1: 05358 case SIG_EMWINK: 05359 case SIG_FEATD: 05360 case SIG_FEATDMF: 05361 case SIG_FEATDMF_TA: 05362 case SIG_E911: 05363 case SIG_FGC_CAMA: 05364 case SIG_FGC_CAMAMF: 05365 case SIG_FEATB: 05366 case SIG_SF: 05367 case SIG_SFWINK: 05368 case SIG_SF_FEATD: 05369 case SIG_SF_FEATDMF: 05370 case SIG_SF_FEATB: 05371 if (ast->_state == AST_STATE_PRERING) 05372 ast_setstate(ast, AST_STATE_RING); 05373 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05374 if (option_debug) 05375 ast_log(LOG_DEBUG, "Ring detected\n"); 05376 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05377 p->subs[index].f.subclass = AST_CONTROL_RING; 05378 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05379 if (option_debug) 05380 ast_log(LOG_DEBUG, "Line answered\n"); 05381 if (p->confirmanswer) { 05382 p->subs[index].f.frametype = AST_FRAME_NULL; 05383 p->subs[index].f.subclass = 0; 05384 } else { 05385 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05386 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 05387 ast_setstate(ast, AST_STATE_UP); 05388 } 05389 } else if (ast->_state != AST_STATE_RING) 05390 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05391 break; 05392 default: 05393 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05394 } 05395 break; 05396 #ifdef DAHDI_EVENT_RINGBEGIN 05397 case DAHDI_EVENT_RINGBEGIN: 05398 switch (p->sig) { 05399 case SIG_FXSLS: 05400 case SIG_FXSGS: 05401 case SIG_FXSKS: 05402 if (ast->_state == AST_STATE_RING) { 05403 p->ringt = p->ringt_base; 05404 } 05405 break; 05406 } 05407 break; 05408 #endif 05409 case DAHDI_EVENT_RINGEROFF: 05410 if (p->inalarm) break; 05411 if ((p->radio || (p->oprmode < 0))) break; 05412 ast->rings++; 05413 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05414 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05415 free(p->cidspill); 05416 p->cidspill = NULL; 05417 p->callwaitcas = 0; 05418 } 05419 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05420 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05421 break; 05422 case DAHDI_EVENT_RINGERON: 05423 break; 05424 case DAHDI_EVENT_NOALARM: 05425 p->inalarm = 0; 05426 #ifdef HAVE_PRI 05427 /* Extremely unlikely but just in case */ 05428 if (p->bearer) 05429 p->bearer->inalarm = 0; 05430 #endif 05431 if (!p->unknown_alarm) { 05432 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05433 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05434 "Channel: %d\r\n", p->channel); 05435 } else { 05436 p->unknown_alarm = 0; 05437 } 05438 break; 05439 case DAHDI_EVENT_WINKFLASH: 05440 if (p->inalarm) break; 05441 if (p->radio) break; 05442 if (p->oprmode < 0) break; 05443 if (p->oprmode > 1) 05444 { 05445 struct dahdi_params par; 05446 05447 memset(&par, 0, sizeof(par)); 05448 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05449 { 05450 if (!par.rxisoffhook) 05451 { 05452 /* Make sure it stops ringing */ 05453 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05454 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05455 save_conference(p); 05456 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05457 } 05458 } 05459 break; 05460 } 05461 /* Remember last time we got a flash-hook */ 05462 gettimeofday(&p->flashtime, NULL); 05463 switch (mysig) { 05464 case SIG_FXOLS: 05465 case SIG_FXOGS: 05466 case SIG_FXOKS: 05467 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05468 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05469 p->callwaitcas = 0; 05470 05471 if (index != SUB_REAL) { 05472 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 05473 goto winkflashdone; 05474 } 05475 05476 if (p->subs[SUB_CALLWAIT].owner) { 05477 /* Swap to call-wait */ 05478 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05479 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05480 p->owner = p->subs[SUB_REAL].owner; 05481 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 05482 if (p->owner->_state == AST_STATE_RINGING) { 05483 ast_setstate(p->owner, AST_STATE_UP); 05484 p->subs[SUB_REAL].needanswer = 1; 05485 } 05486 p->callwaitingrepeat = 0; 05487 p->cidcwexpire = 0; 05488 /* Start music on hold if appropriate */ 05489 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05490 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05491 S_OR(p->mohsuggest, NULL), 05492 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05493 } 05494 p->subs[SUB_CALLWAIT].needhold = 1; 05495 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05496 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05497 S_OR(p->mohsuggest, NULL), 05498 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05499 } 05500 p->subs[SUB_REAL].needunhold = 1; 05501 } else if (!p->subs[SUB_THREEWAY].owner) { 05502 if (!p->threewaycalling) { 05503 /* Just send a flash if no 3-way calling */ 05504 p->subs[SUB_REAL].needflash = 1; 05505 goto winkflashdone; 05506 } else if (!check_for_conference(p)) { 05507 char cid_num[256]; 05508 char cid_name[256]; 05509 05510 cid_num[0] = 0; 05511 cid_name[0] = 0; 05512 if (p->dahditrcallerid && p->owner) { 05513 if (p->owner->cid.cid_num) 05514 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05515 if (p->owner->cid.cid_name) 05516 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05517 } 05518 /* XXX This section needs much more error checking!!! XXX */ 05519 /* Start a 3-way call if feasible */ 05520 if (!((ast->pbx) || 05521 (ast->_state == AST_STATE_UP) || 05522 (ast->_state == AST_STATE_RING))) { 05523 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 05524 goto winkflashdone; 05525 } 05526 if (alloc_sub(p, SUB_THREEWAY)) { 05527 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05528 goto winkflashdone; 05529 } 05530 /* Make new channel */ 05531 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05532 if (p->dahditrcallerid) { 05533 if (!p->origcid_num) 05534 p->origcid_num = ast_strdup(p->cid_num); 05535 if (!p->origcid_name) 05536 p->origcid_name = ast_strdup(p->cid_name); 05537 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05538 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05539 } 05540 /* Swap things around between the three-way and real call */ 05541 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05542 /* Disable echo canceller for better dialing */ 05543 dahdi_disable_ec(p); 05544 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05545 if (res) 05546 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05547 p->owner = chan; 05548 pthread_attr_init(&attr); 05549 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05550 if (!chan) { 05551 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05552 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 05553 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05554 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05555 dahdi_enable_ec(p); 05556 ast_hangup(chan); 05557 } else { 05558 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05559 int way3bridge = 0, cdr3way = 0; 05560 05561 if (!other) { 05562 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05563 } else 05564 way3bridge = 1; 05565 05566 if (p->subs[SUB_THREEWAY].owner->cdr) 05567 cdr3way = 1; 05568 05569 if (option_verbose > 2) 05570 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 05571 /* Start music on hold if appropriate */ 05572 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05573 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05574 S_OR(p->mohsuggest, NULL), 05575 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05576 } 05577 p->subs[SUB_THREEWAY].needhold = 1; 05578 } 05579 pthread_attr_destroy(&attr); 05580 } 05581 } else { 05582 /* Already have a 3 way call */ 05583 if (p->subs[SUB_THREEWAY].inthreeway) { 05584 /* Call is already up, drop the last person */ 05585 if (option_debug) 05586 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05587 /* If the primary call isn't answered yet, use it */ 05588 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05589 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05590 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05591 p->owner = p->subs[SUB_REAL].owner; 05592 } 05593 /* Drop the last call and stop the conference */ 05594 if (option_verbose > 2) 05595 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05596 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05597 p->subs[SUB_REAL].inthreeway = 0; 05598 p->subs[SUB_THREEWAY].inthreeway = 0; 05599 } else { 05600 /* Lets see what we're up to */ 05601 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05602 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05603 int otherindex = SUB_THREEWAY; 05604 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05605 int way3bridge = 0, cdr3way = 0; 05606 05607 if (!other) { 05608 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05609 } else 05610 way3bridge = 1; 05611 05612 if (p->subs[SUB_THREEWAY].owner->cdr) 05613 cdr3way = 1; 05614 05615 if (option_verbose > 2) 05616 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05617 /* Put them in the threeway, and flip */ 05618 p->subs[SUB_THREEWAY].inthreeway = 1; 05619 p->subs[SUB_REAL].inthreeway = 1; 05620 if (ast->_state == AST_STATE_UP) { 05621 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05622 otherindex = SUB_REAL; 05623 } 05624 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05625 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05626 p->subs[otherindex].needunhold = 1; 05627 p->owner = p->subs[SUB_REAL].owner; 05628 if (ast->_state == AST_STATE_RINGING) { 05629 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 05630 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05631 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05632 } 05633 } else { 05634 if (option_verbose > 2) 05635 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05636 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05637 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05638 p->owner = p->subs[SUB_REAL].owner; 05639 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05640 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05641 p->subs[SUB_REAL].needunhold = 1; 05642 dahdi_enable_ec(p); 05643 } 05644 05645 } 05646 } 05647 winkflashdone: 05648 update_conf(p); 05649 break; 05650 case SIG_EM: 05651 case SIG_EM_E1: 05652 case SIG_FEATD: 05653 case SIG_SF: 05654 case SIG_SFWINK: 05655 case SIG_SF_FEATD: 05656 case SIG_FXSLS: 05657 case SIG_FXSGS: 05658 if (p->dialing) 05659 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 05660 else 05661 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05662 break; 05663 case SIG_FEATDMF_TA: 05664 switch (p->whichwink) { 05665 case 0: 05666 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05667 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05668 break; 05669 case 1: 05670 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05671 break; 05672 case 2: 05673 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05674 return NULL; 05675 } 05676 p->whichwink++; 05677 /* Fall through */ 05678 case SIG_FEATDMF: 05679 case SIG_E911: 05680 case SIG_FGC_CAMAMF: 05681 case SIG_FGC_CAMA: 05682 case SIG_FEATB: 05683 case SIG_SF_FEATDMF: 05684 case SIG_SF_FEATB: 05685 case SIG_EMWINK: 05686 /* FGD MF and EMWINK *Must* wait for wink */ 05687 if (!ast_strlen_zero(p->dop.dialstr)) { 05688 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05689 if (res < 0) { 05690 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05691 p->dop.dialstr[0] = '\0'; 05692 return NULL; 05693 } else 05694 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05695 } 05696 p->dop.dialstr[0] = '\0'; 05697 break; 05698 default: 05699 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 05700 } 05701 break; 05702 case DAHDI_EVENT_HOOKCOMPLETE: 05703 if (p->inalarm) break; 05704 if ((p->radio || (p->oprmode < 0))) break; 05705 switch (mysig) { 05706 case SIG_FXSLS: /* only interesting for FXS */ 05707 case SIG_FXSGS: 05708 case SIG_FXSKS: 05709 case SIG_EM: 05710 case SIG_EM_E1: 05711 case SIG_EMWINK: 05712 case SIG_FEATD: 05713 case SIG_SF: 05714 case SIG_SFWINK: 05715 case SIG_SF_FEATD: 05716 if (!ast_strlen_zero(p->dop.dialstr)) { 05717 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05718 if (res < 0) { 05719 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05720 p->dop.dialstr[0] = '\0'; 05721 return NULL; 05722 } else 05723 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 05724 } 05725 p->dop.dialstr[0] = '\0'; 05726 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05727 break; 05728 case SIG_FEATDMF: 05729 case SIG_FEATDMF_TA: 05730 case SIG_E911: 05731 case SIG_FGC_CAMA: 05732 case SIG_FGC_CAMAMF: 05733 case SIG_FEATB: 05734 case SIG_SF_FEATDMF: 05735 case SIG_SF_FEATB: 05736 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05737 break; 05738 default: 05739 break; 05740 } 05741 break; 05742 case DAHDI_EVENT_POLARITY: 05743 /* 05744 * If we get a Polarity Switch event, check to see 05745 * if we should change the polarity state and 05746 * mark the channel as UP or if this is an indication 05747 * of remote end disconnect. 05748 */ 05749 if (p->polarity == POLARITY_IDLE) { 05750 p->polarity = POLARITY_REV; 05751 if (p->answeronpolarityswitch && 05752 ((ast->_state == AST_STATE_DIALING) || 05753 (ast->_state == AST_STATE_RINGING))) { 05754 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 05755 ast_setstate(p->owner, AST_STATE_UP); 05756 if (p->hanguponpolarityswitch) { 05757 gettimeofday(&p->polaritydelaytv, NULL); 05758 } 05759 } else 05760 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 05761 } 05762 /* Removed else statement from here as it was preventing hangups from ever happening*/ 05763 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 05764 if (p->hanguponpolarityswitch && 05765 (p->polarityonanswerdelay > 0) && 05766 (p->polarity == POLARITY_REV) && 05767 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 05768 /* Added log_debug information below to provide a better indication of what is going on */ 05769 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 05770 05771 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05772 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 05773 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05774 p->polarity = POLARITY_IDLE; 05775 } else { 05776 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state); 05777 } 05778 } else { 05779 p->polarity = POLARITY_IDLE; 05780 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 05781 } 05782 /* Added more log_debug information below to provide a better indication of what is going on */ 05783 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) ); 05784 break; 05785 default: 05786 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05787 } 05788 return &p->subs[index].f; 05789 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3590 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_dsp_digitmode(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_ast_cause_to_r2_cause(), dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_r2_disconnect_call(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2, dahdi_pvt::mfcr2_forced_release, dahdi_pvt::mfcr2call, dahdi_pvt::mohsuggest, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::r2chan, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.
Referenced by pri_dchannel().
03591 { 03592 int res; 03593 int index,x, law; 03594 /*static int restore_gains(struct dahdi_pvt *p);*/ 03595 struct dahdi_pvt *p = ast->tech_pvt; 03596 struct dahdi_pvt *tmp = NULL; 03597 struct dahdi_pvt *prev = NULL; 03598 struct dahdi_params par; 03599 03600 if (option_debug) 03601 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 03602 if (!ast->tech_pvt) { 03603 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03604 return 0; 03605 } 03606 03607 ast_mutex_lock(&p->lock); 03608 03609 index = dahdi_get_index(ast, p, 1); 03610 03611 if (p->sig == SIG_PRI) { 03612 x = 1; 03613 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03614 p->cid_num[0] = '\0'; 03615 p->cid_name[0] = '\0'; 03616 } 03617 03618 x = 0; 03619 dahdi_confmute(p, 0); 03620 restore_gains(p); 03621 if (p->origcid_num) { 03622 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03623 free(p->origcid_num); 03624 p->origcid_num = NULL; 03625 } 03626 if (p->origcid_name) { 03627 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03628 free(p->origcid_name); 03629 p->origcid_name = NULL; 03630 } 03631 if (p->dsp) 03632 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 03633 p->exten[0] = '\0'; 03634 03635 if (option_debug) 03636 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03637 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03638 p->ignoredtmf = 0; 03639 03640 if (index > -1) { 03641 /* Real channel, do some fixup */ 03642 p->subs[index].owner = NULL; 03643 p->subs[index].needanswer = 0; 03644 p->subs[index].needflash = 0; 03645 p->subs[index].needringing = 0; 03646 p->subs[index].needbusy = 0; 03647 p->subs[index].needcongestion = 0; 03648 p->subs[index].linear = 0; 03649 p->subs[index].needcallerid = 0; 03650 p->polarity = POLARITY_IDLE; 03651 dahdi_setlinear(p->subs[index].dfd, 0); 03652 if (index == SUB_REAL) { 03653 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03654 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03655 if (p->subs[SUB_CALLWAIT].inthreeway) { 03656 /* We had flipped over to answer a callwait and now it's gone */ 03657 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 03658 /* Move to the call-wait, but un-own us until they flip back. */ 03659 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03660 unalloc_sub(p, SUB_CALLWAIT); 03661 p->owner = NULL; 03662 } else { 03663 /* The three way hung up, but we still have a call wait */ 03664 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03665 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03666 unalloc_sub(p, SUB_THREEWAY); 03667 if (p->subs[SUB_REAL].inthreeway) { 03668 /* This was part of a three way call. Immediately make way for 03669 another call */ 03670 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03671 p->owner = p->subs[SUB_REAL].owner; 03672 } else { 03673 /* This call hasn't been completed yet... Set owner to NULL */ 03674 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03675 p->owner = NULL; 03676 } 03677 p->subs[SUB_REAL].inthreeway = 0; 03678 } 03679 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03680 /* Move to the call-wait and switch back to them. */ 03681 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03682 unalloc_sub(p, SUB_CALLWAIT); 03683 p->owner = p->subs[SUB_REAL].owner; 03684 if (p->owner->_state != AST_STATE_UP) 03685 p->subs[SUB_REAL].needanswer = 1; 03686 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03687 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03688 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03689 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03690 unalloc_sub(p, SUB_THREEWAY); 03691 if (p->subs[SUB_REAL].inthreeway) { 03692 /* This was part of a three way call. Immediately make way for 03693 another call */ 03694 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 03695 p->owner = p->subs[SUB_REAL].owner; 03696 } else { 03697 /* This call hasn't been completed yet... Set owner to NULL */ 03698 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 03699 p->owner = NULL; 03700 } 03701 p->subs[SUB_REAL].inthreeway = 0; 03702 } 03703 } else if (index == SUB_CALLWAIT) { 03704 /* Ditch the holding callwait call, and immediately make it availabe */ 03705 if (p->subs[SUB_CALLWAIT].inthreeway) { 03706 /* This is actually part of a three way, placed on hold. Place the third part 03707 on music on hold now */ 03708 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03709 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03710 S_OR(p->mohsuggest, NULL), 03711 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03712 } 03713 p->subs[SUB_THREEWAY].inthreeway = 0; 03714 /* Make it the call wait now */ 03715 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03716 unalloc_sub(p, SUB_THREEWAY); 03717 } else 03718 unalloc_sub(p, SUB_CALLWAIT); 03719 } else if (index == SUB_THREEWAY) { 03720 if (p->subs[SUB_CALLWAIT].inthreeway) { 03721 /* The other party of the three way call is currently in a call-wait state. 03722 Start music on hold for them, and take the main guy out of the third call */ 03723 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03724 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03725 S_OR(p->mohsuggest, NULL), 03726 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03727 } 03728 p->subs[SUB_CALLWAIT].inthreeway = 0; 03729 } 03730 p->subs[SUB_REAL].inthreeway = 0; 03731 /* If this was part of a three way call index, let us make 03732 another three way call */ 03733 unalloc_sub(p, SUB_THREEWAY); 03734 } else { 03735 /* This wasn't any sort of call, but how are we an index? */ 03736 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03737 } 03738 } 03739 03740 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03741 p->owner = NULL; 03742 p->ringt = 0; 03743 p->distinctivering = 0; 03744 p->confirmanswer = 0; 03745 p->cidrings = 1; 03746 p->outgoing = 0; 03747 p->digital = 0; 03748 p->faxhandled = 0; 03749 p->pulsedial = 0; 03750 p->onhooktime = time(NULL); 03751 #ifdef HAVE_PRI 03752 p->proceeding = 0; 03753 p->dialing = 0; 03754 p->progress = 0; 03755 p->alerting = 0; 03756 p->setup_ack = 0; 03757 #endif 03758 if (p->dsp) { 03759 ast_dsp_free(p->dsp); 03760 p->dsp = NULL; 03761 } 03762 03763 law = DAHDI_LAW_DEFAULT; 03764 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03765 if (res < 0) 03766 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03767 /* Perform low level hangup if no owner left */ 03768 #ifdef HAVE_OPENR2 03769 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 03770 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 03771 ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause); 03772 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 03773 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 03774 } else { 03775 const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE"); 03776 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 03777 openr2_call_disconnect_cause_t r2cause = r2cause_user 03778 ? dahdi_ast_cause_to_r2_cause(r2cause_user) 03779 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 03780 dahdi_r2_disconnect_call(p, r2cause); 03781 } 03782 } else if (p->mfcr2call) { 03783 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 03784 p->mfcr2call = 0; 03785 } 03786 #endif 03787 #ifdef HAVE_PRI 03788 if (p->pri) { 03789 #ifdef SUPPORT_USERUSER 03790 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03791 #endif 03792 03793 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03794 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03795 if (!pri_grab(p, p->pri)) { 03796 if (p->alreadyhungup) { 03797 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 03798 03799 #ifdef SUPPORT_USERUSER 03800 pri_call_set_useruser(p->call, useruser); 03801 #endif 03802 03803 pri_hangup(p->pri->pri, p->call, -1); 03804 p->call = NULL; 03805 if (p->bearer) 03806 p->bearer->call = NULL; 03807 } else { 03808 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03809 int icause = ast->hangupcause ? ast->hangupcause : -1; 03810 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03811 03812 #ifdef SUPPORT_USERUSER 03813 pri_call_set_useruser(p->call, useruser); 03814 #endif 03815 03816 p->alreadyhungup = 1; 03817 if (p->bearer) 03818 p->bearer->alreadyhungup = 1; 03819 if (cause) { 03820 if (atoi(cause)) 03821 icause = atoi(cause); 03822 } 03823 pri_hangup(p->pri->pri, p->call, icause); 03824 } 03825 if (res < 0) 03826 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03827 pri_rel(p->pri); 03828 } else { 03829 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03830 res = -1; 03831 } 03832 } else { 03833 if (p->bearer) 03834 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03835 p->call = NULL; 03836 res = 0; 03837 } 03838 } 03839 #endif 03840 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2)) 03841 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03842 if (res < 0) { 03843 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03844 } 03845 switch (p->sig) { 03846 case SIG_FXOGS: 03847 case SIG_FXOLS: 03848 case SIG_FXOKS: 03849 memset(&par, 0, sizeof(par)); 03850 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03851 if (!res) { 03852 #if 0 03853 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03854 #endif 03855 /* If they're off hook, try playing congestion */ 03856 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03857 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03858 else 03859 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03860 } 03861 break; 03862 case SIG_FXSGS: 03863 case SIG_FXSLS: 03864 case SIG_FXSKS: 03865 /* Make sure we're not made available for at least two seconds assuming 03866 we were actually used for an inbound or outbound call. */ 03867 if (ast->_state != AST_STATE_RESERVED) { 03868 time(&p->guardtime); 03869 p->guardtime += 2; 03870 } 03871 break; 03872 default: 03873 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03874 } 03875 if (p->cidspill) 03876 free(p->cidspill); 03877 if (p->sig) 03878 dahdi_disable_ec(p); 03879 x = 0; 03880 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03881 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03882 p->didtdd = 0; 03883 p->cidspill = NULL; 03884 p->callwaitcas = 0; 03885 p->callwaiting = p->permcallwaiting; 03886 p->hidecallerid = p->permhidecallerid; 03887 p->dialing = 0; 03888 p->rdnis[0] = '\0'; 03889 update_conf(p); 03890 reset_conf(p); 03891 /* Restore data mode */ 03892 if (p->sig == SIG_PRI) { 03893 x = 0; 03894 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03895 } 03896 #ifdef HAVE_PRI 03897 if (p->bearer) { 03898 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 03899 /* Free up the bearer channel as well, and 03900 don't use its file descriptor anymore */ 03901 update_conf(p->bearer); 03902 reset_conf(p->bearer); 03903 p->bearer->owner = NULL; 03904 p->bearer->realcall = NULL; 03905 p->bearer = NULL; 03906 p->subs[SUB_REAL].dfd = -1; 03907 p->pri = NULL; 03908 } 03909 #endif 03910 if (num_restart_pending == 0) 03911 restart_monitor(); 03912 } 03913 03914 p->callwaitingrepeat = 0; 03915 p->cidcwexpire = 0; 03916 p->oprmode = 0; 03917 ast->tech_pvt = NULL; 03918 ast_mutex_unlock(&p->lock); 03919 ast_module_unref(ast_module_info->self); 03920 if (option_verbose > 2) 03921 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 03922 03923 ast_mutex_lock(&iflock); 03924 03925 if (p->restartpending) { 03926 num_restart_pending--; 03927 } 03928 03929 tmp = iflist; 03930 prev = NULL; 03931 if (p->destroy) { 03932 while (tmp) { 03933 if (tmp == p) { 03934 destroy_channel(prev, tmp, 0); 03935 break; 03936 } else { 03937 prev = tmp; 03938 tmp = tmp->next; 03939 } 03940 } 03941 } 03942 ast_mutex_unlock(&iflock); 03943 return 0; 03944 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 6365 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.
06366 { 06367 struct dahdi_pvt *p = chan->tech_pvt; 06368 int res=-1; 06369 int index; 06370 int func = DAHDI_FLASH; 06371 ast_mutex_lock(&p->lock); 06372 index = dahdi_get_index(chan, p, 0); 06373 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 06374 #ifdef HAVE_OPENR2 06375 if (p->mfcr2 && !p->mfcr2_call_accepted) { 06376 ast_mutex_unlock(&p->lock); 06377 /* if this an R2 call and the call is not yet accepted we don't want the 06378 tone indications to mess up with the MF tones */ 06379 return 0; 06380 } 06381 #endif 06382 if (index == SUB_REAL) { 06383 switch (condition) { 06384 case AST_CONTROL_BUSY: 06385 #ifdef HAVE_PRI 06386 if (p->priindication_oob && p->sig == SIG_PRI) { 06387 chan->hangupcause = AST_CAUSE_USER_BUSY; 06388 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06389 res = 0; 06390 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06391 if (p->pri->pri) { 06392 if (!pri_grab(p, p->pri)) { 06393 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06394 pri_rel(p->pri); 06395 } 06396 else 06397 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06398 } 06399 p->progress = 1; 06400 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06401 } else 06402 #endif 06403 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 06404 break; 06405 case AST_CONTROL_RINGING: 06406 #ifdef HAVE_PRI 06407 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06408 if (p->pri->pri) { 06409 if (!pri_grab(p, p->pri)) { 06410 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06411 pri_rel(p->pri); 06412 } 06413 else 06414 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06415 } 06416 p->alerting = 1; 06417 } 06418 #endif 06419 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 06420 if (chan->_state != AST_STATE_UP) { 06421 if ((chan->_state != AST_STATE_RING) || 06422 ((p->sig != SIG_FXSKS) && 06423 (p->sig != SIG_FXSLS) && 06424 (p->sig != SIG_FXSGS))) 06425 ast_setstate(chan, AST_STATE_RINGING); 06426 } 06427 break; 06428 case AST_CONTROL_PROCEEDING: 06429 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06430 #ifdef HAVE_PRI 06431 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06432 if (p->pri->pri) { 06433 if (!pri_grab(p, p->pri)) { 06434 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06435 pri_rel(p->pri); 06436 } 06437 else 06438 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06439 } 06440 p->proceeding = 1; 06441 p->dialing = 0; 06442 } 06443 #endif 06444 /* don't continue in ast_indicate */ 06445 res = 0; 06446 break; 06447 case AST_CONTROL_PROGRESS: 06448 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06449 #ifdef HAVE_PRI 06450 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06451 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06452 if (p->pri->pri) { 06453 if (!pri_grab(p, p->pri)) { 06454 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06455 pri_rel(p->pri); 06456 } 06457 else 06458 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06459 } 06460 p->progress = 1; 06461 } 06462 #endif 06463 /* don't continue in ast_indicate */ 06464 res = 0; 06465 break; 06466 case AST_CONTROL_CONGESTION: 06467 chan->hangupcause = AST_CAUSE_CONGESTION; 06468 #ifdef HAVE_PRI 06469 if (p->priindication_oob && p->sig == SIG_PRI) { 06470 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06471 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06472 res = 0; 06473 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06474 if (p->pri) { 06475 if (!pri_grab(p, p->pri)) { 06476 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06477 pri_rel(p->pri); 06478 } else 06479 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06480 } 06481 p->progress = 1; 06482 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06483 } else 06484 #endif 06485 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06486 break; 06487 case AST_CONTROL_HOLD: 06488 #ifdef HAVE_PRI 06489 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06490 if (!pri_grab(p, p->pri)) { 06491 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06492 pri_rel(p->pri); 06493 } else 06494 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06495 } else 06496 #endif 06497 ast_moh_start(chan, data, p->mohinterpret); 06498 break; 06499 case AST_CONTROL_UNHOLD: 06500 #ifdef HAVE_PRI 06501 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06502 if (!pri_grab(p, p->pri)) { 06503 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06504 pri_rel(p->pri); 06505 } else 06506 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06507 } else 06508 #endif 06509 ast_moh_stop(chan); 06510 break; 06511 case AST_CONTROL_RADIO_KEY: 06512 if (p->radio) 06513 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 06514 res = 0; 06515 break; 06516 case AST_CONTROL_RADIO_UNKEY: 06517 if (p->radio) 06518 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 06519 res = 0; 06520 break; 06521 case AST_CONTROL_FLASH: 06522 /* flash hookswitch */ 06523 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06524 /* Clear out the dial buffer */ 06525 p->dop.dialstr[0] = '\0'; 06526 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06527 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06528 chan->name, strerror(errno)); 06529 } else 06530 res = 0; 06531 } else 06532 res = 0; 06533 break; 06534 case AST_CONTROL_SRCUPDATE: 06535 res = 0; 06536 break; 06537 case -1: 06538 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06539 break; 06540 } 06541 } else 06542 res = 0; 06543 ast_mutex_unlock(&p->lock); 06544 return res; 06545 }
Definition at line 4311 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
04311 { 04312 int x; 04313 if (!slave || !master) { 04314 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04315 return; 04316 } 04317 for (x = 0; x < MAX_SLAVES; x++) { 04318 if (!master->slaves[x]) { 04319 master->slaves[x] = slave; 04320 break; 04321 } 04322 } 04323 if (x >= MAX_SLAVES) { 04324 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04325 master->slaves[MAX_SLAVES - 1] = slave; 04326 } 04327 if (slave->master) 04328 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04329 slave->master = master; 04330 04331 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04332 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | i, | |
int | state, | |||
int | startpbx, | |||
int | index, | |||
int | law, | |||
int | transfercapability | |||
) | [static] |
Definition at line 6547 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().
06548 { 06549 struct ast_channel *tmp; 06550 int deflaw; 06551 int res; 06552 int x,y; 06553 int features; 06554 char *b2 = NULL; 06555 struct dahdi_params ps; 06556 char chanprefix[*dahdi_chan_name_len + 4]; 06557 06558 if (i->subs[index].owner) { 06559 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 06560 return NULL; 06561 } 06562 y = 1; 06563 do { 06564 if (b2) 06565 free(b2); 06566 #ifdef HAVE_PRI 06567 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06568 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06569 else 06570 #endif 06571 if (i->channel == CHAN_PSEUDO) 06572 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 06573 else 06574 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 06575 for (x = 0; x < 3; x++) { 06576 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 06577 break; 06578 } 06579 y++; 06580 } while (x < 3); 06581 strcpy(chanprefix, dahdi_chan_name); 06582 strcat(chanprefix, "/%s"); 06583 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 06584 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 06585 free(b2); 06586 if (!tmp) 06587 return NULL; 06588 tmp->tech = chan_tech; 06589 memset(&ps, 0, sizeof(ps)); 06590 ps.channo = i->channel; 06591 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06592 if (res) { 06593 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06594 ps.curlaw = DAHDI_LAW_MULAW; 06595 } 06596 if (ps.curlaw == DAHDI_LAW_ALAW) 06597 deflaw = AST_FORMAT_ALAW; 06598 else 06599 deflaw = AST_FORMAT_ULAW; 06600 if (law) { 06601 if (law == DAHDI_LAW_ALAW) 06602 deflaw = AST_FORMAT_ALAW; 06603 else 06604 deflaw = AST_FORMAT_ULAW; 06605 } 06606 tmp->fds[0] = i->subs[index].dfd; 06607 tmp->nativeformats = deflaw; 06608 /* Start out assuming ulaw since it's smaller :) */ 06609 tmp->rawreadformat = deflaw; 06610 tmp->readformat = deflaw; 06611 tmp->rawwriteformat = deflaw; 06612 tmp->writeformat = deflaw; 06613 i->subs[index].linear = 0; 06614 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 06615 features = 0; 06616 if (index == SUB_REAL) { 06617 if (i->busydetect && CANBUSYDETECT(i)) 06618 features |= DSP_FEATURE_BUSY_DETECT; 06619 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 06620 features |= DSP_FEATURE_CALL_PROGRESS; 06621 if ((!i->outgoing && (i->callprogress & 4)) || 06622 (i->outgoing && (i->callprogress & 2))) { 06623 features |= DSP_FEATURE_FAX_DETECT; 06624 } 06625 #ifdef DAHDI_TONEDETECT 06626 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06627 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 06628 #endif 06629 i->hardwaredtmf = 0; 06630 features |= DSP_FEATURE_DTMF_DETECT; 06631 #ifdef DAHDI_TONEDETECT 06632 } else if (NEED_MFDETECT(i)) { 06633 i->hardwaredtmf = 1; 06634 features |= DSP_FEATURE_DTMF_DETECT; 06635 } 06636 #endif 06637 } 06638 if (features) { 06639 if (i->dsp) { 06640 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 06641 } else { 06642 if (i->channel != CHAN_PSEUDO) 06643 i->dsp = ast_dsp_new(); 06644 else 06645 i->dsp = NULL; 06646 if (i->dsp) { 06647 i->dsp_features = features; 06648 #ifdef HAVE_PRI 06649 /* We cannot do progress detection until receives PROGRESS message */ 06650 if (i->outgoing && (i->sig == SIG_PRI)) { 06651 /* Remember requested DSP features, don't treat 06652 talking as ANSWER */ 06653 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06654 features = 0; 06655 } 06656 #endif 06657 ast_dsp_set_features(i->dsp, features); 06658 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06659 if (!ast_strlen_zero(progzone)) 06660 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06661 if (i->busydetect && CANBUSYDETECT(i)) { 06662 if(i->silencethreshold > 0) 06663 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 06664 ast_dsp_set_busy_count(i->dsp, i->busycount); 06665 if(i->busytonelength > 0) 06666 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 06667 if((i->busytonelength == i->busyquietlength) && i->busycompare) 06668 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 06669 } 06670 } 06671 } 06672 } 06673 06674 if (state == AST_STATE_RING) 06675 tmp->rings = 1; 06676 tmp->tech_pvt = i; 06677 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06678 /* Only FXO signalled stuff can be picked up */ 06679 tmp->callgroup = i->callgroup; 06680 tmp->pickupgroup = i->pickupgroup; 06681 } 06682 if (!ast_strlen_zero(i->language)) 06683 ast_string_field_set(tmp, language, i->language); 06684 if (!i->owner) 06685 i->owner = tmp; 06686 if (!ast_strlen_zero(i->accountcode)) 06687 ast_string_field_set(tmp, accountcode, i->accountcode); 06688 if (i->amaflags) 06689 tmp->amaflags = i->amaflags; 06690 i->subs[index].owner = tmp; 06691 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06692 ast_string_field_set(tmp, call_forward, i->call_forward); 06693 /* If we've been told "no ADSI" then enforce it */ 06694 if (!i->adsi) 06695 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06696 if (!ast_strlen_zero(i->exten)) 06697 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06698 if (!ast_strlen_zero(i->rdnis)) 06699 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06700 if (!ast_strlen_zero(i->dnid)) 06701 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06702 06703 /* Don't use ast_set_callerid() here because it will 06704 * generate a needless NewCallerID event */ 06705 #ifdef PRI_ANI 06706 if (!ast_strlen_zero(i->cid_ani)) 06707 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06708 else 06709 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06710 #else 06711 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06712 #endif 06713 tmp->cid.cid_pres = i->callingpres; 06714 tmp->cid.cid_ton = i->cid_ton; 06715 #ifdef HAVE_PRI 06716 tmp->transfercapability = transfercapability; 06717 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06718 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 06719 i->digital = 1; 06720 /* Assume calls are not idle calls unless we're told differently */ 06721 i->isidlecall = 0; 06722 i->alreadyhungup = 0; 06723 #endif 06724 /* clear the fake event in case we posted one before we had ast_channel */ 06725 i->fake_event = 0; 06726 /* Assure there is no confmute on this channel */ 06727 dahdi_confmute(i, 0); 06728 /* Configure the new channel jb */ 06729 ast_jb_configure(tmp, &global_jbconf); 06730 if (startpbx) { 06731 #ifdef HAVE_OPENR2 06732 if (i->mfcr2call) { 06733 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 06734 } 06735 #endif 06736 if (ast_pbx_start(tmp)) { 06737 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06738 ast_hangup(tmp); 06739 i->owner = NULL; 06740 return NULL; 06741 } 06742 } 06743 06744 ast_module_ref(ast_module_info->self); 06745 06746 return tmp; 06747 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1800 of file chan_dahdi.c.
References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01801 { 01802 int fd; 01803 int isnum; 01804 int chan = 0; 01805 int bs; 01806 int x; 01807 isnum = 1; 01808 for (x = 0; x < strlen(fn); x++) { 01809 if (!isdigit(fn[x])) { 01810 isnum = 0; 01811 break; 01812 } 01813 } 01814 if (isnum) { 01815 chan = atoi(fn); 01816 if (chan < 1) { 01817 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01818 return -1; 01819 } 01820 fn = DAHDI_FILE_CHANNEL; 01821 } 01822 fd = open(fn, O_RDWR | O_NONBLOCK); 01823 if (fd < 0) { 01824 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01825 return -1; 01826 } 01827 if (chan) { 01828 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01829 x = errno; 01830 close(fd); 01831 errno = x; 01832 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01833 return -1; 01834 } 01835 } 01836 bs = READ_SIZE; 01837 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01838 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01839 x = errno; 01840 close(fd); 01841 errno = x; 01842 return -1; 01843 } 01844 return fd; 01845 }
static void dahdi_pri_error | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9944 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().
09945 { 09946 int x, y; 09947 int dchan = -1, span = -1; 09948 int dchancount = 0; 09949 09950 if (pri) { 09951 for (x = 0; x < NUM_SPANS; x++) { 09952 for (y = 0; y < NUM_DCHANS; y++) { 09953 if (pris[x].dchans[y]) 09954 dchancount++; 09955 09956 if (pris[x].dchans[y] == pri) 09957 dchan = y; 09958 } 09959 if (dchan >= 0) { 09960 span = x; 09961 break; 09962 } 09963 dchancount = 0; 09964 } 09965 if ((dchan >= 0) && (span >= 0)) { 09966 if (dchancount > 1) 09967 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 09968 else 09969 ast_log(LOG_ERROR, "%s", s); 09970 } else 09971 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09972 } else 09973 ast_log(LOG_ERROR, "%s", s); 09974 09975 ast_mutex_lock(&pridebugfdlock); 09976 09977 if (pridebugfd >= 0) { 09978 if (write(pridebugfd, s, strlen(s)) < 0) { 09979 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09980 } 09981 } 09982 09983 ast_mutex_unlock(&pridebugfdlock); 09984 }
static void dahdi_pri_message | ( | struct pri * | pri, | |
char * | s | |||
) | [static] |
Definition at line 9902 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().
09903 { 09904 int x, y; 09905 int dchan = -1, span = -1; 09906 int dchancount = 0; 09907 09908 if (pri) { 09909 for (x = 0; x < NUM_SPANS; x++) { 09910 for (y = 0; y < NUM_DCHANS; y++) { 09911 if (pris[x].dchans[y]) 09912 dchancount++; 09913 09914 if (pris[x].dchans[y] == pri) 09915 dchan = y; 09916 } 09917 if (dchan >= 0) { 09918 span = x; 09919 break; 09920 } 09921 dchancount = 0; 09922 } 09923 if ((dchan >= 0) && (span >= 0)) { 09924 if (dchancount > 1) 09925 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 09926 else 09927 ast_verbose("%s", s); 09928 } else 09929 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n"); 09930 } else 09931 ast_verbose("%s", s); 09932 09933 ast_mutex_lock(&pridebugfdlock); 09934 09935 if (pridebugfd >= 0) { 09936 if (write(pridebugfd, s, strlen(s)) < 0) { 09937 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 09938 } 09939 } 09940 09941 ast_mutex_unlock(&pridebugfdlock); 09942 }
static void dahdi_queue_frame | ( | struct dahdi_pvt * | p, | |
struct ast_frame * | f, | |||
struct dahdi_pri * | pri | |||
) | [static] |
Definition at line 1236 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __action_dialoffhook().
01240 { 01241 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01242 #ifdef HAVE_PRI 01243 if (pri) 01244 ast_mutex_unlock(&pri->lock); 01245 #endif 01246 for (;;) { 01247 if (p->owner) { 01248 if (ast_mutex_trylock(&p->owner->lock)) { 01249 DEADLOCK_AVOIDANCE(&p->lock); 01250 } else { 01251 ast_queue_frame(p->owner, f); 01252 ast_mutex_unlock(&p->owner->lock); 01253 break; 01254 } 01255 } else 01256 break; 01257 } 01258 #ifdef HAVE_PRI 01259 if (pri) 01260 ast_mutex_lock(&pri->lock); 01261 #endif 01262 }
static int16_t dahdi_r2_alaw_to_linear | ( | uint8_t | sample | ) | [inline, static] |
Definition at line 1753 of file chan_dahdi.c.
References AST_ALAW.
01754 { 01755 return AST_ALAW(sample); 01756 }
static int dahdi_r2_answer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1298 of file chan_dahdi.c.
References ast_true(), dahdi_pvt::owner, pbx_builtin_getvar_helper(), and dahdi_pvt::r2chan.
Referenced by dahdi_answer(), and dahdi_r2_on_call_accepted().
01299 { 01300 int res = 0; 01301 /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE 01302 * and does not has support for openr2_chan_answer_call_with_mode 01303 * */ 01304 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01305 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER"); 01306 int wants_double_answer = ast_true(double_answer) ? 1 : 0; 01307 if (!double_answer) { 01308 /* this still can result in double answer if the channel context 01309 * was configured that way */ 01310 res = openr2_chan_answer_call(p->r2chan); 01311 } else if (wants_double_answer) { 01312 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE); 01313 } else { 01314 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE); 01315 } 01316 #else 01317 res = openr2_chan_answer_call(p->r2chan); 01318 #endif 01319 return res; 01320 }
static void dahdi_r2_disconnect_call | ( | struct dahdi_pvt * | p, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1411 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::lock, LOG_NOTICE, dahdi_pvt::mfcr2call, and dahdi_pvt::r2chan.
Referenced by dahdi_hangup(), dahdi_r2_on_call_accepted(), dahdi_r2_on_call_disconnect(), and dahdi_r2_on_call_offered().
01412 { 01413 if (openr2_chan_disconnect_call(p->r2chan, cause)) { 01414 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 01415 p->channel, openr2_proto_get_disconnect_string(cause)); 01416 /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */ 01417 openr2_chan_set_idle(p->r2chan); 01418 ast_mutex_lock(&p->lock); 01419 p->mfcr2call = 0; 01420 ast_mutex_unlock(&p->lock); 01421 } 01422 }
static openr2_calling_party_category_t dahdi_r2_get_channel_category | ( | struct ast_channel * | c | ) | [static] |
Definition at line 1322 of file chan_dahdi.c.
References ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mfcr2_category, ast_channel::name, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.
Referenced by dahdi_call().
01323 { 01324 openr2_calling_party_category_t cat; 01325 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY"); 01326 struct dahdi_pvt *p = c->tech_pvt; 01327 if (ast_strlen_zero(catstr)) { 01328 ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 01329 c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01330 return p->mfcr2_category; 01331 } 01332 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) { 01333 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n", 01334 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category)); 01335 return p->mfcr2_category; 01336 } 01337 ast_log(LOG_DEBUG, "Using category %s\n", catstr); 01338 return cat; 01339 }
static uint8_t dahdi_r2_linear_to_alaw | ( | int | sample | ) | [inline, static] |
Definition at line 1758 of file chan_dahdi.c.
References AST_LIN2A.
01759 { 01760 return AST_LIN2A(sample); 01761 }
static void dahdi_r2_on_ani_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1717 of file chan_dahdi.c.
References dahdi_pvt::cid_name, dahdi_pvt::cid_num, and dahdi_pvt::mfcr2_ani_index.
01718 { 01719 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01720 p->cid_num[p->mfcr2_ani_index] = digit; 01721 p->cid_name[p->mfcr2_ani_index] = digit; 01722 p->mfcr2_ani_index++; 01723 p->cid_num[p->mfcr2_ani_index] = 0; 01724 p->cid_name[p->mfcr2_ani_index] = 0; 01725 }
static void dahdi_r2_on_billing_pulse_received | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1727 of file chan_dahdi.c.
References ast_log(), and LOG_NOTICE.
01728 { 01729 ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan)); 01730 }
static void dahdi_r2_on_call_accepted | ( | openr2_chan_t * | r2chan, | |
openr2_call_mode_t | mode | |||
) | [static] |
Definition at line 1485 of file chan_dahdi.c.
References ast_log(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_enable_ec(), dahdi_new(), dahdi_r2_answer(), dahdi_r2_disconnect_call(), dahdi_pvt::dialing, LOG_ERROR, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_call_accepted, dahdi_subchannel::needringing, SUB_REAL, and dahdi_pvt::subs.
01486 { 01487 struct dahdi_pvt *p = NULL; 01488 struct ast_channel *c = NULL; 01489 p = openr2_chan_get_client_data(r2chan); 01490 dahdi_enable_ec(p); 01491 p->mfcr2_call_accepted = 1; 01492 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { 01493 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan)); 01494 /* if accept on offer is not set, it means at this point the PBX thread is already 01495 launched and therefore this callback is being executed in the PBX thread rather than 01496 the monitor thread, don't launch any other thread, just disable the R2 reading and 01497 answer the call */ 01498 if (!p->mfcr2_accept_on_offer) { 01499 openr2_chan_disable_read(r2chan); 01500 ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan)); 01501 dahdi_r2_answer(p); 01502 return; 01503 } 01504 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01505 if (c) { 01506 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01507 openr2_chan_disable_read(r2chan); 01508 } else { 01509 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01510 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01511 return; 01512 } 01513 } else { 01514 ast_verbose("Call accepted on forward channel %d\n", p->channel); 01515 p->subs[SUB_REAL].needringing = 1; 01516 p->dialing = 0; 01517 /* chan_dahdi will take care of reading from now on, tell the library to forget about it */ 01518 openr2_chan_disable_read(r2chan); 01519 } 01520 }
static void dahdi_r2_on_call_answered | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1522 of file chan_dahdi.c.
References ast_verbose(), dahdi_subchannel::needanswer, SUB_REAL, and dahdi_pvt::subs.
01523 { 01524 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01525 ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan)); 01526 p->subs[SUB_REAL].needanswer = 1; 01527 }
static void dahdi_r2_on_call_disconnect | ( | openr2_chan_t * | r2chan, | |
openr2_call_disconnect_cause_t | cause | |||
) | [static] |
Definition at line 1555 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, AST_CAUSE_BUSY, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_verbose(), dahdi_r2_disconnect_call(), ast_channel::hangupcause, dahdi_pvt::lock, LOG_WARNING, dahdi_subchannel::needbusy, dahdi_subchannel::needcongestion, dahdi_pvt::owner, SUB_REAL, and dahdi_pvt::subs.
01556 { 01557 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01558 ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan)); 01559 ast_mutex_lock(&p->lock); 01560 if (p->owner) { 01561 /* when we have an owner we don't call openr2_chan_disconnect_call here, that will 01562 be done in zt_hangup */ 01563 if (p->owner->_state == AST_STATE_UP) { 01564 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01565 ast_mutex_unlock(&p->lock); 01566 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) { 01567 /* being the forward side we must report what happened to the call to whoever requested it */ 01568 switch (cause) { 01569 case OR2_CAUSE_BUSY_NUMBER: 01570 p->owner->hangupcause = AST_CAUSE_BUSY; 01571 p->subs[SUB_REAL].needbusy = 1; 01572 break; 01573 case OR2_CAUSE_NUMBER_CHANGED: 01574 p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED; 01575 p->subs[SUB_REAL].needcongestion = 1; 01576 break; 01577 case OR2_CAUSE_NETWORK_CONGESTION: 01578 p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER; 01579 p->subs[SUB_REAL].needcongestion = 1; 01580 break; 01581 case OR2_CAUSE_OUT_OF_ORDER: 01582 p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01583 p->subs[SUB_REAL].needcongestion = 1; 01584 break; 01585 case OR2_CAUSE_UNALLOCATED_NUMBER: 01586 p->owner->hangupcause = AST_CAUSE_UNALLOCATED; 01587 p->subs[SUB_REAL].needcongestion = 1; 01588 break; 01589 case OR2_CAUSE_NO_ANSWER: 01590 p->owner->hangupcause = AST_CAUSE_NO_ANSWER; 01591 p->subs[SUB_REAL].needcongestion = 1; 01592 break; 01593 case OR2_CAUSE_UNSPECIFIED: 01594 p->owner->hangupcause = AST_CAUSE_NOTDEFINED; 01595 p->subs[SUB_REAL].needcongestion = 1; 01596 break; 01597 case OR2_CAUSE_NORMAL_CLEARING: 01598 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01599 p->subs[SUB_REAL].needcongestion = 1; 01600 break; 01601 default: 01602 ast_log(LOG_WARNING, "Unhandled cause %d\n", cause); 01603 } 01604 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01605 ast_mutex_unlock(&p->lock); 01606 } else { 01607 ast_mutex_unlock(&p->lock); 01608 /* being the backward side and not UP yet, we only need to request hangup */ 01609 /* TODO: what about doing this same thing when were AST_STATE_UP? */ 01610 ast_queue_hangup(p->owner); 01611 } 01612 } else { 01613 ast_mutex_unlock(&p->lock); 01614 /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */ 01615 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING); 01616 } 01617 }
static void dahdi_r2_on_call_end | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1475 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::lock, and dahdi_pvt::mfcr2call.
01476 { 01477 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01478 ast_verbose("MFC/R2 call end on chan %d\n", p->channel); 01479 ast_mutex_lock(&p->lock); 01480 p->mfcr2call = 0; 01481 ast_mutex_unlock(&p->lock); 01482 }
static void dahdi_r2_on_call_init | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1341 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::exten, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2_ani_index, dahdi_pvt::mfcr2_call_accepted, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, dahdi_pvt::mfcr2call, and dahdi_pvt::rdnis.
01342 { 01343 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01344 ast_mutex_lock(&p->lock); 01345 if (p->mfcr2call) { 01346 ast_mutex_unlock(&p->lock); 01347 /* TODO: This can happen when some other thread just finished zt_request requesting this very same 01348 interface but has not yet seized the line (zt_call), and the far end wins and seize the line, 01349 can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since 01350 the other end will see our seize as a forced release and drop the call, we will see an invalid 01351 pattern that will be seen and treated as protocol error. */ 01352 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan)); 01353 return; 01354 } 01355 p->mfcr2call = 1; 01356 /* better safe than sorry ... */ 01357 p->cid_name[0] = 0; 01358 p->cid_num[0] = 0; 01359 p->rdnis[0] = 0; 01360 p->exten[0] = 0; 01361 p->mfcr2_ani_index = 0; 01362 p->mfcr2_dnis_index = 0; 01363 p->mfcr2_dnis_matched = 0; 01364 p->mfcr2_call_accepted = 0; 01365 ast_mutex_unlock(&p->lock); 01366 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); 01367 }
static void dahdi_r2_on_call_offered | ( | openr2_chan_t * | r2chan, | |
const char * | ani, | |||
const char * | dnis, | |||
openr2_calling_party_category_t | category | |||
) | [static] |
Definition at line 1424 of file chan_dahdi.c.
References ast_exists_extension(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_new(), dahdi_r2_disconnect_call(), dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, dahdi_pvt::mfcr2_accept_on_offer, dahdi_pvt::mfcr2_allow_collect_calls, dahdi_pvt::mfcr2_charge_calls, dahdi_pvt::mfcr2_recvd_category, SUB_REAL, and dahdi_pvt::use_callerid.
01425 { 01426 struct dahdi_pvt *p; 01427 struct ast_channel *c; 01428 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 01429 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category)); 01430 p = openr2_chan_get_client_data(r2chan); 01431 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { 01432 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel); 01433 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED); 01434 return; 01435 } 01436 ast_mutex_lock(&p->lock); 01437 p->mfcr2_recvd_category = category; 01438 /* if we're not supposed to use CID, clear whatever we have */ 01439 if (!p->use_callerid) { 01440 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n"); 01441 p->cid_num[0] = 0; 01442 p->cid_name[0] = 0; 01443 } 01444 /* if we're supposed to answer immediately, clear DNIS and set 's' exten */ 01445 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) { 01446 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n"); 01447 p->exten[0] = 's'; 01448 p->exten[1] = 0; 01449 } 01450 ast_mutex_unlock(&p->lock); 01451 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01452 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n", 01453 p->channel, p->exten, p->context); 01454 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER); 01455 } else { 01456 /* if the user does not want to accept on offer, then we should launch the PBX thread now */ 01457 if (!p->mfcr2_accept_on_offer) { 01458 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0); 01459 if (!c) { 01460 ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel); 01461 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER); 01462 } 01463 /* Don't disable reading since we still need to generate MF tone to accept 01464 the call or reject it and detect the tone off condition of the other end */ 01465 } else if (p->mfcr2_charge_calls) { 01466 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel); 01467 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE); 01468 } else { 01469 ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel); 01470 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE); 01471 } 01472 } 01473 }
static void dahdi_r2_on_call_read | ( | openr2_chan_t * | r2chan, | |
const unsigned char * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 1529 of file chan_dahdi.c.
01530 { 01531 /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/ 01532 }
static void dahdi_r2_on_chan_log | ( | openr2_chan_t * | r2chan, | |
openr2_log_level_t | level, | |||
const char * | fmt, | |||
va_list | ap | |||
) | [static] |
Definition at line 1678 of file chan_dahdi.c.
References dahdi_r2_write_log().
Referenced by mkintf().
01679 { 01680 char logmsg[256]; 01681 char completemsg[sizeof(logmsg)+50]; 01682 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01683 snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg); 01684 dahdi_r2_write_log(level, completemsg); 01685 }
static void dahdi_r2_on_context_log | ( | openr2_context_t * | r2context, | |
openr2_log_level_t | level, | |||
const char * | fmt, | |||
va_list | ap | |||
) | [static] |
Definition at line 1667 of file chan_dahdi.c.
References dahdi_r2_write_log().
01668 { 01669 char logmsg[256]; 01670 char completemsg[sizeof(logmsg)+50]; 01671 vsnprintf(logmsg, sizeof(logmsg), fmt, ap); 01672 snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg); 01673 dahdi_r2_write_log(level, completemsg); 01674 }
static int dahdi_r2_on_dnis_digit_received | ( | openr2_chan_t * | r2chan, | |
char | digit | |||
) | [static] |
Definition at line 1687 of file chan_dahdi.c.
References ast_exists_extension(), ast_matchmore_extension(), dahdi_pvt::cid_num, dahdi_pvt::context, dahdi_pvt::exten, dahdi_pvt::immediate, dahdi_pvt::mfcr2_dnis_index, dahdi_pvt::mfcr2_dnis_matched, and dahdi_pvt::rdnis.
01688 { 01689 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01690 /* if 'immediate' is set, let's stop requesting DNIS */ 01691 if (p->immediate) { 01692 return 0; 01693 } 01694 p->exten[p->mfcr2_dnis_index] = digit; 01695 p->rdnis[p->mfcr2_dnis_index] = digit; 01696 p->mfcr2_dnis_index++; 01697 p->exten[p->mfcr2_dnis_index] = 0; 01698 p->rdnis[p->mfcr2_dnis_index] = 0; 01699 /* 01700 ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten); 01701 int ret; 01702 ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num); 01703 ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01704 ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num); 01705 ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret); 01706 */ 01707 /* if the DNIS is a match and cannot match more, stop requesting DNIS */ 01708 if ((p->mfcr2_dnis_matched || 01709 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) && 01710 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 01711 return 0; 01712 } 01713 /* otherwise keep going */ 01714 return 1; 01715 }
static void dahdi_r2_on_hardware_alarm | ( | openr2_chan_t * | r2chan, | |
int | alarm | |||
) | [static] |
Definition at line 1371 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, manager_event(), and dahdi_pvt::unknown_alarm.
01372 { 01373 int res; 01374 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01375 ast_mutex_lock(&p->lock); 01376 p->inalarm = alarm ? 1 : 0; 01377 if (p->inalarm) { 01378 res = get_alarms(p); 01379 /* unknown_alarm may be set here */ 01380 handle_alarms(p, res); 01381 } else { 01382 if (!p->unknown_alarm) { 01383 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 01384 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); 01385 } else { 01386 p->unknown_alarm = 0; 01387 } 01388 } 01389 ast_mutex_unlock(&p->lock); 01390 ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan)); 01391 }
static void dahdi_r2_on_line_blocked | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1647 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.
01648 { 01649 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01650 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel); 01651 ast_mutex_lock(&p->lock); 01652 p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK; 01653 ast_mutex_unlock(&p->lock); 01654 }
static void dahdi_r2_on_line_idle | ( | openr2_chan_t * | r2chan | ) | [static] |
Definition at line 1656 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DAHDI_R2_REMOTE_BLOCK, dahdi_pvt::lock, LOG_NOTICE, and dahdi_pvt::mfcr2block.
01657 { 01658 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01659 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan)); 01660 ast_mutex_lock(&p->lock); 01661 p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK; 01662 ast_mutex_unlock(&p->lock); 01663 }
static void dahdi_r2_on_os_error | ( | openr2_chan_t * | r2chan, | |
int | errorcode | |||
) | [static] |
static void dahdi_r2_on_protocol_error | ( | openr2_chan_t * | r2chan, | |
openr2_protocol_error_t | reason | |||
) | [static] |
Definition at line 1398 of file chan_dahdi.c.
References ast_channel::_softhangup, AST_CAUSE_PROTOCOL_ERROR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, ast_channel::hangupcause, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::mfcr2call, and dahdi_pvt::owner.
01399 { 01400 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan); 01401 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason)); 01402 if (p->owner) { 01403 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR; 01404 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 01405 } 01406 ast_mutex_lock(&p->lock); 01407 p->mfcr2call = 0; 01408 ast_mutex_unlock(&p->lock); 01409 }
static void dahdi_r2_write_log | ( | openr2_log_level_t | level, | |
char * | logmessage | |||
) | [static] |
Definition at line 1619 of file chan_dahdi.c.
References ast_log(), ast_verbose(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.
Referenced by dahdi_r2_on_chan_log(), and dahdi_r2_on_context_log().
01620 { 01621 switch (level) { 01622 case OR2_LOG_NOTICE: 01623 ast_verbose("%s", logmessage); 01624 break; 01625 case OR2_LOG_WARNING: 01626 ast_log(LOG_WARNING, "%s", logmessage); 01627 break; 01628 case OR2_LOG_ERROR: 01629 ast_log(LOG_ERROR, "%s", logmessage); 01630 break; 01631 case OR2_LOG_STACK_TRACE: 01632 case OR2_LOG_MF_TRACE: 01633 case OR2_LOG_CAS_TRACE: 01634 case OR2_LOG_DEBUG: 01635 case OR2_LOG_EX_DEBUG: 01636 ast_log(LOG_DEBUG, "%s", logmessage); 01637 break; 01638 default: 01639 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level); 01640 ast_log(LOG_NOTICE, "%s", logmessage); 01641 break; 01642 } 01643 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 5909 of file chan_dahdi.c.
References ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_FLAG_BLOCKING, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRIENDLY_OFFSET, ast_getformatname(), AST_LIN2MU, ast_log(), AST_MULAW, ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_setstate(), AST_STATE_PRERING, AST_STATE_RINGING, ast_tv(), dahdi_subchannel::buffer, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_subchannel::f, f, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, dahdi_pvt::mfcr2, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::r2chan, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, dahdi_pvt::ringt, S_OR, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::use_callerid.
05910 { 05911 struct dahdi_pvt *p = ast->tech_pvt; 05912 int res; 05913 int index; 05914 void *readbuf; 05915 struct ast_frame *f; 05916 05917 while (ast_mutex_trylock(&p->lock)) { 05918 DEADLOCK_AVOIDANCE(&ast->lock); 05919 } 05920 05921 index = dahdi_get_index(ast, p, 0); 05922 05923 /* Hang up if we don't really exist */ 05924 if (index < 0) { 05925 ast_log(LOG_WARNING, "We dont exist?\n"); 05926 ast_mutex_unlock(&p->lock); 05927 return NULL; 05928 } 05929 05930 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05931 ast_mutex_unlock(&p->lock); 05932 return NULL; 05933 } 05934 05935 p->subs[index].f.frametype = AST_FRAME_NULL; 05936 p->subs[index].f.datalen = 0; 05937 p->subs[index].f.samples = 0; 05938 p->subs[index].f.mallocd = 0; 05939 p->subs[index].f.offset = 0; 05940 p->subs[index].f.subclass = 0; 05941 p->subs[index].f.delivery = ast_tv(0,0); 05942 p->subs[index].f.src = "dahdi_read"; 05943 p->subs[index].f.data = NULL; 05944 05945 /* make sure it sends initial key state as first frame */ 05946 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05947 { 05948 struct dahdi_params ps; 05949 05950 memset(&ps, 0, sizeof(ps)); 05951 ps.channo = p->channel; 05952 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05953 ast_mutex_unlock(&p->lock); 05954 return NULL; 05955 } 05956 p->firstradio = 1; 05957 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05958 if (ps.rxisoffhook) 05959 { 05960 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 05961 } 05962 else 05963 { 05964 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 05965 } 05966 ast_mutex_unlock(&p->lock); 05967 return &p->subs[index].f; 05968 } 05969 if (p->ringt == 1) { 05970 ast_mutex_unlock(&p->lock); 05971 return NULL; 05972 } 05973 else if (p->ringt > 0) 05974 p->ringt--; 05975 05976 #ifdef HAVE_OPENR2 05977 if (p->mfcr2) { 05978 openr2_chan_process_event(p->r2chan); 05979 } 05980 #endif 05981 05982 if (p->subs[index].needringing) { 05983 /* Send ringing frame if requested */ 05984 p->subs[index].needringing = 0; 05985 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05986 p->subs[index].f.subclass = AST_CONTROL_RINGING; 05987 ast_setstate(ast, AST_STATE_RINGING); 05988 ast_mutex_unlock(&p->lock); 05989 return &p->subs[index].f; 05990 } 05991 05992 if (p->subs[index].needbusy) { 05993 /* Send busy frame if requested */ 05994 p->subs[index].needbusy = 0; 05995 p->subs[index].f.frametype = AST_FRAME_CONTROL; 05996 p->subs[index].f.subclass = AST_CONTROL_BUSY; 05997 ast_mutex_unlock(&p->lock); 05998 return &p->subs[index].f; 05999 } 06000 06001 if (p->subs[index].needcongestion) { 06002 /* Send congestion frame if requested */ 06003 p->subs[index].needcongestion = 0; 06004 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06005 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 06006 ast_mutex_unlock(&p->lock); 06007 return &p->subs[index].f; 06008 } 06009 06010 if (p->subs[index].needcallerid) { 06011 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06012 S_OR(p->lastcid_name, NULL), 06013 S_OR(p->lastcid_num, NULL) 06014 ); 06015 p->subs[index].needcallerid = 0; 06016 } 06017 06018 if (p->subs[index].needanswer) { 06019 /* Send answer frame if requested */ 06020 p->subs[index].needanswer = 0; 06021 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06022 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 06023 ast_mutex_unlock(&p->lock); 06024 return &p->subs[index].f; 06025 } 06026 06027 #ifdef HAVE_OPENR2 06028 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06029 /* openr2 took care of reading and handling any event 06030 (needanswer, needbusy etc), if we continue we will read() 06031 twice, lets just return a null frame. This should only 06032 happen when openr2 is dialing out */ 06033 p->subs[index].f.frametype = AST_FRAME_NULL; 06034 p->subs[index].f.subclass = 0; 06035 p->subs[index].f.samples = 0; 06036 p->subs[index].f.mallocd = 0; 06037 p->subs[index].f.offset = 0; 06038 p->subs[index].f.data = NULL; 06039 p->subs[index].f.datalen= 0; 06040 ast_mutex_unlock(&p->lock); 06041 return &p->subs[index].f; 06042 } 06043 #endif 06044 06045 if (p->subs[index].needflash) { 06046 /* Send answer frame if requested */ 06047 p->subs[index].needflash = 0; 06048 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06049 p->subs[index].f.subclass = AST_CONTROL_FLASH; 06050 ast_mutex_unlock(&p->lock); 06051 return &p->subs[index].f; 06052 } 06053 06054 if (p->subs[index].needhold) { 06055 /* Send answer frame if requested */ 06056 p->subs[index].needhold = 0; 06057 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06058 p->subs[index].f.subclass = AST_CONTROL_HOLD; 06059 ast_mutex_unlock(&p->lock); 06060 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 06061 return &p->subs[index].f; 06062 } 06063 06064 if (p->subs[index].needunhold) { 06065 /* Send answer frame if requested */ 06066 p->subs[index].needunhold = 0; 06067 p->subs[index].f.frametype = AST_FRAME_CONTROL; 06068 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 06069 ast_mutex_unlock(&p->lock); 06070 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 06071 return &p->subs[index].f; 06072 } 06073 06074 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06075 if (!p->subs[index].linear) { 06076 p->subs[index].linear = 1; 06077 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06078 if (res) 06079 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 06080 } 06081 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06082 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06083 if (p->subs[index].linear) { 06084 p->subs[index].linear = 0; 06085 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06086 if (res) 06087 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 06088 } 06089 } else { 06090 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06091 ast_mutex_unlock(&p->lock); 06092 return NULL; 06093 } 06094 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 06095 CHECK_BLOCKING(ast); 06096 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06097 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06098 06099 if (p->use_callerid && (ast->_state == AST_STATE_PRERING && 06100 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) { 06101 //ast_log(LOG_NOTICE, "use_callerid %u, cid_start %i\n", p->use_callerid, p->cid_start); 06102 if (!p->subs[index].linear) { 06103 int x, samplin; 06104 int mean, ssum; 06105 06106 /* First calc mean signal (DC offset) */ 06107 for (x = 0, ssum = 0; x < READ_SIZE; x++) { 06108 //ssum += (ast->rawreadformat == AST_FORMAT_ULAW ? AST_MULAW((u_char *)readbuf) : AST_ALAW((u_char *)readbuf[x])); 06109 ssum += AST_MULAW(((u_char *)readbuf)[x]); 06110 if (option_verbose > 5 && (x % 10 == 0)) 06111 ast_log(LOG_NOTICE, "dahdi_read ssum %i, mean %i \n", ssum, ssum / READ_SIZE); 06112 } 06113 mean = ssum / READ_SIZE; 06114 06115 if (option_verbose > 5) 06116 ast_log(LOG_WARNING, "dahdi_read channel %s, mean %i \n", ast->name, mean); 06117 if (ast->rawreadformat == AST_FORMAT_ULAW) { 06118 for (x = 0; x < READ_SIZE; x++) { 06119 samplin = AST_MULAW(((u_char *)readbuf)[x]); 06120 if (option_verbose > 6 && (x % 10 == 0)) 06121 ast_log(LOG_NOTICE, "dahdi_read,x %i, samporig %i samplin %i, samplinconv %i, xconv %i\n", x, ((u_char *)readbuf)[x], samplin, samplin - mean, AST_LIN2MU(samplin - mean)); 06122 ((u_char *)readbuf)[x] = AST_LIN2MU(samplin - mean); 06123 } 06124 } 06125 } 06126 } 06127 06128 /* Check for hangup */ 06129 if (res < 0) { 06130 f = NULL; 06131 if (res == -1) { 06132 if (errno == EAGAIN) { 06133 /* Return "NULL" frame if there is nobody there */ 06134 ast_mutex_unlock(&p->lock); 06135 return &p->subs[index].f; 06136 } else if (errno == ELAST) { 06137 f = __dahdi_exception(ast); 06138 } else 06139 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06140 } 06141 ast_mutex_unlock(&p->lock); 06142 return f; 06143 } 06144 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 06145 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 06146 f = __dahdi_exception(ast); 06147 ast_mutex_unlock(&p->lock); 06148 return f; 06149 } 06150 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06151 int c; 06152 06153 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06154 if (c < 0) { 06155 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 06156 ast_mutex_unlock(&p->lock); 06157 return NULL; 06158 } 06159 if (c) { /* if a char to return */ 06160 p->subs[index].f.subclass = 0; 06161 p->subs[index].f.frametype = AST_FRAME_TEXT; 06162 p->subs[index].f.mallocd = 0; 06163 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06164 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 06165 p->subs[index].f.datalen = 1; 06166 *((char *) p->subs[index].f.data) = c; 06167 ast_mutex_unlock(&p->lock); 06168 return &p->subs[index].f; 06169 } 06170 } 06171 /* Ensure the CW timer decrements only on a single subchannel */ 06172 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 06173 p->callwaitingrepeat--; 06174 } 06175 if (p->cidcwexpire) 06176 p->cidcwexpire--; 06177 /* Repeat callwaiting */ 06178 if (p->callwaitingrepeat == 1) { 06179 p->callwaitrings++; 06180 dahdi_callwait(ast); 06181 } 06182 /* Expire CID/CW */ 06183 if (p->cidcwexpire == 1) { 06184 if (option_verbose > 2) 06185 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 06186 restore_conference(p); 06187 } 06188 if (p->subs[index].linear) { 06189 p->subs[index].f.datalen = READ_SIZE * 2; 06190 } else 06191 p->subs[index].f.datalen = READ_SIZE; 06192 06193 /* Handle CallerID Transmission */ 06194 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06195 send_callerid(p); 06196 } 06197 06198 p->subs[index].f.frametype = AST_FRAME_VOICE; 06199 p->subs[index].f.subclass = ast->rawreadformat; 06200 p->subs[index].f.samples = READ_SIZE; 06201 p->subs[index].f.mallocd = 0; 06202 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 06203 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 06204 #if 0 06205 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 06206 #endif 06207 if (p->dialing || /* Transmitting something */ 06208 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06209 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06210 ) { 06211 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06212 don't send anything */ 06213 p->subs[index].f.frametype = AST_FRAME_NULL; 06214 p->subs[index].f.subclass = 0; 06215 p->subs[index].f.samples = 0; 06216 p->subs[index].f.mallocd = 0; 06217 p->subs[index].f.offset = 0; 06218 p->subs[index].f.data = NULL; 06219 p->subs[index].f.datalen= 0; 06220 } 06221 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 06222 /* Perform busy detection. etc on the dahdi line */ 06223 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 06224 if (f) { 06225 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 06226 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 06227 /* Treat this as a "hangup" instead of a "busy" on the assumption that 06228 a busy */ 06229 f = NULL; 06230 } 06231 } else if (f->frametype == AST_FRAME_DTMF) { 06232 #ifdef HAVE_PRI 06233 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial && 06234 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 06235 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 06236 /* Don't accept in-band DTMF when in overlap dial mode */ 06237 f->frametype = AST_FRAME_NULL; 06238 f->subclass = 0; 06239 } 06240 #endif 06241 /* DSP clears us of being pulse */ 06242 p->pulsedial = 0; 06243 } 06244 } 06245 } else 06246 f = &p->subs[index].f; 06247 06248 if (f && (f->frametype == AST_FRAME_DTMF)) 06249 dahdi_handle_dtmfup(ast, index, &f); 06250 06251 /* If we have a fake_event, trigger exception to handle it */ 06252 if (p->fake_event) 06253 ast_set_flag(ast, AST_FLAG_EXCEPTION); 06254 06255 ast_mutex_unlock(&p->lock); 06256 return f; 06257 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 9373 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().
09374 { 09375 ast_group_t groupmatch = 0; 09376 int channelmatch = -1; 09377 int roundrobin = 0; 09378 int callwait = 0; 09379 int busy = 0; 09380 struct dahdi_pvt *p; 09381 struct ast_channel *tmp = NULL; 09382 char *dest=NULL; 09383 int x; 09384 char *s; 09385 char opt=0; 09386 int res=0, y=0; 09387 int backwards = 0; 09388 #ifdef HAVE_PRI 09389 int crv; 09390 int bearer = -1; 09391 int trunkgroup; 09392 struct dahdi_pri *pri=NULL; 09393 #endif 09394 struct dahdi_pvt *exit, *start, *end; 09395 ast_mutex_t *lock; 09396 int channelmatched = 0; 09397 int groupmatched = 0; 09398 09399 /* 09400 * data is ---v 09401 * Dial(DAHDI/pseudo[/extension]) 09402 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09403 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09404 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09405 * 09406 * g - channel group allocation search forward 09407 * G - channel group allocation search backward 09408 * r - channel group allocation round robin search forward 09409 * R - channel group allocation round robin search backward 09410 * 09411 * c - Wait for DTMF digit to confirm answer 09412 * r<cadance#> - Set distintive ring cadance number 09413 * d - Force bearer capability for ISDN call to digital. 09414 */ 09415 09416 /* Assume we're locking the iflock */ 09417 lock = &iflock; 09418 start = iflist; 09419 end = ifend; 09420 if (data) { 09421 dest = ast_strdupa((char *)data); 09422 } else { 09423 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09424 return NULL; 09425 } 09426 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09427 /* Retrieve the group number */ 09428 char *stringp; 09429 09430 stringp = dest + 1; 09431 s = strsep(&stringp, "/"); 09432 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09433 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09434 return NULL; 09435 } 09436 groupmatch = ((ast_group_t) 1 << x); 09437 if (toupper(dest[0]) == 'G') { 09438 if (dest[0] == 'G') { 09439 backwards = 1; 09440 p = ifend; 09441 } else 09442 p = iflist; 09443 } else { 09444 if (dest[0] == 'R') { 09445 backwards = 1; 09446 p = round_robin[x]?round_robin[x]->prev:ifend; 09447 if (!p) 09448 p = ifend; 09449 } else { 09450 p = round_robin[x]?round_robin[x]->next:iflist; 09451 if (!p) 09452 p = iflist; 09453 } 09454 roundrobin = 1; 09455 } 09456 } else { 09457 char *stringp; 09458 09459 stringp = dest; 09460 s = strsep(&stringp, "/"); 09461 p = iflist; 09462 if (!strcasecmp(s, "pseudo")) { 09463 /* Special case for pseudo */ 09464 x = CHAN_PSEUDO; 09465 channelmatch = x; 09466 } 09467 #ifdef HAVE_PRI 09468 else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09469 if ((trunkgroup < 1) || (crv < 1)) { 09470 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09471 return NULL; 09472 } 09473 res--; 09474 for (x = 0; x < NUM_SPANS; x++) { 09475 if (pris[x].trunkgroup == trunkgroup) { 09476 pri = pris + x; 09477 lock = &pri->lock; 09478 start = pri->crvs; 09479 end = pri->crvend; 09480 break; 09481 } 09482 } 09483 if (!pri) { 09484 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09485 return NULL; 09486 } 09487 channelmatch = crv; 09488 p = pris[x].crvs; 09489 } 09490 #endif 09491 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09492 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09493 return NULL; 09494 } else { 09495 channelmatch = x; 09496 } 09497 } 09498 /* Search for an unowned channel */ 09499 ast_mutex_lock(lock); 09500 exit = p; 09501 while (p && !tmp) { 09502 if (roundrobin) 09503 round_robin[x] = p; 09504 #if 0 09505 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09506 #endif 09507 09508 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09509 if (option_debug) 09510 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 09511 if (p->inalarm) 09512 goto next; 09513 09514 callwait = (p->owner != NULL); 09515 #ifdef HAVE_PRI 09516 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09517 if (p->sig != SIG_FXSKS) { 09518 /* Gotta find an actual channel to use for this 09519 CRV if this isn't a callwait */ 09520 bearer = pri_find_empty_chan(pri, 0); 09521 if (bearer < 0) { 09522 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09523 p = NULL; 09524 break; 09525 } 09526 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09527 } else { 09528 if (alloc_sub(p, 0)) { 09529 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09530 p = NULL; 09531 break; 09532 } else 09533 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 09534 p->pri = pri; 09535 } 09536 } 09537 #endif 09538 #ifdef HAVE_OPENR2 09539 if (p->mfcr2) { 09540 ast_mutex_lock(&p->lock); 09541 if (p->mfcr2call) { 09542 ast_mutex_unlock(&p->lock); 09543 ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 09544 goto next; 09545 } 09546 if (p->mfcr2block) { 09547 ast_mutex_unlock(&p->lock); 09548 ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block); 09549 goto next; 09550 } 09551 p->mfcr2call = 1; 09552 ast_mutex_unlock(&p->lock); 09553 } 09554 #endif 09555 if (p->channel == CHAN_PSEUDO) { 09556 p = chandup(p); 09557 if (!p) { 09558 break; 09559 } 09560 } 09561 if (p->owner) { 09562 if (alloc_sub(p, SUB_CALLWAIT)) { 09563 p = NULL; 09564 break; 09565 } 09566 } 09567 p->outgoing = 1; 09568 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09569 if (!tmp) { 09570 p->outgoing = 0; 09571 } 09572 #ifdef HAVE_PRI 09573 if (p->bearer) { 09574 /* Log owner to bearer channel, too */ 09575 p->bearer->owner = tmp; 09576 } 09577 #endif 09578 /* Make special notes */ 09579 if (res > 1) { 09580 if (opt == 'c') { 09581 /* Confirm answer */ 09582 p->confirmanswer = 1; 09583 } else if (opt == 'r') { 09584 /* Distinctive ring */ 09585 if (res < 3) 09586 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09587 else 09588 p->distinctivering = y; 09589 } else if (opt == 'd') { 09590 /* If this is an ISDN call, make it digital */ 09591 p->digital = 1; 09592 if (tmp) 09593 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09594 } else { 09595 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09596 } 09597 } 09598 /* Note if the call is a call waiting call */ 09599 if (tmp && callwait) 09600 tmp->cdrflags |= AST_CDR_CALLWAIT; 09601 break; 09602 } 09603 next: 09604 if (backwards) { 09605 p = p->prev; 09606 if (!p) 09607 p = end; 09608 } else { 09609 p = p->next; 09610 if (!p) 09611 p = start; 09612 } 09613 /* stop when you roll to the one that we started from */ 09614 if (p == exit) 09615 break; 09616 } 09617 ast_mutex_unlock(lock); 09618 restart_monitor(); 09619 if (callwait) 09620 *cause = AST_CAUSE_BUSY; 09621 else if (!tmp) { 09622 if (channelmatched) { 09623 if (busy) 09624 *cause = AST_CAUSE_BUSY; 09625 } else if (groupmatched) { 09626 *cause = AST_CAUSE_CONGESTION; 09627 } 09628 } 09629 09630 return tmp; 09631 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12005 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().
12006 { 12007 #ifdef HAVE_OPENR2 12008 int r; 12009 #endif 12010 #if defined(HAVE_PRI) 12011 int i, j; 12012 #endif 12013 int cancel_code; 12014 struct dahdi_pvt *p; 12015 12016 ast_mutex_lock(&restart_lock); 12017 12018 if (option_verbose) 12019 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 12020 dahdi_softhangup_all(); 12021 if (option_verbose > 3) 12022 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 12023 12024 #ifdef HAVE_OPENR2 12025 for (r = 0; r < NUM_SPANS; r++) { 12026 if (r2links[r].master != AST_PTHREADT_NULL) { 12027 ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master); 12028 pthread_cancel(r2links[r].master); 12029 pthread_join(r2links[r].master, NULL); 12030 openr2_context_delete(r2links[r].protocol_context); 12031 } 12032 } 12033 init_mfcr2_globals(); 12034 #endif 12035 12036 #if defined(HAVE_PRI) 12037 for (i = 0; i < NUM_SPANS; i++) { 12038 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12039 cancel_code = pthread_cancel(pris[i].master); 12040 pthread_kill(pris[i].master, SIGURG); 12041 if (option_debug > 3) 12042 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12043 pthread_join(pris[i].master, NULL); 12044 if (option_debug > 3) 12045 ast_verbose("Joined thread of span %d\n", i); 12046 } 12047 } 12048 #endif 12049 12050 ast_mutex_lock(&monlock); 12051 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12052 cancel_code = pthread_cancel(monitor_thread); 12053 pthread_kill(monitor_thread, SIGURG); 12054 if (option_debug > 3) 12055 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12056 pthread_join(monitor_thread, NULL); 12057 if (option_debug > 3) 12058 ast_verbose("Joined monitor thread\n"); 12059 } 12060 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12061 12062 ast_mutex_lock(&ss_thread_lock); 12063 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12064 int x = DAHDI_FLASH; 12065 if (option_debug > 2) 12066 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12067 12068 for (p = iflist; p; p = p->next) { 12069 if (p->owner) 12070 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 */ 12071 } 12072 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12073 } 12074 12075 /* ensure any created channels before monitor threads were stopped are hungup */ 12076 dahdi_softhangup_all(); 12077 if (option_verbose > 3) 12078 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 12079 destroy_all_channels(); 12080 if (option_debug) 12081 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12082 12083 ast_mutex_unlock(&monlock); 12084 12085 #ifdef HAVE_PRI 12086 for (i = 0; i < NUM_SPANS; i++) { 12087 for (j = 0; j < NUM_DCHANS; j++) 12088 dahdi_close_pri_fd(&(pris[i]), j); 12089 } 12090 12091 memset(pris, 0, sizeof(pris)); 12092 for (i = 0; i < NUM_SPANS; i++) { 12093 ast_mutex_init(&pris[i].lock); 12094 pris[i].offset = -1; 12095 pris[i].master = AST_PTHREADT_NULL; 12096 for (j = 0; j < NUM_DCHANS; j++) 12097 pris[i].fds[j] = -1; 12098 } 12099 pri_set_error(dahdi_pri_error); 12100 pri_set_message(dahdi_pri_message); 12101 #endif 12102 12103 if (setup_dahdi(2) != 0) { 12104 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12105 ast_mutex_unlock(&ss_thread_lock); 12106 return 1; 12107 } 12108 ast_mutex_unlock(&ss_thread_lock); 12109 ast_mutex_unlock(&restart_lock); 12110 return 0; 12111 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12113 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
12114 { 12115 if (argc != 2) { 12116 return RESULT_SHOWUSAGE; 12117 } 12118 12119 if (dahdi_restart() != 0) 12120 return RESULT_FAILURE; 12121 return RESULT_SUCCESS; 12122 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4686 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
04687 { 04688 int x; 04689 int res; 04690 /* Make sure our transmit state is on hook */ 04691 x = 0; 04692 x = DAHDI_ONHOOK; 04693 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04694 do { 04695 x = DAHDI_RING; 04696 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04697 if (res) { 04698 switch (errno) { 04699 case EBUSY: 04700 case EINTR: 04701 /* Wait just in case */ 04702 usleep(10000); 04703 continue; 04704 case EINPROGRESS: 04705 res = 0; 04706 break; 04707 default: 04708 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04709 res = 0; 04710 } 04711 } 04712 } while (res); 04713 return res; 04714 }
static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3340 of file chan_dahdi.c.
References send_keypad_facility_exec().
Referenced by load_module().
03341 { 03342 return send_keypad_facility_exec(chan, data); 03343 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 14045 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, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
14046 { 14047 #define END_SILENCE_LEN 400 14048 #define HEADER_MS 50 14049 #define TRAILER_MS 5 14050 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 14051 #define ASCII_BYTES_PER_CHAR 80 14052 14053 unsigned char *buf,*mybuf; 14054 struct dahdi_pvt *p = c->tech_pvt; 14055 struct pollfd fds[1]; 14056 int size,res,fd,len,x; 14057 int bytes=0; 14058 /* Initial carrier (imaginary) */ 14059 float cr = 1.0; 14060 float ci = 0.0; 14061 float scont = 0.0; 14062 int index; 14063 14064 index = dahdi_get_index(c, p, 0); 14065 if (index < 0) { 14066 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 14067 return -1; 14068 } 14069 if (!text[0]) return(0); /* if nothing to send, dont */ 14070 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 14071 if (p->mate) 14072 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 14073 else 14074 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 14075 if (!buf) 14076 return -1; 14077 mybuf = buf; 14078 if (p->mate) { 14079 int codec = AST_LAW(p); 14080 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 14081 PUT_CLID_MARKMS; 14082 } 14083 /* Put actual message */ 14084 for (x = 0; text[x]; x++) { 14085 PUT_CLID(text[x]); 14086 } 14087 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 14088 PUT_CLID_MARKMS; 14089 } 14090 len = bytes; 14091 buf = mybuf; 14092 } else { 14093 len = tdd_generate(p->tdd, buf, text); 14094 if (len < 1) { 14095 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 14096 free(mybuf); 14097 return -1; 14098 } 14099 } 14100 memset(buf + len, 0x7f, END_SILENCE_LEN); 14101 len += END_SILENCE_LEN; 14102 fd = p->subs[index].dfd; 14103 while (len) { 14104 if (ast_check_hangup(c)) { 14105 free(mybuf); 14106 return -1; 14107 } 14108 size = len; 14109 if (size > READ_SIZE) 14110 size = READ_SIZE; 14111 fds[0].fd = fd; 14112 fds[0].events = POLLOUT | POLLPRI; 14113 fds[0].revents = 0; 14114 res = poll(fds, 1, -1); 14115 if (!res) { 14116 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 14117 continue; 14118 } 14119 /* if got exception */ 14120 if (fds[0].revents & POLLPRI) { 14121 ast_free(mybuf); 14122 return -1; 14123 } 14124 if (!(fds[0].revents & POLLOUT)) { 14125 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 14126 continue; 14127 } 14128 res = write(fd, buf, size); 14129 if (res != size) { 14130 if (res == -1) { 14131 free(mybuf); 14132 return -1; 14133 } 14134 if (option_debug) 14135 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 14136 break; 14137 } 14138 len -= size; 14139 buf += size; 14140 } 14141 free(mybuf); 14142 return(0); 14143 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 2553 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), and ss_thread().
02554 { 02555 int x, res; 02556 02557 x = hs; 02558 res = ioctl(fd, DAHDI_HOOK, &x); 02559 02560 if (res < 0) { 02561 if (errno == EINPROGRESS) 02562 return 0; 02563 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02564 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02565 } 02566 02567 return res; 02568 }
static int dahdi_setlaw | ( | int | dfd, | |
int | law | |||
) | [static] |
Definition at line 10076 of file chan_dahdi.c.
10077 { 10078 int res; 10079 res = ioctl(dfd, DAHDI_SETLAW, &law); 10080 if (res) 10081 return res; 10082 return 0; 10083 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 1867 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
01868 { 01869 int res; 01870 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 01871 if (res) 01872 return res; 01873 return 0; 01874 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 4050 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
04051 { 04052 char *cp; 04053 signed char *scp; 04054 int x; 04055 int index; 04056 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04057 struct oprmode *oprmode; 04058 04059 04060 /* all supported options require data */ 04061 if (!data || (datalen < 1)) { 04062 errno = EINVAL; 04063 return -1; 04064 } 04065 04066 switch (option) { 04067 case AST_OPTION_TXGAIN: 04068 scp = (signed char *) data; 04069 index = dahdi_get_index(chan, p, 0); 04070 if (index < 0) { 04071 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04072 return -1; 04073 } 04074 if (option_debug) 04075 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04076 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 04077 case AST_OPTION_RXGAIN: 04078 scp = (signed char *) data; 04079 index = dahdi_get_index(chan, p, 0); 04080 if (index < 0) { 04081 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04082 return -1; 04083 } 04084 if (option_debug) 04085 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04086 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 04087 case AST_OPTION_TONE_VERIFY: 04088 if (!p->dsp) 04089 break; 04090 cp = (char *) data; 04091 switch (*cp) { 04092 case 1: 04093 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04094 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04095 break; 04096 case 2: 04097 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04098 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04099 break; 04100 default: 04101 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04102 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04103 break; 04104 } 04105 break; 04106 case AST_OPTION_TDD: 04107 /* turn on or off TDD */ 04108 cp = (char *) data; 04109 p->mate = 0; 04110 if (!*cp) { /* turn it off */ 04111 if (option_debug) 04112 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04113 if (p->tdd) 04114 tdd_free(p->tdd); 04115 p->tdd = 0; 04116 break; 04117 } 04118 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 04119 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04120 dahdi_disable_ec(p); 04121 /* otherwise, turn it on */ 04122 if (!p->didtdd) { /* if havent done it yet */ 04123 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04124 unsigned char *buf; 04125 int size, res, fd, len; 04126 struct pollfd fds[1]; 04127 04128 buf = mybuf; 04129 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04130 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04131 len = 40000; 04132 index = dahdi_get_index(chan, p, 0); 04133 if (index < 0) { 04134 ast_log(LOG_WARNING, "No index in TDD?\n"); 04135 return -1; 04136 } 04137 fd = p->subs[index].dfd; 04138 while (len) { 04139 if (ast_check_hangup(chan)) 04140 return -1; 04141 size = len; 04142 if (size > READ_SIZE) 04143 size = READ_SIZE; 04144 fds[0].fd = fd; 04145 fds[0].events = POLLPRI | POLLOUT; 04146 fds[0].revents = 0; 04147 res = poll(fds, 1, -1); 04148 if (!res) { 04149 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 04150 continue; 04151 } 04152 /* if got exception */ 04153 if (fds[0].revents & POLLPRI) 04154 return -1; 04155 if (!(fds[0].revents & POLLOUT)) { 04156 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 04157 continue; 04158 } 04159 res = write(fd, buf, size); 04160 if (res != size) { 04161 if (res == -1) return -1; 04162 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04163 break; 04164 } 04165 len -= size; 04166 buf += size; 04167 } 04168 p->didtdd = 1; /* set to have done it now */ 04169 } 04170 if (*cp == 2) { /* Mate mode */ 04171 if (p->tdd) 04172 tdd_free(p->tdd); 04173 p->tdd = 0; 04174 p->mate = 1; 04175 break; 04176 } 04177 if (!p->tdd) { /* if we dont have one yet */ 04178 p->tdd = tdd_new(); /* allocate one */ 04179 } 04180 break; 04181 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04182 if (!p->dsp) 04183 break; 04184 cp = (char *) data; 04185 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04186 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04187 p->dtmfrelax = 0; 04188 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 04189 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04190 break; 04191 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04192 cp = (char *) data; 04193 if (!*cp) { 04194 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04195 x = 0; 04196 dahdi_disable_ec(p); 04197 } else { 04198 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04199 x = 1; 04200 } 04201 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04202 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04203 break; 04204 case AST_OPTION_OPRMODE: /* Operator services mode */ 04205 oprmode = (struct oprmode *) data; 04206 pp = oprmode->peer->tech_pvt; 04207 p->oprmode = pp->oprmode = 0; 04208 /* setup peers */ 04209 p->oprpeer = pp; 04210 pp->oprpeer = p; 04211 /* setup modes, if any */ 04212 if (oprmode->mode) 04213 { 04214 pp->oprmode = oprmode->mode; 04215 p->oprmode = -oprmode->mode; 04216 } 04217 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 04218 oprmode->mode, chan->name,oprmode->peer->name);; 04219 break; 04220 case AST_OPTION_ECHOCAN: 04221 cp = (char *) data; 04222 if (*cp) { 04223 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 04224 dahdi_enable_ec(p); 04225 } else { 04226 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 04227 dahdi_disable_ec(p); 04228 } 04229 break; 04230 } 04231 errno = 0; 04232 04233 return 0; 04234 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12185 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.
12186 { 12187 int channel; 12188 struct dahdi_pvt *tmp = NULL; 12189 struct dahdi_confinfo ci; 12190 struct dahdi_params ps; 12191 int x; 12192 ast_mutex_t *lock; 12193 struct dahdi_pvt *start; 12194 #ifdef HAVE_PRI 12195 char *c; 12196 int trunkgroup; 12197 struct dahdi_pri *pri=NULL; 12198 #endif 12199 12200 lock = &iflock; 12201 start = iflist; 12202 12203 if (argc != 4) 12204 return RESULT_SHOWUSAGE; 12205 #ifdef HAVE_PRI 12206 if ((c = strchr(argv[3], ':'))) { 12207 if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12208 return RESULT_SHOWUSAGE; 12209 if ((trunkgroup < 1) || (channel < 1)) 12210 return RESULT_SHOWUSAGE; 12211 for (x = 0; x < NUM_SPANS; x++) { 12212 if (pris[x].trunkgroup == trunkgroup) { 12213 pri = pris + x; 12214 break; 12215 } 12216 } 12217 if (pri) { 12218 start = pri->crvs; 12219 lock = &pri->lock; 12220 } else { 12221 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12222 return RESULT_FAILURE; 12223 } 12224 } else 12225 #endif 12226 channel = atoi(argv[3]); 12227 12228 ast_mutex_lock(lock); 12229 tmp = start; 12230 while (tmp) { 12231 if (tmp->channel == channel) { 12232 #ifdef HAVE_PRI 12233 if (pri) 12234 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12235 else 12236 #endif 12237 ast_cli(fd, "Channel: %d\n", tmp->channel); 12238 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12239 ast_cli(fd, "Span: %d\n", tmp->span); 12240 ast_cli(fd, "Extension: %s\n", tmp->exten); 12241 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12242 ast_cli(fd, "Context: %s\n", tmp->context); 12243 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 12244 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 12245 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 12246 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 12247 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 12248 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12249 ast_cli(fd, "Radio: %d\n", tmp->radio); 12250 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12251 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)" : ""); 12252 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)" : ""); 12253 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)" : ""); 12254 ast_cli(fd, "Confno: %d\n", tmp->confno); 12255 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 12256 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 12257 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12258 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12259 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12260 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12261 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12262 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12263 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 12264 if (tmp->master) 12265 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 12266 for (x = 0; x < MAX_SLAVES; x++) { 12267 if (tmp->slaves[x]) 12268 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12269 } 12270 #ifdef HAVE_OPENR2 12271 if (tmp->mfcr2) { 12272 char calldir[OR2_MAX_PATH]; 12273 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 12274 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 12275 ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No"); 12276 ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No"); 12277 ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 12278 ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 12279 ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 12280 ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 12281 ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 12282 ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 12283 ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 12284 ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 12285 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 12286 ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No"); 12287 ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No"); 12288 #endif 12289 ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 12290 ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 12291 ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 12292 ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 12293 ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 12294 ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 12295 ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 12296 ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 12297 ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 12298 ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 12299 ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 12300 ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 12301 ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 12302 ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 12303 } 12304 #endif 12305 #ifdef HAVE_PRI 12306 if (tmp->pri) { 12307 ast_cli(fd, "PRI Flags: "); 12308 if (tmp->resetting) 12309 ast_cli(fd, "Resetting "); 12310 if (tmp->call) 12311 ast_cli(fd, "Call "); 12312 if (tmp->bearer) 12313 ast_cli(fd, "Bearer "); 12314 ast_cli(fd, "\n"); 12315 if (tmp->logicalspan) 12316 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12317 else 12318 ast_cli(fd, "PRI Logical Span: Implicit\n"); 12319 } 12320 12321 #endif 12322 memset(&ci, 0, sizeof(ci)); 12323 ps.channo = tmp->channel; 12324 if (tmp->subs[SUB_REAL].dfd > -1) { 12325 memset(&ci, 0, sizeof(ci)); 12326 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12327 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12328 } 12329 #ifdef DAHDI_GETCONFMUTE 12330 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12331 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12332 } 12333 #endif 12334 memset(&ps, 0, sizeof(ps)); 12335 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12336 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12337 } else { 12338 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12339 } 12340 } 12341 if (ISTRUNK(tmp)) { 12342 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 12343 if (!ast_strlen_zero(progzone)) 12344 ast_cli(fd, "Progress Zone: %s\n", progzone); 12345 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 12346 if(tmp->busydetect) { 12347 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 12348 if(tmp->busytonelength > 0) { 12349 ast_cli(fd, "Busy Pattern:\n"); 12350 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 12351 if (tmp->busyquietlength > 0) 12352 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 12353 else 12354 ast_cli(fd, " -- Detect Tone Only\n"); 12355 if(tmp->busyfuzziness > 0) 12356 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 12357 } 12358 } 12359 } 12360 ast_mutex_unlock(lock); 12361 return RESULT_SUCCESS; 12362 } 12363 tmp = tmp->next; 12364 } 12365 12366 ast_cli(fd, "Unable to find given channel %d\n", channel); 12367 ast_mutex_unlock(lock); 12368 return RESULT_FAILURE; 12369 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 12124 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.
12125 { 12126 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12127 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 12128 struct dahdi_pvt *tmp = NULL; 12129 char tmps[20] = ""; 12130 ast_mutex_t *lock; 12131 struct dahdi_pvt *start; 12132 #ifdef HAVE_PRI 12133 int trunkgroup; 12134 struct dahdi_pri *pri = NULL; 12135 int x; 12136 #endif 12137 12138 lock = &iflock; 12139 start = iflist; 12140 12141 #ifdef HAVE_PRI 12142 if (argc == 4) { 12143 if ((trunkgroup = atoi(argv[3])) < 1) 12144 return RESULT_SHOWUSAGE; 12145 for (x = 0; x < NUM_SPANS; x++) { 12146 if (pris[x].trunkgroup == trunkgroup) { 12147 pri = pris + x; 12148 break; 12149 } 12150 } 12151 if (pri) { 12152 start = pri->crvs; 12153 lock = &pri->lock; 12154 } else { 12155 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 12156 return RESULT_FAILURE; 12157 } 12158 } else 12159 #endif 12160 if (argc != 3) 12161 return RESULT_SHOWUSAGE; 12162 12163 ast_mutex_lock(lock); 12164 #ifdef HAVE_PRI 12165 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12166 #else 12167 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 12168 #endif 12169 12170 tmp = start; 12171 while (tmp) { 12172 if (tmp->channel > 0) { 12173 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12174 } else 12175 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12176 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 12177 tmp = tmp->next; 12178 } 12179 ast_mutex_unlock(lock); 12180 return RESULT_SUCCESS; 12181 #undef FORMAT 12182 #undef FORMAT2 12183 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12402 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.
12402 { 12403 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 12404 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 12405 12406 int span; 12407 int res; 12408 char alarms[50]; 12409 12410 int ctl; 12411 struct dahdi_spaninfo s; 12412 12413 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) { 12414 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno)); 12415 ast_cli(fd, "No " DAHDI_NAME " interface found.\n"); 12416 return RESULT_FAILURE; 12417 } 12418 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 12419 12420 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 12421 s.spanno = span; 12422 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 12423 if (res) { 12424 continue; 12425 } 12426 alarms[0] = '\0'; 12427 if (s.alarms > 0) { 12428 if (s.alarms & DAHDI_ALARM_BLUE) 12429 strcat(alarms, "BLU/"); 12430 if (s.alarms & DAHDI_ALARM_YELLOW) 12431 strcat(alarms, "YEL/"); 12432 if (s.alarms & DAHDI_ALARM_RED) 12433 strcat(alarms, "RED/"); 12434 if (s.alarms & DAHDI_ALARM_LOOPBACK) 12435 strcat(alarms, "LB/"); 12436 if (s.alarms & DAHDI_ALARM_RECOVER) 12437 strcat(alarms, "REC/"); 12438 if (s.alarms & DAHDI_ALARM_NOTOPEN) 12439 strcat(alarms, "NOP/"); 12440 if (!strlen(alarms)) 12441 strcat(alarms, "UUU/"); 12442 if (strlen(alarms)) { 12443 /* Strip trailing / */ 12444 alarms[strlen(alarms) - 1] = '\0'; 12445 } 12446 } else { 12447 if (s.numchans) 12448 strcpy(alarms, "OK"); 12449 else 12450 strcpy(alarms, "UNCONFIGURED"); 12451 } 12452 12453 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 12454 } 12455 close(ctl); 12456 12457 return RESULT_SUCCESS; 12458 #undef FORMAT 12459 #undef FORMAT2 12460 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2104 of file chan_dahdi.c.
References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.
02105 { 02106 static char buf[256]; 02107 switch (sig) { 02108 case SIG_EM: 02109 return "E & M Immediate"; 02110 case SIG_EMWINK: 02111 return "E & M Wink"; 02112 case SIG_EM_E1: 02113 return "E & M E1"; 02114 case SIG_FEATD: 02115 return "Feature Group D (DTMF)"; 02116 case SIG_FEATDMF: 02117 return "Feature Group D (MF)"; 02118 case SIG_FEATDMF_TA: 02119 return "Feature Groud D (MF) Tandem Access"; 02120 case SIG_FEATB: 02121 return "Feature Group B (MF)"; 02122 case SIG_E911: 02123 return "E911 (MF)"; 02124 case SIG_FGC_CAMA: 02125 return "FGC/CAMA (Dialpulse)"; 02126 case SIG_FGC_CAMAMF: 02127 return "FGC/CAMA (MF)"; 02128 case SIG_FXSLS: 02129 return "FXS Loopstart"; 02130 case SIG_FXSGS: 02131 return "FXS Groundstart"; 02132 case SIG_FXSKS: 02133 return "FXS Kewlstart"; 02134 case SIG_FXOLS: 02135 return "FXO Loopstart"; 02136 case SIG_FXOGS: 02137 return "FXO Groundstart"; 02138 case SIG_FXOKS: 02139 return "FXO Kewlstart"; 02140 case SIG_PRI: 02141 return "ISDN PRI"; 02142 case SIG_MFCR2: 02143 return "MFC/R2"; 02144 case SIG_SF: 02145 return "SF (Tone) Immediate"; 02146 case SIG_SFWINK: 02147 return "SF (Tone) Wink"; 02148 case SIG_SF_FEATD: 02149 return "SF (Tone) with Feature Group D (DTMF)"; 02150 case SIG_SF_FEATDMF: 02151 return "SF (Tone) with Feature Group D (MF)"; 02152 case SIG_SF_FEATB: 02153 return "SF (Tone) with Feature Group B (MF)"; 02154 case SIG_GR303FXOKS: 02155 return "GR-303 with FXOKS"; 02156 case SIG_GR303FXSKS: 02157 return "GR-303 with FXSKS"; 02158 case 0: 02159 return "Pseudo"; 02160 default: 02161 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 02162 return buf; 02163 } 02164 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 11976 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().
11977 { 11978 struct dahdi_pvt *p; 11979 retry: 11980 ast_mutex_lock(&iflock); 11981 for (p = iflist; p; p = p->next) { 11982 ast_mutex_lock(&p->lock); 11983 if (p->owner && !p->restartpending) { 11984 if (ast_channel_trylock(p->owner)) { 11985 if (option_debug > 2) 11986 ast_verbose("Avoiding deadlock\n"); 11987 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 11988 ast_mutex_unlock(&p->lock); 11989 ast_mutex_unlock(&iflock); 11990 goto retry; 11991 } 11992 if (option_debug > 2) 11993 ast_verbose("Softhanging up on %s\n", p->owner->name); 11994 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 11995 p->restartpending = 1; 11996 num_restart_pending++; 11997 ast_channel_unlock(p->owner); 11998 } 11999 ast_mutex_unlock(&p->lock); 12000 } 12001 ast_mutex_unlock(&iflock); 12002 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2385 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
02386 { 02387 int x; 02388 int res; 02389 if (p && p->echocancel && p->echotraining) { 02390 x = p->echotraining; 02391 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02392 if (res) 02393 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02394 else { 02395 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 02396 } 02397 } else 02398 ast_log(LOG_DEBUG, "No echo training requested\n"); 02399 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 4255 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, LOG_DEBUG, master, and SUB_REAL.
Referenced by dahdi_bridge(), and dahdi_fixup().
04256 { 04257 /* Unlink a specific slave or all slaves/masters from a given master */ 04258 int x; 04259 int hasslaves; 04260 if (!master) 04261 return; 04262 if (needlock) { 04263 ast_mutex_lock(&master->lock); 04264 if (slave) { 04265 while (ast_mutex_trylock(&slave->lock)) { 04266 DEADLOCK_AVOIDANCE(&master->lock); 04267 } 04268 } 04269 } 04270 hasslaves = 0; 04271 for (x = 0; x < MAX_SLAVES; x++) { 04272 if (master->slaves[x]) { 04273 if (!slave || (master->slaves[x] == slave)) { 04274 /* Take slave out of the conference */ 04275 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04276 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04277 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04278 master->slaves[x]->master = NULL; 04279 master->slaves[x] = NULL; 04280 } else 04281 hasslaves = 1; 04282 } 04283 if (!hasslaves) 04284 master->inconference = 0; 04285 } 04286 if (!slave) { 04287 if (master->master) { 04288 /* Take master out of the conference */ 04289 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04290 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04291 hasslaves = 0; 04292 for (x = 0; x < MAX_SLAVES; x++) { 04293 if (master->master->slaves[x] == master) 04294 master->master->slaves[x] = NULL; 04295 else if (master->master->slaves[x]) 04296 hasslaves = 1; 04297 } 04298 if (!hasslaves) 04299 master->master->inconference = 0; 04300 } 04301 master->master = NULL; 04302 } 04303 update_conf(master); 04304 if (needlock) { 04305 if (slave) 04306 ast_mutex_unlock(&slave->lock); 04307 ast_mutex_unlock(&master->lock); 04308 } 04309 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 281 of file chan_dahdi.c.
Referenced by ss_thread().
00282 { 00283 int i, j = 0; 00284 i = DAHDI_IOMUX_SIGEVENT; 00285 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00286 return -1; 00287 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00288 return -1; 00289 return j; 00290 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 6769 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06770 { 06771 int j; 06772 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 06773 for (;;) 06774 { 06775 /* set bits of interest */ 06776 j = DAHDI_IOMUX_SIGEVENT; 06777 /* wait for some happening */ 06778 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06779 /* exit loop if we have it */ 06780 if (j & DAHDI_IOMUX_SIGEVENT) break; 06781 } 06782 /* get the event info */ 06783 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06784 return 0; 06785 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 6282 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.
06283 { 06284 struct dahdi_pvt *p = ast->tech_pvt; 06285 int res; 06286 int index; 06287 index = dahdi_get_index(ast, p, 0); 06288 if (index < 0) { 06289 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06290 return -1; 06291 } 06292 06293 #if 0 06294 #ifdef HAVE_PRI 06295 ast_mutex_lock(&p->lock); 06296 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06297 if (p->pri->pri) { 06298 if (!pri_grab(p, p->pri)) { 06299 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06300 pri_rel(p->pri); 06301 } else 06302 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06303 } 06304 p->proceeding=1; 06305 } 06306 ast_mutex_unlock(&p->lock); 06307 #endif 06308 #endif 06309 /* Write a frame of (presumably voice) data */ 06310 if (frame->frametype != AST_FRAME_VOICE) { 06311 if (frame->frametype != AST_FRAME_IMAGE) 06312 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06313 return 0; 06314 } 06315 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06316 (frame->subclass != AST_FORMAT_ULAW) && 06317 (frame->subclass != AST_FORMAT_ALAW)) { 06318 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06319 return -1; 06320 } 06321 if (p->dialing) { 06322 if (option_debug) 06323 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06324 return 0; 06325 } 06326 if (!p->owner) { 06327 if (option_debug) 06328 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 06329 return 0; 06330 } 06331 if (p->cidspill) { 06332 if (option_debug) 06333 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 06334 return 0; 06335 } 06336 /* Return if it's not valid data */ 06337 if (!frame->data || !frame->datalen) 06338 return 0; 06339 06340 if (frame->subclass == AST_FORMAT_SLINEAR) { 06341 if (!p->subs[index].linear) { 06342 p->subs[index].linear = 1; 06343 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06344 if (res) 06345 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06346 } 06347 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 06348 } else { 06349 /* x-law already */ 06350 if (p->subs[index].linear) { 06351 p->subs[index].linear = 0; 06352 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06353 if (res) 06354 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06355 } 06356 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 06357 } 06358 if (res < 0) { 06359 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06360 return -1; 06361 } 06362 return 0; 06363 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3256 of file chan_dahdi.c.
References ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cidspill, destroy_dahdi_pvt(), iflist, iflock, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.
Referenced by __unload_module(), and dahdi_restart().
03257 { 03258 int x; 03259 struct dahdi_pvt *p, *pl; 03260 03261 while (num_restart_pending) { 03262 usleep(1); 03263 } 03264 03265 ast_mutex_lock(&iflock); 03266 /* Destroy all the interfaces and free their memory */ 03267 p = iflist; 03268 while (p) { 03269 /* Free any callerid */ 03270 if (p->cidspill) 03271 ast_free(p->cidspill); 03272 pl = p; 03273 p = p->next; 03274 x = pl->channel; 03275 /* Free associated memory */ 03276 if (pl) 03277 destroy_dahdi_pvt(&pl); 03278 if (option_verbose > 2) 03279 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03280 } 03281 iflist = NULL; 03282 ifcount = 0; 03283 ast_mutex_unlock(&iflock); 03284 }
Definition at line 3206 of file chan_dahdi.c.
References destroy_dahdi_pvt(), iflist, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::prev, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().
03207 { 03208 int owned = 0; 03209 int i = 0; 03210 03211 if (!now) { 03212 if (cur->owner) { 03213 owned = 1; 03214 } 03215 03216 for (i = 0; i < 3; i++) { 03217 if (cur->subs[i].owner) { 03218 owned = 1; 03219 } 03220 } 03221 if (!owned) { 03222 if (prev) { 03223 prev->next = cur->next; 03224 if (prev->next) 03225 prev->next->prev = prev; 03226 else 03227 ifend = prev; 03228 } else { 03229 iflist = cur->next; 03230 if (iflist) 03231 iflist->prev = NULL; 03232 else 03233 ifend = NULL; 03234 } 03235 destroy_dahdi_pvt(&cur); 03236 } 03237 } else { 03238 if (prev) { 03239 prev->next = cur->next; 03240 if (prev->next) 03241 prev->next->prev = prev; 03242 else 03243 ifend = prev; 03244 } else { 03245 iflist = cur->next; 03246 if (iflist) 03247 iflist->prev = NULL; 03248 else 03249 ifend = NULL; 03250 } 03251 destroy_dahdi_pvt(&cur); 03252 } 03253 return 0; 03254 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3188 of file chan_dahdi.c.
References ast_mutex_destroy(), ast_smdi_interface_unref(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.
Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().
03189 { 03190 struct dahdi_pvt *p = *pvt; 03191 /* Remove channel from the list */ 03192 if (p->prev) 03193 p->prev->next = p->next; 03194 if (p->next) 03195 p->next->prev = p->prev; 03196 if (p->use_smdi) 03197 ast_smdi_interface_unref(p->smdi_iface); 03198 ast_mutex_destroy(&p->lock); 03199 dahdi_close_sub(p, SUB_REAL); 03200 if (p->owner) 03201 p->owner->tech_pvt = NULL; 03202 free(p); 03203 *pvt = NULL; 03204 }
static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2095 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
02096 { 02097 if (dialplan == -1) { 02098 return("Dynamically set dialplan in ISDN"); 02099 } 02100 return (pri_plan2str(dialplan)); 02101 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1928 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01929 { 01930 if (isdigit(digit)) 01931 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01932 else if (digit >= 'A' && digit <= 'D') 01933 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01934 else if (digit >= 'a' && digit <= 'd') 01935 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01936 else if (digit == '*') 01937 return DAHDI_TONE_DTMF_s; 01938 else if (digit == '#') 01939 return DAHDI_TONE_DTMF_p; 01940 else 01941 return -1; 01942 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4334 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04335 { 04336 #ifdef DAHDI_TONEDETECT 04337 int val; 04338 #endif 04339 04340 p->ignoredtmf = 1; 04341 04342 #ifdef DAHDI_TONEDETECT 04343 val = 0; 04344 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04345 #endif 04346 if (!p->hardwaredtmf && p->dsp) { 04347 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 04348 ast_dsp_set_features(p->dsp, p->dsp_features); 04349 } 04350 }
static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 9847 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().
09848 { 09849 struct ast_channel *chan = vchan; 09850 struct dahdi_pvt *pvt = chan->tech_pvt; 09851 struct ast_frame *f; 09852 char ex[80]; 09853 /* Wait up to 30 seconds for an answer */ 09854 int newms, ms = 30000; 09855 if (option_verbose > 2) 09856 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name); 09857 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 09858 if (ast_call(chan, ex, 0)) { 09859 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 09860 ast_hangup(chan); 09861 return NULL; 09862 } 09863 while ((newms = ast_waitfor(chan, ms)) > 0) { 09864 f = ast_read(chan); 09865 if (!f) { 09866 /* Got hangup */ 09867 break; 09868 } 09869 if (f->frametype == AST_FRAME_CONTROL) { 09870 switch (f->subclass) { 09871 case AST_CONTROL_ANSWER: 09872 /* Launch the PBX */ 09873 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 09874 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 09875 chan->priority = 1; 09876 if (option_verbose > 3) 09877 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 09878 ast_pbx_run(chan); 09879 /* It's already hungup, return immediately */ 09880 return NULL; 09881 case AST_CONTROL_BUSY: 09882 if (option_verbose > 3) 09883 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name); 09884 break; 09885 case AST_CONTROL_CONGESTION: 09886 if (option_verbose > 3) 09887 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name); 09888 break; 09889 }; 09890 } 09891 ast_frfree(f); 09892 ms = newms; 09893 } 09894 /* Hangup the channel since nothing happend */ 09895 ast_hangup(chan); 09896 return NULL; 09897 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8208 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, dahdi_pvt::cidspill, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
08209 { 08210 int count, res, res2, spoint, pollres=0; 08211 struct dahdi_pvt *i; 08212 struct dahdi_pvt *last = NULL; 08213 struct dahdi_pvt *doomed; 08214 time_t thispass = 0, lastpass = 0; 08215 int found; 08216 char buf[1024]; 08217 struct pollfd *pfds=NULL; 08218 int lastalloc = -1; 08219 /* This thread monitors all the frame relay interfaces which are not yet in use 08220 (and thus do not have a separate thread) indefinitely */ 08221 /* From here on out, we die whenever asked */ 08222 #if 0 08223 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08224 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08225 return NULL; 08226 } 08227 ast_log(LOG_DEBUG, "Monitor starting...\n"); 08228 #endif 08229 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08230 08231 for (;;) { 08232 /* Lock the interface list */ 08233 ast_mutex_lock(&iflock); 08234 if (!pfds || (lastalloc != ifcount)) { 08235 if (pfds) { 08236 free(pfds); 08237 pfds = NULL; 08238 } 08239 if (ifcount) { 08240 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08241 ast_mutex_unlock(&iflock); 08242 return NULL; 08243 } 08244 } 08245 lastalloc = ifcount; 08246 } 08247 /* Build the stuff we're going to poll on, that is the socket of every 08248 dahdi_pvt that does not have an associated owner channel */ 08249 count = 0; 08250 i = iflist; 08251 while (i) { 08252 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 08253 if (!i->owner && !i->subs[SUB_REAL].owner) { 08254 /* This needs to be watched, as it lacks an owner */ 08255 pfds[count].fd = i->subs[SUB_REAL].dfd; 08256 pfds[count].events = POLLPRI; 08257 pfds[count].revents = 0; 08258 /* Message waiting or r2 channels also get watched for reading */ 08259 if (i->cidspill || 08260 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) { 08261 pfds[count].events |= POLLIN; 08262 } 08263 count++; 08264 } 08265 } 08266 i = i->next; 08267 } 08268 /* Okay, now that we know what to do, release the interface lock */ 08269 ast_mutex_unlock(&iflock); 08270 08271 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08272 pthread_testcancel(); 08273 /* Wait at least a second for something to happen */ 08274 res = poll(pfds, count, 1000); 08275 pthread_testcancel(); 08276 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08277 08278 /* Okay, poll has finished. Let's see what happened. */ 08279 if (res < 0) { 08280 if ((errno != EAGAIN) && (errno != EINTR)) 08281 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08282 continue; 08283 } 08284 /* Alright, lock the interface list again, and let's look and see what has 08285 happened */ 08286 ast_mutex_lock(&iflock); 08287 found = 0; 08288 spoint = 0; 08289 lastpass = thispass; 08290 thispass = time(NULL); 08291 doomed = NULL; 08292 for (i = iflist;; i = i->next) { 08293 if (doomed) { 08294 int res; 08295 res = dahdi_destroy_channel_bynum(doomed->channel); 08296 if (!res) { 08297 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08298 } 08299 doomed = NULL; 08300 } 08301 if (!i) { 08302 break; 08303 } 08304 if (thispass != lastpass) { 08305 if (!found && ((i == last) || ((i == iflist) && !last))) { 08306 last = i; 08307 if (last) { 08308 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 08309 (last->sig & __DAHDI_SIG_FXO)) { 08310 res = ast_app_has_voicemail(last->mailbox, NULL); 08311 if (last->msgstate != res) { 08312 int x; 08313 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 08314 x = DAHDI_FLUSH_BOTH; 08315 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 08316 if (res2) 08317 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 08318 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 08319 /* Turn on on hook transfer for 4 seconds */ 08320 x = 4000; 08321 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 08322 last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 08323 last->cidpos = 0; 08324 last->msgstate = res; 08325 last->onhooktime = thispass; 08326 } 08327 found ++; 08328 } 08329 } 08330 last = last->next; 08331 } 08332 } 08333 } 08334 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08335 if (i->radio && !i->owner) 08336 { 08337 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08338 if (res) 08339 { 08340 if (option_debug) 08341 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08342 /* Don't hold iflock while handling init events */ 08343 ast_mutex_unlock(&iflock); 08344 doomed = handle_init_event(i, res); 08345 ast_mutex_lock(&iflock); 08346 } 08347 continue; 08348 } 08349 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08350 if (pollres & POLLIN) { 08351 if (i->owner || i->subs[SUB_REAL].owner) { 08352 #ifdef HAVE_PRI 08353 if (!i->pri) 08354 #endif 08355 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08356 continue; 08357 } 08358 // if (!i->cidspill) { 08359 // ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08360 // continue; 08361 //} 08362 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08363 if (res > 0) { 08364 /* We read some number of bytes. Write an equal amount of data */ 08365 /* if (res > i->cidlen - i->cidpos) */ 08366 /* res = i->cidlen - i->cidpos; */ 08367 /* res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); */ 08368 /* if (res2 > 0) { */ 08369 /* i->cidpos += res2; */ 08370 /* if (i->cidpos >= i->cidlen) { */ 08371 /* free(i->cidspill); */ 08372 /* i->cidspill = 0; */ 08373 /* i->cidpos = 0; */ 08374 /* i->cidlen = 0; */ 08375 /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */ 08376 if (i->cid_start == CID_START_DTMF_NOALERT) { 08377 int energy; 08378 struct timeval now; 08379 /* State machine dtmfcid_holdoff_state allows for the line to settle 08380 * before checking agin for dtmf energy. Presently waits for 500 mS before checking again 08381 */ 08382 if (1 == i->dtmfcid_holdoff_state) { 08383 gettimeofday(&i->dtmfcid_delay, NULL); 08384 i->dtmfcid_holdoff_state = 2; 08385 } else if (2 == i->dtmfcid_holdoff_state) { 08386 gettimeofday(&now, NULL); 08387 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) { 08388 i->dtmfcid_holdoff_state = 0; 08389 } 08390 } else { 08391 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i)); 08392 if (energy > dtmfcid_level) { 08393 pthread_t threadid; 08394 struct ast_channel *chan; 08395 ast_mutex_unlock(&iflock); 08396 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08397 if (!chan) { 08398 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08399 } else { 08400 pthread_attr_t attr; 08401 pthread_attr_init(&attr); 08402 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08403 res = ast_pthread_create(&threadid, &attr, ss_thread, chan); 08404 if (res) { 08405 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08406 } else { 08407 i->dtmfcid_holdoff_state = 1; 08408 } 08409 } 08410 ast_mutex_lock(&iflock); 08411 } 08412 } 08413 /* } else { */ 08414 /* ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); */ 08415 /* i->msgstate = -1; */ 08416 } 08417 } else { 08418 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08419 } 08420 } 08421 if (pollres & POLLPRI) { 08422 if (i->owner || i->subs[SUB_REAL].owner) { 08423 #ifdef HAVE_PRI 08424 if (!i->pri) 08425 #endif 08426 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08427 continue; 08428 } 08429 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08430 if (option_debug) 08431 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08432 /* Don't hold iflock while handling init events */ 08433 ast_mutex_unlock(&iflock); 08434 doomed = handle_init_event(i, res); 08435 ast_mutex_lock(&iflock); 08436 } 08437 } 08438 } 08439 ast_mutex_unlock(&iflock); 08440 } 08441 /* Never reached */ 08442 return NULL; 08443 08444 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4352 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
04353 { 04354 #ifdef DAHDI_TONEDETECT 04355 int val; 04356 #endif 04357 04358 if (p->channel == CHAN_PSEUDO) 04359 return; 04360 04361 p->ignoredtmf = 0; 04362 04363 #ifdef DAHDI_TONEDETECT 04364 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04365 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04366 #endif 04367 if (!p->hardwaredtmf && p->dsp) { 04368 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 04369 ast_dsp_set_features(p->dsp, p->dsp_features); 04370 } 04371 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 2085 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
02086 { 02087 static char buf[256]; 02088 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 02089 return events[event]; 02090 sprintf(buf, "Event %d", event); /* safe */ 02091 return buf; 02092 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2450 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02451 { 02452 int j; 02453 int k; 02454 float linear_gain = pow(10.0, gain / 20.0); 02455 02456 switch (law) { 02457 case DAHDI_LAW_ALAW: 02458 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02459 if (gain) { 02460 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02461 if (k > 32767) k = 32767; 02462 if (k < -32767) k = -32767; 02463 g->rxgain[j] = AST_LIN2A(k); 02464 } else { 02465 g->rxgain[j] = j; 02466 } 02467 } 02468 break; 02469 case DAHDI_LAW_MULAW: 02470 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 02471 if (gain) { 02472 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02473 if (k > 32767) k = 32767; 02474 if (k < -32767) k = -32767; 02475 g->rxgain[j] = AST_LIN2MU(k); 02476 } else { 02477 g->rxgain[j] = j; 02478 } 02479 } 02480 break; 02481 } 02482 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2416 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02417 { 02418 int j; 02419 int k; 02420 float linear_gain = pow(10.0, gain / 20.0); 02421 02422 switch (law) { 02423 case DAHDI_LAW_ALAW: 02424 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02425 if (gain) { 02426 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02427 if (k > 32767) k = 32767; 02428 if (k < -32767) k = -32767; 02429 g->txgain[j] = AST_LIN2A(k); 02430 } else { 02431 g->txgain[j] = j; 02432 } 02433 } 02434 break; 02435 case DAHDI_LAW_MULAW: 02436 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 02437 if (gain) { 02438 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02439 if (k > 32767) k = 32767; 02440 if (k < -32767) k = -32767; 02441 g->txgain[j] = AST_LIN2MU(k); 02442 } else { 02443 g->txgain[j] = j; 02444 } 02445 } 02446 break; 02447 } 02448 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 12560 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().
12561 { 12562 struct dahdi_pvt *p = iflist; 12563 while (p) { 12564 if (p->channel == channel) { 12565 break; 12566 } 12567 p = p->next; 12568 } 12569 return p; 12570 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4792 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by __action_showchannels(), dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), and handle_init_event().
04793 { 04794 int res; 04795 struct dahdi_spaninfo zi; 04796 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04797 /* 04798 * The conditional compilation is needed only in asterisk-1.4 for 04799 * backward compatibility with old zaptel drivers that don't have 04800 * a DAHDI_PARAMS.chan_alarms field. 04801 */ 04802 struct dahdi_params params; 04803 #endif 04804 04805 memset(&zi, 0, sizeof(zi)); 04806 zi.spanno = p->span; 04807 04808 /* First check for span alarms */ 04809 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 04810 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04811 return 0; 04812 } 04813 if (zi.alarms != DAHDI_ALARM_NONE) 04814 return zi.alarms; 04815 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS) 04816 /* No alarms on the span. Check for channel alarms. */ 04817 memset(¶ms, 0, sizeof(params)); 04818 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04819 return params.chan_alarms; 04820 /* ioctl failed */ 04821 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04822 #endif 04823 return DAHDI_ALARM_NONE; 04824 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 4908 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.
Referenced by dahdi_handle_event(), dahdi_r2_on_hardware_alarm(), and handle_init_event().
04909 { 04910 const char *alarm_str = alarm2str(alarms); 04911 04912 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 04913 * doesn't know what to do with it. Don't confuse users with log messages. */ 04914 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 04915 p->unknown_alarm = 1; 04916 return; 04917 } else { 04918 p->unknown_alarm = 0; 04919 } 04920 04921 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04922 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04923 "Alarm: %s\r\n" 04924 "Channel: %d\r\n", 04925 alarm_str, p->channel); 04926 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 12375 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
12376 { 12377 int i, j; 12378 for (i = 0; i < num_cadence; i++) { 12379 char output[1024]; 12380 char tmp[16], tmp2[64]; 12381 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 12382 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 12383 12384 for (j = 0; j < 16; j++) { 12385 if (cadences[i].ringcadence[j] == 0) 12386 break; 12387 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 12388 if (cidrings[i] * 2 - 1 == j) 12389 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 12390 else 12391 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 12392 if (j != 0) 12393 strncat(output, ",", sizeof(output) - strlen(output) - 1); 12394 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 12395 } 12396 ast_cli(fd,"%s\n",output); 12397 } 12398 return 0; 12399 }
Definition at line 7998 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.
07999 { 08000 int res; 08001 pthread_t threadid; 08002 pthread_attr_t attr; 08003 struct ast_channel *chan; 08004 pthread_attr_init(&attr); 08005 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08006 /* Handle an event on a given channel for the monitor thread. */ 08007 switch (event) { 08008 case DAHDI_EVENT_NONE: 08009 case DAHDI_EVENT_BITSCHANGED: 08010 break; 08011 case DAHDI_EVENT_WINKFLASH: 08012 case DAHDI_EVENT_RINGOFFHOOK: 08013 if (i->inalarm) break; 08014 if (i->radio) break; 08015 /* Got a ring/answer. What kind of channel are we? */ 08016 switch (i->sig) { 08017 case SIG_FXOLS: 08018 case SIG_FXOGS: 08019 case SIG_FXOKS: 08020 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08021 if (res && (errno == EBUSY)) 08022 break; 08023 if (i->cidspill) { 08024 /* Cancel VMWI spill */ 08025 free(i->cidspill); 08026 i->cidspill = NULL; 08027 } 08028 if (i->immediate) { 08029 dahdi_enable_ec(i); 08030 /* The channel is immediately up. Start right away */ 08031 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08032 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08033 if (!chan) { 08034 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08035 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08036 if (res < 0) 08037 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08038 } 08039 } else { 08040 /* Check for callerid, digits, etc */ 08041 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08042 if (chan) { 08043 if (has_voicemail(i)) 08044 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08045 else 08046 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08047 if (res < 0) 08048 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08049 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08050 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08051 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08052 if (res < 0) 08053 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08054 ast_hangup(chan); 08055 } 08056 } else 08057 ast_log(LOG_WARNING, "Unable to create channel\n"); 08058 } 08059 break; 08060 case SIG_FXSLS: 08061 case SIG_FXSGS: 08062 case SIG_FXSKS: 08063 i->ringt = i->ringt_base; 08064 /* Fall through */ 08065 case SIG_EMWINK: 08066 case SIG_FEATD: 08067 case SIG_FEATDMF: 08068 case SIG_FEATDMF_TA: 08069 case SIG_E911: 08070 case SIG_FGC_CAMA: 08071 case SIG_FGC_CAMAMF: 08072 case SIG_FEATB: 08073 case SIG_EM: 08074 case SIG_EM_E1: 08075 case SIG_SFWINK: 08076 case SIG_SF_FEATD: 08077 case SIG_SF_FEATDMF: 08078 case SIG_SF_FEATB: 08079 case SIG_SF: 08080 /* Check for callerid, digits, etc */ 08081 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08082 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08083 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08084 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08085 if (res < 0) 08086 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08087 ast_hangup(chan); 08088 } else if (!chan) { 08089 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08090 } 08091 break; 08092 default: 08093 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08095 if (res < 0) 08096 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08097 pthread_attr_destroy(&attr); 08098 return NULL; 08099 } 08100 break; 08101 case DAHDI_EVENT_NOALARM: 08102 i->inalarm = 0; 08103 if (!i->unknown_alarm) { 08104 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08105 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08106 "Channel: %d\r\n", i->channel); 08107 } else { 08108 i->unknown_alarm = 0; 08109 } 08110 break; 08111 case DAHDI_EVENT_ALARM: 08112 i->inalarm = 1; 08113 res = get_alarms(i); 08114 handle_alarms(i, res); 08115 /* fall thru intentionally */ 08116 case DAHDI_EVENT_ONHOOK: 08117 if (i->radio) 08118 break; 08119 /* Back on hook. Hang up. */ 08120 switch (i->sig) { 08121 case SIG_FXOLS: 08122 case SIG_FXOGS: 08123 case SIG_FEATD: 08124 case SIG_FEATDMF: 08125 case SIG_FEATDMF_TA: 08126 case SIG_E911: 08127 case SIG_FGC_CAMA: 08128 case SIG_FGC_CAMAMF: 08129 case SIG_FEATB: 08130 case SIG_EM: 08131 case SIG_EM_E1: 08132 case SIG_EMWINK: 08133 case SIG_SF_FEATD: 08134 case SIG_SF_FEATDMF: 08135 case SIG_SF_FEATB: 08136 case SIG_SF: 08137 case SIG_SFWINK: 08138 case SIG_FXSLS: 08139 case SIG_FXSGS: 08140 case SIG_FXSKS: 08141 case SIG_GR303FXSKS: 08142 dahdi_disable_ec(i); 08143 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08144 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08145 break; 08146 case SIG_GR303FXOKS: 08147 case SIG_FXOKS: 08148 dahdi_disable_ec(i); 08149 /* Diddle the battery for the zhone */ 08150 #ifdef ZHONE_HACK 08151 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08152 usleep(1); 08153 #endif 08154 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08155 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08156 break; 08157 case SIG_PRI: 08158 dahdi_disable_ec(i); 08159 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08160 break; 08161 default: 08162 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08163 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08164 pthread_attr_destroy(&attr); 08165 return NULL; 08166 } 08167 break; 08168 case DAHDI_EVENT_POLARITY: 08169 switch (i->sig) { 08170 case SIG_FXSLS: 08171 case SIG_FXSKS: 08172 case SIG_FXSGS: 08173 /* We have already got a PR before the channel was 08174 created, but it wasn't handled. We need polarity 08175 to be REV for remote hangup detection to work. 08176 At least in Spain */ 08177 if (i->hanguponpolarityswitch) 08178 i->polarity = POLARITY_REV; 08179 08180 if (i->cid_start == CID_START_POLARITY) { 08181 i->polarity = POLARITY_REV; 08182 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 08183 "CID detection on channel %d\n", 08184 i->channel); 08185 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08186 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 08187 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08188 } 08189 } 08190 break; 08191 default: 08192 ast_log(LOG_WARNING, "handle_init_event detected " 08193 "polarity reversal on non-FXO (SIG_FXS) " 08194 "interface %d\n", i->channel); 08195 } 08196 break; 08197 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08198 ast_log(LOG_NOTICE, 08199 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08200 i->channel); 08201 pthread_attr_destroy(&attr); 08202 return i; 08203 } 08204 pthread_attr_destroy(&attr); 08205 return NULL; 08206 }
static int handle_mfcr2_call_files | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11783 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.
11784 { 11785 struct dahdi_pvt *p = NULL; 11786 int channo = 0; 11787 if (argc < 4) { 11788 return RESULT_SHOWUSAGE; 11789 } 11790 channo = (argc == 5) ? atoi(argv[4]) : -1; 11791 ast_mutex_lock(&iflock); 11792 p = iflist; 11793 while (p) { 11794 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11795 p = p->next; 11796 continue; 11797 } 11798 if ((channo != -1) && (p->channel != channo )) { 11799 p = p->next; 11800 continue; 11801 } 11802 if (ast_true(argv[3])) { 11803 openr2_chan_enable_call_files(p->r2chan); 11804 } else { 11805 openr2_chan_disable_call_files(p->r2chan); 11806 } 11807 if (channo != -1) { 11808 if (ast_true(argv[3])) { 11809 ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel); 11810 } else { 11811 ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel); 11812 } 11813 break; 11814 } else { 11815 p = p->next; 11816 } 11817 } 11818 if ((channo != -1) && !p) { 11819 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11820 } 11821 if (channo == -1) { 11822 if (ast_true(argv[3])) { 11823 ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n"); 11824 } else { 11825 ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n"); 11826 } 11827 } 11828 ast_mutex_unlock(&iflock); 11829 return RESULT_SUCCESS; 11830 }
static int handle_mfcr2_set_blocked | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11867 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.
11868 { 11869 struct dahdi_pvt *p = NULL; 11870 int channo = 0; 11871 channo = (argc == 4) ? atoi(argv[3]) : -1; 11872 ast_mutex_lock(&iflock); 11873 p = iflist; 11874 while (p) { 11875 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11876 p = p->next; 11877 continue; 11878 } 11879 if ((channo != -1) && (p->channel != channo )) { 11880 p = p->next; 11881 continue; 11882 } 11883 if (!openr2_chan_set_blocked(p->r2chan)) { 11884 ast_mutex_lock(&p->lock); 11885 p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK; 11886 ast_mutex_unlock(&p->lock); 11887 } else { 11888 ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel); 11889 } 11890 if (channo != -1) { 11891 break; 11892 } else { 11893 p = p->next; 11894 } 11895 } 11896 if ((channo != -1) && !p) { 11897 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11898 } 11899 ast_mutex_unlock(&iflock); 11900 return RESULT_SUCCESS; 11901 }
static int handle_mfcr2_set_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11724 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.
11725 { 11726 struct dahdi_pvt *p = NULL; 11727 int channo = 0; 11728 char *toklevel = NULL; 11729 char *saveptr = NULL; 11730 char *logval = NULL; 11731 openr2_log_level_t loglevel = OR2_LOG_NOTHING; 11732 openr2_log_level_t tmplevel = OR2_LOG_NOTHING; 11733 if (argc < 4) { 11734 return RESULT_SHOWUSAGE; 11735 } 11736 channo = (argc == 5) ? atoi(argv[4]) : -1; 11737 logval = ast_strdupa(argv[3]); 11738 toklevel = strtok_r(logval, ",", &saveptr); 11739 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11740 ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]); 11741 return RESULT_FAILURE; 11742 } else if (OR2_LOG_NOTHING == tmplevel) { 11743 loglevel = tmplevel; 11744 } else { 11745 loglevel |= tmplevel; 11746 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 11747 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 11748 ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel); 11749 continue; 11750 } 11751 loglevel |= tmplevel; 11752 } 11753 } 11754 ast_mutex_lock(&iflock); 11755 p = iflist; 11756 while (p) { 11757 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11758 p = p->next; 11759 continue; 11760 } 11761 if ((channo != -1) && (p->channel != channo )) { 11762 p = p->next; 11763 continue; 11764 } 11765 openr2_chan_set_log_level(p->r2chan, loglevel); 11766 if (channo != -1) { 11767 ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel); 11768 break; 11769 } else { 11770 p = p->next; 11771 } 11772 } 11773 if ((channo != -1) && !p) { 11774 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11775 } 11776 if (channo == -1) { 11777 ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]); 11778 } 11779 ast_mutex_unlock(&iflock); 11780 return RESULT_SUCCESS; 11781 }
static int handle_mfcr2_set_idle | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11832 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.
11833 { 11834 struct dahdi_pvt *p = NULL; 11835 int channo = 0; 11836 channo = (argc == 4) ? atoi(argv[3]) : -1; 11837 ast_mutex_lock(&iflock); 11838 p = iflist; 11839 while (p) { 11840 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11841 p = p->next; 11842 continue; 11843 } 11844 if ((channo != -1) && (p->channel != channo )) { 11845 p = p->next; 11846 continue; 11847 } 11848 if (!openr2_chan_set_idle(p->r2chan)) { 11849 ast_mutex_lock(&p->lock); 11850 p->mfcr2call = 0; 11851 p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 11852 ast_mutex_unlock(&p->lock); 11853 } 11854 if (channo != -1) { 11855 break; 11856 } else { 11857 p = p->next; 11858 } 11859 } 11860 if ((channo != -1) && !p) { 11861 ast_cli(fd, "MFC/R2 channel %d not found.\n", channo); 11862 } 11863 ast_mutex_unlock(&iflock); 11864 return RESULT_SUCCESS; 11865 }
static int handle_mfcr2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11655 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.
11656 { 11657 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n" 11658 int filtertype = 0; 11659 int targetnum = 0; 11660 char channo[5]; 11661 char anino[5]; 11662 char dnisno[5]; 11663 struct dahdi_pvt *p; 11664 openr2_context_t *r2context; 11665 openr2_variant_t r2variant; 11666 if (!((argc == 3) || (argc == 5))) { 11667 return RESULT_SHOWUSAGE; 11668 } 11669 if (argc == 5) { 11670 if (!strcasecmp(argv[3], "group")) { 11671 targetnum = atoi(argv[4]); 11672 if ((targetnum < 0) || (targetnum > 63)) 11673 return RESULT_SHOWUSAGE; 11674 targetnum = 1 << targetnum; 11675 filtertype = 1; 11676 } else if (!strcasecmp(argv[3], "context")) { 11677 filtertype = 2; 11678 } else { 11679 return RESULT_SHOWUSAGE; 11680 } 11681 } 11682 ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS"); 11683 ast_mutex_lock(&iflock); 11684 p = iflist; 11685 while (p) { 11686 if (!(p->sig & SIG_MFCR2) || !p->r2chan) { 11687 p = p->next; 11688 continue; 11689 } 11690 if (filtertype) { 11691 switch(filtertype) { 11692 case 1: /* mfcr2 show channels group <group> */ 11693 if (p->group != targetnum) { 11694 p = p->next; 11695 continue; 11696 } 11697 break; 11698 case 2: /* mfcr2 show channels context <context> */ 11699 if (strcasecmp(p->context, argv[4])) { 11700 p= p->next; 11701 continue; 11702 } 11703 break; 11704 default: 11705 ; 11706 } 11707 } 11708 r2context = openr2_chan_get_context(p->r2chan); 11709 r2variant = openr2_context_get_variant(r2context); 11710 snprintf(channo, sizeof(channo), "%d", p->channel); 11711 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context)); 11712 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context)); 11713 ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 11714 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No", 11715 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", 11716 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan)); 11717 p = p->next; 11718 } 11719 ast_mutex_unlock(&iflock); 11720 return RESULT_SUCCESS; 11721 #undef FORMAT 11722 }
static int handle_mfcr2_show_variants | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11637 of file chan_dahdi.c.
References ast_cli(), country, FORMAT, name, RESULT_FAILURE, and RESULT_SUCCESS.
11638 { 11639 #define FORMAT "%4s %40s\n" 11640 int numvariants = 0; 11641 int i; 11642 const openr2_variant_entry_t *variants; 11643 if (!(variants = openr2_proto_get_variant_list(&numvariants))) { 11644 ast_cli(fd, "Failed to get list of variants.\n"); 11645 return RESULT_FAILURE; 11646 } 11647 ast_cli(fd, FORMAT, "Variant Code", "Country"); 11648 for (i = 0; i < numvariants; i++) { 11649 ast_cli(fd, FORMAT, variants[i].name, variants[i].country); 11650 } 11651 return RESULT_SUCCESS; 11652 #undef FORMAT 11653 }
static int handle_mfcr2_version | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11631 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11632 { 11633 ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); 11634 return RESULT_SUCCESS; 11635 }
static int handle_pri_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11384 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11385 { 11386 int span; 11387 int x; 11388 if (argc < 4) { 11389 return RESULT_SHOWUSAGE; 11390 } 11391 span = atoi(argv[3]); 11392 if ((span < 1) || (span > NUM_SPANS)) { 11393 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS); 11394 return RESULT_SUCCESS; 11395 } 11396 if (!pris[span-1].pri) { 11397 ast_cli(fd, "No PRI running on span %d\n", span); 11398 return RESULT_SUCCESS; 11399 } 11400 for (x = 0; x < NUM_DCHANS; x++) { 11401 if (pris[span-1].dchans[x]) 11402 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11403 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11404 PRI_DEBUG_Q921_STATE); 11405 } 11406 ast_cli(fd, "Enabled debugging on span %d\n", span); 11407 return RESULT_SUCCESS; 11408 }
static int handle_pri_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11412 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11413 { 11414 int span; 11415 int x; 11416 if (argc < 5) 11417 return RESULT_SHOWUSAGE; 11418 span = atoi(argv[4]); 11419 if ((span < 1) || (span > NUM_SPANS)) { 11420 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11421 return RESULT_SUCCESS; 11422 } 11423 if (!pris[span-1].pri) { 11424 ast_cli(fd, "No PRI running on span %d\n", span); 11425 return RESULT_SUCCESS; 11426 } 11427 for (x = 0; x < NUM_DCHANS; x++) { 11428 if (pris[span-1].dchans[x]) 11429 pri_set_debug(pris[span-1].dchans[x], 0); 11430 } 11431 ast_cli(fd, "Disabled debugging on span %d\n", span); 11432 return RESULT_SUCCESS; 11433 }
static int handle_pri_really_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11435 of file chan_dahdi.c.
References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11436 { 11437 int span; 11438 int x; 11439 if (argc < 5) 11440 return RESULT_SHOWUSAGE; 11441 span = atoi(argv[4]); 11442 if ((span < 1) || (span > NUM_SPANS)) { 11443 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS); 11444 return RESULT_SUCCESS; 11445 } 11446 if (!pris[span-1].pri) { 11447 ast_cli(fd, "No PRI running on span %d\n", span); 11448 return RESULT_SUCCESS; 11449 } 11450 for (x = 0; x < NUM_DCHANS; x++) { 11451 if (pris[span-1].dchans[x]) 11452 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 11453 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 11454 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 11455 } 11456 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span); 11457 return RESULT_SUCCESS; 11458 }
static int handle_pri_set_debug_file | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 11337 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.
11338 { 11339 int myfd; 11340 11341 if (!strncasecmp(argv[1], "set", 3)) { 11342 if (argc < 5) 11343 return RESULT_SHOWUSAGE; 11344 11345 if (ast_strlen_zero(argv[4])) 11346 return RESULT_SHOWUSAGE; 11347 11348 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600); 11349 if (myfd < 0) { 11350 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]); 11351 return RESULT_SUCCESS; 11352 } 11353 11354 ast_mutex_lock(&pridebugfdlock); 11355 11356 if (pridebugfd >= 0) 11357 close(pridebugfd); 11358 11359 pridebugfd = myfd; 11360 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename)); 11361 11362 ast_mutex_unlock(&pridebugfdlock); 11363 11364 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]); 11365 } else { 11366 /* Assume it is unset */ 11367 ast_mutex_lock(&pridebugfdlock); 11368 close(pridebugfd); 11369 pridebugfd = -1; 11370 ast_cli(fd, "PRI debug output to file disabled\n"); 11371 ast_mutex_unlock(&pridebugfdlock); 11372 } 11373 11374 return RESULT_SUCCESS; 11375 }
static int handle_pri_show_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11541 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.
11542 { 11543 int x; 11544 int span; 11545 int count=0; 11546 int debug=0; 11547 11548 for (span = 0; span < NUM_SPANS; span++) { 11549 if (pris[span].pri) { 11550 for (x = 0; x < NUM_DCHANS; x++) { 11551 debug = 0; 11552 if (pris[span].dchans[x]) { 11553 debug = pri_get_debug(pris[span].dchans[x]); 11554 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" ); 11555 count++; 11556 } 11557 } 11558 } 11559 11560 } 11561 ast_mutex_lock(&pridebugfdlock); 11562 if (pridebugfd >= 0) 11563 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename); 11564 ast_mutex_unlock(&pridebugfdlock); 11565 11566 if (!count) 11567 ast_cli(fd, "No debug set or no PRI running\n"); 11568 return RESULT_SUCCESS; 11569 }
static int handle_pri_show_span | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11502 of file chan_dahdi.c.
References ast_cli(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11503 { 11504 int span; 11505 int x; 11506 char status[256]; 11507 if (argc < 4) 11508 return RESULT_SHOWUSAGE; 11509 span = atoi(argv[3]); 11510 if ((span < 1) || (span > NUM_SPANS)) { 11511 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS); 11512 return RESULT_SUCCESS; 11513 } 11514 if (!pris[span-1].pri) { 11515 ast_cli(fd, "No PRI running on span %d\n", span); 11516 return RESULT_SUCCESS; 11517 } 11518 for (x = 0; x < NUM_DCHANS; x++) { 11519 if (pris[span-1].dchannels[x]) { 11520 #ifdef PRI_DUMP_INFO_STR 11521 char *info_str = NULL; 11522 #endif 11523 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 11524 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 11525 ast_cli(fd, "Status: %s\n", status); 11526 #ifdef PRI_DUMP_INFO_STR 11527 info_str = pri_dump_info_str(pris[span-1].pri); 11528 if (info_str) { 11529 ast_cli(fd, "%s", info_str); 11530 free(info_str); 11531 } 11532 #else 11533 pri_dump_info(pris[span-1].pri); 11534 #endif 11535 ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 11536 } 11537 } 11538 return RESULT_SUCCESS; 11539 }
static int handle_pri_show_spans | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11481 of file chan_dahdi.c.
References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
11482 { 11483 int span; 11484 int x; 11485 char status[256]; 11486 if (argc != 3) 11487 return RESULT_SHOWUSAGE; 11488 11489 for (span = 0; span < NUM_SPANS; span++) { 11490 if (pris[span].pri) { 11491 for (x = 0; x < NUM_DCHANS; x++) { 11492 if (pris[span].dchannels[x]) { 11493 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 11494 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status); 11495 } 11496 } 11497 } 11498 } 11499 return RESULT_SUCCESS; 11500 }
static int handle_pri_version | ( | int | fd, | |
int | agc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 11378 of file chan_dahdi.c.
References ast_cli(), and RESULT_SUCCESS.
11378 { 11379 ast_cli(fd, "libpri version: %s\n", pri_get_version()); 11380 return RESULT_SUCCESS; 11381 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2647 of file chan_dahdi.c.
References ast_app_has_voicemail(), and dahdi_pvt::mailbox.
Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().
02648 { 02649 02650 return ast_app_has_voicemail(p->mailbox, NULL); 02651 }
static void init_mfcr2_globals | ( | void | ) | [static] |
Definition at line 1266 of file chan_dahdi.c.
References AST_PTHREADT_NULL, master, NUM_SPANS, and r2links.
Referenced by dahdi_restart(), and load_module().
01267 { 01268 int r; 01269 mfcr2_cur_context_index = 0; 01270 mfcr2_cur_variant = OR2_VAR_UNKNOWN; 01271 mfcr2_cur_mfback_timeout = -1; 01272 mfcr2_cur_metering_pulse_timeout = -1; 01273 mfcr2_cur_max_ani = 10; 01274 mfcr2_cur_max_dnis = 4; 01275 mfcr2_cur_get_ani_first = -1; 01276 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 01277 mfcr2_cur_dtmf_dialing = -1; 01278 mfcr2_cur_dtmf_detection = -1; 01279 mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON; 01280 mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF; 01281 #endif 01282 mfcr2_cur_skip_category = -1; 01283 mfcr2_cur_call_files = 0; 01284 mfcr2_cur_allow_collect_calls = 0; 01285 mfcr2_cur_forced_release = 0; 01286 mfcr2_cur_double_answer = 0; 01287 mfcr2_cur_immediate_accept = -1; 01288 mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING; 01289 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 01290 memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir)); 01291 memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file)); 01292 memset(r2links, 0, sizeof(r2links)); 01293 for (r = 0; r < NUM_SPANS; r++) { 01294 r2links[r].master = AST_PTHREADT_NULL; 01295 } 01296 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 2206 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
02207 { 02208 /* If they're listening to our channel, they're ours */ 02209 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 02210 return 1; 02211 /* If they're a talker on our (allocated) conference, they're ours */ 02212 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 02213 return 1; 02214 return 0; 02215 }
Definition at line 2236 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
02237 { 02238 int x; 02239 int useslavenative; 02240 struct dahdi_pvt *slave = NULL; 02241 /* Start out optimistic */ 02242 useslavenative = 1; 02243 /* Update conference state in a stateless fashion */ 02244 for (x = 0; x < 3; x++) { 02245 /* Any three-way calling makes slave native mode *definitely* out 02246 of the question */ 02247 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 02248 useslavenative = 0; 02249 } 02250 /* If we don't have any 3-way calls, check to see if we have 02251 precisely one slave */ 02252 if (useslavenative) { 02253 for (x = 0; x < MAX_SLAVES; x++) { 02254 if (p->slaves[x]) { 02255 if (slave) { 02256 /* Whoops already have a slave! No 02257 slave native and stop right away */ 02258 slave = NULL; 02259 useslavenative = 0; 02260 break; 02261 } else { 02262 /* We have one slave so far */ 02263 slave = p->slaves[x]; 02264 } 02265 } 02266 } 02267 } 02268 /* If no slave, slave native definitely out */ 02269 if (!slave) 02270 useslavenative = 0; 02271 else if (slave->law != p->law) { 02272 useslavenative = 0; 02273 slave = NULL; 02274 } 02275 if (out) 02276 *out = slave; 02277 return useslavenative; 02278 }
static int load_module | ( | void | ) | [static] |
Definition at line 13976 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.
13977 { 13978 int res; 13979 13980 #ifdef HAVE_PRI 13981 int y,i; 13982 memset(pris, 0, sizeof(pris)); 13983 for (y = 0; y < NUM_SPANS; y++) { 13984 ast_mutex_init(&pris[y].lock); 13985 pris[y].offset = -1; 13986 pris[y].master = AST_PTHREADT_NULL; 13987 for (i = 0; i < NUM_DCHANS; i++) 13988 pris[y].fds[i] = -1; 13989 } 13990 pri_set_error(dahdi_pri_error); 13991 pri_set_message(dahdi_pri_message); 13992 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 13993 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 13994 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 13995 } 13996 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 13997 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 13998 #endif 13999 #ifdef HAVE_OPENR2 14000 init_mfcr2_globals(); 14001 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 14002 ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec, 14003 dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip); 14004 } 14005 ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec, 14006 zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip); 14007 #endif 14008 if ((res = setup_dahdi(0))) { 14009 return AST_MODULE_LOAD_DECLINE; 14010 } 14011 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 14012 chan_tech = &dahdi_tech; 14013 } else { 14014 chan_tech = &zap_tech; 14015 } 14016 if (ast_channel_register(chan_tech)) { 14017 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 14018 __unload_module(); 14019 return -1; 14020 } 14021 #ifdef HAVE_PRI 14022 ast_string_field_init(&inuse, 16); 14023 ast_string_field_set(&inuse, name, "GR-303InUse"); 14024 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 14025 #endif 14026 #ifdef HAVE_OPENR2 14027 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 14028 #endif 14029 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14030 14031 memset(round_robin, 0, sizeof(round_robin)); 14032 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 14033 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 14034 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 14035 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 14036 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 14037 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 14038 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 14039 14040 ast_cond_init(&ss_thread_complete, NULL); 14041 14042 return res; 14043 }
static struct dahdi_mfcr2* mfcr2_get_context | ( | int | id | ) | [static] |
Definition at line 8478 of file chan_dahdi.c.
References ast_log(), LOG_ERROR, and r2links.
Referenced by mkintf().
08479 { 08480 if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) { 08481 ast_log(LOG_ERROR, "No more R2 links available!.\n"); 08482 return NULL; 08483 } 08484 return &r2links[id]; 08485 }
static void* mfcr2_monitor | ( | void * | data | ) | [static] |
Definition at line 9634 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, DAHDI_R2_LOCAL_BLOCK, dahdi_pvt::lock, LOG_ERROR, dahdi_pvt::r2chan, SUB_REAL, and dahdi_pvt::subs.
Referenced by setup_dahdi().
09635 { 09636 struct dahdi_pvt *p; 09637 struct dahdi_mfcr2 *mfcr2 = data; 09638 /* we should be using pthread_key_create 09639 and allocate pollers dynamically. 09640 I think do_monitor() could be leaking, since it 09641 could be cancelled at any time and is not 09642 using thread keys, why?, */ 09643 struct pollfd pollers[mfcr2->numchans]; 09644 int maxsleep = 20; 09645 int res = 0; 09646 int i = 0; 09647 int pollsize = 0; 09648 int oldstate = 0; 09649 int was_idle = 0; 09650 int quit_loop = 0; 09651 /* now that we're ready to get calls, unblock our side and 09652 get current line state */ 09653 for (i = 0; i < mfcr2->numchans; i++) { 09654 p = mfcr2->pvts[i]; 09655 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd; 09656 if (openr2_chan_set_idle(p->r2chan)) { 09657 ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel); 09658 } else { 09659 ast_mutex_lock(&p->lock); 09660 mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK; 09661 mfcr2->pvts[i]->mfcr2call = 0; 09662 ast_mutex_unlock(&p->lock); 09663 } 09664 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan); 09665 } 09666 while(1) { 09667 /* we trust here that the mfcr2 channel list will not ever change once 09668 the module is loaded */ 09669 pollsize = 0; 09670 for (i = 0; i < mfcr2->numchans; i++) { 09671 pollers[i].events = 0; 09672 pollers[i].revents = 0; 09673 if (mfcr2->pvts[i]->owner) { 09674 continue; 09675 } 09676 if (!mfcr2->pvts[i]->r2chan) { 09677 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel); 09678 quit_loop = 1; 09679 break; 09680 } 09681 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan); 09682 pollers[i].events = POLLIN | POLLPRI; 09683 pollsize++; 09684 } 09685 if (quit_loop) { 09686 break; 09687 } 09688 09689 if (pollsize == 0) { 09690 if (!was_idle) { 09691 ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n"); 09692 was_idle = 1; 09693 } 09694 poll(NULL, 0, maxsleep); 09695 continue; 09696 } 09697 was_idle = 0; 09698 09699 /* probably poll() is a valid cancel point, lets just be on the safe side 09700 by calling pthread_testcancel */ 09701 pthread_testcancel(); 09702 res = poll(pollers, mfcr2->numchans, maxsleep); 09703 pthread_testcancel(); 09704 if ((res < 0) && (errno != EINTR)) { 09705 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno)); 09706 break; 09707 } 09708 /* do we want to allow to cancel while processing events? */ 09709 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 09710 for (i = 0; i < mfcr2->numchans; i++) { 09711 if ((pollers[i].revents & POLLPRI) || (pollers[i].revents & POLLIN)) { 09712 openr2_chan_process_event(mfcr2->pvts[i]->r2chan); 09713 } 09714 } 09715 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); 09716 } 09717 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n"); 09718 return 0; 09719 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 8611 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().
08612 { 08613 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08614 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08615 char fn[80]; 08616 #if 1 08617 struct dahdi_bufferinfo bi; 08618 #endif 08619 int res; 08620 int span=0; 08621 int here = 0; 08622 int x; 08623 struct dahdi_pvt **wlist; 08624 struct dahdi_pvt **wend; 08625 struct dahdi_params p; 08626 08627 wlist = &iflist; 08628 wend = &ifend; 08629 08630 #ifdef HAVE_PRI 08631 if (pri) { 08632 wlist = &pri->crvs; 08633 wend = &pri->crvend; 08634 } 08635 #endif 08636 08637 tmp2 = *wlist; 08638 prev = NULL; 08639 08640 while (tmp2) { 08641 if (!tmp2->destroy) { 08642 if (tmp2->channel == channel) { 08643 tmp = tmp2; 08644 here = 1; 08645 break; 08646 } 08647 if (tmp2->channel > channel) { 08648 break; 08649 } 08650 } 08651 prev = tmp2; 08652 tmp2 = tmp2->next; 08653 } 08654 08655 if (!here && reloading != 1) { 08656 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08657 if (tmp) 08658 free(tmp); 08659 return NULL; 08660 } 08661 ast_mutex_init(&tmp->lock); 08662 ifcount++; 08663 for (x = 0; x < 3; x++) 08664 tmp->subs[x].dfd = -1; 08665 tmp->channel = channel; 08666 tmp->priindication_oob = conf->chan.priindication_oob; 08667 } 08668 08669 if (tmp) { 08670 int chan_sig = conf->chan.sig; 08671 if (!here) { 08672 if ((channel != CHAN_PSEUDO) && !pri) { 08673 int count = 0; 08674 snprintf(fn, sizeof(fn), "%d", channel); 08675 /* Open non-blocking */ 08676 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08677 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 */ 08678 usleep(1); 08679 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08680 count++; 08681 } 08682 /* Allocate a DAHDI structure */ 08683 if (tmp->subs[SUB_REAL].dfd < 0) { 08684 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); 08685 destroy_dahdi_pvt(&tmp); 08686 return NULL; 08687 } 08688 memset(&p, 0, sizeof(p)); 08689 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08690 if (res < 0) { 08691 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08692 destroy_dahdi_pvt(&tmp); 08693 return NULL; 08694 } 08695 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 08696 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)); 08697 destroy_dahdi_pvt(&tmp); 08698 return NULL; 08699 } 08700 tmp->law = p.curlaw; 08701 tmp->span = p.spanno; 08702 span = p.spanno - 1; 08703 } else { 08704 if (channel == CHAN_PSEUDO) 08705 chan_sig = 0; 08706 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08707 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08708 return NULL; 08709 } 08710 } 08711 #ifdef HAVE_PRI 08712 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08713 int offset; 08714 int myswitchtype; 08715 int matchesdchan; 08716 int x,y; 08717 offset = 0; 08718 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08719 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08720 destroy_dahdi_pvt(&tmp); 08721 return NULL; 08722 } 08723 if (span >= NUM_SPANS) { 08724 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08725 destroy_dahdi_pvt(&tmp); 08726 return NULL; 08727 } else { 08728 struct dahdi_spaninfo si; 08729 si.spanno = 0; 08730 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08731 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08732 destroy_dahdi_pvt(&tmp); 08733 return NULL; 08734 } 08735 /* Store the logical span first based upon the real span */ 08736 tmp->logicalspan = pris[span].prilogicalspan; 08737 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08738 if (span < 0) { 08739 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08740 destroy_dahdi_pvt(&tmp); 08741 return NULL; 08742 } 08743 if (chan_sig == SIG_PRI) 08744 myswitchtype = conf->pri.switchtype; 08745 else 08746 myswitchtype = PRI_SWITCH_GR303_TMC; 08747 /* Make sure this isn't a d-channel */ 08748 matchesdchan=0; 08749 for (x = 0; x < NUM_SPANS; x++) { 08750 for (y = 0; y < NUM_DCHANS; y++) { 08751 if (pris[x].dchannels[y] == tmp->channel) { 08752 matchesdchan = 1; 08753 break; 08754 } 08755 } 08756 } 08757 offset = p.chanpos; 08758 if (!matchesdchan) { 08759 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08760 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08761 destroy_dahdi_pvt(&tmp); 08762 return NULL; 08763 } 08764 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08765 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08766 destroy_dahdi_pvt(&tmp); 08767 return NULL; 08768 } 08769 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08770 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08771 destroy_dahdi_pvt(&tmp); 08772 return NULL; 08773 } 08774 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08775 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08776 destroy_dahdi_pvt(&tmp); 08777 return NULL; 08778 } 08779 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08780 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08781 destroy_dahdi_pvt(&tmp); 08782 return NULL; 08783 } 08784 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08785 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08786 destroy_dahdi_pvt(&tmp); 08787 return NULL; 08788 } 08789 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08790 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08791 destroy_dahdi_pvt(&tmp); 08792 return NULL; 08793 } 08794 if (pris[span].numchans >= MAX_CHANNELS) { 08795 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08796 pris[span].trunkgroup); 08797 destroy_dahdi_pvt(&tmp); 08798 return NULL; 08799 } 08800 pris[span].nodetype = conf->pri.nodetype; 08801 pris[span].switchtype = myswitchtype; 08802 pris[span].nsf = conf->pri.nsf; 08803 pris[span].dialplan = conf->pri.dialplan; 08804 pris[span].localdialplan = conf->pri.localdialplan; 08805 pris[span].pvts[pris[span].numchans++] = tmp; 08806 pris[span].minunused = conf->pri.minunused; 08807 pris[span].minidle = conf->pri.minidle; 08808 pris[span].overlapdial = conf->pri.overlapdial; 08809 #ifdef HAVE_PRI_INBANDDISCONNECT 08810 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08811 #endif 08812 pris[span].facilityenable = conf->pri.facilityenable; 08813 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08814 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08815 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08816 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08817 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08818 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08819 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08820 pris[span].resetinterval = conf->pri.resetinterval; 08821 08822 tmp->pri = &pris[span]; 08823 tmp->prioffset = offset; 08824 tmp->call = NULL; 08825 } else { 08826 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08827 destroy_dahdi_pvt(&tmp); 08828 return NULL; 08829 } 08830 } 08831 } else { 08832 tmp->prioffset = 0; 08833 } 08834 #endif 08835 #ifdef HAVE_OPENR2 08836 if (chan_sig == SIG_MFCR2 && reloading != 1) { 08837 char logdir[OR2_MAX_PATH]; 08838 struct dahdi_mfcr2 *dahdi_r2; 08839 int threshold = 0; 08840 int snres = 0; 08841 dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index); 08842 if (!dahdi_r2) { 08843 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 08844 } else if (!dahdi_r2->protocol_context){ 08845 char tmplogdir[] = "/tmp"; 08846 dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 08847 &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis); 08848 if (!dahdi_r2->protocol_context) { 08849 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 08850 destroy_dahdi_pvt(&tmp); 08851 return NULL; 08852 } 08853 openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel); 08854 openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first); 08855 openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category); 08856 openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold); 08857 openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout); 08858 openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout); 08859 openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer); 08860 openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept); 08861 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 08862 openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off); 08863 openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection); 08864 #endif 08865 if (ast_strlen_zero(mfcr2_cur_logdir)) { 08866 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) { 08867 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08868 } 08869 } else { 08870 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir); 08871 if (snres >= sizeof(logdir)) { 08872 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir); 08873 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08874 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir); 08875 } 08876 } else { 08877 if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) { 08878 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir); 08879 } 08880 } 08881 } 08882 if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) { 08883 if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) { 08884 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file); 08885 } 08886 } 08887 } 08888 if (dahdi_r2) { 08889 /* TODO: should we check numchans overflow, or is it already done by DAHDI? */ 08890 dahdi_r2->pvts[dahdi_r2->numchans++] = tmp; 08891 tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context, 08892 tmp->subs[SUB_REAL].dfd, NULL, NULL); 08893 if (!tmp->r2chan) { 08894 openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context); 08895 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 08896 destroy_dahdi_pvt(&tmp); 08897 return NULL; 08898 } 08899 openr2_chan_set_client_data(tmp->r2chan, tmp); 08900 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 08901 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 08902 openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel); 08903 if (mfcr2_cur_call_files) { 08904 openr2_chan_enable_call_files(tmp->r2chan); 08905 } 08906 tmp->mfcr2_category = mfcr2_cur_category; 08907 tmp->mfcr2 = dahdi_r2; 08908 tmp->mfcr2call = 0; 08909 tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK; 08910 tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer; 08911 tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls; 08912 tmp->mfcr2_ani_index = 0; 08913 tmp->mfcr2_dnis_index = 0; 08914 tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls; 08915 tmp->mfcr2_forced_release = mfcr2_cur_forced_release; 08916 } 08917 } 08918 #endif 08919 } else { 08920 chan_sig = tmp->sig; 08921 if (tmp->subs[SUB_REAL].dfd > -1) { 08922 memset(&p, 0, sizeof(p)); 08923 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08924 } 08925 } 08926 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08927 switch (chan_sig) { 08928 case SIG_FXSKS: 08929 case SIG_FXSLS: 08930 case SIG_EM: 08931 case SIG_EM_E1: 08932 case SIG_EMWINK: 08933 case SIG_FEATD: 08934 case SIG_FEATDMF: 08935 case SIG_FEATDMF_TA: 08936 case SIG_FEATB: 08937 case SIG_E911: 08938 case SIG_SF: 08939 case SIG_SFWINK: 08940 case SIG_FGC_CAMA: 08941 case SIG_FGC_CAMAMF: 08942 case SIG_SF_FEATD: 08943 case SIG_SF_FEATDMF: 08944 case SIG_SF_FEATB: 08945 p.starttime = 250; 08946 break; 08947 } 08948 08949 if (tmp->radio) { 08950 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 08951 p.channo = channel; 08952 p.rxwinktime = 1; 08953 p.rxflashtime = 1; 08954 p.starttime = 1; 08955 p.debouncetime = 5; 08956 } 08957 if (!tmp->radio) { 08958 p.channo = channel; 08959 /* Override timing settings based on config file */ 08960 if (conf->timing.prewinktime >= 0) 08961 p.prewinktime = conf->timing.prewinktime; 08962 if (conf->timing.preflashtime >= 0) 08963 p.preflashtime = conf->timing.preflashtime; 08964 if (conf->timing.winktime >= 0) 08965 p.winktime = conf->timing.winktime; 08966 if (conf->timing.flashtime >= 0) 08967 p.flashtime = conf->timing.flashtime; 08968 if (conf->timing.starttime >= 0) 08969 p.starttime = conf->timing.starttime; 08970 if (conf->timing.rxwinktime >= 0) 08971 p.rxwinktime = conf->timing.rxwinktime; 08972 if (conf->timing.rxflashtime >= 0) 08973 p.rxflashtime = conf->timing.rxflashtime; 08974 if (conf->timing.debouncetime >= 0) 08975 p.debouncetime = conf->timing.debouncetime; 08976 } 08977 08978 /* dont set parms on a pseudo-channel (or CRV) */ 08979 if (tmp->subs[SUB_REAL].dfd >= 0) 08980 { 08981 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 08982 if (res < 0) { 08983 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 08984 destroy_dahdi_pvt(&tmp); 08985 return NULL; 08986 } 08987 } 08988 #if 1 08989 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 08990 memset(&bi, 0, sizeof(bi)); 08991 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 08992 if (!res) { 08993 bi.txbufpolicy = conf->chan.buf_policy; 08994 bi.rxbufpolicy = conf->chan.buf_policy; 08995 bi.numbufs = conf->chan.buf_no; 08996 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 08997 if (res < 0) { 08998 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 08999 } 09000 } else 09001 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09002 } 09003 #endif 09004 tmp->immediate = conf->chan.immediate; 09005 tmp->transfertobusy = conf->chan.transfertobusy; 09006 tmp->sig = chan_sig; 09007 tmp->outsigmod = conf->chan.outsigmod; 09008 tmp->ringt_base = ringt_base; 09009 tmp->firstradio = 0; 09010 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09011 tmp->permcallwaiting = conf->chan.callwaiting; 09012 else 09013 tmp->permcallwaiting = 0; 09014 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09015 tmp->destroy = 0; 09016 tmp->drings = drings; 09017 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 09018 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09019 tmp->threewaycalling = conf->chan.threewaycalling; 09020 tmp->adsi = conf->chan.adsi; 09021 tmp->use_smdi = conf->chan.use_smdi; 09022 tmp->permhidecallerid = conf->chan.hidecallerid; 09023 tmp->callreturn = conf->chan.callreturn; 09024 tmp->echocancel = conf->chan.echocancel; 09025 tmp->echotraining = conf->chan.echotraining; 09026 tmp->pulse = conf->chan.pulse; 09027 if (tmp->echocancel) 09028 tmp->echocanbridged = conf->chan.echocanbridged; 09029 else { 09030 if (conf->chan.echocanbridged) 09031 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09032 tmp->echocanbridged = 0; 09033 } 09034 tmp->busydetect = conf->chan.busydetect; 09035 tmp->busycount = conf->chan.busycount; 09036 tmp->busycompare = conf->chan.busycompare; 09037 tmp->busytonelength = conf->chan.busytonelength; 09038 tmp->busyquietlength = conf->chan.busyquietlength; 09039 tmp->busyfuzziness = conf->chan.busyfuzziness; 09040 tmp->silencethreshold = conf->chan.silencethreshold; 09041 tmp->callprogress = conf->chan.callprogress; 09042 tmp->cancallforward = conf->chan.cancallforward; 09043 tmp->dtmfrelax = conf->chan.dtmfrelax; 09044 tmp->callwaiting = tmp->permcallwaiting; 09045 tmp->hidecallerid = tmp->permhidecallerid; 09046 tmp->channel = channel; 09047 tmp->stripmsd = conf->chan.stripmsd; 09048 tmp->use_callerid = conf->chan.use_callerid; 09049 tmp->cid_signalling = conf->chan.cid_signalling; 09050 tmp->cid_start = conf->chan.cid_start; 09051 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09052 tmp->restrictcid = conf->chan.restrictcid; 09053 tmp->use_callingpres = conf->chan.use_callingpres; 09054 tmp->priexclusive = conf->chan.priexclusive; 09055 if (tmp->usedistinctiveringdetection) { 09056 if (!tmp->use_callerid) { 09057 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09058 tmp->use_callerid = 1; 09059 } 09060 } 09061 09062 if (tmp->cid_signalling == CID_SIG_SMDI) { 09063 if (!tmp->use_smdi) { 09064 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09065 tmp->use_smdi = 1; 09066 } 09067 } 09068 if (tmp->use_smdi) { 09069 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09070 if (!(tmp->smdi_iface)) { 09071 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09072 tmp->use_smdi = 0; 09073 } 09074 } 09075 09076 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09077 tmp->amaflags = conf->chan.amaflags; 09078 if (!here) { 09079 tmp->confno = -1; 09080 tmp->propconfno = -1; 09081 } 09082 tmp->canpark = conf->chan.canpark; 09083 tmp->transfer = conf->chan.transfer; 09084 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09085 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09086 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09087 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09088 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09089 tmp->cid_ton = 0; 09090 if (chan_sig != SIG_PRI) { 09091 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09092 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09093 } else { 09094 tmp->cid_num[0] = '\0'; 09095 tmp->cid_name[0] = '\0'; 09096 } 09097 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09098 tmp->msgstate = -1; 09099 tmp->group = conf->chan.group; 09100 tmp->callgroup = conf->chan.callgroup; 09101 tmp->pickupgroup= conf->chan.pickupgroup; 09102 tmp->rxgain = conf->chan.rxgain; 09103 tmp->txgain = conf->chan.txgain; 09104 tmp->tonezone = conf->chan.tonezone; 09105 tmp->onhooktime = time(NULL); 09106 if (tmp->subs[SUB_REAL].dfd > -1) { 09107 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09108 if (tmp->dsp) 09109 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09110 update_conf(tmp); 09111 if (!here) { 09112 if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2)) 09113 /* Hang it up to be sure it's good */ 09114 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09115 } 09116 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09117 #ifdef HAVE_PRI 09118 /* the dchannel is down so put the channel in alarm */ 09119 if (tmp->pri && !pri_is_up(tmp->pri)) { 09120 tmp->inalarm = 1; 09121 } 09122 #endif 09123 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09124 tmp->inalarm = 1; 09125 handle_alarms(tmp, res); 09126 } else { 09127 /* yes, this looks strange... the unknown_alarm flag is only used to 09128 control whether an 'alarm cleared' message gets generated when we 09129 get an indication that the channel is no longer in alarm status. 09130 however, the channel *could* be in an alarm status that we aren't 09131 aware of (since get_alarms() only reports span alarms, not channel 09132 alarms). setting this flag will cause any potential 'alarm cleared' 09133 message to be suppressed, but if a real alarm occurs before that 09134 happens, this flag will get cleared by it and the situation will 09135 be normal. 09136 */ 09137 tmp->unknown_alarm = 1; 09138 } 09139 } 09140 09141 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09142 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09143 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09144 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09145 09146 } 09147 if (tmp && !here) { 09148 /* nothing on the iflist */ 09149 if (!*wlist) { 09150 *wlist = tmp; 09151 tmp->prev = NULL; 09152 tmp->next = NULL; 09153 *wend = tmp; 09154 } else { 09155 /* at least one member on the iflist */ 09156 struct dahdi_pvt *working = *wlist; 09157 09158 /* check if we maybe have to put it on the begining */ 09159 if (working->channel > tmp->channel) { 09160 tmp->next = *wlist; 09161 tmp->prev = NULL; 09162 (*wlist)->prev = tmp; 09163 *wlist = tmp; 09164 } else { 09165 /* go through all the members and put the member in the right place */ 09166 while (working) { 09167 /* in the middle */ 09168 if (working->next) { 09169 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09170 tmp->next = working->next; 09171 tmp->prev = working; 09172 working->next->prev = tmp; 09173 working->next = tmp; 09174 break; 09175 } 09176 } else { 09177 /* the last */ 09178 if (working->channel < tmp->channel) { 09179 working->next = tmp; 09180 tmp->next = NULL; 09181 tmp->prev = working; 09182 *wend = tmp; 09183 break; 09184 } 09185 } 09186 working = working->next; 09187 } 09188 } 09189 } 09190 } 09191 return tmp; 09192 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 6259 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, and dahdi_pvt::subs.
Referenced by dahdi_write().
06260 { 06261 int sent=0; 06262 int size; 06263 int res; 06264 int fd; 06265 fd = p->subs[index].dfd; 06266 while (len) { 06267 size = len; 06268 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 06269 size = (linear ? READ_SIZE * 2 : READ_SIZE); 06270 res = write(fd, buf, size); 06271 if (res != size) { 06272 if (option_debug) 06273 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 06274 return sent; 06275 } 06276 len -= size; 06277 buf += size; 06278 } 06279 return sent; 06280 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 6750 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06751 { 06752 char c; 06753 06754 *str = 0; /* start with empty output buffer */ 06755 for (;;) 06756 { 06757 /* Wait for the first digit (up to specified ms). */ 06758 c = ast_waitfordigit(chan, ms); 06759 /* if timeout, hangup or error, return as such */ 06760 if (c < 1) 06761 return c; 06762 *str++ = c; 06763 *str = 0; 06764 if (strchr(term, c)) 06765 return 1; 06766 } 06767 }
static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3391 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, dahdi_pri::pri, and dahdi_pvt::pri.
Referenced by pri_find_principle().
03392 { 03393 int x = -1; 03394 03395 for (x = 0; x < NUM_DCHANS; x++) { 03396 if ((pri->dchans[x] == pri->pri)) 03397 break; 03398 } 03399 03400 return pri->fds[x]; 03401 }
static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
struct dahdi_pri * | pri, | |||
struct dahdi_pvt * | bearer | |||
) | [static] |
Definition at line 3361 of file chan_dahdi.c.
References dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, ast_channel::fds, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_request().
03362 { 03363 bearer->owner = &inuse; 03364 bearer->realcall = crv; 03365 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03366 if (crv->subs[SUB_REAL].owner) 03367 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd; 03368 crv->bearer = bearer; 03369 crv->call = bearer->call; 03370 crv->pri = pri; 03371 return 0; 03372 }
static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 9986 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().
09987 { 09988 do { 09989 pri->resetpos++; 09990 } while ((pri->resetpos < pri->numchans) && 09991 (!pri->pvts[pri->resetpos] || 09992 pri->pvts[pri->resetpos]->call || 09993 pri->pvts[pri->resetpos]->resetting)); 09994 if (pri->resetpos < pri->numchans) { 09995 /* Mark the channel as resetting and restart it */ 09996 pri->pvts[pri->resetpos]->resetting = 1; 09997 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 09998 } else { 09999 pri->resetting = 0; 10000 time(&pri->lastreset); 10001 } 10002 return 0; 10003 }
static int pri_create_spanmap | ( | int | span, | |
int | trunkgroup, | |||
int | logicalspan | |||
) | [static] |
Definition at line 8598 of file chan_dahdi.c.
References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08599 { 08600 if (pris[span].mastertrunkgroup) { 08601 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); 08602 return -1; 08603 } 08604 pris[span].mastertrunkgroup = trunkgroup; 08605 pris[span].prilogicalspan = logicalspan; 08606 return 0; 08607 }
static int pri_create_trunkgroup | ( | int | trunkgroup, | |
int * | channels | |||
) | [static] |
Definition at line 8535 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().
08536 { 08537 struct dahdi_spaninfo si; 08538 struct dahdi_params p; 08539 int fd; 08540 int span; 08541 int ospan=0; 08542 int x,y; 08543 for (x = 0; x < NUM_SPANS; x++) { 08544 if (pris[x].trunkgroup == trunkgroup) { 08545 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08546 return -1; 08547 } 08548 } 08549 for (y = 0; y < NUM_DCHANS; y++) { 08550 if (!channels[y]) 08551 break; 08552 memset(&si, 0, sizeof(si)); 08553 memset(&p, 0, sizeof(p)); 08554 fd = open(DAHDI_FILE_CHANNEL, O_RDWR); 08555 if (fd < 0) { 08556 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08557 return -1; 08558 } 08559 x = channels[y]; 08560 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08561 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08562 close(fd); 08563 return -1; 08564 } 08565 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08566 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08567 return -1; 08568 } 08569 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08570 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08571 close(fd); 08572 return -1; 08573 } 08574 span = p.spanno - 1; 08575 if (pris[span].trunkgroup) { 08576 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08577 close(fd); 08578 return -1; 08579 } 08580 if (pris[span].pvts[0]) { 08581 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08582 close(fd); 08583 return -1; 08584 } 08585 if (!y) { 08586 pris[span].trunkgroup = trunkgroup; 08587 pris[span].offset = channels[y] - p.chanpos; 08588 ospan = span; 08589 } 08590 pris[ospan].dchannels[y] = channels[y]; 08591 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08592 pris[span].span = span + 1; 08593 close(fd); 08594 } 08595 return 0; 08596 }
static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10085 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.
10086 { 10087 struct dahdi_pri *pri = vpri; 10088 pri_event *e; 10089 struct pollfd fds[NUM_DCHANS]; 10090 int res; 10091 int chanpos = 0; 10092 int x; 10093 int haveidles; 10094 int activeidles; 10095 int nextidle = -1; 10096 struct ast_channel *c; 10097 struct timeval tv, lowest, *next; 10098 struct timeval lastidle = { 0, 0 }; 10099 int doidling=0; 10100 char *cc; 10101 char idlen[80]; 10102 struct ast_channel *idle; 10103 pthread_t p; 10104 time_t t; 10105 int i, which=-1; 10106 int numdchans; 10107 int cause=0; 10108 struct dahdi_pvt *crv; 10109 pthread_t threadid; 10110 pthread_attr_t attr; 10111 char ani2str[6]; 10112 char plancallingnum[256]; 10113 char plancallingani[256]; 10114 char calledtonstr[10]; 10115 10116 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10117 10118 gettimeofday(&lastidle, NULL); 10119 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10120 /* Need to do idle dialing, check to be sure though */ 10121 cc = strchr(pri->idleext, '@'); 10122 if (cc) { 10123 *cc = '\0'; 10124 cc++; 10125 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10126 #if 0 10127 /* Extensions may not be loaded yet */ 10128 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10129 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10130 else 10131 #endif 10132 doidling = 1; 10133 } else 10134 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10135 } 10136 for (;;) { 10137 for (i = 0; i < NUM_DCHANS; i++) { 10138 if (!pri->dchannels[i]) 10139 break; 10140 fds[i].fd = pri->fds[i]; 10141 fds[i].events = POLLIN | POLLPRI; 10142 fds[i].revents = 0; 10143 } 10144 numdchans = i; 10145 time(&t); 10146 ast_mutex_lock(&pri->lock); 10147 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10148 if (pri->resetting && pri_is_up(pri)) { 10149 if (pri->resetpos < 0) 10150 pri_check_restart(pri); 10151 } else { 10152 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10153 pri->resetting = 1; 10154 pri->resetpos = -1; 10155 } 10156 } 10157 } 10158 /* Look for any idle channels if appropriate */ 10159 if (doidling && pri_is_up(pri)) { 10160 nextidle = -1; 10161 haveidles = 0; 10162 activeidles = 0; 10163 for (x = pri->numchans; x >= 0; x--) { 10164 if (pri->pvts[x] && !pri->pvts[x]->owner && 10165 !pri->pvts[x]->call) { 10166 if (haveidles < pri->minunused) { 10167 haveidles++; 10168 } else if (!pri->pvts[x]->resetting) { 10169 nextidle = x; 10170 break; 10171 } 10172 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10173 activeidles++; 10174 } 10175 if (nextidle > -1) { 10176 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10177 /* Don't create a new idle call more than once per second */ 10178 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10179 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause); 10180 if (idle) { 10181 pri->pvts[nextidle]->isidlecall = 1; 10182 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10183 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10184 dahdi_hangup(idle); 10185 } 10186 } else 10187 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10188 gettimeofday(&lastidle, NULL); 10189 } 10190 } else if ((haveidles < pri->minunused) && 10191 (activeidles > pri->minidle)) { 10192 /* Mark something for hangup if there is something 10193 that can be hungup */ 10194 for (x = pri->numchans; x >= 0; x--) { 10195 /* find a candidate channel */ 10196 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10197 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10198 haveidles++; 10199 /* Stop if we have enough idle channels or 10200 can't spare any more active idle ones */ 10201 if ((haveidles >= pri->minunused) || 10202 (activeidles <= pri->minidle)) 10203 break; 10204 } 10205 } 10206 } 10207 } 10208 /* Start with reasonable max */ 10209 lowest = ast_tv(60, 0); 10210 for (i = 0; i < NUM_DCHANS; i++) { 10211 /* Find lowest available d-channel */ 10212 if (!pri->dchannels[i]) 10213 break; 10214 if ((next = pri_schedule_next(pri->dchans[i]))) { 10215 /* We need relative time here */ 10216 tv = ast_tvsub(*next, ast_tvnow()); 10217 if (tv.tv_sec < 0) { 10218 tv = ast_tv(0,0); 10219 } 10220 if (doidling || pri->resetting) { 10221 if (tv.tv_sec > 1) { 10222 tv = ast_tv(1, 0); 10223 } 10224 } else { 10225 if (tv.tv_sec > 60) { 10226 tv = ast_tv(60, 0); 10227 } 10228 } 10229 } else if (doidling || pri->resetting) { 10230 /* Make sure we stop at least once per second if we're 10231 monitoring idle channels */ 10232 tv = ast_tv(1,0); 10233 } else { 10234 /* Don't poll for more than 60 seconds */ 10235 tv = ast_tv(60, 0); 10236 } 10237 if (!i || ast_tvcmp(tv, lowest) < 0) { 10238 lowest = tv; 10239 } 10240 } 10241 ast_mutex_unlock(&pri->lock); 10242 10243 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 10244 pthread_testcancel(); 10245 e = NULL; 10246 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 10247 pthread_testcancel(); 10248 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10249 10250 ast_mutex_lock(&pri->lock); 10251 if (!res) { 10252 for (which = 0; which < NUM_DCHANS; which++) { 10253 if (!pri->dchans[which]) 10254 break; 10255 /* Just a timeout, run the scheduler */ 10256 e = pri_schedule_run(pri->dchans[which]); 10257 if (e) 10258 break; 10259 } 10260 } else if (res > -1) { 10261 for (which = 0; which < NUM_DCHANS; which++) { 10262 if (!pri->dchans[which]) 10263 break; 10264 if (fds[which].revents & POLLPRI) { 10265 /* Check for an event */ 10266 x = 0; 10267 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 10268 if (x) 10269 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); 10270 /* Keep track of alarm state */ 10271 if (x == DAHDI_EVENT_ALARM) { 10272 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 10273 pri_find_dchan(pri); 10274 } else if (x == DAHDI_EVENT_NOALARM) { 10275 pri->dchanavail[which] |= DCHAN_NOTINALARM; 10276 pri_restart(pri->dchans[which]); 10277 } 10278 10279 if (option_debug) 10280 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 10281 } else if (fds[which].revents & POLLIN) { 10282 e = pri_check_event(pri->dchans[which]); 10283 } 10284 if (e) 10285 break; 10286 } 10287 } else if (errno != EINTR) 10288 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 10289 10290 if (e) { 10291 if (pri->debug) 10292 pri_dump_event(pri->dchans[which], e); 10293 10294 if (e->e != PRI_EVENT_DCHAN_DOWN) { 10295 if (!(pri->dchanavail[which] & DCHAN_UP)) { 10296 if (option_verbose > 1) 10297 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span); 10298 } 10299 pri->dchanavail[which] |= DCHAN_UP; 10300 } else { 10301 if (pri->dchanavail[which] & DCHAN_UP) { 10302 if (option_verbose > 1) 10303 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span); 10304 } 10305 pri->dchanavail[which] &= ~DCHAN_UP; 10306 } 10307 10308 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 10309 /* Must be an NFAS group that has the secondary dchan active */ 10310 pri->pri = pri->dchans[which]; 10311 10312 switch (e->e) { 10313 case PRI_EVENT_DCHAN_UP: 10314 if (!pri->pri) pri_find_dchan(pri); 10315 10316 /* Note presense of D-channel */ 10317 time(&pri->lastreset); 10318 10319 /* Restart in 5 seconds */ 10320 if (pri->resetinterval > -1) { 10321 pri->lastreset -= pri->resetinterval; 10322 pri->lastreset += 5; 10323 } 10324 pri->resetting = 0; 10325 /* Take the channels from inalarm condition */ 10326 for (i = 0; i < pri->numchans; i++) 10327 if (pri->pvts[i]) { 10328 pri->pvts[i]->inalarm = 0; 10329 } 10330 break; 10331 case PRI_EVENT_DCHAN_DOWN: 10332 pri_find_dchan(pri); 10333 if (!pri_is_up(pri)) { 10334 pri->resetting = 0; 10335 /* Hangup active channels and put them in alarm mode */ 10336 for (i = 0; i < pri->numchans; i++) { 10337 struct dahdi_pvt *p = pri->pvts[i]; 10338 if (p) { 10339 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 10340 /* T309 is not enabled : hangup calls when alarm occurs */ 10341 if (p->call) { 10342 if (p->pri && p->pri->pri) { 10343 pri_hangup(p->pri->pri, p->call, -1); 10344 pri_destroycall(p->pri->pri, p->call); 10345 p->call = NULL; 10346 } else 10347 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 10348 } 10349 if (p->realcall) { 10350 pri_hangup_all(p->realcall, pri); 10351 } else if (p->owner) 10352 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10353 } 10354 p->inalarm = 1; 10355 } 10356 } 10357 } 10358 break; 10359 case PRI_EVENT_RESTART: 10360 if (e->restart.channel > -1) { 10361 chanpos = pri_find_principle(pri, e->restart.channel); 10362 if (chanpos < 0) 10363 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 10364 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10365 else { 10366 if (option_verbose > 2) 10367 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 10368 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 10369 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10370 if (pri->pvts[chanpos]->call) { 10371 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 10372 pri->pvts[chanpos]->call = NULL; 10373 } 10374 /* Force soft hangup if appropriate */ 10375 if (pri->pvts[chanpos]->realcall) 10376 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10377 else if (pri->pvts[chanpos]->owner) 10378 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10379 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10380 } 10381 } else { 10382 if (option_verbose > 2) 10383 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span); 10384 for (x = 0; x < pri->numchans; x++) 10385 if (pri->pvts[x]) { 10386 ast_mutex_lock(&pri->pvts[x]->lock); 10387 if (pri->pvts[x]->call) { 10388 pri_destroycall(pri->pri, pri->pvts[x]->call); 10389 pri->pvts[x]->call = NULL; 10390 } 10391 if (pri->pvts[x]->realcall) 10392 pri_hangup_all(pri->pvts[x]->realcall, pri); 10393 else if (pri->pvts[x]->owner) 10394 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10395 ast_mutex_unlock(&pri->pvts[x]->lock); 10396 } 10397 } 10398 break; 10399 case PRI_EVENT_KEYPAD_DIGIT: 10400 chanpos = pri_find_principle(pri, e->digit.channel); 10401 if (chanpos < 0) { 10402 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 10403 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 10404 } else { 10405 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 10406 if (chanpos > -1) { 10407 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10408 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 10409 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 10410 /* how to do that */ 10411 int digitlen = strlen(e->digit.digits); 10412 char digit; 10413 int i; 10414 for (i = 0; i < digitlen; i++) { 10415 digit = e->digit.digits[i]; 10416 { 10417 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10418 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10419 } 10420 } 10421 } 10422 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10423 } 10424 } 10425 break; 10426 10427 case PRI_EVENT_INFO_RECEIVED: 10428 chanpos = pri_find_principle(pri, e->ring.channel); 10429 if (chanpos < 0) { 10430 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 10431 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10432 } else { 10433 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 10434 if (chanpos > -1) { 10435 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10436 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 10437 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 10438 /* how to do that */ 10439 int digitlen = strlen(e->ring.callednum); 10440 char digit; 10441 int i; 10442 for (i = 0; i < digitlen; i++) { 10443 digit = e->ring.callednum[i]; 10444 { 10445 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 10446 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10447 } 10448 } 10449 } 10450 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10451 } 10452 } 10453 break; 10454 case PRI_EVENT_RING: 10455 crv = NULL; 10456 if (e->ring.channel == -1) 10457 chanpos = pri_find_empty_chan(pri, 1); 10458 else 10459 chanpos = pri_find_principle(pri, e->ring.channel); 10460 /* if no channel specified find one empty */ 10461 if (chanpos < 0) { 10462 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 10463 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10464 } else { 10465 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10466 if (pri->pvts[chanpos]->owner) { 10467 if (pri->pvts[chanpos]->call == e->ring.call) { 10468 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 10469 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10470 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10471 break; 10472 } else { 10473 /* This is where we handle initial glare */ 10474 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n", 10475 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 10476 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10477 chanpos = -1; 10478 } 10479 } 10480 if (chanpos > -1) 10481 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10482 } 10483 if ((chanpos < 0) && (e->ring.flexible)) 10484 chanpos = pri_find_empty_chan(pri, 1); 10485 if (chanpos > -1) { 10486 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10487 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 10488 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 10489 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 10490 if (crv) 10491 ast_mutex_lock(&crv->lock); 10492 if (!crv || crv->owner) { 10493 pri->pvts[chanpos]->call = NULL; 10494 if (crv) { 10495 if (crv->owner) 10496 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10497 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); 10498 } else 10499 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); 10500 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 10501 if (crv) 10502 ast_mutex_unlock(&crv->lock); 10503 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10504 break; 10505 } 10506 } 10507 pri->pvts[chanpos]->call = e->ring.call; 10508 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 10509 if (pri->pvts[chanpos]->use_callerid) { 10510 ast_shrink_phone_number(plancallingnum); 10511 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 10512 #ifdef PRI_ANI 10513 if (!ast_strlen_zero(e->ring.callingani)) { 10514 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 10515 ast_shrink_phone_number(plancallingani); 10516 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 10517 } else { 10518 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10519 } 10520 #endif 10521 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 10522 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 10523 } else { 10524 pri->pvts[chanpos]->cid_num[0] = '\0'; 10525 pri->pvts[chanpos]->cid_ani[0] = '\0'; 10526 pri->pvts[chanpos]->cid_name[0] = '\0'; 10527 pri->pvts[chanpos]->cid_ton = 0; 10528 } 10529 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 10530 e->ring.redirectingnum, e->ring.callingplanrdnis); 10531 /* If immediate=yes go to s|1 */ 10532 if (pri->pvts[chanpos]->immediate) { 10533 if (option_verbose > 2) 10534 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n"); 10535 pri->pvts[chanpos]->exten[0] = 's'; 10536 pri->pvts[chanpos]->exten[1] = '\0'; 10537 } 10538 /* Get called number */ 10539 else if (!ast_strlen_zero(e->ring.callednum)) { 10540 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 10541 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10542 } else if (pri->overlapdial) 10543 pri->pvts[chanpos]->exten[0] = '\0'; 10544 else { 10545 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 10546 pri->pvts[chanpos]->exten[0] = 's'; 10547 pri->pvts[chanpos]->exten[1] = '\0'; 10548 } 10549 /* Set DNID on all incoming calls -- even immediate */ 10550 if (!ast_strlen_zero(e->ring.callednum)) 10551 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 10552 /* No number yet, but received "sending complete"? */ 10553 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 10554 if (option_verbose > 2) 10555 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); 10556 pri->pvts[chanpos]->exten[0] = 's'; 10557 pri->pvts[chanpos]->exten[1] = '\0'; 10558 } 10559 10560 /* Make sure extension exists (or in overlap dial mode, can exist) */ 10561 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 10562 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10563 /* Setup law */ 10564 int law; 10565 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 10566 /* Set to audio mode at this point */ 10567 law = 1; 10568 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 10569 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 10570 } 10571 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 10572 law = DAHDI_LAW_ALAW; 10573 else 10574 law = DAHDI_LAW_MULAW; 10575 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 10576 if (res < 0) 10577 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 10578 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 10579 if (res < 0) 10580 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 10581 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 10582 /* Just announce proceeding */ 10583 pri->pvts[chanpos]->proceeding = 1; 10584 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 10585 } else { 10586 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 10587 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10588 else 10589 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 10590 } 10591 /* Get the use_callingpres state */ 10592 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 10593 10594 /* Start PBX */ 10595 if (!e->ring.complete 10596 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 10597 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 10598 /* 10599 * Release the PRI lock while we create the channel 10600 * so other threads can send D channel messages. 10601 */ 10602 ast_mutex_unlock(&pri->lock); 10603 if (crv) { 10604 /* Set bearer and such */ 10605 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 10606 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10607 pri->pvts[chanpos]->owner = &inuse; 10608 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 10609 } else { 10610 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 10611 } 10612 ast_mutex_lock(&pri->lock); 10613 if (c) { 10614 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10615 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10616 } 10617 if (e->ring.ani2 >= 0) { 10618 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10619 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10620 } 10621 10622 #ifdef SUPPORT_USERUSER 10623 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10624 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10625 } 10626 #endif 10627 10628 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10629 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10630 if (e->ring.redirectingreason >= 0) 10631 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10632 } 10633 10634 pthread_attr_init(&attr); 10635 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 10636 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { 10637 if (option_verbose > 2) 10638 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 10639 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 10640 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10641 } else { 10642 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10643 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10644 if (c) 10645 ast_hangup(c); 10646 else { 10647 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10648 pri->pvts[chanpos]->call = NULL; 10649 } 10650 } 10651 pthread_attr_destroy(&attr); 10652 } else { 10653 /* 10654 * Release the PRI lock while we create the channel 10655 * so other threads can send D channel messages. 10656 */ 10657 ast_mutex_unlock(&pri->lock); 10658 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 10659 ast_mutex_lock(&pri->lock); 10660 if (c) { 10661 /* 10662 * It is reasonably safe to set the following 10663 * channel variables while the PRI and DAHDI private 10664 * structures are locked. The PBX has not been 10665 * started yet and it is unlikely that any other task 10666 * will do anything with the channel we have just 10667 * created. 10668 */ 10669 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 10670 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 10671 } 10672 if (e->ring.ani2 >= 0) { 10673 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 10674 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 10675 } 10676 10677 #ifdef SUPPORT_USERUSER 10678 if (!ast_strlen_zero(e->ring.useruserinfo)) { 10679 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 10680 } 10681 #endif 10682 10683 if (e->ring.redirectingreason >= 0) 10684 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 10685 10686 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 10687 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 10688 } 10689 if (c && !ast_pbx_start(c)) { 10690 if (option_verbose > 2) 10691 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 10692 plancallingnum, pri->pvts[chanpos]->exten, 10693 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10694 10695 dahdi_enable_ec(pri->pvts[chanpos]); 10696 } else { 10697 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 10698 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 10699 if (c) { 10700 ast_hangup(c); 10701 } else { 10702 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 10703 pri->pvts[chanpos]->call = NULL; 10704 } 10705 } 10706 } 10707 } else { 10708 if (option_verbose > 2) 10709 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 10710 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 10711 pri->pvts[chanpos]->prioffset, pri->span); 10712 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 10713 pri->pvts[chanpos]->call = NULL; 10714 pri->pvts[chanpos]->exten[0] = '\0'; 10715 } 10716 if (crv) 10717 ast_mutex_unlock(&crv->lock); 10718 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10719 } else { 10720 if (e->ring.flexible) 10721 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 10722 else 10723 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 10724 } 10725 break; 10726 case PRI_EVENT_RINGING: 10727 chanpos = pri_find_principle(pri, e->ringing.channel); 10728 if (chanpos < 0) { 10729 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 10730 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10731 } else { 10732 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 10733 if (chanpos < 0) { 10734 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 10735 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 10736 } else { 10737 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10738 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10739 dahdi_enable_ec(pri->pvts[chanpos]); 10740 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 10741 pri->pvts[chanpos]->alerting = 1; 10742 } else 10743 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n"); 10744 #ifdef PRI_PROGRESS_MASK 10745 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10746 #else 10747 if (e->ringing.progress == 8) { 10748 #endif 10749 /* Now we can do call progress detection */ 10750 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10751 /* RINGING detection isn't required because we got ALERTING signal */ 10752 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 10753 pri->pvts[chanpos]->dsp_features = 0; 10754 } 10755 } 10756 10757 #ifdef SUPPORT_USERUSER 10758 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 10759 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10760 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10761 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 10762 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10763 } 10764 #endif 10765 10766 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10767 } 10768 } 10769 break; 10770 case PRI_EVENT_PROGRESS: 10771 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 10772 chanpos = pri_find_principle(pri, e->proceeding.channel); 10773 if (chanpos > -1) { 10774 #ifdef PRI_PROGRESS_MASK 10775 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 10776 #else 10777 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 10778 #endif 10779 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10780 10781 if (e->proceeding.cause > -1) { 10782 if (option_verbose > 2) 10783 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause); 10784 10785 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 10786 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 10787 if (pri->pvts[chanpos]->owner) { 10788 if (option_verbose > 2) 10789 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 10790 10791 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 10792 f.subclass = AST_CONTROL_BUSY; 10793 } 10794 } 10795 } 10796 10797 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10798 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 10799 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10800 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10801 #ifdef PRI_PROGRESS_MASK 10802 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10803 #else 10804 if (e->proceeding.progress == 8) { 10805 #endif 10806 /* Now we can do call progress detection */ 10807 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10808 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10809 pri->pvts[chanpos]->dsp_features = 0; 10810 } 10811 /* Bring voice path up */ 10812 f.subclass = AST_CONTROL_PROGRESS; 10813 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10814 } 10815 pri->pvts[chanpos]->progress = 1; 10816 pri->pvts[chanpos]->dialing = 0; 10817 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10818 } 10819 } 10820 break; 10821 case PRI_EVENT_PROCEEDING: 10822 chanpos = pri_find_principle(pri, e->proceeding.channel); 10823 if (chanpos > -1) { 10824 if (!pri->pvts[chanpos]->proceeding) { 10825 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10826 10827 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10828 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 10829 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 10830 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10831 #ifdef PRI_PROGRESS_MASK 10832 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 10833 #else 10834 if (e->proceeding.progress == 8) { 10835 #endif 10836 /* Now we can do call progress detection */ 10837 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10838 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10839 pri->pvts[chanpos]->dsp_features = 0; 10840 } 10841 /* Bring voice path up */ 10842 f.subclass = AST_CONTROL_PROGRESS; 10843 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 10844 } 10845 pri->pvts[chanpos]->proceeding = 1; 10846 pri->pvts[chanpos]->dialing = 0; 10847 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10848 } 10849 } 10850 break; 10851 case PRI_EVENT_FACNAME: 10852 chanpos = pri_find_principle(pri, e->facname.channel); 10853 if (chanpos < 0) { 10854 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 10855 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10856 } else { 10857 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 10858 if (chanpos < 0) { 10859 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 10860 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 10861 } else { 10862 /* Re-use *69 field for PRI */ 10863 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10864 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 10865 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 10866 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 10867 dahdi_enable_ec(pri->pvts[chanpos]); 10868 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10869 } 10870 } 10871 break; 10872 case PRI_EVENT_ANSWER: 10873 chanpos = pri_find_principle(pri, e->answer.channel); 10874 if (chanpos < 0) { 10875 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 10876 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10877 } else { 10878 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 10879 if (chanpos < 0) { 10880 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 10881 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 10882 } else { 10883 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10884 /* Now we can do call progress detection */ 10885 10886 /* We changed this so it turns on the DSP no matter what... progress or no progress. 10887 * By this time, we need DTMF detection and other features that were previously disabled 10888 * -- Matt F */ 10889 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 10890 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 10891 pri->pvts[chanpos]->dsp_features = 0; 10892 } 10893 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 10894 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n"); 10895 x = DAHDI_START; 10896 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 10897 if (res < 0) { 10898 if (errno != EINPROGRESS) { 10899 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 10900 } 10901 } 10902 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 10903 pri->pvts[chanpos]->dialing = 1; 10904 /* Send any "w" waited stuff */ 10905 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 10906 if (res < 0) { 10907 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 10908 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10909 } else 10910 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 10911 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 10912 } else if (pri->pvts[chanpos]->confirmanswer) { 10913 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 10914 } else { 10915 pri->pvts[chanpos]->dialing = 0; 10916 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 10917 /* Enable echo cancellation if it's not on already */ 10918 dahdi_enable_ec(pri->pvts[chanpos]); 10919 } 10920 10921 #ifdef SUPPORT_USERUSER 10922 if (!ast_strlen_zero(e->answer.useruserinfo)) { 10923 struct ast_channel *owner = pri->pvts[chanpos]->owner; 10924 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10925 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 10926 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10927 } 10928 #endif 10929 10930 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 10931 } 10932 } 10933 break; 10934 case PRI_EVENT_HANGUP: 10935 chanpos = pri_find_principle(pri, e->hangup.channel); 10936 if (chanpos < 0) { 10937 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 10938 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10939 } else { 10940 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 10941 if (chanpos > -1) { 10942 ast_mutex_lock(&pri->pvts[chanpos]->lock); 10943 if (!pri->pvts[chanpos]->alreadyhungup) { 10944 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 10945 pri->pvts[chanpos]->alreadyhungup = 1; 10946 if (pri->pvts[chanpos]->realcall) 10947 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 10948 else if (pri->pvts[chanpos]->owner) { 10949 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 10950 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 10951 switch (pri->pvts[chanpos]->owner->_state) { 10952 case AST_STATE_BUSY: 10953 case AST_STATE_UP: 10954 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10955 break; 10956 default: 10957 switch (e->hangup.cause) { 10958 case PRI_CAUSE_USER_BUSY: 10959 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 10960 break; 10961 case PRI_CAUSE_CALL_REJECTED: 10962 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 10963 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 10964 case PRI_CAUSE_SWITCH_CONGESTION: 10965 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 10966 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 10967 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 10968 break; 10969 default: 10970 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10971 } 10972 break; 10973 } 10974 } 10975 if (option_verbose > 2) 10976 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 10977 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 10978 } else { 10979 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 10980 pri->pvts[chanpos]->call = NULL; 10981 } 10982 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 10983 if (option_verbose > 2) 10984 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 10985 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 10986 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 10987 pri->pvts[chanpos]->resetting = 1; 10988 } 10989 if (e->hangup.aoc_units > -1) 10990 if (option_verbose > 2) 10991 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 10992 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 10993 10994 #ifdef SUPPORT_USERUSER 10995 if (pri->pvts[chanpos]->owner && !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 } else { 11005 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11006 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11007 } 11008 } 11009 break; 11010 #ifndef PRI_EVENT_HANGUP_REQ 11011 #error please update libpri 11012 #endif 11013 case PRI_EVENT_HANGUP_REQ: 11014 chanpos = pri_find_principle(pri, e->hangup.channel); 11015 if (chanpos < 0) { 11016 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11017 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11018 } else { 11019 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11020 if (chanpos > -1) { 11021 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11022 if (pri->pvts[chanpos]->realcall) 11023 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11024 else if (pri->pvts[chanpos]->owner) { 11025 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11026 switch (pri->pvts[chanpos]->owner->_state) { 11027 case AST_STATE_BUSY: 11028 case AST_STATE_UP: 11029 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11030 break; 11031 default: 11032 switch (e->hangup.cause) { 11033 case PRI_CAUSE_USER_BUSY: 11034 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11035 break; 11036 case PRI_CAUSE_CALL_REJECTED: 11037 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11038 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11039 case PRI_CAUSE_SWITCH_CONGESTION: 11040 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11041 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11042 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11043 break; 11044 default: 11045 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11046 } 11047 break; 11048 } 11049 if (option_verbose > 2) 11050 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); 11051 if (e->hangup.aoc_units > -1) 11052 if (option_verbose > 2) 11053 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11054 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11055 } else { 11056 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11057 pri->pvts[chanpos]->call = NULL; 11058 } 11059 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11060 if (option_verbose > 2) 11061 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11062 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11063 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11064 pri->pvts[chanpos]->resetting = 1; 11065 } 11066 11067 #ifdef SUPPORT_USERUSER 11068 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11069 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11070 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11071 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11072 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11073 } 11074 #endif 11075 11076 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11077 } else { 11078 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); 11079 } 11080 } 11081 break; 11082 case PRI_EVENT_HANGUP_ACK: 11083 chanpos = pri_find_principle(pri, e->hangup.channel); 11084 if (chanpos < 0) { 11085 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11086 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11087 } else { 11088 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11089 if (chanpos > -1) { 11090 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11091 pri->pvts[chanpos]->call = NULL; 11092 pri->pvts[chanpos]->resetting = 0; 11093 if (pri->pvts[chanpos]->owner) { 11094 if (option_verbose > 2) 11095 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); 11096 } 11097 11098 #ifdef SUPPORT_USERUSER 11099 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11100 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11101 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11102 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11103 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11104 } 11105 #endif 11106 11107 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11108 } 11109 } 11110 break; 11111 case PRI_EVENT_CONFIG_ERR: 11112 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11113 break; 11114 case PRI_EVENT_RESTART_ACK: 11115 chanpos = pri_find_principle(pri, e->restartack.channel); 11116 if (chanpos < 0) { 11117 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11118 channel number, so we have to figure it out... This must be why 11119 everybody resets exactly a channel at a time. */ 11120 for (x = 0; x < pri->numchans; x++) { 11121 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11122 chanpos = x; 11123 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11124 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11125 pri->pvts[chanpos]->prioffset, pri->span); 11126 if (pri->pvts[chanpos]->realcall) 11127 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11128 else if (pri->pvts[chanpos]->owner) { 11129 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11130 pri->pvts[chanpos]->prioffset, pri->span); 11131 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11132 } 11133 pri->pvts[chanpos]->resetting = 0; 11134 if (option_verbose > 2) 11135 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11136 pri->pvts[chanpos]->prioffset, pri->span); 11137 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11138 if (pri->resetting) 11139 pri_check_restart(pri); 11140 break; 11141 } 11142 } 11143 if (chanpos < 0) { 11144 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11145 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11146 } 11147 } else { 11148 if (pri->pvts[chanpos]) { 11149 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11150 if (pri->pvts[chanpos]->realcall) 11151 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11152 else if (pri->pvts[chanpos]->owner) { 11153 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11154 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11155 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11156 } 11157 pri->pvts[chanpos]->resetting = 0; 11158 if (option_verbose > 2) 11159 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11160 pri->pvts[chanpos]->prioffset, pri->span); 11161 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11162 if (pri->resetting) 11163 pri_check_restart(pri); 11164 } 11165 } 11166 break; 11167 case PRI_EVENT_SETUP_ACK: 11168 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11169 if (chanpos < 0) { 11170 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11171 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11172 } else { 11173 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11174 if (chanpos > -1) { 11175 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11176 pri->pvts[chanpos]->setup_ack = 1; 11177 /* Send any queued digits */ 11178 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11179 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11180 pri_information(pri->pri, pri->pvts[chanpos]->call, 11181 pri->pvts[chanpos]->dialdest[x]); 11182 } 11183 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11184 } else 11185 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11186 } 11187 break; 11188 case PRI_EVENT_NOTIFY: 11189 chanpos = pri_find_principle(pri, e->notify.channel); 11190 if (chanpos < 0) { 11191 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11192 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11193 } else { 11194 struct ast_frame f = { AST_FRAME_CONTROL, }; 11195 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11196 switch (e->notify.info) { 11197 case PRI_NOTIFY_REMOTE_HOLD: 11198 f.subclass = AST_CONTROL_HOLD; 11199 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11200 break; 11201 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11202 f.subclass = AST_CONTROL_UNHOLD; 11203 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11204 break; 11205 } 11206 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11207 } 11208 break; 11209 default: 11210 ast_log(LOG_DEBUG, "Event: %d\n", e->e); 11211 } 11212 } 11213 ast_mutex_unlock(&pri->lock); 11214 } 11215 /* Never reached */ 11216 return NULL; 11217 }
Definition at line 9724 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.
09725 { 09726 struct dahdi_pvt *p; 09727 p = pri->crvs; 09728 while (p) { 09729 if (p->channel == crv) 09730 return p; 09731 p = p->next; 09732 } 09733 return NULL; 09734 }
static int pri_find_dchan | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3403 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.
03404 { 03405 int oldslot = -1; 03406 struct pri *old; 03407 int newslot = -1; 03408 int x; 03409 old = pri->pri; 03410 for (x = 0; x < NUM_DCHANS; x++) { 03411 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03412 newslot = x; 03413 if (pri->dchans[x] == old) { 03414 oldslot = x; 03415 } 03416 } 03417 if (newslot < 0) { 03418 newslot = 0; 03419 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03420 pri->dchannels[newslot]); 03421 } 03422 if (old && (oldslot != newslot)) 03423 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03424 pri->dchannels[oldslot], pri->dchannels[newslot]); 03425 pri->pri = pri->dchans[newslot]; 03426 return 0; 03427 }
static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
int | backwards | |||
) | [static] |
Definition at line 9347 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().
09348 { 09349 int x; 09350 if (backwards) 09351 x = pri->numchans; 09352 else 09353 x = 0; 09354 for (;;) { 09355 if (backwards && (x < 0)) 09356 break; 09357 if (!backwards && (x >= pri->numchans)) 09358 break; 09359 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09360 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 09361 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09362 return x; 09363 } 09364 if (backwards) 09365 x--; 09366 else 09367 x++; 09368 } 09369 return -1; 09370 }
static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
int | channel | |||
) | [static] |
Definition at line 9737 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.
09738 { 09739 int x; 09740 int span = PRI_SPAN(channel); 09741 int spanfd; 09742 struct dahdi_params param; 09743 int principle = -1; 09744 int explicit = PRI_EXPLICIT(channel); 09745 channel = PRI_CHANNEL(channel); 09746 09747 if (!explicit) { 09748 spanfd = pri_active_dchan_fd(pri); 09749 memset(¶m, 0, sizeof(param)); 09750 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 09751 return -1; 09752 span = pris[param.spanno - 1].prilogicalspan; 09753 } 09754 09755 for (x = 0; x < pri->numchans; x++) { 09756 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 09757 principle = x; 09758 break; 09759 } 09760 } 09761 09762 return principle; 09763 }
static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
int | principle, | |||
q931_call * | c | |||
) | [static] |
Definition at line 9765 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.
09766 { 09767 int x; 09768 struct dahdi_pvt *crv; 09769 if (!c) { 09770 if (principle < 0) 09771 return -1; 09772 return principle; 09773 } 09774 if ((principle > -1) && 09775 (principle < pri->numchans) && 09776 (pri->pvts[principle]) && 09777 (pri->pvts[principle]->call == c)) 09778 return principle; 09779 /* First, check for other bearers */ 09780 for (x = 0; x < pri->numchans; x++) { 09781 if (!pri->pvts[x]) 09782 continue; 09783 if (pri->pvts[x]->call == c) { 09784 /* Found our call */ 09785 if (principle != x) { 09786 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 09787 09788 if (option_verbose > 2) 09789 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n", 09790 old->channel, new->channel); 09791 if (new->owner) { 09792 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 09793 old->channel, new->channel, new->channel); 09794 return -1; 09795 } 09796 /* Fix it all up now */ 09797 new->owner = old->owner; 09798 old->owner = NULL; 09799 if (new->owner) { 09800 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1); 09801 new->owner->tech_pvt = new; 09802 new->owner->fds[0] = new->subs[SUB_REAL].dfd; 09803 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 09804 old->subs[SUB_REAL].owner = NULL; 09805 } else 09806 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); 09807 new->call = old->call; 09808 old->call = NULL; 09809 09810 /* Copy any DSP that may be present */ 09811 new->dsp = old->dsp; 09812 new->dsp_features = old->dsp_features; 09813 old->dsp = NULL; 09814 old->dsp_features = 0; 09815 } 09816 return principle; 09817 } 09818 } 09819 /* Now check for a CRV with no bearer */ 09820 crv = pri->crvs; 09821 while (crv) { 09822 if (crv->call == c) { 09823 /* This is our match... Perform some basic checks */ 09824 if (crv->bearer) 09825 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 09826 else if (pri->pvts[principle]->owner) 09827 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 09828 else { 09829 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 09830 wakeup the potential sleeper */ 09831 dahdi_close_sub(crv, SUB_REAL); 09832 pri->pvts[principle]->call = crv->call; 09833 pri_assign_bearer(crv, pri, pri->pvts[principle]); 09834 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n", 09835 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 09836 pri->trunkgroup, crv->channel); 09837 wakeup_sub(crv, SUB_REAL, pri); 09838 } 09839 return principle; 09840 } 09841 crv = crv->next; 09842 } 09843 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 09844 return -1; 09845 }
Definition at line 1145 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pri::master, and dahdi_pvt::pri.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().
01146 { 01147 int res; 01148 /* Grab the lock first */ 01149 do { 01150 res = ast_mutex_trylock(&pri->lock); 01151 if (res) { 01152 DEADLOCK_AVOIDANCE(&pvt->lock); 01153 } 01154 } while (res); 01155 /* Then break the poll */ 01156 if (pri->master != AST_PTHREADT_NULL) 01157 pthread_kill(pri->master, SIGURG); 01158 return 0; 01159 }
Definition at line 10005 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.
10006 { 10007 int x; 10008 int redo; 10009 ast_mutex_unlock(&pri->lock); 10010 ast_mutex_lock(&p->lock); 10011 do { 10012 redo = 0; 10013 for (x = 0; x < 3; x++) { 10014 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) { 10015 redo++; 10016 DEADLOCK_AVOIDANCE(&p->lock); 10017 } 10018 if (p->subs[x].owner) { 10019 ast_queue_hangup(p->subs[x].owner); 10020 ast_mutex_unlock(&p->subs[x].owner->lock); 10021 } 10022 } 10023 } while (redo); 10024 ast_mutex_unlock(&p->lock); 10025 ast_mutex_lock(&pri->lock); 10026 return 0; 10027 }
static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3351 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.
Referenced by pri_dchannel().
03352 { 03353 int x; 03354 for (x = 0; x < NUM_DCHANS; x++) { 03355 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03356 return 1; 03357 } 03358 return 0; 03359 }
static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3374 of file chan_dahdi.c.
Referenced by handle_pri_show_span().
03375 { 03376 switch (level) { 03377 case 0: 03378 return "Primary"; 03379 case 1: 03380 return "Secondary"; 03381 case 2: 03382 return "Tertiary"; 03383 case 3: 03384 return "Quaternary"; 03385 default: 03386 return "<Unknown>"; 03387 } 03388 }
static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 416 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::pri.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().
00417 { 00418 ast_mutex_unlock(&pri->lock); 00419 }
static int pri_resolve_span | ( | int * | span, | |
int | channel, | |||
int | offset, | |||
struct dahdi_spaninfo * | si | |||
) | [static] |
Definition at line 8489 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().
08490 { 08491 int x; 08492 int trunkgroup; 08493 /* Get appropriate trunk group if there is one */ 08494 trunkgroup = pris[*span].mastertrunkgroup; 08495 if (trunkgroup) { 08496 /* Select a specific trunk group */ 08497 for (x = 0; x < NUM_SPANS; x++) { 08498 if (pris[x].trunkgroup == trunkgroup) { 08499 *span = x; 08500 return 0; 08501 } 08502 } 08503 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08504 *span = -1; 08505 } else { 08506 if (pris[*span].trunkgroup) { 08507 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08508 *span = -1; 08509 } else if (pris[*span].mastertrunkgroup) { 08510 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08511 *span = -1; 08512 } else { 08513 if (si->totalchans == 31) { 08514 /* E1 */ 08515 pris[*span].dchannels[0] = 16 + offset; 08516 } else if (si->totalchans == 24) { 08517 /* T1 or J1 */ 08518 pris[*span].dchannels[0] = 24 + offset; 08519 } else if (si->totalchans == 3) { 08520 /* BRI */ 08521 pris[*span].dchannels[0] = 3 + offset; 08522 } else { 08523 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); 08524 *span = -1; 08525 return 0; 08526 } 08527 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08528 pris[*span].offset = offset; 08529 pris[*span].span = *span + 1; 08530 } 08531 } 08532 return 0; 08533 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 12988 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, 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().
12989 { 12990 struct dahdi_pvt *tmp; 12991 int y; 12992 int found_pseudo = 0; 12993 char dahdichan[MAX_CHANLIST_LEN] = {}; 12994 12995 for (; v; v = v->next) { 12996 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 12997 continue; 12998 12999 /* Create the interface list */ 13000 if (!strcasecmp(v->name, "channel") 13001 #ifdef HAVE_PRI 13002 || !strcasecmp(v->name, "crv") 13003 #endif 13004 ) { 13005 int iscrv; 13006 if (skipchannels) 13007 continue; 13008 iscrv = !strcasecmp(v->name, "crv"); 13009 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 13010 return -1; 13011 } else if (!strcasecmp(v->name, "buffers")) { 13012 int res; 13013 char policy[21] = ""; 13014 13015 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 13016 if (res != 2) { 13017 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 13018 confp->chan.buf_no = numbufs; 13019 continue; 13020 } 13021 if (confp->chan.buf_no < 0) 13022 confp->chan.buf_no = numbufs; 13023 if (!strcasecmp(policy, "full")) { 13024 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 13025 } else if (!strcasecmp(policy, "immediate")) { 13026 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 13027 } else { 13028 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 13029 } 13030 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 13031 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 13032 if (v->name[0] == 'z' || v->name[0] == 'Z') { 13033 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 13034 } 13035 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 13036 if (ast_true(v->value)) 13037 confp->chan.usedistinctiveringdetection = 1; 13038 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 13039 if (ast_true(v->value)) 13040 distinctiveringaftercid = 1; 13041 } else if (!strcasecmp(v->name, "dring1context")) { 13042 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 13043 } else if (!strcasecmp(v->name, "dring2context")) { 13044 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 13045 } else if (!strcasecmp(v->name, "dring3context")) { 13046 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 13047 } else if (!strcasecmp(v->name, "dring1")) { 13048 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 13049 } else if (!strcasecmp(v->name, "dring2")) { 13050 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 13051 } else if (!strcasecmp(v->name, "dring3")) { 13052 sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 13053 } else if (!strcasecmp(v->name, "usecallerid")) { 13054 confp->chan.use_callerid = ast_true(v->value); 13055 } else if (!strcasecmp(v->name, "cidsignalling")) { 13056 if (!strcasecmp(v->value, "bell")) 13057 confp->chan.cid_signalling = CID_SIG_BELL; 13058 else if (!strcasecmp(v->value, "v23")) 13059 confp->chan.cid_signalling = CID_SIG_V23; 13060 else if (!strcasecmp(v->value, "dtmf")) 13061 confp->chan.cid_signalling = CID_SIG_DTMF; 13062 else if (!strcasecmp(v->value, "smdi")) 13063 confp->chan.cid_signalling = CID_SIG_SMDI; 13064 else if (!strcasecmp(v->value, "v23_jp")) 13065 confp->chan.cid_signalling = CID_SIG_V23_JP; 13066 else if (ast_true(v->value)) 13067 confp->chan.cid_signalling = CID_SIG_BELL; 13068 } else if (!strcasecmp(v->name, "cidstart")) { 13069 if (!strcasecmp(v->value, "ring")) 13070 confp->chan.cid_start = CID_START_RING; 13071 else if (!strcasecmp(v->value, "polarity")) 13072 confp->chan.cid_start = CID_START_POLARITY; 13073 else if (!strcasecmp(v->value, "dtmf")) 13074 confp->chan.cid_start = CID_START_DTMF_NOALERT; 13075 else if (ast_true(v->value)) 13076 confp->chan.cid_start = CID_START_RING; 13077 } else if (!strcasecmp(v->name, "threewaycalling")) { 13078 confp->chan.threewaycalling = ast_true(v->value); 13079 } else if (!strcasecmp(v->name, "cancallforward")) { 13080 confp->chan.cancallforward = ast_true(v->value); 13081 } else if (!strcasecmp(v->name, "relaxdtmf")) { 13082 if (ast_true(v->value)) 13083 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 13084 else 13085 confp->chan.dtmfrelax = 0; 13086 } else if (!strcasecmp(v->name, "mailbox")) { 13087 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 13088 } else if (!strcasecmp(v->name, "hasvoicemail")) { 13089 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 13090 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 13091 } 13092 } else if (!strcasecmp(v->name, "adsi")) { 13093 confp->chan.adsi = ast_true(v->value); 13094 } else if (!strcasecmp(v->name, "usesmdi")) { 13095 confp->chan.use_smdi = ast_true(v->value); 13096 } else if (!strcasecmp(v->name, "smdiport")) { 13097 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 13098 } else if (!strcasecmp(v->name, "transfer")) { 13099 confp->chan.transfer = ast_true(v->value); 13100 } else if (!strcasecmp(v->name, "canpark")) { 13101 confp->chan.canpark = ast_true(v->value); 13102 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 13103 confp->chan.echocanbridged = ast_true(v->value); 13104 } else if (!strcasecmp(v->name, "busydetect")) { 13105 confp->chan.busydetect = ast_true(v->value); 13106 } else if (!strcasecmp(v->name, "busycount")) { 13107 confp->chan.busycount = atoi(v->value); 13108 } else if (!strcasecmp(v->name, "silencethreshold")) { 13109 confp->chan.silencethreshold = atoi(v->value); 13110 } else if (!strcasecmp(v->name, "busycompare")) { 13111 confp->chan.busycompare = ast_true(v->value); 13112 } else if (!strcasecmp(v->name, "busypattern")) { 13113 int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 13114 if (count == 1) 13115 confp->chan.busyquietlength = 0; 13116 else if (count < 1) 13117 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 13118 } else if (!strcasecmp(v->name, "busyfuzziness")) { 13119 confp->chan.busyfuzziness = atoi(v->value); 13120 } else if (!strcasecmp(v->name, "callprogress")) { 13121 if (ast_true(v->value)) 13122 confp->chan.callprogress |= 1; 13123 else 13124 confp->chan.callprogress &= ~1; 13125 } else if (!strcasecmp(v->name, "faxdetect")) { 13126 if (!strcasecmp(v->value, "incoming")) { 13127 confp->chan.callprogress |= 4; 13128 confp->chan.callprogress &= ~2; 13129 } else if (!strcasecmp(v->value, "outgoing")) { 13130 confp->chan.callprogress &= ~4; 13131 confp->chan.callprogress |= 2; 13132 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 13133 confp->chan.callprogress |= 6; 13134 else 13135 confp->chan.callprogress &= ~6; 13136 } else if (!strcasecmp(v->name, "echocancel")) { 13137 if (!ast_strlen_zero(v->value)) { 13138 y = atoi(v->value); 13139 } else 13140 y = 0; 13141 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 13142 confp->chan.echocancel = y; 13143 else { 13144 confp->chan.echocancel = ast_true(v->value); 13145 if (confp->chan.echocancel) 13146 confp->chan.echocancel=128; 13147 } 13148 } else if (!strcasecmp(v->name, "echotraining")) { 13149 if (sscanf(v->value, "%30d", &y) == 1) { 13150 if ((y < 10) || (y > 4000)) { 13151 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 13152 } else { 13153 confp->chan.echotraining = y; 13154 } 13155 } else if (ast_true(v->value)) { 13156 confp->chan.echotraining = 400; 13157 } else 13158 confp->chan.echotraining = 0; 13159 } else if (!strcasecmp(v->name, "hidecallerid")) { 13160 confp->chan.hidecallerid = ast_true(v->value); 13161 } else if (!strcasecmp(v->name, "hidecalleridname")) { 13162 confp->chan.hidecalleridname = ast_true(v->value); 13163 } else if (!strcasecmp(v->name, "pulsedial")) { 13164 confp->chan.pulse = ast_true(v->value); 13165 } else if (!strcasecmp(v->name, "callreturn")) { 13166 confp->chan.callreturn = ast_true(v->value); 13167 } else if (!strcasecmp(v->name, "callwaiting")) { 13168 confp->chan.callwaiting = ast_true(v->value); 13169 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 13170 confp->chan.callwaitingcallerid = ast_true(v->value); 13171 } else if (!strcasecmp(v->name, "context")) { 13172 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 13173 } else if (!strcasecmp(v->name, "language")) { 13174 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 13175 } else if (!strcasecmp(v->name, "progzone")) { 13176 ast_copy_string(progzone, v->value, sizeof(progzone)); 13177 } else if (!strcasecmp(v->name, "mohinterpret") 13178 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 13179 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 13180 } else if (!strcasecmp(v->name, "mohsuggest")) { 13181 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 13182 } else if (!strcasecmp(v->name, "stripmsd")) { 13183 confp->chan.stripmsd = atoi(v->value); 13184 } else if (!strcasecmp(v->name, "jitterbuffers")) { 13185 numbufs = atoi(v->value); 13186 } else if (!strcasecmp(v->name, "group")) { 13187 confp->chan.group = ast_get_group(v->value); 13188 } else if (!strcasecmp(v->name, "callgroup")) { 13189 confp->chan.callgroup = ast_get_group(v->value); 13190 } else if (!strcasecmp(v->name, "pickupgroup")) { 13191 confp->chan.pickupgroup = ast_get_group(v->value); 13192 } else if (!strcasecmp(v->name, "immediate")) { 13193 confp->chan.immediate = ast_true(v->value); 13194 } else if (!strcasecmp(v->name, "transfertobusy")) { 13195 confp->chan.transfertobusy = ast_true(v->value); 13196 } else if (!strcasecmp(v->name, "rxgain")) { 13197 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 13198 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 13199 } 13200 } else if (!strcasecmp(v->name, "txgain")) { 13201 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 13202 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 13203 } 13204 } else if (!strcasecmp(v->name, "tonezone")) { 13205 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 13206 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 13207 } 13208 } else if (!strcasecmp(v->name, "callerid")) { 13209 if (!strcasecmp(v->value, "asreceived")) { 13210 confp->chan.cid_num[0] = '\0'; 13211 confp->chan.cid_name[0] = '\0'; 13212 } else { 13213 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 13214 } 13215 } else if (!strcasecmp(v->name, "fullname")) { 13216 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 13217 } else if (!strcasecmp(v->name, "cid_number")) { 13218 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 13219 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 13220 confp->chan.dahditrcallerid = ast_true(v->value); 13221 if (strstr(v->name, "zap")) { 13222 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 13223 } 13224 } else if (!strcasecmp(v->name, "restrictcid")) { 13225 confp->chan.restrictcid = ast_true(v->value); 13226 } else if (!strcasecmp(v->name, "usecallingpres")) { 13227 confp->chan.use_callingpres = ast_true(v->value); 13228 } else if (!strcasecmp(v->name, "accountcode")) { 13229 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 13230 } else if (!strcasecmp(v->name, "amaflags")) { 13231 y = ast_cdr_amaflags2int(v->value); 13232 if (y < 0) 13233 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 13234 else 13235 confp->chan.amaflags = y; 13236 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 13237 confp->chan.polarityonanswerdelay = atoi(v->value); 13238 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 13239 confp->chan.answeronpolarityswitch = ast_true(v->value); 13240 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 13241 confp->chan.hanguponpolarityswitch = ast_true(v->value); 13242 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 13243 confp->chan.sendcalleridafter = atoi(v->value); 13244 } else if (reload != 1) { 13245 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 13246 confp->chan.outsigmod = -1; 13247 if (!strcasecmp(v->value, "em")) { 13248 confp->chan.sig = SIG_EM; 13249 } else if (!strcasecmp(v->value, "em_e1")) { 13250 confp->chan.sig = SIG_EM_E1; 13251 } else if (!strcasecmp(v->value, "em_w")) { 13252 confp->chan.sig = SIG_EMWINK; 13253 confp->chan.radio = 0; 13254 } else if (!strcasecmp(v->value, "fxs_ls")) { 13255 confp->chan.sig = SIG_FXSLS; 13256 confp->chan.radio = 0; 13257 } else if (!strcasecmp(v->value, "fxs_gs")) { 13258 confp->chan.sig = SIG_FXSGS; 13259 confp->chan.radio = 0; 13260 } else if (!strcasecmp(v->value, "fxs_ks")) { 13261 confp->chan.sig = SIG_FXSKS; 13262 confp->chan.radio = 0; 13263 } else if (!strcasecmp(v->value, "fxo_ls")) { 13264 confp->chan.sig = SIG_FXOLS; 13265 confp->chan.radio = 0; 13266 } else if (!strcasecmp(v->value, "fxo_gs")) { 13267 confp->chan.sig = SIG_FXOGS; 13268 confp->chan.radio = 0; 13269 } else if (!strcasecmp(v->value, "fxo_ks")) { 13270 confp->chan.sig = SIG_FXOKS; 13271 confp->chan.radio = 0; 13272 } else if (!strcasecmp(v->value, "fxs_rx")) { 13273 confp->chan.sig = SIG_FXSKS; 13274 confp->chan.radio = 1; 13275 } else if (!strcasecmp(v->value, "fxo_rx")) { 13276 confp->chan.sig = SIG_FXOLS; 13277 confp->chan.radio = 1; 13278 } else if (!strcasecmp(v->value, "fxs_tx")) { 13279 confp->chan.sig = SIG_FXSLS; 13280 confp->chan.radio = 1; 13281 } else if (!strcasecmp(v->value, "fxo_tx")) { 13282 confp->chan.sig = SIG_FXOGS; 13283 confp->chan.radio = 1; 13284 } else if (!strcasecmp(v->value, "em_rx")) { 13285 confp->chan.sig = SIG_EM; 13286 confp->chan.radio = 1; 13287 } else if (!strcasecmp(v->value, "em_tx")) { 13288 confp->chan.sig = SIG_EM; 13289 confp->chan.radio = 1; 13290 } else if (!strcasecmp(v->value, "em_rxtx")) { 13291 confp->chan.sig = SIG_EM; 13292 confp->chan.radio = 2; 13293 } else if (!strcasecmp(v->value, "em_txrx")) { 13294 confp->chan.sig = SIG_EM; 13295 confp->chan.radio = 2; 13296 } else if (!strcasecmp(v->value, "sf")) { 13297 confp->chan.sig = SIG_SF; 13298 confp->chan.radio = 0; 13299 } else if (!strcasecmp(v->value, "sf_w")) { 13300 confp->chan.sig = SIG_SFWINK; 13301 confp->chan.radio = 0; 13302 } else if (!strcasecmp(v->value, "sf_featd")) { 13303 confp->chan.sig = SIG_FEATD; 13304 confp->chan.radio = 0; 13305 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13306 confp->chan.sig = SIG_FEATDMF; 13307 confp->chan.radio = 0; 13308 } else if (!strcasecmp(v->value, "sf_featb")) { 13309 confp->chan.sig = SIG_SF_FEATB; 13310 confp->chan.radio = 0; 13311 } else if (!strcasecmp(v->value, "sf")) { 13312 confp->chan.sig = SIG_SF; 13313 confp->chan.radio = 0; 13314 } else if (!strcasecmp(v->value, "sf_rx")) { 13315 confp->chan.sig = SIG_SF; 13316 confp->chan.radio = 1; 13317 } else if (!strcasecmp(v->value, "sf_tx")) { 13318 confp->chan.sig = SIG_SF; 13319 confp->chan.radio = 1; 13320 } else if (!strcasecmp(v->value, "sf_rxtx")) { 13321 confp->chan.sig = SIG_SF; 13322 confp->chan.radio = 2; 13323 } else if (!strcasecmp(v->value, "sf_txrx")) { 13324 confp->chan.sig = SIG_SF; 13325 confp->chan.radio = 2; 13326 } else if (!strcasecmp(v->value, "featd")) { 13327 confp->chan.sig = SIG_FEATD; 13328 confp->chan.radio = 0; 13329 } else if (!strcasecmp(v->value, "featdmf")) { 13330 confp->chan.sig = SIG_FEATDMF; 13331 confp->chan.radio = 0; 13332 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13333 confp->chan.sig = SIG_FEATDMF_TA; 13334 confp->chan.radio = 0; 13335 } else if (!strcasecmp(v->value, "e911")) { 13336 confp->chan.sig = SIG_E911; 13337 confp->chan.radio = 0; 13338 } else if (!strcasecmp(v->value, "fgccama")) { 13339 confp->chan.sig = SIG_FGC_CAMA; 13340 confp->chan.radio = 0; 13341 } else if (!strcasecmp(v->value, "fgccamamf")) { 13342 confp->chan.sig = SIG_FGC_CAMAMF; 13343 confp->chan.radio = 0; 13344 } else if (!strcasecmp(v->value, "featb")) { 13345 confp->chan.sig = SIG_FEATB; 13346 confp->chan.radio = 0; 13347 #ifdef HAVE_OPENR2 13348 } else if (!strcasecmp(v->value, "mfcr2")) { 13349 confp->chan.sig = SIG_MFCR2; 13350 #endif 13351 #ifdef HAVE_PRI 13352 } else if (!strcasecmp(v->value, "pri_net")) { 13353 confp->chan.radio = 0; 13354 confp->chan.sig = SIG_PRI; 13355 confp->pri.nodetype = PRI_NETWORK; 13356 } else if (!strcasecmp(v->value, "pri_cpe")) { 13357 confp->chan.sig = SIG_PRI; 13358 confp->chan.radio = 0; 13359 confp->pri.nodetype = PRI_CPE; 13360 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 13361 confp->chan.sig = SIG_GR303FXOKS; 13362 confp->chan.radio = 0; 13363 confp->pri.nodetype = PRI_NETWORK; 13364 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 13365 confp->chan.sig = SIG_GR303FXSKS; 13366 confp->chan.radio = 0; 13367 confp->pri.nodetype = PRI_CPE; 13368 #endif 13369 } else { 13370 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13371 } 13372 } else if (!strcasecmp(v->name, "outsignalling")) { 13373 if (!strcasecmp(v->value, "em")) { 13374 confp->chan.outsigmod = SIG_EM; 13375 } else if (!strcasecmp(v->value, "em_e1")) { 13376 confp->chan.outsigmod = SIG_EM_E1; 13377 } else if (!strcasecmp(v->value, "em_w")) { 13378 confp->chan.outsigmod = SIG_EMWINK; 13379 } else if (!strcasecmp(v->value, "sf")) { 13380 confp->chan.outsigmod = SIG_SF; 13381 } else if (!strcasecmp(v->value, "sf_w")) { 13382 confp->chan.outsigmod = SIG_SFWINK; 13383 } else if (!strcasecmp(v->value, "sf_featd")) { 13384 confp->chan.outsigmod = SIG_FEATD; 13385 } else if (!strcasecmp(v->value, "sf_featdmf")) { 13386 confp->chan.outsigmod = SIG_FEATDMF; 13387 } else if (!strcasecmp(v->value, "sf_featb")) { 13388 confp->chan.outsigmod = SIG_SF_FEATB; 13389 } else if (!strcasecmp(v->value, "sf")) { 13390 confp->chan.outsigmod = SIG_SF; 13391 } else if (!strcasecmp(v->value, "featd")) { 13392 confp->chan.outsigmod = SIG_FEATD; 13393 } else if (!strcasecmp(v->value, "featdmf")) { 13394 confp->chan.outsigmod = SIG_FEATDMF; 13395 } else if (!strcasecmp(v->value, "featdmf_ta")) { 13396 confp->chan.outsigmod = SIG_FEATDMF_TA; 13397 } else if (!strcasecmp(v->value, "e911")) { 13398 confp->chan.outsigmod = SIG_E911; 13399 } else if (!strcasecmp(v->value, "fgccama")) { 13400 confp->chan.outsigmod = SIG_FGC_CAMA; 13401 } else if (!strcasecmp(v->value, "fgccamamf")) { 13402 confp->chan.outsigmod = SIG_FGC_CAMAMF; 13403 } else if (!strcasecmp(v->value, "featb")) { 13404 confp->chan.outsigmod = SIG_FEATB; 13405 } else { 13406 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 13407 } 13408 #ifdef HAVE_PRI 13409 } else if (!strcasecmp(v->name, "pridialplan")) { 13410 if (!strcasecmp(v->value, "national")) { 13411 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 13412 } else if (!strcasecmp(v->value, "unknown")) { 13413 confp->pri.dialplan = PRI_UNKNOWN + 1; 13414 } else if (!strcasecmp(v->value, "private")) { 13415 confp->pri.dialplan = PRI_PRIVATE + 1; 13416 } else if (!strcasecmp(v->value, "international")) { 13417 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 13418 } else if (!strcasecmp(v->value, "local")) { 13419 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 13420 } else if (!strcasecmp(v->value, "dynamic")) { 13421 confp->pri.dialplan = -1; 13422 } else { 13423 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13424 } 13425 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 13426 if (!strcasecmp(v->value, "national")) { 13427 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 13428 } else if (!strcasecmp(v->value, "unknown")) { 13429 confp->pri.localdialplan = PRI_UNKNOWN + 1; 13430 } else if (!strcasecmp(v->value, "private")) { 13431 confp->pri.localdialplan = PRI_PRIVATE + 1; 13432 } else if (!strcasecmp(v->value, "international")) { 13433 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 13434 } else if (!strcasecmp(v->value, "local")) { 13435 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 13436 } else if (!strcasecmp(v->value, "dynamic")) { 13437 confp->pri.localdialplan = -1; 13438 } else { 13439 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 13440 } 13441 } else if (!strcasecmp(v->name, "switchtype")) { 13442 if (!strcasecmp(v->value, "national")) 13443 confp->pri.switchtype = PRI_SWITCH_NI2; 13444 else if (!strcasecmp(v->value, "ni1")) 13445 confp->pri.switchtype = PRI_SWITCH_NI1; 13446 else if (!strcasecmp(v->value, "dms100")) 13447 confp->pri.switchtype = PRI_SWITCH_DMS100; 13448 else if (!strcasecmp(v->value, "4ess")) 13449 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 13450 else if (!strcasecmp(v->value, "5ess")) 13451 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 13452 else if (!strcasecmp(v->value, "euroisdn")) 13453 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 13454 else if (!strcasecmp(v->value, "qsig")) 13455 confp->pri.switchtype = PRI_SWITCH_QSIG; 13456 else { 13457 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 13458 return -1; 13459 } 13460 } else if (!strcasecmp(v->name, "nsf")) { 13461 if (!strcasecmp(v->value, "sdn")) 13462 confp->pri.nsf = PRI_NSF_SDN; 13463 else if (!strcasecmp(v->value, "megacom")) 13464 confp->pri.nsf = PRI_NSF_MEGACOM; 13465 else if (!strcasecmp(v->value, "tollfreemegacom")) 13466 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 13467 else if (!strcasecmp(v->value, "accunet")) 13468 confp->pri.nsf = PRI_NSF_ACCUNET; 13469 else if (!strcasecmp(v->value, "none")) 13470 confp->pri.nsf = PRI_NSF_NONE; 13471 else { 13472 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 13473 confp->pri.nsf = PRI_NSF_NONE; 13474 } 13475 } else if (!strcasecmp(v->name, "priindication")) { 13476 if (!strcasecmp(v->value, "outofband")) 13477 confp->chan.priindication_oob = 1; 13478 else if (!strcasecmp(v->value, "inband")) 13479 confp->chan.priindication_oob = 0; 13480 else 13481 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 13482 v->value, v->lineno); 13483 } else if (!strcasecmp(v->name, "priexclusive")) { 13484 confp->chan.priexclusive = ast_true(v->value); 13485 } else if (!strcasecmp(v->name, "internationalprefix")) { 13486 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 13487 } else if (!strcasecmp(v->name, "nationalprefix")) { 13488 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 13489 } else if (!strcasecmp(v->name, "localprefix")) { 13490 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 13491 } else if (!strcasecmp(v->name, "privateprefix")) { 13492 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 13493 } else if (!strcasecmp(v->name, "unknownprefix")) { 13494 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 13495 } else if (!strcasecmp(v->name, "resetinterval")) { 13496 if (!strcasecmp(v->value, "never")) 13497 confp->pri.resetinterval = -1; 13498 else if (atoi(v->value) >= 60) 13499 confp->pri.resetinterval = atoi(v->value); 13500 else 13501 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 13502 v->value, v->lineno); 13503 } else if (!strcasecmp(v->name, "minunused")) { 13504 confp->pri.minunused = atoi(v->value); 13505 } else if (!strcasecmp(v->name, "minidle")) { 13506 confp->pri.minidle = atoi(v->value); 13507 } else if (!strcasecmp(v->name, "idleext")) { 13508 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 13509 } else if (!strcasecmp(v->name, "idledial")) { 13510 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 13511 } else if (!strcasecmp(v->name, "overlapdial")) { 13512 if (ast_true(v->value)) { 13513 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13514 } else if (!strcasecmp(v->value, "incoming")) { 13515 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 13516 } else if (!strcasecmp(v->value, "outgoing")) { 13517 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 13518 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 13519 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 13520 } else { 13521 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 13522 } 13523 #ifdef HAVE_PRI_INBANDDISCONNECT 13524 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 13525 confp->pri.inbanddisconnect = ast_true(v->value); 13526 #endif 13527 } else if (!strcasecmp(v->name, "pritimer")) { 13528 #ifdef PRI_GETSET_TIMERS 13529 char tmp[20]; 13530 char *timerc; 13531 char *c; 13532 int timer; 13533 int timeridx; 13534 13535 ast_copy_string(tmp, v->value, sizeof(tmp)); 13536 c = tmp; 13537 timerc = strsep(&c, ","); 13538 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 13539 timeridx = pri_timer2idx(timerc); 13540 timer = atoi(c); 13541 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 13542 ast_log(LOG_WARNING, 13543 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 13544 v->lineno); 13545 } else if (!timer) { 13546 ast_log(LOG_WARNING, 13547 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 13548 c, timerc, v->lineno); 13549 } else { 13550 pritimers[timeridx] = timer; 13551 } 13552 } else { 13553 ast_log(LOG_WARNING, 13554 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 13555 v->value, v->lineno); 13556 } 13557 #endif /* PRI_GETSET_TIMERS */ 13558 } else if (!strcasecmp(v->name, "facilityenable")) { 13559 confp->pri.facilityenable = ast_true(v->value); 13560 #endif /* HAVE_PRI */ 13561 #ifdef HAVE_OPENR2 13562 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 13563 ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file)); 13564 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); 13565 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 13566 ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir)); 13567 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 13568 mfcr2_cur_variant = openr2_proto_get_variant(v->value); 13569 if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) { 13570 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno); 13571 } 13572 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 13573 mfcr2_cur_mfback_timeout = atoi(v->value); 13574 if (!mfcr2_cur_mfback_timeout) { 13575 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 13576 mfcr2_cur_mfback_timeout = -1; 13577 } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) { 13578 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 13579 } 13580 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 13581 mfcr2_cur_metering_pulse_timeout = atoi(v->value); 13582 if (mfcr2_cur_metering_pulse_timeout > 500) { 13583 ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n"); 13584 } 13585 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2 13586 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) { 13587 mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0; 13588 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) { 13589 mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0; 13590 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) { 13591 mfcr2_cur_dtmf_time_on = atoi(v->value); 13592 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) { 13593 mfcr2_cur_dtmf_time_off = atoi(v->value); 13594 #endif 13595 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 13596 mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0; 13597 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) { 13598 mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0; 13599 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 13600 mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0; 13601 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 13602 mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0; 13603 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 13604 mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0; 13605 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 13606 mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0; 13607 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 13608 mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0; 13609 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 13610 mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0; 13611 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 13612 mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0; 13613 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 13614 mfcr2_cur_max_ani = atoi(v->value); 13615 if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) { 13616 mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1; 13617 } 13618 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 13619 mfcr2_cur_max_dnis = atoi(v->value); 13620 if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) { 13621 mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1; 13622 } 13623 } else if (!strcasecmp(v->name, "mfcr2_category")) { 13624 mfcr2_cur_category = openr2_proto_get_category(v->value); 13625 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) { 13626 mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 13627 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 13628 v->value, v->lineno); 13629 } 13630 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 13631 openr2_log_level_t tmplevel; 13632 char *toklevel = NULL; 13633 char *saveptr = NULL; 13634 char *logval = ast_strdupa(v->value); 13635 toklevel = strtok_r(logval, ",", &saveptr); 13636 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13637 ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno); 13638 } else if (OR2_LOG_NOTHING == tmplevel) { 13639 mfcr2_cur_loglevel = tmplevel; 13640 } else { 13641 mfcr2_cur_loglevel |= tmplevel; 13642 while ((toklevel = strtok_r(NULL, ",", &saveptr))) { 13643 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) { 13644 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno); 13645 continue; 13646 } 13647 mfcr2_cur_loglevel |= tmplevel; 13648 } 13649 } 13650 #endif /* HAVE_OPENR2 */ 13651 13652 } else if (!strcasecmp(v->name, "cadence")) { 13653 /* setup to scan our argument */ 13654 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 13655 int i; 13656 struct dahdi_ring_cadence new_cadence; 13657 int cid_location = -1; 13658 int firstcadencepos = 0; 13659 char original_args[80]; 13660 int cadence_is_ok = 1; 13661 13662 ast_copy_string(original_args, v->value, sizeof(original_args)); 13663 /* 16 cadences allowed (8 pairs) */ 13664 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]); 13665 13666 /* Cadence must be even (on/off) */ 13667 if (element_count % 2 == 1) { 13668 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 13669 cadence_is_ok = 0; 13670 } 13671 13672 /* Ring cadences cannot be negative */ 13673 for (i = 0; i < element_count; i++) { 13674 if (c[i] == 0) { 13675 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 13676 cadence_is_ok = 0; 13677 break; 13678 } else if (c[i] < 0) { 13679 if (i % 2 == 1) { 13680 /* Silence duration, negative possibly okay */ 13681 if (cid_location == -1) { 13682 cid_location = i; 13683 c[i] *= -1; 13684 } else { 13685 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 13686 cadence_is_ok = 0; 13687 break; 13688 } 13689 } else { 13690 if (firstcadencepos == 0) { 13691 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 13692 /* duration will be passed negative to the DAHDI driver */ 13693 } else { 13694 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 13695 cadence_is_ok = 0; 13696 break; 13697 } 13698 } 13699 } 13700 } 13701 13702 /* Substitute our scanned cadence */ 13703 for (i = 0; i < 16; i++) { 13704 new_cadence.ringcadence[i] = c[i]; 13705 } 13706 13707 if (cadence_is_ok) { 13708 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 13709 if (element_count < 2) { 13710 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 13711 } else { 13712 if (cid_location == -1) { 13713 /* user didn't say; default to first pause */ 13714 cid_location = 1; 13715 } else { 13716 /* convert element_index to cidrings value */ 13717 cid_location = (cid_location + 1) / 2; 13718 } 13719 /* ---we like their cadence; try to install it--- */ 13720 if (!user_has_defined_cadences++) 13721 /* this is the first user-defined cadence; clear the default user cadences */ 13722 num_cadence = 0; 13723 if ((num_cadence+1) >= NUM_CADENCE_MAX) 13724 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 13725 else { 13726 cadences[num_cadence] = new_cadence; 13727 cidrings[num_cadence++] = cid_location; 13728 if (option_verbose > 2) 13729 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 13730 } 13731 } 13732 } 13733 } else if (!strcasecmp(v->name, "ringtimeout")) { 13734 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 13735 } else if (!strcasecmp(v->name, "prewink")) { 13736 confp->timing.prewinktime = atoi(v->value); 13737 } else if (!strcasecmp(v->name, "preflash")) { 13738 confp->timing.preflashtime = atoi(v->value); 13739 } else if (!strcasecmp(v->name, "wink")) { 13740 confp->timing.winktime = atoi(v->value); 13741 } else if (!strcasecmp(v->name, "flash")) { 13742 confp->timing.flashtime = atoi(v->value); 13743 } else if (!strcasecmp(v->name, "start")) { 13744 confp->timing.starttime = atoi(v->value); 13745 } else if (!strcasecmp(v->name, "rxwink")) { 13746 confp->timing.rxwinktime = atoi(v->value); 13747 } else if (!strcasecmp(v->name, "rxflash")) { 13748 confp->timing.rxflashtime = atoi(v->value); 13749 } else if (!strcasecmp(v->name, "debounce")) { 13750 confp->timing.debouncetime = atoi(v->value); 13751 } else if (!strcasecmp(v->name, "toneduration")) { 13752 int toneduration; 13753 int ctlfd; 13754 int res; 13755 struct dahdi_dialparams dps; 13756 13757 ctlfd = open(DAHDI_FILE_CTL, O_RDWR); 13758 13759 if (ctlfd == -1) { 13760 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n"); 13761 return -1; 13762 } 13763 13764 toneduration = atoi(v->value); 13765 if (toneduration > -1) { 13766 memset(&dps, 0, sizeof(dps)); 13767 13768 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 13769 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 13770 if (res < 0) { 13771 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 13772 return -1; 13773 } 13774 } 13775 close(ctlfd); 13776 } else if (!strcasecmp(v->name, "defaultcic")) { 13777 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 13778 } else if (!strcasecmp(v->name, "defaultozz")) { 13779 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 13780 } else if (!strcasecmp(v->name, "dtmfcidlevel")) { 13781 dtmfcid_level = atoi(v->value); 13782 } 13783 } else if (!skipchannels) 13784 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name); 13785 } 13786 if (dahdichan[0]) { 13787 /* The user has set 'dahdichan' */ 13788 /*< \todo pass proper line number instead of 0 */ 13789 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 13790 return -1; 13791 } 13792 } 13793 /*< \todo why check for the pseudo in the per-channel section. 13794 * Any actual use for manual setup of the pseudo channel? */ 13795 if (!found_pseudo && reload != 1) { 13796 /* use the default configuration for a channel, so 13797 that any settings from real configured channels 13798 don't "leak" into the pseudo channel config 13799 */ 13800 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13801 13802 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 13803 13804 if (tmp) { 13805 if (option_verbose > 2) 13806 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 13807 } else { 13808 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 13809 } 13810 } 13811 return 0; 13812 }
static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10029 of file chan_dahdi.c.
Referenced by __oh323_new().
10030 { 10031 switch (redirectingreason) { 10032 case 0: 10033 return "UNKNOWN"; 10034 case 1: 10035 return "BUSY"; 10036 case 2: 10037 return "NO_REPLY"; 10038 case 0xF: 10039 return "UNCONDITIONAL"; 10040 default: 10041 return "NOREDIRECT"; 10042 } 10043 }
static int reload | ( | void | ) | [static] |
Definition at line 14146 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
14147 { 14148 int res = 0; 14149 14150 res = setup_dahdi(1); 14151 if (res) { 14152 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 14153 return -1; 14154 } 14155 return 0; 14156 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2280 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
02281 { 02282 p->confno = -1; 02283 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 02284 if (p->subs[SUB_REAL].dfd > -1) { 02285 struct dahdi_confinfo zi; 02286 02287 memset(&zi, 0, sizeof(zi)); 02288 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 02289 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 02290 } 02291 return 0; 02292 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 8446 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().
08447 { 08448 pthread_attr_t attr; 08449 pthread_attr_init(&attr); 08450 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08451 /* If we're supposed to be stopped -- stay stopped */ 08452 if (monitor_thread == AST_PTHREADT_STOP) 08453 return 0; 08454 ast_mutex_lock(&monlock); 08455 if (monitor_thread == pthread_self()) { 08456 ast_mutex_unlock(&monlock); 08457 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08458 return -1; 08459 } 08460 if (monitor_thread != AST_PTHREADT_NULL) { 08461 /* Wake up the thread */ 08462 pthread_kill(monitor_thread, SIGURG); 08463 } else { 08464 /* Start a new monitor */ 08465 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 08466 ast_mutex_unlock(&monlock); 08467 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08468 pthread_attr_destroy(&attr); 08469 return -1; 08470 } 08471 } 08472 ast_mutex_unlock(&monlock); 08473 pthread_attr_destroy(&attr); 08474 return 0; 08475 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2613 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), and send_callerid().
02614 { 02615 int res; 02616 if (p->saveconf.confmode) { 02617 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02618 p->saveconf.confmode = 0; 02619 if (res) { 02620 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02621 return -1; 02622 } 02623 } 02624 if (option_debug) 02625 ast_log(LOG_DEBUG, "Restored conferencing\n"); 02626 return 0; 02627 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2540 of file chan_dahdi.c.
References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by dahdi_hangup(), and ss_thread().
02541 { 02542 int res; 02543 02544 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02545 if (res) { 02546 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02547 return -1; 02548 } 02549 02550 return 0; 02551 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2586 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
02587 { 02588 struct dahdi_confinfo c; 02589 int res; 02590 if (p->saveconf.confmode) { 02591 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02592 return -1; 02593 } 02594 p->saveconf.chan = 0; 02595 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02596 if (res) { 02597 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02598 p->saveconf.confmode = 0; 02599 return -1; 02600 } 02601 memset(&c, 0, sizeof(c)); 02602 c.confmode = DAHDI_CONF_NORMAL; 02603 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02604 if (res) { 02605 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02606 return -1; 02607 } 02608 if (option_debug) 02609 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 02610 return 0; 02611 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2653 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), errno, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_call(), dahdi_callwait(), and send_cwcidspill().
02654 { 02655 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02656 int res; 02657 /* Take out of linear mode if necessary */ 02658 if (p->subs[SUB_REAL].linear) { 02659 p->subs[SUB_REAL].linear = 0; 02660 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02661 } 02662 while (p->cidpos < p->cidlen) { 02663 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02664 if (res < 0) { 02665 if (errno == EAGAIN) 02666 return 0; 02667 else { 02668 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02669 return -1; 02670 } 02671 } 02672 if (!res) 02673 return 0; 02674 p->cidpos += res; 02675 } 02676 free(p->cidspill); 02677 p->cidspill = NULL; 02678 if (p->callwaitcas) { 02679 /* Wait for CID/CW to expire */ 02680 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02681 } else 02682 restore_conference(p); 02683 return 0; 02684 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2631 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_dtmfup().
02632 { 02633 p->callwaitcas = 0; 02634 p->cidcwexpire = 0; 02635 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02636 return -1; 02637 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02638 /* Make sure we account for the end */ 02639 p->cidlen += READ_SIZE * 4; 02640 p->cidpos = 0; 02641 send_callerid(p); 02642 if (option_verbose > 2) 02643 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02644 return 0; 02645 }
static int send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3300 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, LOG_DEBUG, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.
Referenced by dahdi_send_keypad_facility_exec(), and zap_send_keypad_facility_exec().
03301 { 03302 /* Data will be our digit string */ 03303 struct dahdi_pvt *p; 03304 char *digits = (char *) data; 03305 03306 if (ast_strlen_zero(digits)) { 03307 ast_log(LOG_DEBUG, "No digit string sent to application!\n"); 03308 return -1; 03309 } 03310 03311 p = (struct dahdi_pvt *)chan->tech_pvt; 03312 03313 if (!p) { 03314 ast_log(LOG_DEBUG, "Unable to find technology private\n"); 03315 return -1; 03316 } 03317 03318 ast_mutex_lock(&p->lock); 03319 03320 if (!p->pri || !p->call) { 03321 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n"); 03322 ast_mutex_unlock(&p->lock); 03323 return -1; 03324 } 03325 03326 if (!pri_grab(p, p->pri)) { 03327 pri_keypad_facility(p->pri->pri, p->call, digits); 03328 pri_rel(p->pri); 03329 } else { 03330 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n"); 03331 ast_mutex_unlock(&p->lock); 03332 return -1; 03333 } 03334 03335 ast_mutex_unlock(&p->lock); 03336 03337 return 0; 03338 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 2521 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
02522 { 02523 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02524 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2503 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
02504 { 02505 struct dahdi_gains g; 02506 int res; 02507 02508 memset(&g, 0, sizeof(g)); 02509 g.chan = chan; 02510 res = ioctl(fd, DAHDI_GETGAINS, &g); 02511 if (res) { 02512 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02513 return res; 02514 } 02515 02516 fill_rxgain(&g, gain, law); 02517 02518 return ioctl(fd, DAHDI_SETGAINS, &g); 02519 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 2484 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
02485 { 02486 struct dahdi_gains g; 02487 int res; 02488 02489 memset(&g, 0, sizeof(g)); 02490 g.chan = chan; 02491 res = ioctl(fd, DAHDI_GETGAINS, &g); 02492 if (res) { 02493 if (option_debug) 02494 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 02495 return res; 02496 } 02497 02498 fill_txgain(&g, gain, law); 02499 02500 return ioctl(fd, DAHDI_SETGAINS, &g); 02501 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 13814 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().
13815 { 13816 struct ast_config *cfg; 13817 struct ast_variable *v; 13818 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 13819 int res; 13820 13821 #ifdef HAVE_PRI 13822 char *c; 13823 int spanno; 13824 int i, x; 13825 int logicalspan; 13826 int trunkgroup; 13827 int dchannels[NUM_DCHANS]; 13828 #endif 13829 13830 #ifdef HAVE_ZAPTEL 13831 int load_from_zapata_conf = 1; 13832 #else 13833 int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE); 13834 #endif 13835 13836 if (load_from_zapata_conf) { 13837 if (!(cfg = ast_config_load("zapata.conf"))) { 13838 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 13839 return 0; 13840 } 13841 } else { 13842 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 13843 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 13844 return 0; 13845 } 13846 } 13847 13848 /* It's a little silly to lock it, but we mind as well just to be sure */ 13849 ast_mutex_lock(&iflock); 13850 #ifdef HAVE_PRI 13851 if (reload != 1) { 13852 /* Process trunkgroups first */ 13853 v = ast_variable_browse(cfg, "trunkgroups"); 13854 while (v) { 13855 if (!strcasecmp(v->name, "trunkgroup")) { 13856 trunkgroup = atoi(v->value); 13857 if (trunkgroup > 0) { 13858 if ((c = strchr(v->value, ','))) { 13859 i = 0; 13860 memset(dchannels, 0, sizeof(dchannels)); 13861 while (c && (i < NUM_DCHANS)) { 13862 dchannels[i] = atoi(c + 1); 13863 if (dchannels[i] < 0) { 13864 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); 13865 } else 13866 i++; 13867 c = strchr(c + 1, ','); 13868 } 13869 if (i) { 13870 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 13871 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); 13872 } else if (option_verbose > 1) 13873 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"); 13874 } else 13875 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13876 } else 13877 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 13878 } else 13879 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 13880 } else if (!strcasecmp(v->name, "spanmap")) { 13881 spanno = atoi(v->value); 13882 if (spanno > 0) { 13883 if ((c = strchr(v->value, ','))) { 13884 trunkgroup = atoi(c + 1); 13885 if (trunkgroup > 0) { 13886 if ((c = strchr(c + 1, ','))) 13887 logicalspan = atoi(c + 1); 13888 else 13889 logicalspan = 0; 13890 if (logicalspan >= 0) { 13891 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 13892 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13893 } else if (option_verbose > 1) 13894 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 13895 } else 13896 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); 13897 } else 13898 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 13899 } else 13900 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 13901 } else 13902 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 13903 } else { 13904 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 13905 } 13906 v = v->next; 13907 } 13908 } 13909 #endif 13910 13911 /* Copy the default jb config over global_jbconf */ 13912 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 13913 13914 v = ast_variable_browse(cfg, "channels"); 13915 res = process_dahdi(&conf, "", v, reload, 0); 13916 ast_mutex_unlock(&iflock); 13917 ast_config_destroy(cfg); 13918 if (res) 13919 return res; 13920 cfg = ast_config_load("users.conf"); 13921 if (cfg) { 13922 char *cat; 13923 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 13924 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 13925 if (!strcasecmp(cat, "general")) 13926 continue; 13927 if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) { 13928 struct dahdi_chan_conf sect_conf; 13929 memcpy(§_conf, &conf, sizeof(sect_conf)); 13930 13931 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 13932 } 13933 } 13934 ast_config_destroy(cfg); 13935 } 13936 #ifdef HAVE_PRI 13937 if (reload != 1) { 13938 for (x = 0; x < NUM_SPANS; x++) { 13939 if (pris[x].pvts[0]) { 13940 if (start_pri(pris + x)) { 13941 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 13942 return -1; 13943 } else if (option_verbose > 1) 13944 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 13945 } 13946 } 13947 } 13948 #endif 13949 #ifdef HAVE_OPENR2 13950 if (reload != 1) { 13951 int x; 13952 for (x = 0; x < NUM_SPANS; x++) { 13953 if (r2links[x].protocol_context) { 13954 if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) { 13955 ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1); 13956 return -1; 13957 } else { 13958 ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1); 13959 } 13960 } 13961 } 13962 } 13963 #endif 13964 /* And start the monitor for the first time */ 13965 restart_monitor(); 13966 return 0; 13967 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6787 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call, dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_DTMF_NOALERT, CID_START_POLARITY, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, f, free, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_lock, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event(), and handle_init_event().
06788 { 06789 struct ast_channel *chan = data; 06790 struct dahdi_pvt *p = chan->tech_pvt; 06791 char exten[AST_MAX_EXTENSION] = ""; 06792 char exten2[AST_MAX_EXTENSION] = ""; 06793 unsigned char buf[256]; 06794 char dtmfcid[300]; 06795 char dtmfbuf[300]; 06796 struct callerid_state *cs = NULL; 06797 char *name = NULL, *number = NULL; 06798 int distMatches; 06799 int curRingData[3]; 06800 int receivedRingT; 06801 int counter1; 06802 int counter; 06803 int samples = 0; 06804 struct ast_smdi_md_message *smdi_msg = NULL; 06805 int flags = 0; 06806 int i; 06807 int timeout; 06808 int getforward = 0; 06809 char *s1, *s2; 06810 int len = 0; 06811 int res; 06812 int index; 06813 06814 ast_mutex_lock(&ss_thread_lock); 06815 ss_thread_count++; 06816 ast_mutex_unlock(&ss_thread_lock); 06817 /* in the bizarre case where the channel has become a zombie before we 06818 even get started here, abort safely 06819 */ 06820 if (!p) { 06821 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06822 ast_hangup(chan); 06823 goto quit; 06824 } 06825 if (option_verbose > 2) 06826 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 06827 index = dahdi_get_index(chan, p, 1); 06828 if (index < 0) { 06829 ast_log(LOG_WARNING, "Huh?\n"); 06830 ast_hangup(chan); 06831 goto quit; 06832 } 06833 if (p->dsp) 06834 ast_dsp_digitreset(p->dsp); 06835 switch (p->sig) { 06836 #ifdef HAVE_PRI 06837 case SIG_PRI: 06838 /* Now loop looking for an extension */ 06839 ast_copy_string(exten, p->exten, sizeof(exten)); 06840 len = strlen(exten); 06841 res = 0; 06842 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06843 if (len && !ast_ignore_pattern(chan->context, exten)) 06844 tone_zone_play_tone(p->subs[index].dfd, -1); 06845 else 06846 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 06847 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06848 timeout = matchdigittimeout; 06849 else 06850 timeout = gendigittimeout; 06851 res = ast_waitfordigit(chan, timeout); 06852 if (res < 0) { 06853 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 06854 ast_hangup(chan); 06855 goto quit; 06856 } else if (res) { 06857 exten[len++] = res; 06858 exten[len] = '\0'; 06859 } else 06860 break; 06861 } 06862 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06863 if (ast_strlen_zero(exten)) { 06864 if (option_verbose > 2) 06865 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 06866 exten[0] = 's'; 06867 exten[1] = '\0'; 06868 } 06869 tone_zone_play_tone(p->subs[index].dfd, -1); 06870 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06871 /* Start the real PBX */ 06872 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06873 if (p->dsp) ast_dsp_digitreset(p->dsp); 06874 dahdi_enable_ec(p); 06875 ast_setstate(chan, AST_STATE_RING); 06876 res = ast_pbx_run(chan); 06877 if (res) { 06878 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06879 } 06880 } else { 06881 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06882 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06883 ast_hangup(chan); 06884 p->exten[0] = '\0'; 06885 /* Since we send release complete here, we won't get one */ 06886 p->call = NULL; 06887 } 06888 goto quit; 06889 break; 06890 #endif 06891 case SIG_FEATD: 06892 case SIG_FEATDMF: 06893 case SIG_FEATDMF_TA: 06894 case SIG_E911: 06895 case SIG_FGC_CAMAMF: 06896 case SIG_FEATB: 06897 case SIG_EMWINK: 06898 case SIG_SF_FEATD: 06899 case SIG_SF_FEATDMF: 06900 case SIG_SF_FEATB: 06901 case SIG_SFWINK: 06902 if (dahdi_wink(p, index)) 06903 goto quit; 06904 /* Fall through */ 06905 case SIG_EM: 06906 case SIG_EM_E1: 06907 case SIG_SF: 06908 case SIG_FGC_CAMA: 06909 res = tone_zone_play_tone(p->subs[index].dfd, -1); 06910 if (p->dsp) 06911 ast_dsp_digitreset(p->dsp); 06912 /* set digit mode appropriately */ 06913 if (p->dsp) { 06914 if (NEED_MFDETECT(p)) 06915 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 06916 else 06917 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 06918 } 06919 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06920 /* Wait for the first digit only if immediate=no */ 06921 if (!p->immediate) 06922 /* Wait for the first digit (up to 5 seconds). */ 06923 res = ast_waitfordigit(chan, 5000); 06924 else 06925 res = 0; 06926 if (res > 0) { 06927 /* save first char */ 06928 dtmfbuf[0] = res; 06929 switch (p->sig) { 06930 case SIG_FEATD: 06931 case SIG_SF_FEATD: 06932 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06933 if (res > 0) 06934 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06935 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06936 break; 06937 case SIG_FEATDMF_TA: 06938 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06939 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06940 if (dahdi_wink(p, index)) goto quit; 06941 dtmfbuf[0] = 0; 06942 /* Wait for the first digit (up to 5 seconds). */ 06943 res = ast_waitfordigit(chan, 5000); 06944 if (res <= 0) break; 06945 dtmfbuf[0] = res; 06946 /* fall through intentionally */ 06947 case SIG_FEATDMF: 06948 case SIG_E911: 06949 case SIG_FGC_CAMAMF: 06950 case SIG_SF_FEATDMF: 06951 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06952 /* if international caca, do it again to get real ANO */ 06953 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06954 { 06955 if (dahdi_wink(p, index)) goto quit; 06956 dtmfbuf[0] = 0; 06957 /* Wait for the first digit (up to 5 seconds). */ 06958 res = ast_waitfordigit(chan, 5000); 06959 if (res <= 0) break; 06960 dtmfbuf[0] = res; 06961 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06962 } 06963 if (res > 0) { 06964 /* if E911, take off hook */ 06965 if (p->sig == SIG_E911) 06966 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06967 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06968 } 06969 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06970 break; 06971 case SIG_FEATB: 06972 case SIG_SF_FEATB: 06973 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06974 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06975 break; 06976 case SIG_EMWINK: 06977 /* if we received a '*', we are actually receiving Feature Group D 06978 dial syntax, so use that mode; otherwise, fall through to normal 06979 mode 06980 */ 06981 if (res == '*') { 06982 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06983 if (res > 0) 06984 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06985 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06986 break; 06987 } 06988 default: 06989 /* If we got the first digit, get the rest */ 06990 len = 1; 06991 dtmfbuf[len] = '\0'; 06992 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06993 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06994 timeout = matchdigittimeout; 06995 } else { 06996 timeout = gendigittimeout; 06997 } 06998 res = ast_waitfordigit(chan, timeout); 06999 if (res < 0) { 07000 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07001 ast_hangup(chan); 07002 goto quit; 07003 } else if (res) { 07004 dtmfbuf[len++] = res; 07005 dtmfbuf[len] = '\0'; 07006 } else { 07007 break; 07008 } 07009 } 07010 break; 07011 } 07012 } 07013 if (res == -1) { 07014 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 07015 ast_hangup(chan); 07016 goto quit; 07017 } else if (res < 0) { 07018 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 07019 ast_hangup(chan); 07020 goto quit; 07021 } 07022 07023 if (p->sig == SIG_FGC_CAMA) { 07024 char anibuf[100]; 07025 07026 if (ast_safe_sleep(chan,1000) == -1) { 07027 ast_hangup(chan); 07028 goto quit; 07029 } 07030 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07031 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 07032 res = my_getsigstr(chan, anibuf, "#", 10000); 07033 if ((res > 0) && (strlen(anibuf) > 2)) { 07034 if (anibuf[strlen(anibuf) - 1] == '#') 07035 anibuf[strlen(anibuf) - 1] = 0; 07036 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07037 } 07038 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07039 } 07040 07041 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07042 if (ast_strlen_zero(exten)) 07043 ast_copy_string(exten, "s", sizeof(exten)); 07044 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07045 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07046 if (exten[0] == '*') { 07047 char *stringp=NULL; 07048 ast_copy_string(exten2, exten, sizeof(exten2)); 07049 /* Parse out extension and callerid */ 07050 stringp=exten2 +1; 07051 s1 = strsep(&stringp, "*"); 07052 s2 = strsep(&stringp, "*"); 07053 if (s2) { 07054 if (!ast_strlen_zero(p->cid_num)) 07055 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07056 else 07057 ast_set_callerid(chan, s1, NULL, s1); 07058 ast_copy_string(exten, s2, sizeof(exten)); 07059 } else 07060 ast_copy_string(exten, s1, sizeof(exten)); 07061 } else if (p->sig == SIG_FEATD) 07062 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07063 } 07064 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 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 s2 = strsep(&stringp, "#"); 07072 if (s2) { 07073 if (!ast_strlen_zero(p->cid_num)) 07074 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07075 else 07076 if (*(s1 + 2)) 07077 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07078 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07079 } else 07080 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07081 } else 07082 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07083 } 07084 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07085 if (exten[0] == '*') { 07086 char *stringp=NULL; 07087 ast_copy_string(exten2, exten, sizeof(exten2)); 07088 /* Parse out extension and callerid */ 07089 stringp=exten2 +1; 07090 s1 = strsep(&stringp, "#"); 07091 s2 = strsep(&stringp, "#"); 07092 if (s2 && (*(s2 + 1) == '0')) { 07093 if (*(s2 + 2)) 07094 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07095 } 07096 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07097 else ast_copy_string(exten, "911", sizeof(exten)); 07098 } else 07099 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 07100 } 07101 if (p->sig == SIG_FEATB) { 07102 if (exten[0] == '*') { 07103 char *stringp=NULL; 07104 ast_copy_string(exten2, exten, sizeof(exten2)); 07105 /* Parse out extension and callerid */ 07106 stringp=exten2 +1; 07107 s1 = strsep(&stringp, "#"); 07108 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 07109 } else 07110 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 07111 } 07112 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07113 dahdi_wink(p, index); 07114 /* some switches require a minimum guard time between 07115 the last FGD wink and something that answers 07116 immediately. This ensures it */ 07117 if (ast_safe_sleep(chan,100)) goto quit; 07118 } 07119 dahdi_enable_ec(p); 07120 if (NEED_MFDETECT(p)) { 07121 if (p->dsp) { 07122 if (!p->hardwaredtmf) 07123 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 07124 else { 07125 ast_dsp_free(p->dsp); 07126 p->dsp = NULL; 07127 } 07128 } 07129 } 07130 07131 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 07132 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07133 if (p->dsp) ast_dsp_digitreset(p->dsp); 07134 res = ast_pbx_run(chan); 07135 if (res) { 07136 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07137 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07138 } 07139 goto quit; 07140 } else { 07141 if (option_verbose > 2) 07142 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 07143 sleep(2); 07144 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 07145 if (res < 0) 07146 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 07147 else 07148 sleep(1); 07149 res = ast_streamfile(chan, "ss-noservice", chan->language); 07150 if (res >= 0) 07151 ast_waitstream(chan, ""); 07152 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07153 ast_hangup(chan); 07154 goto quit; 07155 } 07156 break; 07157 case SIG_FXOLS: 07158 case SIG_FXOGS: 07159 case SIG_FXOKS: 07160 /* Read the first digit */ 07161 timeout = firstdigittimeout; 07162 /* If starting a threeway call, never timeout on the first digit so someone 07163 can use flash-hook as a "hold" feature */ 07164 if (p->subs[SUB_THREEWAY].owner) 07165 timeout = 999999; 07166 while (len < AST_MAX_EXTENSION-1) { 07167 /* Read digit unless it's supposed to be immediate, in which case the 07168 only answer is 's' */ 07169 if (p->immediate) 07170 res = 's'; 07171 else 07172 res = ast_waitfordigit(chan, timeout); 07173 timeout = 0; 07174 if (res < 0) { 07175 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 07176 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07177 ast_hangup(chan); 07178 goto quit; 07179 } else if (res) { 07180 exten[len++]=res; 07181 exten[len] = '\0'; 07182 } 07183 if (!ast_ignore_pattern(chan->context, exten)) 07184 tone_zone_play_tone(p->subs[index].dfd, -1); 07185 else 07186 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07187 if (!strcmp(exten,ast_pickup_ext())) { 07188 /* Scan all channels and see if there are any 07189 * ringing channels that have call groups 07190 * that equal this channels pickup group 07191 */ 07192 if (index == SUB_REAL) { 07193 /* Switch us from Third call to Call Wait */ 07194 if (p->subs[SUB_THREEWAY].owner) { 07195 /* If you make a threeway call and the *8# a call, it should actually 07196 look like a callwait */ 07197 alloc_sub(p, SUB_CALLWAIT); 07198 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07199 unalloc_sub(p, SUB_THREEWAY); 07200 } 07201 dahdi_enable_ec(p); 07202 if (ast_pickup_call(chan)) { 07203 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 07204 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07205 dahdi_wait_event(p->subs[index].dfd); 07206 } 07207 ast_hangup(chan); 07208 goto quit; 07209 } else { 07210 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07211 ast_hangup(chan); 07212 goto quit; 07213 } 07214 07215 } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 07216 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07217 if (getforward) { 07218 /* Record this as the forwarding extension */ 07219 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 07220 if (option_verbose > 2) 07221 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 07222 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07223 if (res) 07224 break; 07225 usleep(500000); 07226 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07227 sleep(1); 07228 memset(exten, 0, sizeof(exten)); 07229 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 07230 len = 0; 07231 getforward = 0; 07232 } else { 07233 res = tone_zone_play_tone(p->subs[index].dfd, -1); 07234 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07235 if (!ast_strlen_zero(p->cid_num)) { 07236 if (!p->hidecallerid) 07237 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07238 else 07239 ast_set_callerid(chan, NULL, NULL, p->cid_num); 07240 } 07241 if (!ast_strlen_zero(p->cid_name)) { 07242 if (!p->hidecallerid) 07243 ast_set_callerid(chan, NULL, p->cid_name, NULL); 07244 } 07245 ast_setstate(chan, AST_STATE_RING); 07246 dahdi_enable_ec(p); 07247 res = ast_pbx_run(chan); 07248 if (res) { 07249 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07250 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07251 } 07252 goto quit; 07253 } 07254 } else { 07255 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07256 so just set the timeout to matchdigittimeout and wait some more */ 07257 timeout = matchdigittimeout; 07258 } 07259 } else if (res == 0) { 07260 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 07261 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07262 dahdi_wait_event(p->subs[index].dfd); 07263 ast_hangup(chan); 07264 goto quit; 07265 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07266 if (option_verbose > 2) 07267 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 07268 /* Disable call waiting if enabled */ 07269 p->callwaiting = 0; 07270 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07271 if (res) { 07272 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07273 chan->name, strerror(errno)); 07274 } 07275 len = 0; 07276 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 07277 memset(exten, 0, sizeof(exten)); 07278 timeout = firstdigittimeout; 07279 07280 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07281 if (option_verbose > 2) 07282 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 07283 /* Disable Caller*ID if enabled */ 07284 p->hidecallerid = 1; 07285 if (chan->cid.cid_num) 07286 free(chan->cid.cid_num); 07287 chan->cid.cid_num = NULL; 07288 if (chan->cid.cid_name) 07289 free(chan->cid.cid_name); 07290 chan->cid.cid_name = NULL; 07291 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07292 if (res) { 07293 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07294 chan->name, strerror(errno)); 07295 } 07296 len = 0; 07297 memset(exten, 0, sizeof(exten)); 07298 timeout = firstdigittimeout; 07299 } else if (p->callreturn && !strcmp(exten, "*69")) { 07300 res = 0; 07301 if (!ast_strlen_zero(p->lastcid_num)) { 07302 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07303 } 07304 if (!res) 07305 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07306 break; 07307 } else if (!strcmp(exten, "*78")) { 07308 /* Do not disturb */ 07309 if (option_verbose > 2) 07310 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 07311 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07312 "Channel: %s/%d\r\n" 07313 "Status: enabled\r\n", dahdi_chan_name, p->channel); 07314 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07315 p->dnd = 1; 07316 getforward = 0; 07317 memset(exten, 0, sizeof(exten)); 07318 len = 0; 07319 } else if (!strcmp(exten, "*79")) { 07320 /* Do not disturb */ 07321 if (option_verbose > 2) 07322 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 07323 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07324 "Channel: %s/%d\r\n" 07325 "Status: disabled\r\n", dahdi_chan_name, p->channel); 07326 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07327 p->dnd = 0; 07328 getforward = 0; 07329 memset(exten, 0, sizeof(exten)); 07330 len = 0; 07331 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07332 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07333 getforward = 1; 07334 memset(exten, 0, sizeof(exten)); 07335 len = 0; 07336 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07337 if (option_verbose > 2) 07338 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 07339 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07340 memset(p->call_forward, 0, sizeof(p->call_forward)); 07341 getforward = 0; 07342 memset(exten, 0, sizeof(exten)); 07343 len = 0; 07344 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07345 p->subs[SUB_THREEWAY].owner && 07346 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07347 /* This is a three way call, the main call being a real channel, 07348 and we're parking the first call. */ 07349 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07350 if (option_verbose > 2) 07351 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 07352 break; 07353 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07354 if (option_verbose > 2) 07355 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 07356 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07357 if (!res) { 07358 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07359 memset(exten, 0, sizeof(exten)); 07360 len = 0; 07361 } 07362 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07363 if (option_verbose > 2) 07364 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 07365 /* Enable Caller*ID if enabled */ 07366 p->hidecallerid = 0; 07367 if (chan->cid.cid_num) 07368 free(chan->cid.cid_num); 07369 chan->cid.cid_num = NULL; 07370 if (chan->cid.cid_name) 07371 free(chan->cid.cid_name); 07372 chan->cid.cid_name = NULL; 07373 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07374 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 07375 if (res) { 07376 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07377 chan->name, strerror(errno)); 07378 } 07379 len = 0; 07380 memset(exten, 0, sizeof(exten)); 07381 timeout = firstdigittimeout; 07382 } else if (!strcmp(exten, "*0")) { 07383 struct ast_channel *nbridge = 07384 p->subs[SUB_THREEWAY].owner; 07385 struct dahdi_pvt *pbridge = NULL; 07386 /* set up the private struct of the bridged one, if any */ 07387 if (nbridge && ast_bridged_channel(nbridge)) 07388 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07389 if (nbridge && pbridge && 07390 (nbridge->tech == chan_tech) && 07391 (ast_bridged_channel(nbridge)->tech == chan_tech) && 07392 ISTRUNK(pbridge)) { 07393 int func = DAHDI_FLASH; 07394 /* Clear out the dial buffer */ 07395 p->dop.dialstr[0] = '\0'; 07396 /* flash hookswitch */ 07397 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07398 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07399 nbridge->name, strerror(errno)); 07400 } 07401 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07402 unalloc_sub(p, SUB_THREEWAY); 07403 p->owner = p->subs[SUB_REAL].owner; 07404 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07405 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07406 ast_hangup(chan); 07407 goto quit; 07408 } else { 07409 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07410 dahdi_wait_event(p->subs[index].dfd); 07411 tone_zone_play_tone(p->subs[index].dfd, -1); 07412 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07413 unalloc_sub(p, SUB_THREEWAY); 07414 p->owner = p->subs[SUB_REAL].owner; 07415 ast_hangup(chan); 07416 goto quit; 07417 } 07418 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07419 ((exten[0] != '*') || (strlen(exten) > 2))) { 07420 if (option_debug) 07421 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); 07422 break; 07423 } 07424 if (!timeout) 07425 timeout = gendigittimeout; 07426 if (len && !ast_ignore_pattern(chan->context, exten)) 07427 tone_zone_play_tone(p->subs[index].dfd, -1); 07428 } 07429 break; 07430 case SIG_FXSLS: 07431 case SIG_FXSGS: 07432 case SIG_FXSKS: 07433 #ifdef HAVE_PRI 07434 if (p->pri) { 07435 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07436 struct ast_frame *f; 07437 int res; 07438 time_t start; 07439 07440 time(&start); 07441 ast_setstate(chan, AST_STATE_RING); 07442 while (time(NULL) < start + 3) { 07443 res = ast_waitfor(chan, 1000); 07444 if (res) { 07445 f = ast_read(chan); 07446 if (!f) { 07447 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07448 ast_hangup(chan); 07449 goto quit; 07450 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07451 res = 1; 07452 } else 07453 res = 0; 07454 ast_frfree(f); 07455 if (res) { 07456 ast_log(LOG_DEBUG, "Got ring!\n"); 07457 res = 0; 07458 break; 07459 } 07460 } 07461 } 07462 } 07463 #endif 07464 /* check for SMDI messages */ 07465 if (p->use_smdi && p->smdi_iface) { 07466 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07467 07468 if (smdi_msg != NULL) { 07469 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07470 07471 if (smdi_msg->type == 'B') 07472 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07473 else if (smdi_msg->type == 'N') 07474 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07475 07476 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 07477 } else { 07478 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07479 } 07480 } 07481 07482 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07483 number = smdi_msg->calling_st; 07484 07485 /* If we want caller id, we're in a prering state due to a polarity reversal 07486 * and we're set to use a polarity reversal to trigger the start of caller id, 07487 * grab the caller id and wait for ringing to start... */ 07488 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && 07489 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) { 07490 /* If set to use DTMF CID signalling, listen for DTMF */ 07491 if (p->cid_signalling == CID_SIG_DTMF) { 07492 int i = 0; 07493 cs = NULL; 07494 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 07495 "channel %s\n", chan->name); 07496 dahdi_setlinear(p->subs[index].dfd, 0); 07497 res = 2000; 07498 for (;;) { 07499 struct ast_frame *f; 07500 res = ast_waitfor(chan, res); 07501 if (res <= 0) { 07502 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07503 "Exiting simple switch\n"); 07504 ast_hangup(chan); 07505 goto quit; 07506 } 07507 f = ast_read(chan); 07508 if (!f) 07509 break; 07510 if (f->frametype == AST_FRAME_DTMF) { 07511 dtmfbuf[i++] = f->subclass; 07512 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07513 res = 2000; 07514 } 07515 ast_frfree(f); 07516 if (chan->_state == AST_STATE_RING || 07517 chan->_state == AST_STATE_RINGING) 07518 break; /* Got ring */ 07519 } 07520 dtmfbuf[i] = '\0'; 07521 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07522 /* Got cid and ring. */ 07523 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 07524 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07525 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07526 dtmfcid, flags); 07527 /* If first byte is NULL, we have no cid */ 07528 if (!ast_strlen_zero(dtmfcid)) 07529 number = dtmfcid; 07530 else 07531 number = NULL; 07532 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07533 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07534 cs = callerid_new(p->cid_signalling); 07535 if (cs) { 07536 samples = 0; 07537 #if 1 07538 bump_gains(p); 07539 #endif 07540 /* Take out of linear mode for Caller*ID processing */ 07541 dahdi_setlinear(p->subs[index].dfd, 0); 07542 07543 /* First we wait and listen for the Caller*ID */ 07544 for (;;) { 07545 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07546 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07547 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07548 callerid_free(cs); 07549 ast_hangup(chan); 07550 goto quit; 07551 } 07552 if (i & DAHDI_IOMUX_SIGEVENT) { 07553 res = dahdi_get_event(p->subs[index].dfd); 07554 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07555 07556 if (p->cid_signalling == CID_SIG_V23_JP) { 07557 #ifdef DAHDI_EVENT_RINGBEGIN 07558 if (res == DAHDI_EVENT_RINGBEGIN) { 07559 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07560 usleep(1); 07561 } 07562 #endif 07563 } else { 07564 res = 0; 07565 break; 07566 } 07567 } else if (i & DAHDI_IOMUX_READ) { 07568 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07569 if (res < 0) { 07570 if (errno != ELAST) { 07571 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07572 callerid_free(cs); 07573 ast_hangup(chan); 07574 goto quit; 07575 } 07576 break; 07577 } 07578 samples += res; 07579 07580 if (p->cid_signalling == CID_SIG_V23_JP) { 07581 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07582 } else { 07583 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07584 } 07585 07586 if (res < 0) { 07587 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07588 break; 07589 } else if (res) 07590 break; 07591 else if (samples > (8000 * 10)) 07592 break; 07593 } 07594 } 07595 if (res == 1) { 07596 callerid_get(cs, &name, &number, &flags); 07597 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07598 } 07599 07600 if (p->cid_signalling == CID_SIG_V23_JP) { 07601 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07602 usleep(1); 07603 res = 4000; 07604 } else { 07605 07606 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07607 res = 2000; 07608 } 07609 07610 for (;;) { 07611 struct ast_frame *f; 07612 res = ast_waitfor(chan, res); 07613 if (res <= 0) { 07614 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07615 "Exiting simple switch\n"); 07616 ast_hangup(chan); 07617 goto quit; 07618 } 07619 if (!(f = ast_read(chan))) { 07620 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07621 ast_hangup(chan); 07622 goto quit; 07623 } 07624 ast_frfree(f); 07625 if (chan->_state == AST_STATE_RING || 07626 chan->_state == AST_STATE_RINGING) 07627 break; /* Got ring */ 07628 } 07629 07630 /* We must have a ring by now, so, if configured, lets try to listen for 07631 * distinctive ringing */ 07632 if (p->usedistinctiveringdetection) { 07633 len = 0; 07634 distMatches = 0; 07635 /* Clear the current ring data array so we dont have old data in it. */ 07636 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07637 curRingData[receivedRingT] = 0; 07638 receivedRingT = 0; 07639 counter = 0; 07640 counter1 = 0; 07641 /* Check to see if context is what it should be, if not set to be. */ 07642 if (strcmp(p->context,p->defcontext) != 0) { 07643 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07644 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07645 } 07646 07647 for (;;) { 07648 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07649 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07650 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07651 callerid_free(cs); 07652 ast_hangup(chan); 07653 goto quit; 07654 } 07655 if (i & DAHDI_IOMUX_SIGEVENT) { 07656 res = dahdi_get_event(p->subs[index].dfd); 07657 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07658 res = 0; 07659 /* Let us detect distinctive ring */ 07660 07661 curRingData[receivedRingT] = p->ringt; 07662 07663 if (p->ringt < p->ringt_base/2) 07664 break; 07665 /* Increment the ringT counter so we can match it against 07666 values in chan_dahdi.conf for distinctive ring */ 07667 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07668 break; 07669 } else if (i & DAHDI_IOMUX_READ) { 07670 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07671 if (res < 0) { 07672 if (errno != ELAST) { 07673 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07674 callerid_free(cs); 07675 ast_hangup(chan); 07676 goto quit; 07677 } 07678 break; 07679 } 07680 if (p->ringt) 07681 p->ringt--; 07682 if (p->ringt == 1) { 07683 res = -1; 07684 break; 07685 } 07686 } 07687 } 07688 if (option_verbose > 2) 07689 /* this only shows up if you have n of the dring patterns filled in */ 07690 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07691 07692 for (counter = 0; counter < 3; counter++) { 07693 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07694 channel */ 07695 distMatches = 0; 07696 for (counter1 = 0; counter1 < 3; counter1++) { 07697 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07698 (p->drings.ringnum[counter].ring[counter1]-10)) { 07699 distMatches++; 07700 } 07701 } 07702 if (distMatches == 3) { 07703 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07704 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07705 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07706 if (option_verbose > 2) 07707 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07708 break; 07709 } 07710 } 07711 } 07712 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07713 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07714 #if 1 07715 restore_gains(p); 07716 #endif 07717 } else 07718 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07719 } else { 07720 ast_log(LOG_WARNING, "Channel %s in prering " 07721 "state, but I have nothing to do. " 07722 "Terminating simple switch, should be " 07723 "restarted by the actual ring.\n", 07724 chan->name); 07725 ast_hangup(chan); 07726 goto quit; 07727 } 07728 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07729 /* FSK Bell202 callerID */ 07730 cs = callerid_new(p->cid_signalling); 07731 if (cs) { 07732 #if 1 07733 bump_gains(p); 07734 #endif 07735 samples = 0; 07736 len = 0; 07737 distMatches = 0; 07738 /* Clear the current ring data array so we dont have old data in it. */ 07739 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 07740 curRingData[receivedRingT] = 0; 07741 receivedRingT = 0; 07742 counter = 0; 07743 counter1 = 0; 07744 /* Check to see if context is what it should be, if not set to be. */ 07745 if (strcmp(p->context,p->defcontext) != 0) { 07746 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07747 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07748 } 07749 07750 /* Take out of linear mode for Caller*ID processing */ 07751 dahdi_setlinear(p->subs[index].dfd, 0); 07752 for (;;) { 07753 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07754 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07755 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07756 callerid_free(cs); 07757 ast_hangup(chan); 07758 goto quit; 07759 } 07760 if (i & DAHDI_IOMUX_SIGEVENT) { 07761 res = dahdi_get_event(p->subs[index].dfd); 07762 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07763 /* If we get a PR event, they hung up while processing calerid */ 07764 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07765 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07766 p->polarity = POLARITY_IDLE; 07767 callerid_free(cs); 07768 ast_hangup(chan); 07769 goto quit; 07770 } 07771 res = 0; 07772 /* Let us detect callerid when the telco uses distinctive ring */ 07773 07774 curRingData[receivedRingT] = p->ringt; 07775 07776 if (p->ringt < p->ringt_base/2) 07777 break; 07778 /* Increment the ringT counter so we can match it against 07779 values in chan_dahdi.conf for distinctive ring */ 07780 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07781 break; 07782 } else if (i & DAHDI_IOMUX_READ) { 07783 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07784 if (res < 0) { 07785 if (errno != ELAST) { 07786 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07787 callerid_free(cs); 07788 ast_hangup(chan); 07789 goto quit; 07790 } 07791 break; 07792 } 07793 if (p->ringt) 07794 p->ringt--; 07795 if (p->ringt == 1) { 07796 res = -1; 07797 break; 07798 } 07799 samples += res; 07800 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07801 if (res < 0) { 07802 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07803 break; 07804 } else if (res) 07805 break; 07806 else if (samples > (8000 * 10)) 07807 break; 07808 } 07809 } 07810 if (res == 1) { 07811 callerid_get(cs, &name, &number, &flags); 07812 if (option_debug) 07813 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07814 } 07815 if (distinctiveringaftercid == 1) { 07816 /* Clear the current ring data array so we dont have old data in it. */ 07817 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07818 curRingData[receivedRingT] = 0; 07819 } 07820 receivedRingT = 0; 07821 if (option_verbose > 2) 07822 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 07823 for (;;) { 07824 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07825 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 07826 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07827 callerid_free(cs); 07828 ast_hangup(chan); 07829 goto quit; 07830 } 07831 if (i & DAHDI_IOMUX_SIGEVENT) { 07832 res = dahdi_get_event(p->subs[index].dfd); 07833 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07834 res = 0; 07835 /* Let us detect callerid when the telco uses distinctive ring */ 07836 07837 curRingData[receivedRingT] = p->ringt; 07838 07839 if (p->ringt < p->ringt_base/2) 07840 break; 07841 /* Increment the ringT counter so we can match it against 07842 values in chan_dahdi.conf for distinctive ring */ 07843 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 07844 break; 07845 } else if (i & DAHDI_IOMUX_READ) { 07846 res = read(p->subs[index].dfd, buf, sizeof(buf)); 07847 if (res < 0) { 07848 if (errno != ELAST) { 07849 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07850 callerid_free(cs); 07851 ast_hangup(chan); 07852 goto quit; 07853 } 07854 break; 07855 } 07856 if (p->ringt) 07857 p->ringt--; 07858 if (p->ringt == 1) { 07859 res = -1; 07860 break; 07861 } 07862 } 07863 } 07864 } 07865 if (p->usedistinctiveringdetection) { 07866 if (option_verbose > 2) 07867 /* this only shows up if you have n of the dring patterns filled in */ 07868 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07869 07870 for (counter = 0; counter < 3; counter++) { 07871 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07872 channel */ 07873 if (option_verbose > 2) 07874 /* this only shows up if you have n of the dring patterns filled in */ 07875 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 07876 p->drings.ringnum[counter].ring[0], 07877 p->drings.ringnum[counter].ring[1], 07878 p->drings.ringnum[counter].ring[2]); 07879 distMatches = 0; 07880 for (counter1 = 0; counter1 < 3; counter1++) { 07881 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 07882 (p->drings.ringnum[counter].ring[counter1]-10)) { 07883 distMatches++; 07884 } 07885 } 07886 if (distMatches == 3) { 07887 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07888 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07889 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07890 if (option_verbose > 2) 07891 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 07892 break; 07893 } 07894 } 07895 } 07896 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07897 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 07898 #if 1 07899 restore_gains(p); 07900 #endif 07901 if (res < 0) { 07902 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07903 } 07904 } else 07905 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07906 } 07907 else 07908 cs = NULL; 07909 07910 if (number) 07911 ast_shrink_phone_number(number); 07912 ast_set_callerid(chan, number, name, number); 07913 07914 if (smdi_msg) 07915 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07916 07917 if (cs) 07918 callerid_free(cs); 07919 07920 ast_setstate(chan, AST_STATE_RING); 07921 chan->rings = 1; 07922 p->ringt = p->ringt_base; 07923 res = ast_pbx_run(chan); 07924 if (res) { 07925 ast_hangup(chan); 07926 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07927 } 07928 goto quit; 07929 default: 07930 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07931 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07932 if (res < 0) 07933 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07934 } 07935 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 07936 if (res < 0) 07937 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07938 ast_hangup(chan); 07939 quit: 07940 ast_mutex_lock(&ss_thread_lock); 07941 ss_thread_count--; 07942 ast_cond_signal(&ss_thread_complete); 07943 ast_mutex_unlock(&ss_thread_lock); 07944 return NULL; 07945 }
static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 11219 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().
11220 { 11221 int res, x; 11222 struct dahdi_params p; 11223 struct dahdi_bufferinfo bi; 11224 struct dahdi_spaninfo si; 11225 int i; 11226 11227 for (i = 0; i < NUM_DCHANS; i++) { 11228 if (!pri->dchannels[i]) 11229 break; 11230 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600); 11231 x = pri->dchannels[i]; 11232 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 11233 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 11234 return -1; 11235 } 11236 memset(&p, 0, sizeof(p)); 11237 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 11238 if (res) { 11239 dahdi_close_pri_fd(pri, i); 11240 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 11241 return -1; 11242 } 11243 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 11244 dahdi_close_pri_fd(pri, i); 11245 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x); 11246 return -1; 11247 } 11248 memset(&si, 0, sizeof(si)); 11249 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 11250 if (res) { 11251 dahdi_close_pri_fd(pri, i); 11252 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 11253 } 11254 if (!si.alarms) 11255 pri->dchanavail[i] |= DCHAN_NOTINALARM; 11256 else 11257 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 11258 memset(&bi, 0, sizeof(bi)); 11259 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 11260 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 11261 bi.numbufs = 32; 11262 bi.bufsize = 1024; 11263 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 11264 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 11265 dahdi_close_pri_fd(pri, i); 11266 return -1; 11267 } 11268 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 11269 /* Force overlap dial if we're doing GR-303! */ 11270 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 11271 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 11272 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 11273 #ifdef HAVE_PRI_INBANDDISCONNECT 11274 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 11275 #endif 11276 /* Enslave to master if appropriate */ 11277 if (i) 11278 pri_enslave(pri->dchans[0], pri->dchans[i]); 11279 if (!pri->dchans[i]) { 11280 dahdi_close_pri_fd(pri, i); 11281 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 11282 return -1; 11283 } 11284 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 11285 pri_set_nsf(pri->dchans[i], pri->nsf); 11286 #ifdef PRI_GETSET_TIMERS 11287 for (x = 0; x < PRI_MAX_TIMERS; x++) { 11288 if (pritimers[x] != 0) 11289 pri_set_timer(pri->dchans[i], x, pritimers[x]); 11290 } 11291 #endif 11292 } 11293 /* Assume primary is the one we use */ 11294 pri->pri = pri->dchans[0]; 11295 pri->resetpos = -1; 11296 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 11297 for (i = 0; i < NUM_DCHANS; i++) { 11298 if (!pri->dchannels[i]) 11299 break; 11300 dahdi_close_pri_fd(pri, i); 11301 } 11302 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 11303 return -1; 11304 } 11305 return 0; 11306 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 1772 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01773 { 01774 int tchan; 01775 int tinthreeway; 01776 struct ast_channel *towner; 01777 01778 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 01779 01780 tchan = p->subs[a].chan; 01781 towner = p->subs[a].owner; 01782 tinthreeway = p->subs[a].inthreeway; 01783 01784 p->subs[a].chan = p->subs[b].chan; 01785 p->subs[a].owner = p->subs[b].owner; 01786 p->subs[a].inthreeway = p->subs[b].inthreeway; 01787 01788 p->subs[b].chan = tchan; 01789 p->subs[b].owner = towner; 01790 p->subs[b].inthreeway = tinthreeway; 01791 01792 if (p->subs[a].owner) 01793 p->subs[a].owner->fds[0] = p->subs[a].dfd; 01794 if (p->subs[b].owner) 01795 p->subs[b].owner->fds[0] = p->subs[b].dfd; 01796 wakeup_sub(p, a, NULL); 01797 wakeup_sub(p, b, NULL); 01798 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1911 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01912 { 01913 if (!x) { 01914 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01915 return -1; 01916 } 01917 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01918 dahdi_close_sub(p, x); 01919 p->subs[x].linear = 0; 01920 p->subs[x].chan = 0; 01921 p->subs[x].owner = NULL; 01922 p->subs[x].inthreeway = 0; 01923 p->polarity = POLARITY_IDLE; 01924 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01925 return 0; 01926 }
static int unload_module | ( | void | ) | [static] |
Definition at line 12880 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), lock, NUM_SPANS, and pris.
12881 { 12882 #ifdef HAVE_PRI 12883 int y; 12884 for (y = 0; y < NUM_SPANS; y++) 12885 ast_mutex_destroy(&pris[y].lock); 12886 #endif 12887 return __unload_module(); 12888 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2294 of file chan_dahdi.c.
References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), and dahdi_hangup().
02295 { 02296 int needconf = 0; 02297 int x; 02298 int useslavenative; 02299 struct dahdi_pvt *slave = NULL; 02300 02301 useslavenative = isslavenative(p, &slave); 02302 /* Start with the obvious, general stuff */ 02303 for (x = 0; x < 3; x++) { 02304 /* Look for three way calls */ 02305 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 02306 conf_add(p, &p->subs[x], x, 0); 02307 needconf++; 02308 } else { 02309 conf_del(p, &p->subs[x], x); 02310 } 02311 } 02312 /* If we have a slave, add him to our conference now. or DAX 02313 if this is slave native */ 02314 for (x = 0; x < MAX_SLAVES; x++) { 02315 if (p->slaves[x]) { 02316 if (useslavenative) 02317 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02318 else { 02319 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02320 needconf++; 02321 } 02322 } 02323 } 02324 /* If we're supposed to be in there, do so now */ 02325 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02326 if (useslavenative) 02327 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02328 else { 02329 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02330 needconf++; 02331 } 02332 } 02333 /* If we have a master, add ourselves to his conference */ 02334 if (p->master) { 02335 if (isslavenative(p->master, NULL)) { 02336 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02337 } else { 02338 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02339 } 02340 } 02341 if (!needconf) { 02342 /* Nobody is left (or should be left) in our conference. 02343 Kill it. */ 02344 p->confno = -1; 02345 } 02346 if (option_debug) 02347 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02348 return 0; 02349 }
Definition at line 1208 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.
Referenced by swap_subs().
01212 { 01213 #ifdef HAVE_PRI 01214 if (pri) 01215 ast_mutex_unlock(&pri->lock); 01216 #endif 01217 for (;;) { 01218 if (p->subs[a].owner) { 01219 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 01220 DEADLOCK_AVOIDANCE(&p->lock); 01221 } else { 01222 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01223 ast_mutex_unlock(&p->subs[a].owner->lock); 01224 break; 01225 } 01226 } else 01227 break; 01228 } 01229 #ifdef HAVE_PRI 01230 if (pri) 01231 ast_mutex_lock(&pri->lock); 01232 #endif 01233 }
static int zap_accept_r2_call_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3546 of file chan_dahdi.c.
References dahdi_accept_r2_call_exec().
Referenced by load_module().
03547 { 03548 return dahdi_accept_r2_call_exec(chan, data); 03549 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12704 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
12705 { 12706 return __action_dialoffhook(s, m, 1); 12707 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12604 of file chan_dahdi.c.
References __action_dnd(), and s.
12605 { 12606 return __action_dnd(s, m, 1, 0); 12607 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12594 of file chan_dahdi.c.
References __action_dnd(), and s.
12595 { 12596 return __action_dnd(s, m, 1, 1); 12597 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12783 of file chan_dahdi.c.
References __action_restart(), and s.
12784 { 12785 return __action_restart(s, m, 1); 12786 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12759 of file chan_dahdi.c.
References __action_showchannels(), and s.
12760 { 12761 return __action_showchannels(s, m, 1); 12762 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12633 of file chan_dahdi.c.
References __action_transfer(), and s.
12634 { 12635 return __action_transfer(s, m, 1); 12636 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 12661 of file chan_dahdi.c.
References __action_transferhangup(), and s.
12662 { 12663 return __action_transferhangup(s, m, 1); 12664 }
static int zap_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3345 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and send_keypad_facility_exec().
Referenced by load_module().
03346 { 03347 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app); 03348 return send_keypad_facility_exec(chan, data); 03349 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 14172 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 14172 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1166 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 1134 of file chan_dahdi.c.
Referenced by __unload_module(), ast_device_state(), dahdi_new(), load_module(), and ss_thread().
int cidrings[NUM_CADENCE_MAX] [static] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
Definition at line 1177 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_destroy_channel_deprecated [static] |
Initial value:
{ { "zap", "destroy", "channel", NULL }, dahdi_destroy_channel, NULL, NULL }
Definition at line 12500 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 12505 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 12485 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 12495 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 12490 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 12510 of file chan_dahdi.c.
char* dahdi_accept_r2_call_app = "DAHDIAcceptR2Call" [static] |
Definition at line 3431 of file chan_dahdi.c.
char* dahdi_accept_r2_call_descrip [static] |
Initial value:
" DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n" " You can specify yes or no as argument to accept with or without charge.\n"
Definition at line 3437 of file chan_dahdi.c.
char* dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static] |
Definition at line 3434 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
struct ast_cli_entry dahdi_mfcr2_cli[] [static] |
struct ast_cli_entry dahdi_pri_cli[] [static] |
const char dahdi_r2_callfiles_help[] [static] |
Initial value:
"Usage: mfcr2 call files [on|off] <channel>\n" " Enable call files creation on the specified channel.\n" " If no channel is specified call files creation policy will be applied to all channels.\n"
Definition at line 11916 of file chan_dahdi.c.
openr2_event_interface_t dahdi_r2_event_iface [static] |
Definition at line 1732 of file chan_dahdi.c.
const char dahdi_r2_setblocked_help[] [static] |
Initial value:
"Usage: mfcr2 set blocked <channel>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n" " Force the given channel into BLOCKED state.\n" " If no channel is specified, all channels will be set to BLOCKED.\n"
Definition at line 11925 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 11912 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 11920 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 11909 of file chan_dahdi.c.
openr2_transcoder_interface_t dahdi_r2_transcode_iface [static] |
Initial value:
Definition at line 1763 of file chan_dahdi.c.
const char dahdi_r2_variants_help[] [static] |
Initial value:
"Usage: mfcr2 show variants\n" " Show supported MFC/R2 variants.\n"
Definition at line 11906 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 11903 of file chan_dahdi.c.
char dahdi_restart_usage[] [static] |
Definition at line 12478 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3287 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_descrip [static] |
Initial value:
" DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n" " IE over the current channel.\n"
Definition at line 3293 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3290 of file chan_dahdi.c.
char dahdi_show_cadences_usage[] [static] |
Initial value:
"Usage: dahdi show cadences\n" " Shows all cadences currently defined\n"
Definition at line 12371 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 12470 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1092 of file chan_dahdi.c.
Referenced by dahdi_accept_r2_call_exec(), and load_module().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 115 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 214 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 215 of file chan_dahdi.c.
char destroy_channel_usage[] [static] |
Initial value:
"Usage: dahdi destroy channel <chan num>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"
Definition at line 12474 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 219 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
int dtmfcid_level = 256 [static] |
Definition at line 222 of file chan_dahdi.c.
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 234 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), and skinny_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 237 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 122 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 246 of file chan_dahdi.c.
Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 243 of file chan_dahdi.c.
Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call(), find_call_locked(), get_sip_pvt_byid_locked(), handle_mfcr2_call_files(), handle_mfcr2_set_blocked(), handle_mfcr2_set_debug(), handle_mfcr2_set_idle(), handle_mfcr2_show_channels(), handle_request_subscribe(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), sip_alloc(), sip_destroy(), sip_show_channel(), sip_show_history(), and unload_module().
struct ast_channel inuse [static] |
Definition at line 225 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), and update_call_counter().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 240 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
int mfcr2_cur_accept_on_offer = 1 [static] |
Definition at line 332 of file chan_dahdi.c.
int mfcr2_cur_allow_collect_calls = 0 [static] |
Definition at line 331 of file chan_dahdi.c.
int mfcr2_cur_call_files = 0 [static] |
Definition at line 330 of file chan_dahdi.c.
openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER [static] |
Definition at line 347 of file chan_dahdi.c.
int mfcr2_cur_charge_calls = 1 [static] |
Definition at line 333 of file chan_dahdi.c.
int mfcr2_cur_context_index = 0 [static] |
Definition at line 329 of file chan_dahdi.c.
int mfcr2_cur_double_answer = 0 [static] |
Definition at line 335 of file chan_dahdi.c.
int mfcr2_cur_forced_release = 0 [static] |
Definition at line 334 of file chan_dahdi.c.
int mfcr2_cur_get_ani_first = -1 [static] |
Definition at line 327 of file chan_dahdi.c.
int mfcr2_cur_immediate_accept = -1 [static] |
Definition at line 336 of file chan_dahdi.c.
char mfcr2_cur_logdir[OR2_MAX_PATH] [static] |
Definition at line 344 of file chan_dahdi.c.
openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING [static] |
Definition at line 346 of file chan_dahdi.c.
int mfcr2_cur_max_ani = 10 [static] |
Definition at line 325 of file chan_dahdi.c.
int mfcr2_cur_max_dnis = 4 [static] |
Definition at line 326 of file chan_dahdi.c.
int mfcr2_cur_metering_pulse_timeout = -1 [static] |
Definition at line 324 of file chan_dahdi.c.
int mfcr2_cur_mfback_timeout = -1 [static] |
Definition at line 323 of file chan_dahdi.c.
char mfcr2_cur_r2proto_file[OR2_MAX_PATH] [static] |
Definition at line 345 of file chan_dahdi.c.
int mfcr2_cur_skip_category = -1 [static] |
Definition at line 328 of file chan_dahdi.c.
openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN [static] |
Definition at line 322 of file chan_dahdi.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 258 of file chan_dahdi.c.
Referenced by reload_config(), restart_monitor(), and unload_module().
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 254 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().
char* name |
Definition at line 2064 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1163 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 263 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 221 of file chan_dahdi.c.
const char pri_debug_help[] [static] |
Initial value:
"Usage: pri debug span <span>\n" " Enables debugging on a given PRI span\n"
Definition at line 11571 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 11575 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 11579 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 11583 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 11587 of file chan_dahdi.c.
int pridebugfd = -1 [static] |
Definition at line 229 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 249 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), and handle_pri_show_debug().
char pridebugfilename[1024] = "" [static] |
Definition at line 230 of file chan_dahdi.c.
Definition at line 408 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 217 of file chan_dahdi.c.
struct dahdi_mfcr2 r2links[NUM_SPANS] [static] |
Definition at line 321 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), dahdi_restart(), init_mfcr2_globals(), mfcr2_get_context(), and setup_dahdi().
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 310 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
char show_channel_usage[] [static] |
Initial value:
"Usage: dahdi show channel <chan num>\n" " Detailed information about a given channel\n"
Definition at line 12466 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 12462 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 259 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 262 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
char* subnames[] [static] |
const char tdesc[] [static] |
Definition at line 161 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1164 of file chan_dahdi.c.
char* zap_accept_r2_call_app = "ZapAcceptR2Call" [static] |
Definition at line 3432 of file chan_dahdi.c.
char* zap_accept_r2_call_descrip [static] |
Initial value:
" ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n" " You can specify yes or no as argument to accept with or without charge.\n"
Definition at line 3441 of file chan_dahdi.c.
char* zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)" [static] |
Definition at line 3435 of file chan_dahdi.c.
char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static] |
Definition at line 3288 of file chan_dahdi.c.
char* zap_send_keypad_facility_descrip [static] |
Initial value:
" ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n" " IE over the current channel.\n"
Definition at line 3296 of file chan_dahdi.c.
char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3291 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |